diff --git a/src/core.js b/src/core.js index 6746802e6..2ed6d62b6 100644 --- a/src/core.js +++ b/src/core.js @@ -251,11 +251,8 @@ jQuery.fn = jQuery.prototype = { }, ready: function( fn ) { - // Attach the listeners - jQuery.bindReady(); - // Add the callback - readyList.add( fn ); + jQuery.ready.promise().done( fn ); return this; }, @@ -412,7 +409,7 @@ jQuery.extend({ } // If there are functions bound, to execute - readyList.fireWith( document, [ jQuery ] ); + readyList.resolveWith( document, [ jQuery ] ); // Trigger any bound ready events if ( jQuery.fn.trigger ) { @@ -421,51 +418,6 @@ jQuery.extend({ } }, - bindReady: function() { - if ( readyList ) { - return; - } - - readyList = jQuery.Callbacks( "once memory" ); - - // Catch cases where $(document).ready() is called after the - // browser event has already occurred. - if ( document.readyState !== "loading" ) { - // Handle it asynchronously to allow scripts the opportunity to delay ready - return setTimeout( jQuery.ready, 1 ); - } - - // Mozilla, Opera and webkit nightlies currently support this event - if ( document.addEventListener ) { - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); - - // A fallback to window.onload, that will always work - window.addEventListener( "load", jQuery.ready, false ); - - // If IE event model is used - } else if ( document.attachEvent ) { - // ensure firing before onload, - // maybe late but safe also for iframes - document.attachEvent( "onreadystatechange", DOMContentLoaded ); - - // A fallback to window.onload, that will always work - window.attachEvent( "onload", jQuery.ready ); - - // If IE and not a frame - // continually check to see if the document is ready - var toplevel = false; - - try { - toplevel = window.frameElement == null; - } catch(e) {} - - if ( document.documentElement.doScroll && toplevel ) { - doScrollCheck(); - } - } - }, - // See test/unit/core.js for details concerning isFunction. // Since version 1.3, DOM methods and functions like alert // aren't supported. They return false on IE (#2968). @@ -897,6 +849,50 @@ jQuery.extend({ browser: {} }); +jQuery.ready.promise = function( object ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState !== "loading" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + setTimeout( jQuery.ready, 1 ); + + // Mozilla, Opera and webkit nightlies currently support this event + } else if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", DOMContentLoaded ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + } + return readyList.promise( object ); +}; + // Populate the class2type map jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { class2type[ "[object " + name + "]" ] = name.toLowerCase(); diff --git a/test/data/event/promiseReady.html b/test/data/event/promiseReady.html new file mode 100644 index 000000000..f799a7e3e --- /dev/null +++ b/test/data/event/promiseReady.html @@ -0,0 +1,17 @@ + + + + +Test case for jQuery ticket #11470 + + + + + + + \ No newline at end of file diff --git a/test/unit/event.js b/test/unit/event.js index 5d96ec1b7..57adb0443 100644 --- a/test/unit/event.js +++ b/test/unit/event.js @@ -2800,6 +2800,11 @@ test("fixHooks extensions", function() { // which breaks order of execution on async loaded files // also need PHP to make the incepted IFRAME hang if ( hasPHP ) { + testIframeWithCallback( "jQuery.ready promise", "event/promiseReady", function( isOk ) { + expect(1); + ok( isOk, "$.when( $.ready ) works" ); + }); + testIframeWithCallback( "jQuery.ready synchronous load with long loading iframe", "event/syncReady", function( isOk ) { expect(1); ok( isOk, "jQuery loaded synchronously fires ready before all sub-resources are loaded" );