问题
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 tow.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