开发者

Is jQuery.ready() valid when used on iframe.contentDocument?

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 select开发者_StackOverflow中文版ing 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()?


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!


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");
    }
},


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