将 document.ready 绑定到弹出窗口

发布于 2024-12-16 19:41:13 字数 456 浏览 1 评论 0原文

由于 jQuery 绑定 document.ready 事件的方式,本应简单的代码却并非如此:

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

出现问题

  • 当父窗口就绪时,回调执行时
  • ,而不是回调中的子窗口就绪 this 是对 w.opener.document 的引用

是否有一种相当简单的跨浏览器方法将 ready 事件(或类似的)绑定到不同的使用 jQuery 的窗口上下文?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

末蓝 2024-12-23 19:41:13

大约 5 年前,当我问这个问题时,我还没有听说过 Promise。 jQuery 1.7 最近发布了,Deferred 已于今年早些时候在 1.5 中引入。这早于 Promises/A+ 规范,该规范在一年多后发布。

我这么说是因为当时我无法识别 jQuery 的 $(document).ready(...) 到底是什么。

它被绑定为一个事件,并将回调作为一个事件,而 jQuery API 将其视为一个事件,所以我错误地认为它是一个事件,尽管是一个特殊的事件。

文档准备好不是一个事件。 这是一个承诺。

综上所述,我的错误在于尝试跟随 jQuery 的领导并创建一个奇特的事件,而我应该这样做所做的就是使用 Promise(不用介意它们在 JS 世界中还不存在)。


话虽如此,在现代浏览器中的任何窗口引用上支持类似 document.ready 的行为非常简单。我的时间优势在于,许多旧问题已被错误修复,并且新的浏览器功能(例如 Promise)大大减少了实现 Ready 功能的工作量。

我对此问题的解决方案如下所示:

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();
    });
}

并且可以用作:

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

或者如果您使用的是 window.open

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

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
});
失与倦" 2024-12-23 19:41:13

JavaScript 安全策略不允许这样做。例如,您收到控制台错误,

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.

在调用 window.open 和设置同一窗口的 onload 函数之间有必要暂停。在 window.open 调用之后,该窗口没有属性。也许您必须重复使用 setInterval 执行此操作(然后不要忘记clearInterval)
在 jsfiddle 中尝试一下(这是我最好的猜测)

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 /

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/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文