master = jQuery.Deferred(),
// subordinate callback factory
updateFunc = function( i ) {
return function( value ) {
resolveContexts[ i ] = this;
resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
if ( !( --remaining ) ) {
master.resolveWith( resolveContexts, resolveValues );
// Single- and empty arguments are adopted like Promise.resolve
adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject,
// Use .then() to unwrap secondary thenables (cf. gh-3000)
if ( master.state() === "pending" ||
isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
// Multiple arguments are aggregated like Promise.all array elements
adoptValue( resolveValues[ i ], updateFunc( i ), master.reject );
// These usually indicate a programmer mistake during development,
// warn about them ASAP rather than swallowing them by default.
var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;
jQuery.Deferred.exceptionHook = function( error, stack ) {
// Support: IE 8 - 9 only
// Console exists when dev tools are open, which can happen at any time
if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {
window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack );
jQuery.readyException = function( error ) {
window.setTimeout( function() {
// The deferred used on DOM ready
var readyList = jQuery.Deferred();
jQuery.fn.ready = function( fn ) {
// Wrap jQuery.readyException in a function so that the lookup
// happens at the time of error handling instead of callback
.catch( function( error ) {
jQuery.readyException( error );
// Is the DOM ready to be used? Set to true once it occurs.
// A counter to track how many items to wait for before
// the ready event fires. See #6781
// 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 ) {
// Remember that the DOM is ready
// If a normal DOM Ready event fired, decrement, and wait if need be
if ( wait !== true && --jQuery.readyWait > 0 ) {
// If there are functions bound, to execute
readyList.resolveWith( document, [ jQuery ] );
jQuery.ready.then = readyList.then;
// The ready event handler and self cleanup method
document.removeEventListener( "DOMContentLoaded", completed );
window.removeEventListener( "load", completed );
// 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 );
// Use the handy event callback
document.addEventListener( "DOMContentLoaded", completed );
// A fallback to window.onload, that will always work
window.addEventListener( "load", completed );
// Multifunctional method to get and set values of a collection
// The value/s can optionally be executed if it's a function
var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
if ( toType( key ) === "object" ) {
access( elems, fn, i, key[ i ], true, emptyGet, raw );
} else if ( value !== undefined ) {
if ( !isFunction( value ) ) {
// Bulk operations run against the entire set
// ...except when executing function values
fn = function( elem, _key, value ) {
return bulk.call( jQuery( elem ), value );
value.call( elems[ i ], i, fn( elems[ i ], key ) )
return len ? fn( elems[ 0 ], key ) : emptyGet;
// Matches dashed string for camelizing
rdashAlpha = /-([a-z])/g;
// Used by camelCase as callback to replace()
function fcamelCase( _all, letter ) {
return letter.toUpperCase();
// Convert dashed to camelCase; used by the css and data modules
// Support: IE <=9 - 11, Edge 12 - 15
// Microsoft forgot to hump their vendor prefix (#9572)
function camelCase( string ) {
return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
var acceptData = function( owner ) {
return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
this.expando = jQuery.expando + Data.uid++;
cache: function( owner ) {
// Check if the owner object already has a cache
var value = owner[ this.expando ];
// We can accept data for non-element nodes in modern browsers,
// but we should not, see #8335.
// Always return an empty object.
if ( acceptData( owner ) ) {
// If it is a node unlikely to be stringify-ed or looped over
owner[ this.expando ] = value;
// Otherwise secure it in a non-enumerable property
// configurable must be true to allow the property to be
// deleted when data is removed
Object.defineProperty( owner, this.expando, {
set: function( owner, data, value ) {
cache = this.cache( owner );
// Handle: [ owner, key, value ] args
// Always use camelCase key (gh-2257)
if ( typeof data === "string" ) {
cache[ camelCase( data ) ] = value;
// Handle: [ owner, { properties } ] args
// Copy the properties one-by-one to the cache object
cache[ camelCase( prop ) ] = data[ prop ];
get: function( owner, key ) {
return key === undefined ?
// Always use camelCase key (gh-2257)
owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ];
access: function( owner, key, value ) {
// In cases where either:
// 1. No key was specified
// 2. A string key was specified, but no value provided
// Take the "read" path and allow the get method to determine
// which value to return, respectively either:
// 1. The entire cache object
// 2. The data stored at the key
if ( key === undefined ||
( ( key && typeof key === "string" ) && value === undefined ) ) {
return this.get( owner, key );
// When the key is not a string, or both a key and value
// are specified, set or extend (existing objects) with either:
// 1. An object of properties
this.set( owner, key, value );
// Since the "set" path can have two possible entry points
// return the expected data based on which path was taken[*]
return value !== undefined ? value : key;
remove: function( owner, key ) {
cache = owner[ this.expando ];
if ( cache === undefined ) {
if ( key !== undefined ) {
// Support array or space separated string of keys
if ( Array.isArray( key ) ) {
// If key is an array of keys...
// We always set camelCase keys, so remove that.
key = key.map( camelCase );
// If a key with the spaces exists, use it.
// Otherwise, create an array by matching non-whitespace
( key.match( rnothtmlwhite ) || [] );
delete cache[ key[ i ] ];
// Remove the expando if there's no more data
if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
// Support: Chrome <=35 - 45
// Webkit & Blink performance suffers when deleting properties
// from DOM nodes, so set to undefined instead
// https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)
owner[ this.expando ] = undefined;
delete owner[ this.expando ];
hasData: function( owner ) {
var cache = owner[ this.expando ];
return cache !== undefined && !jQuery.isEmptyObject( cache );
var dataPriv = new Data();
var dataUser = new Data();
// Implementation Summary
// 1. Enforce API surface and semantic compatibility with 1.9.x branch
// 2. Improve the module's maintainability by reducing the storage
// paths to a single mechanism.
// 3. Use the same single mechanism to support "private" and "user" data.
// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
// 5. Avoid exposing implementation details on user objects (eg. expando properties)
// 6. Provide a clear path for implementation upgrade to WeakMap in 2014
var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
function getData( data ) {
if ( data === "false" ) {
// Only convert to a number if it doesn't change the string
if ( data === +data + "" ) {
if ( rbrace.test( data ) ) {
return JSON.parse( data );
function dataAttr( elem, key, data ) {
// If nothing was found internally, try to fetch any
// data from the HTML5 data-* attribute
if ( data === undefined && elem.nodeType === 1 ) {
name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
data = elem.getAttribute( name );
if ( typeof data === "string" ) {
// Make sure we set the data so it isn't changed later
dataUser.set( elem, key, data );
hasData: function( elem ) {
return dataUser.hasData( elem ) || dataPriv.hasData( elem );
data: function( elem, name, data ) {
return dataUser.access( elem, name, data );
removeData: function( elem, name ) {
dataUser.remove( elem, name );
// TODO: Now that all calls to _data and _removeData have been replaced
// with direct calls to dataPriv methods, these can be deprecated.
_data: function( elem, name, data ) {
return dataPriv.access( elem, name, data );
_removeData: function( elem, name ) {
dataPriv.remove( elem, name );
data: function( key, value ) {
attrs = elem && elem.attributes;
if ( key === undefined ) {
data = dataUser.get( elem );
if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
// The attrs elements can be null (#14894)
if ( name.indexOf( "data-" ) === 0 ) {
name = camelCase( name.slice( 5 ) );
dataAttr( elem, name, data[ name ] );
dataPriv.set( elem, "hasDataAttrs", true );