jQuery.ready() 在 iframe.contentDocument 上使用时有效吗?

发布于 2024-11-04 23:02:24 字数 1047 浏览 1 评论 0原文

简单问题(如标题所述): 在 iframe.contentDocument 上使用 jQuery.ready() 是否有效?

还有一个复杂的问题:

我必须在 CMS 的输入字段上挂钩 keyup 事件,因此我无法控制 HTML,只能控制脚本。

输入位于嵌套在另一个 iframe 中的 iframe 内,因此有一个顶部窗口(浏览器窗口)、一个 iframe(我们称之为 iframe1)和其中的另一个 iframe(我们称之为 iframe2)。脚本和 jQuery 位于顶部窗口的 部分。

我不太喜欢 setTimeout/setInterval ,所以我最初的想法是像这样使用 jQuery.ready() (我省略了选择 iframe 的代码):

$(document).ready(function(){
  $(iframe1.contentDocument).ready(function(){
    $(iframe2.contentDocument).ready(function(){
      $("input").keyup(function(){ /* Do stuff */ });
    });
  });
});

问题是,当 .ready() 在 iframe1 上触发时,我可以检查 iframe1.contentDocument.body.innerHTML ,结果发现它是一个空字符串。不是人们所期望的那样。因此,代码无法绑定 keyup 事件。

如果有人想“您使用的是正确的选择器上下文吗?”:是的,我正在正确的文档中选择 iframe 元素(尽管上面的代码片段可能无法完全说明这一点,因为我想保持简单)。也不存在任何同源策略问题 - 所有 iframe 和父窗口都位于同一域中。

使用 $(window).load() 似乎可以工作,但是等待加载图像等的等待时间太长,这对于应用程序来说是不可接受的。

有没有办法实现 jQuery.ready() 功能,无需使用 jQuery.load() 即可在 iframe 上工作?

Simple question (as stated in the title):
Is jQuery.ready() valid when used on iframe.contentDocument?

And the complex question:

I have to hook a keyup event on an input field in a CMS, hence I have no control over the HTML, only the script.

The input is inside an iframe that's nested in another iframe, so there's a top window (the browser window), an iframe (lets call it iframe1) and another iframe inside of that (lets call that one iframe2). The script and jQuery are located in the <head> section of the top window.

I'm not really fond of setTimeout/setInterval, so my initial thought was to use jQuery.ready() like this (I have omitted the code selecting the iframes):

$(document).ready(function(){
  $(iframe1.contentDocument).ready(function(){
    $(iframe2.contentDocument).ready(function(){
      $("input").keyup(function(){ /* Do stuff */ });
    });
  });
});

Problem is, by the time .ready() fires on iframe1 I can check iframe1.contentDocument.body.innerHTML and it turns out to be an empty string. Not what one would expect. The code fails to bind the keyup event as a result of this.

In case anyone is thinking "Are you using the correct selector context?": Yep I'm selecting the iframe elements in the correct documents (although the code piece above may not fully examplify this, as I wanted to keep it simple). Nor are there any same origin policy issues - all iframes and parent window are on the same domain.

Using $(window).load() seems to work, but waiting for images etc. to be loaded is subject to far too long waiting times than will be unacceptable for the application.

Is there away to achieve a jQuery.ready() functionality that will work on the iframes without using jQuery.load()?

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

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

发布评论

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

