Bind document.ready to a popout window

谁都会走 提交于 2019-12-24 04:05:15

问题


Due to the manner in which jQuery binds the document.ready event, code that should be simple isn't:

var w = window.open(someSameOriginLocation,'');
$(w).ready(function () { //alternatively selector could be $(w.document)
  console.log('popout ready');
});

Problems

  • the callback executes when the parent window is ready, not the child
  • within the callback this is a reference to w.opener.document

Is there a reasonably simple, cross-browser way of binding the ready event (or similar) to a different window context using jQuery?


回答1:


When I asked this question about 5 years ago I hadn't heard of promises. jQuery 1.7 had recently been released, and Deferred had been introduced in 1.5 earlier in the year. This predated the Promises/A+ specification, which was released just over a year later.

I say this all because at the time I had no way of recognizing jQuery's $(document).ready(...) for what it was.

It was bound as an event, and took a callback as an event, and the jQuery API treated it as an event, so I had mistakenly assumed it was an event, albeit a special one.

Document ready is not an event. It's a promise.

So with all that said, my mistake was in attempting to follow jQuery's lead and create a fancy event, when what I should have done was use a promise (never mind that they didn't exist in the JS world yet).


With all that said, supporting a document.ready-like behavior on any window reference in modern browsers is pretty simple. I have the advantage of time in that many old problems have been bugfixed away, and new browser features (such as Promise) greatly reduce the amount of effort to implement a ready function.

My solution to this problem looks like:

function ready(win) {
    return new Promise(function (resolve) {
        function checkReady() {
            if (win.document.readyState === 'complete') {
                resolve();
            }
        }

        win.document.addEventListener('DOMContentLoaded', checkReady, false);
        win.addEventListener('load', checkReady, false);
        checkReady();
    });
}

and can be used as:

ready(window).then(function () {
  //...do stuff
});

or if you're using window.open:

ready(open('/your/file.html', ...)).then(function () {
  //.../your/file.html is ready
});



回答2:


The JavaScript security policy won't allow this. For example you get console error

Unsafe JavaScript attempt to access frame with URL http://www.example.com/ from frame with URL http://www.example.org/. Domains, protocols and ports must match.

It's necessary that you have a pause between the calling of window.open and setting of the onload function of that same window. Immediately after the window.open call that window has no properties. Perhaps you must do this with setInterval repeatedly (don't forget the clearInterval then)
Try this in jsfiddle (this is my best guess)

function func() {

    var w = window.open('http://fiddle.jshell.net/','windowname');

    setTimeout(function() {
        w.onload = function () {
            $(w).ready(function() {
                console.log(w.name)
            });
        };
    },1000)
}

http://jsfiddle.net/HerrSerker/fTjTr/8/



来源:https://stackoverflow.com/questions/8158612/bind-document-ready-to-a-popout-window

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!