callbacks: [ "deferred" ],
css: [ "effects", "dimensions", "offset" ],
"css/showHide": [ "effects" ],
+ deferred: {
+ remove: [ "ajax", "effects", "queue", "core/ready" ],
+ include: [ "core/ready-no-deferred" ]
+ },
sizzle: [ "css/hiddenVisibleSelectors", "effects/animatedSelector" ]
}
}
* whether it should included or excluded
*/
excluder = function( flag ) {
- var m = /^(\+|\-|)([\w\/-]+)$/.exec( flag ),
+ var additional,
+ m = /^(\+|\-|)([\w\/-]+)$/.exec( flag ),
exclude = m[ 1 ] === "-",
module = m[ 2 ];
}
}
+ additional = removeWith[ module ];
+
// Check removeWith list
- excludeList( removeWith[ module ] );
+ if ( additional ) {
+ excludeList( additional.remove || additional );
+ if ( additional.include ) {
+ included = included.concat( additional.include );
+ grunt.log.writeln( "+" + additional.include );
+ }
+ }
} else {
grunt.log.error( "Module \"" + module + "\" is a minimum requirement." );
if ( module === "selector" ) {
--- /dev/null
+define( [
+ "../core",
+ "../var/document"
+], function( jQuery, document ) {
+
+var readyCallbacks = [],
+ readyFiring = false,
+ whenReady = function( fn ) {
+ readyCallbacks.push( fn );
+ },
+ executeReady = function( fn ) {
+
+ // Prevent errors from freezing future callback execution (gh-1823)
+ // Not backwards-compatible as this does not execute sync
+ window.setTimeout( function() {
+ fn.call( document, jQuery );
+ } );
+ };
+
+jQuery.fn.ready = function( fn ) {
+ whenReady( fn );
+ return this;
+};
+
+jQuery.extend( {
+
+ // Is the DOM ready to be used? Set to true once it occurs.
+ isReady: false,
+
+ // A counter to track how many items to wait for before
+ // the ready event fires. See #6781
+ readyWait: 1,
+
+ // Hold (or release) the ready event
+ holdReady: function( hold ) {
+ if ( hold ) {
+ jQuery.readyWait++;
+ } else {
+ jQuery.ready( true );
+ }
+ },
+
+ ready: function( wait ) {
+
+ // Abort if there are pending holds or we're already ready
+ if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
+ return;
+ }
+
+ // 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;
+ }
+
+ whenReady = function( fn ) {
+ readyCallbacks.push( fn );
+
+ if ( !readyFiring ) {
+ readyFiring = true;
+
+ while ( readyCallbacks.length ) {
+ fn = readyCallbacks.shift();
+ if ( jQuery.isFunction( fn ) ) {
+ executeReady( fn );
+ }
+ }
+ readyFiring = false;
+ }
+ };
+
+ whenReady();
+ }
+} );
+
+// Make jQuery.ready Promise consumable (gh-1778)
+jQuery.ready.then = jQuery.fn.ready;
+
+/**
+ * The ready event handler and self cleanup method
+ */
+function completed() {
+ document.removeEventListener( "DOMContentLoaded", completed );
+ window.removeEventListener( "load", completed );
+ jQuery.ready();
+}
+
+// Catch cases where $(document).ready() is called
+// after the browser event has already occurred.
+// Support: IE9-10 only
+// Older IE sometimes signals "interactive" too soon
+if ( document.readyState === "complete" ||
+ ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
+
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
+ window.setTimeout( jQuery.ready );
+
+} else {
+
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", completed );
+
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", completed );
+}
+
+} );
], function( jQuery, document ) {
// The deferred used on DOM ready
-var readyList;
+var readyList = jQuery.Deferred();
jQuery.fn.ready = function( fn ) {
- // Add the callback
- jQuery.ready.promise().done( fn );
+ readyList.then( fn );
return this;
};
}
} );
-/**
- * The ready event handler and self cleanup method
- */
+jQuery.ready.then = readyList.then;
+
+// The ready event handler and self cleanup method
function completed() {
document.removeEventListener( "DOMContentLoaded", completed );
window.removeEventListener( "load", completed );
jQuery.ready();
}
-jQuery.ready.promise = function( obj ) {
- if ( !readyList ) {
-
- readyList = jQuery.Deferred();
+// Catch cases where $(document).ready() is called
+// after the browser event has already occurred.
+// Support: IE <=9 - 10 only
+// Older IE sometimes signals "interactive" too soon
+if ( document.readyState === "complete" ||
+ ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
- // Catch cases where $(document).ready() is called
- // after the browser event has already occurred.
- // Support: IE <=9 - 10 only
- // Older IE sometimes signals "interactive" too soon
- if ( document.readyState === "complete" ||
- ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
+ window.setTimeout( jQuery.ready );
- // Handle it asynchronously to allow scripts the opportunity to delay ready
- window.setTimeout( jQuery.ready );
+} else {
- } else {
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", completed );
- // Use the handy event callback
- document.addEventListener( "DOMContentLoaded", completed );
-
- // A fallback to window.onload, that will always work
- window.addEventListener( "load", completed );
- }
- }
- return readyList.promise( obj );
-};
-
-// Kick off the DOM ready check even if the user does not
-jQuery.ready.promise();
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", completed );
+}
} );
( function() {
var notYetReady, noEarlyExecution,
+ promisified = Promise.resolve( jQuery.ready ),
order = [],
args = {};
};
}
+ function throwError( num ) {
+
+ // Not a global QUnit failure
+ var onerror = window.onerror;
+ window.onerror = function() {
+ window.onerror = onerror;
+ };
+
+ throw new Error( "Ready error " + num );
+ }
+
// Bind to the ready event in every possible way.
jQuery( makeHandler( "a" ) );
jQuery( document ).ready( makeHandler( "b" ) );
+ // Throw in an error to ensure other callbacks are called
+ jQuery( function() {
+ throwError( 1 );
+ } );
+
+ // Throw two errors in a row
+ jQuery( function() {
+ throwError( 2 );
+ } );
+ jQuery.when( jQuery.ready ).done( makeHandler( "c" ) );
+
// Do it twice, just to be sure.
- jQuery( makeHandler( "c" ) );
- jQuery( document ).ready( makeHandler( "d" ) );
+ jQuery( makeHandler( "d" ) );
+ jQuery( document ).ready( makeHandler( "e" ) );
+ jQuery.when( jQuery.ready ).done( makeHandler( "f" ) );
noEarlyExecution = order.length === 0;
"Handlers bound to DOM ready should not execute before DOM ready" );
// Ensure execution order.
- assert.deepEqual( order, [ "a", "b", "c", "d" ],
+ assert.deepEqual( order, [ "a", "b", "c", "d", "e", "f" ],
"Bound DOM ready handlers should execute in on-order" );
// Ensure handler argument is correct.
order = [];
- // Now that the ready event has fired, again bind to the ready event
- // in every possible way. These event handlers should execute immediately.
+ // Now that the ready event has fired, again bind to the ready event.
+ // These ready handlers should execute asynchronously.
+ var done = assert.async();
jQuery( makeHandler( "g" ) );
- assert.equal( order.pop(), "g", "Event handler should execute immediately" );
- assert.equal( args.g, jQuery, "Argument passed to fn in jQuery( fn ) should be jQuery" );
-
jQuery( document ).ready( makeHandler( "h" ) );
- assert.equal( order.pop(), "h", "Event handler should execute immediately" );
- assert.equal( args.h, jQuery,
- "Argument passed to fn in jQuery(document).ready( fn ) should be jQuery" );
+ window.setTimeout( function() {
+ assert.equal( order.shift(), "g", "Event handler should execute immediately, but async" );
+ assert.equal( args.g, jQuery, "Argument passed to fn in jQuery( fn ) should be jQuery" );
+
+ assert.equal( order.shift(), "h", "Event handler should execute immediately, but async" );
+ assert.equal( args.h, jQuery,
+ "Argument passed to fn in jQuery(document).ready( fn ) should be jQuery" );
+ done();
+ } );
} );
+ QUnit.test( "Promise.resolve(jQuery.ready)", function( assert ) {
+ assert.expect( 2 );
+ var done = jQuery.map( new Array( 2 ), function() { return assert.async(); } );
+
+ promisified.then( function() {
+ assert.ok( jQuery.isReady, "Native promised resolved" );
+ done.pop()();
+ } );
+
+ Promise.resolve( jQuery.ready ).then( function() {
+ assert.ok( jQuery.isReady, "Native promised resolved" );
+ done.pop()();
+ } );
+ } );
+
+ QUnit.test( "Error in ready callback does not halt all future executions (gh-1823)", function( assert ) {
+ assert.expect( 1 );
+ var done = assert.async();
+
+ jQuery( function() {
+ throwError( 3 );
+ } );
+
+ jQuery( function() {
+ assert.ok( true, "Subsequent handler called" );
+ done();
+ } );
+ } );
} )();