评论(3

甜警司 2024-11-11 23:02:25

我不确定您是否厌恶使用 $(window).load() 但您可以将 load() 直接绑定到 iframe 并获取尽可能关闭,而无需直接访问添加 jquery 的 iframe 内容。

我过去做过类似的事情,根据 iframe 内容的高度动态调整 iframe 的大小。这是一个可能不直接相关的示例,但您应该能够了解它正在做什么的要点。

    $(function(){
    var $content_iframe = $('#content_iframe')

    $content_iframe.load(
        function(){
            var contentHeight = $content_iframe.contents().find('html body').height();
            if (contentHeight > 1070){
                $(this).height(contentHeight + 30);
            }
            else{
                $(this).height(1100);
            }
        }
    );
})

就图像加载时间等而言,这可能具有相同的缺点。祝你好运!

I'm not sure if it was implied in your aversion to using $(window).load() but you can bind load() directly to the iframe and get as close as is possible without having direct access to adding jquery the iframe contents.

I've done something similar in the past to resize an iframe dynamically based on the height of its contents. Here is an example that may not be directly related, but you should be able to get the gist of what it's doing.

    $(function(){
    var $content_iframe = $('#content_iframe')

    $content_iframe.load(
        function(){
            var contentHeight = $content_iframe.contents().find('html body').height();
            if (contentHeight > 1070){
                $(this).height(contentHeight + 30);
            }
            else{
                $(this).height(1100);
            }
        }
    );
})

This may have the same drawbacks as far as image load times etc. Best of luck!

熟人话多 2024-11-11 23:02:25

只是注意到我从未接受过这个问题的答案。

简短回答:否。

详细回答:

一旦 jQuery 认为 DOM 已准备好并触发绑定到就绪事件的事件处理程序,jQuery.isReady 就会设置为 true。它检查(以及其他一些事情)document.body 是否使用重复的 setTimeout() 定义,直到它被定义,但仅限于 jQuery 所在的窗口被定义。换句话说,它不适用于 (i)Frames。

当前版本 jQuery (1.8.0) 的就绪代码:

// Handle when the DOM is ready
ready: function( wait ) {

    // Abort if there are pending holds or we're already ready
    if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
        return;
    }

    // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
    if ( !document.body ) {
        return setTimeout( jQuery.ready, 1 );
    }

    // Remember that the DOM is ready
    jQuery.isReady = true;

    // If a normal DOM Ready event fired, decrement, and wait if need be
    if ( wait !== true && --jQuery.readyWait > 0 ) {
        return;
    }

    // If there are functions bound, to execute
    readyList.resolveWith( document, [ jQuery ] );

    // Trigger any bound ready events
    if ( jQuery.fn.trigger ) {
        jQuery( document ).trigger("ready").off("ready");
    }
},

Just noticed I never accepted an answer for this.

Short answer: No.

Long answer:

The jQuery.isReady is set to true once jQuery thinks the DOM is ready and fires the event handlers bound to the ready event. It checks (among a few other things) whether or not document.body is defined with a repeating setTimeout() until it is defined, but only for the window in which jQuery is defined. In other words, it doesn't work for (i)Frames.

Ready code from current version of jQuery (1.8.0):

// Handle when the DOM is ready
ready: function( wait ) {

    // Abort if there are pending holds or we're already ready
    if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
        return;
    }

    // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
    if ( !document.body ) {
        return setTimeout( jQuery.ready, 1 );
    }

    // Remember that the DOM is ready
    jQuery.isReady = true;

    // If a normal DOM Ready event fired, decrement, and wait if need be
    if ( wait !== true && --jQuery.readyWait > 0 ) {
        return;
    }

    // If there are functions bound, to execute
    readyList.resolveWith( document, [ jQuery ] );

    // Trigger any bound ready events
    if ( jQuery.fn.trigger ) {
        jQuery( document ).trigger("ready").off("ready");
    }
},
酷到爆炸 2024-11-11 23:02:25

如果您可以控制加载到 框中的页面,它们也可以加载自己的 jQuery 副本并拥有自己的“.ready()”处理程序。这些处理程序可以依次与“顶部”页面的 JavaScript 代码进行通信(可能通过 jQuery“延迟”对象),以便可以将外部页面设置为在所有 iframe 都“就绪”时运行代码。

您需要在“就绪”状态之前设置父页面代码,因为您不确定父页面是否会在子 页面。

If you have control over the pages loaded into the <iframe> boxes, they too can load their own copies of jQuery and have their own ".ready()" handlers. Those handlers can, in turn, communicate with the "top" page's JavaScript code (possibly through a jQuery "Deferred" object), so that your outer page can be set up to run code when all the iframes have become "ready".

You'd want to set up the parent page code before the "ready" state, because you don't know for sure that the parent page will be ready before the child <iframe> pages.

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