好的,我整理了一个脚本来执行此操作:


发出ajax请求(通过getHTTPObject(),不使用任何库)
使用脚本创建iframe,src为“ blank.html”。
使用iframe.document.write()在iframe中执行脚本(包括基于document.write的脚本)。
调用父窗口的文档以克隆iframe内容。
将内容克隆追加到父正文。


在IE之外的所有浏览器中,它的工作方式都像魅力一样,在IE中,每个版本(包括IE9 beta)都挂在具有空缓存的iframeWindow.document.close()上,从而使窗口/标签不负责任。当我强制退出时,重新启动并再次加载页面即可。

我已经尝试过的


谷歌搜索。
手动使用字符串而不是request.responseText来调用ajax请求回调-即使在此处使用空缓存时也可以使用。
删除了document.close()-导致iframe中的脚本根本不执行(再次,只有在使用空缓存的情况下,缓存页面才能正常运行)。
经过测试,使ajax请求同步-没有区别。


有任何想法吗?

现场示例:
http://labs.adeprimo.se/~adupanyt/ot/unlimited_scroll/

这是代码。 install(),finish()和append()函数管理iframe。

/*!
 * Cross browser unlimited scroll snippet
 * Copyright (c) 2010 by Adeprimo.
 * Released under the MIT license.
 */
/* Code assumptions:
 *
 *      <div id="unlimited-scroll-wrapper">
 *
 *          ... first content ...
 *
 *          <a id="load-more-unlimited-content" href="/nyheter">
 *            Ladda mer innehåll</a>
 *      </div>
 */
(function(window, document, undefined){
    /**
     * This snippet has two running modes, and it is the load_on_scroll
     * directive which rules it.
     *
     * true     = a scroll event is initiated, which will wait
     *            until the bottom is reached before it load any new content.
     * false    = this script will continue loading more content, one piece
     *            at the time, until there is no more to get.
     *
     */
    load_on_scroll = false;

    var request;    // results of getHTTPObject()
    var wrapper;    // reference to the element which stores the new contents.
    var callsCount; // keep the count of ajax calls, helps css targeting.
    var attachEvent;// stores result of window.attachEvent for performance

    // locks, these are updated by the script.
    window.mkt_nothing_more_to_load = false;// true when end of queue reached.
    window.mkt_prevent_new_loading = false; // true when ajax in progress.

    wrapper = document.getElementById('unlimited-scroll-wrapper');
    callsCount = 1;
    attachEvent = window.attachEvent;

    /**
     * Customize this function for your need.
     * It is called each time a new document fragment
     * shall load.
     * In here, you might add some nifty jQuery or Prototype if your app
     * has it.
     */
    function load_and_append() {
        var src; // href attribute of the #load-more-unlimited-content A element

        // get the source
        src = document.getElementById('load-more-unlimited-content').href;

        // mktwebb specific, will only return the content and
        // not the header or footer.
        src = src.replace(/\?.+?$/, '') + '?segment=content,footer';

        if (!request) {
            request = getHTTPObject();  // getHTTPObject must be declared
        }                               // separately!

        if (request) {
            request.onreadystatechange = function() {
                if (request.readyState == 4) {
                    if (request.status == 200 || request.status == 304) {
                        console.log('append() begin');
                        append(request.responseText, src);
                        console.log('append() done');
                    }
                }
            };

            request.open("GET", src, false);
            request.send(null);
        }
    }

    function finish(iframe_window) {
        var acc_elm = (function(doc){
            return doc.getElementsByTagName('div')[0].cloneNode(true);
        })(iframe_window.document);

        document.getElementById('unlimited-scroll-wrapper').appendChild(acc_elm);

        window.mkt_prevent_new_loading = false; // we are ready to more content.

        // we are done with the iframe, let's remove it.
        var iframe_container = document.getElementById('mkt_iframe-container');
        iframe_container.parentNode.removeChild(iframe_container);

        // basically, the script continues as long as it finds a new
        // #load-more-unlimited-content element in the newly added content.
        // if it can't find the #load-more-unlimited-content,
        // the script will stop and unattach itself.
        if (document.getElementById('load-more-unlimited-content')) {
            // if load_on_scroll, the new content is added under
            // the control of the scroll event. There is no need to call
            // load_and_append here since the scroll event will manage
            // that fine.
            // however, when not load_on_scroll,
            // new content should be loaded asap.
            if (!load_on_scroll) {
                window.mkt_prevent_new_loading = true;
                // give the browser some time to reflow and rest, then continue.
                setTimeout(load_and_append, 2 * 1000);
            }
        } else {
            nothing_more_to_load = true; // tell the scroll event to stop.

            // remove scroll event since it is not needed anymore
            if (attachEvent) {
                window.detachEvent('onscroll',
                    look_for_trouble); // ie
            } else {
                window.removeEventListener('scroll',
                    look_for_trouble, false); // w3c
            }
        }
    };
    window['mkt_importFromIframe'] = finish;

    // ------------------------------------------------------------------------
    // We are now ready to start.
    // ------------------------------------------------------------------------

    // see head section in this file for how to configure load_on_scroll
    function init() {
        if (load_on_scroll) {
            if (attachEvent) {
                window.attachEvent('onscroll', look_for_trouble);
            } else {
                window.addEventListener('scroll', look_for_trouble, false);
            }
        } else {
            load_and_append();
        }
    }

    // we are using window.onload since we want "everything" to run
    // in the first screeen before we continue.
    if (attachEvent) {
        window.attachEvent('onload', init);
    } else {
        window.addEventListener('load', init, false);
    }

    // ------------------------------------------------------------------------
    // the script has started. Below functions are supporting it.
    // ------------------------------------------------------------------------

    // loaded in load_and_append after a successful ajax call.
    function append(txt, src) {
        // remove previously #load-more-unlimited-content links since
        // it i not needed anymore.
        (function(elm_to_remove){
            elm_to_remove.parentNode.removeChild(elm_to_remove);
        })(document.getElementById('load-more-unlimited-content'));

        console.log('install() begin');
        install(txt, src);
        console.log('install() done');
    }

    /**
     * cleaning function to strip unecessary tags(oup) out.
     * also attach and execute scripts with the help of an
     * handy little snippet.
     */
    function install(ajax_result, src) {
        var acc_elm;        // final wrapper DIV,
        var acc_class;      // and it's unique class.

        // remove the footer since we don't want that in our result.
        ajax_result = ajax_result.match(/^([\n\s\S]+?)<div id="mainBottom/im)
                    || ['', ajax_result];

        // rename #startPageContainer to avoid css conflicts.
        ajax_result = ajax_result[1].replace(/startpageContainer/m,
                                'startPageContainer_'
                                + Math.floor(Math.random() * 1000));

        ajax_result = ajax_result.replace(/<scr/ig, '\x3Cscr').replace(/<\/scr/ig, '\x3C/scr');

        acc_class = 'aCC-' + src.match(/:\/\/.+?\/(.+?)\?/)[1].replace(/[\/.]/g, '_');
        acc_class += ' aCC'+ ++callsCount;

        acc_class = 'allColumnsContainer ' + acc_class;

        // mount ajax response in a temporary iframe
        // and send the markup upwards when done. by doing
        // this, all scripts in the ajax response is executed
        // correctly.
        console.log('iframe begin');
        (function(iframe_container){
            var iframe_window;  // reference
            var splitted;       // for cross browser script execution

            iframe_window = getIFrameWindow(document.getElementById('unlimited-loader'));

            iframe_window.document.open();

            // open wrappers DIVs.
            iframe_window.document.write(
                '<div class="' + acc_class +
                '"><div class="allColumnsContainer-inner">');

            // now comes a tricky part: all but IE will execute
            // script tags without any complains. To make the
            // last stubborn one work with us, we need to split
            // strings to mimic the rusty ol':
            //       '<scr' + 'ipt>doAmazingStuff()</scr' + 'ipt>';
            splitted = ajax_result.split('<scr');

            // first chunk can be added right away.
            iframe_window.document.write(splitted[0]);

            // we are done now unless there was a script in
            // the ajax response, which we know if we have more
            // than one chunk.
            if (splitted.length > 1) {
                for (var extracted, i = 1, max = splitted.length; i < max; i++) {
                    // this is necessary since we need to
                    // split the end tags as well.
                    extracted = splitted[i].split('</scr');

                    // now we can put it together
                    iframe_window.document.write('<scr'
                        + extracted[0] + '</scr' + extracted[1]);
                }
            }

            // close wrapper DIVs
            iframe_window.document.write('</div></div>');

            // finally, we ask the iframe to send the html
            // up to the parent.
            iframe_window.document.write('<scr');
            iframe_window.document.write('ipt>setTimeout(function(){parent.mkt_importFromIframe(this);}, 999);</scr' + 'ipt>');
            iframe_window.document.write('<h1>bu!</h1>');

            console.log('iframe document.close begin');

            console.log('iframe document.close done');
        })((function(){
            var div = document.createElement('div');

            // the iframe should be visually hidden so
            // lets add some css for that.
            div.style.position = "absolute";
            div.style.left = "-9999px";
            div.style.top = "-99px";

            div.id = 'mkt_iframe-container'; // do not change this!

            div.innerHTML = '<iframe id="unlimited-loader" name="unlimited-loader" src="inner.html"></iframe>';

            (function(scr){
                 scr.parentNode.insertBefore(div, scr);
            })(document.getElementsByTagName('script')[0]);

            return div;
        })());
        console.log('iframe done');
    }

    /**
     * callback function which is called when we are using
     * scrollbased loading and fires a scroll event.
     * It makes sure we are not loading anything
     * until it is necessary.
     */
    function look_for_trouble(e) {
        // first, check to see if we should continue.
        if (window.mkt_nothing_more_to_load || window.mkt_prevent_new_loading) {
            return; // one or more locks is still active, so we wait.
        }

        // second, we only want to load new content
        // if we are at the bottom of the page.
        if (getDocHeight() - getScrollTop() <= window.outerHeight) {
            window.mkt_prevent_new_loading = true;
            load_and_append();
        }
    };

    //
    // borrowed functions.
    //

    // found at http://james.padolsey.com/javascript/get-document-height-cross-browser/
    function getDocHeight() {
        return Math.max(
            Math.max(document.body.scrollHeight,
                document.documentElement.scrollHeight),
            Math.max(document.body.offsetHeight,
                document.documentElement.offsetHeight),
            Math.max(document.body.clientHeight,
                document.documentElement.clientHeight)
        );
    }

    // found at http://stackoverflow.com/questions/871399/cross-browser-method-for-detecting-the-scrolltop-of-the-browser-window
    function getScrollTop(){
        if(typeof pageYOffset!= 'undefined'){
            //most browsers
            return pageYOffset;
        }
        else{
            var B= document.body; //IE 'quirks'
            var D= document.documentElement; //IE with doctype
            D= (D.clientHeight)? D: B;
            return D.scrollTop;
        }
    }

    // http://av5.com/docs/changing-parent-window-s-url-from-iframe-content.html
    function getIFrameWindow(iframe) {
        return (iframe.contentWindow) ? iframe.contentWindow : (iframe.contentDocument.document) ? iframe.contentDocument.document : iframe.contentDocument;
    }

    function getHTTPObject() {
        var xhr = false;//set to false, so if it fails, do nothing
        if(window.XMLHttpRequest) {//detect to see if browser allows this method
            var xhr = new XMLHttpRequest();//set var the new request
        } else if(window.ActiveXObject) {//detect to see if browser allows this method
            try {
                var xhr = new ActiveXObject("Msxml2.XMLHTTP");//try this method first
            } catch(e) {//if it fails move onto the next
                try {
                    var xhr = new ActiveXObject("Microsoft.XMLHTTP");//try this method next
                } catch(e) {//if that also fails return false.
                    xhr = false;
                }
            }
        }
        return xhr;//return the value of xhr
    }
})(window, document);

最佳答案

也许我错了,但据我所知,按照DOM规范,MSIE中无法在文档之间移动节点。(关于您的描述,这就是您要做的)

供测试用:

<html>
<head>
<script type="text/javascript">
<!--
function fx(o)
{
  var doc=o.contentWindow.document;
  doc.body.appendChild(doc.createTextNode('This works with nodes \
                                           from the same document'));
  try{
      doc.body.appendChild(document.createTextNode(' and also with nodes \
                                                     from another document'));
     }
  catch(e)
    {
      doc.body.appendChild(doc.createTextNode(' but not  with nodes from \
                                                another document=>['+e.description+']'));
    }
}
//-->
</script>
</head>
<body>
<iframe onload="fx(this)" src="about:blank"></iframe>
</body>
</html>

关于javascript - Internet Explorer(IE)中的脚本挂起,并且对空缓存不负责(对缓存正常工作),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4509226/

10-12 07:34
查看更多