(function( jQuery ) {
-var rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
- rselectTextarea = /^(?:select|textarea)/i,
- rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
+var r20 = /%20/g,
rbracket = /\[\]$/,
+ rhash = /#.*$/,
+ rheaders = /^(.*?):\s*(.*?)\r?$/mg, // IE leaves an \r character at EOL
+ rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
+ rnoContent = /^(?:GET|HEAD)$/,
rquery = /\?/,
- r20 = /%20/g,
+ rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
+ rselectTextarea = /^(?:select|textarea)/i,
+ rts = /([?&])_=[^&]*/,
+ rurl = /^(\w+:)?\/\/([^\/?#]+)/,
+ // Slice function
+ sliceFunc = Array.prototype.slice,
+
// Keep a copy of the old load method
_load = jQuery.fn.load;
};
});
- jQuery.extend({
-
- get: function( url, data, callback, type ) {
+ jQuery.each( [ "get", "post" ], function( i, method ) {
+ jQuery[ method ] = function( url, data, callback, type ) {
// shift arguments if data argument was omited
if ( jQuery.isFunction( data ) ) {
type = type || callback;
}
return jQuery.ajax({
- type: "GET",
+ type: method,
url: url,
data: data,
success: callback,
dataType: type
});
- },
+ };
+ });
+
+ jQuery.extend({
getScript: function( url, callback ) {
return jQuery.get(url, null, callback, "script");
return jQuery.get(url, data, callback, "json");
},
- post: function( url, data, callback, type ) {
- // shift arguments if data argument was omited
- if ( jQuery.isFunction( data ) ) {
- type = type || callback;
- callback = data;
- data = {};
- }
-
- return jQuery.ajax({
- type: "POST",
- url: url,
- data: data,
- success: callback,
- dataType: type
- });
- },
-
ajaxSetup: function( settings ) {
jQuery.extend( jQuery.ajaxSettings, settings );
},
xhr: function() {
return new window.XMLHttpRequest();
},
- xhrResponseFields: {
- xml: "XML",
- text: "Text",
- json: "JSON"
- },
-
+
accepts: {
xml: "application/xml, text/xml",
html: "text/html",
json: "application/json, text/javascript",
"*": "*/*"
},
-
+
autoDataType: {
xml: /xml/,
html: /html/,
json: /json/
},
-
+
// Prefilters
// 1) They are useful to introduce custom dataTypes (see transport/jsonp for an example)
// 2) These are called:
// * BEFORE asking for a transport
// * AFTER param serialization (s.data is a string if s.processData is true)
- // 3) They MUST be order agnostic
- prefilters: [],
-
+ // 3) key is the dataType
+ // 4) the catchall symbol "*" can be used
+ // 5) execution will start with transport dataType and THEN continue down to "*" if needed
+ prefilters: {},
+
// Transports bindings
// 1) key is the dataType
// 2) the catchall symbol "*" can be used
// 3) selection will start with transport dataType and THEN go to "*" if needed
- transports: {
- },
+ transports: {},
+
+ // List of data converters
+ // 1) key format is "source_type destination_type" (a single space in-between)
+ // 2) the catchall symbol "*" can be used for source_type
+ dataConverters: {
+
+ // Convert anything to text
+ "* text": window.String,
+
+ // Text to html (true = no transformation)
+ "text html": true,
+
+ // Evaluate text as a json expression
+ "text json": jQuery.parseJSON,
+
+ // Parse text as xml
+ "text xml": jQuery.parseXML
+ }
+ },
+
+ // Main method
+ // (s is used internally)
+ ajax: function( url , options , s ) {
- // Checkers
- // 1) key is dataType
- // 2) they are called to control successful response
- // 3) error throws is used as error data
- dataCheckers: {
-
- // Check if data is a string
- "text": function(data) {
- if ( typeof data != "string" ) {
- jQuery.error("typeerror");
+ // Handle varargs
+ if ( arguments.length === 1 ) {
+ options = url;
+ url = options ? options.url : undefined;
+ }
+
+ // Force options to be an object
+ options = options || {};
+
+ // Get the url if provided separately
+ options.url = url || options.url;
+
+ // Create the final options object
+ s = jQuery.extend( true , {} , jQuery.ajaxSettings , options );
+
+ // We force the original context
+ // (plain objects used as context get extended)
+ s.context = options.context;
+
+ var // jQuery lists
+ jQuery_lastModified = jQuery.lastModified,
+ jQuery_etag = jQuery.etag,
+ // Callbacks contexts
+ callbackContext = s.context || s,
+ globalEventContext = s.context ? jQuery( s.context ) : jQuery.event,
+ // Deferreds
+ deferred = jQuery.Deferred(),
+ completeDeferred = jQuery._Deferred(),
+ // Headers (they are sent all at once)
+ requestHeaders = {},
+ // Response headers
+ responseHeadersString,
+ responseHeaders,
+ // transport
+ transport,
+ // timeout handle
+ timeoutTimer,
+ // The jXHR state
+ state = 0,
+ // Loop variable
+ i,
+ // Fake xhr
+ jXHR = {
+
+ readyState: 0,
+
+ // Caches the header
+ setRequestHeader: function(name,value) {
+ if ( state === 0 ) {
+ requestHeaders[ name.toLowerCase() ] = value;
+ }
+ return this;
+ },
+
+ // Raw string
+ getAllResponseHeaders: function() {
+ return state === 2 ? responseHeadersString : null;
+ },
+
+ // Builds headers hashtable if needed
+ // (match is used internally)
+ getResponseHeader: function( key , match ) {
+
+ if ( state !== 2 ) {
+ return null;
+ }
+
+ if ( responseHeaders === undefined ) {
+
+ responseHeaders = {};
+
+ if ( typeof responseHeadersString === "string" ) {
+
+ while( ( match = rheaders.exec( responseHeadersString ) ) ) {
+ responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
+ }
+ }
+ }
+ return responseHeaders[ key.toLowerCase() ];
+ },
+
+ // Cancel the request
+ abort: function( statusText ) {
+ if ( transport && state !== 2 ) {
+ transport.abort( statusText || "abort" );
+ done( 0 , statusText );
+ }
+ return this;
}
- },
-
- // Check if xml has been properly parsed
- "xml": function(data) {
- var documentElement = data ? data.documentElement : data;
- if ( ! documentElement || ! documentElement.nodeName ) {
- jQuery.error("typeerror");
+ };
+
+ // Callback for when everything is done
+ // It is defined here because jslint complains if it is declared
+ // at the end of the function (which would be more logical and readable)
+ function done( status , statusText , response , headers) {
+
+ // Called once
+ if ( state === 2 ) {
+ return;
+ }
+
+ // State is "done" now
+ state = 2;
+
+ // Set readyState
+ jXHR.readyState = status ? 4 : 0;
+
+ // Cache response headers
+ responseHeadersString = headers || "";
+
+ // Clear timeout if it exists
+ if ( timeoutTimer ) {
+ clearTimeout(timeoutTimer);
+ }
+
+ var // Reference url
+ url = s.url,
+ // and ifModified status
+ ifModified = s.ifModified,
+
+ // Is it a success?
+ isSuccess = 0,
+ // Stored success
+ success,
+ // Stored error
+ error = statusText;
+
+ // If not timeout, force a jQuery-compliant status text
+ if ( statusText != "timeout" ) {
+ statusText = ( status >= 200 && status < 300 ) ?
+ "success" :
+ ( status === 304 ? "notmodified" : "error" );
+ }
+
+ // If successful, handle type chaining
+ if ( statusText === "success" || statusText === "notmodified" ) {
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+
+ var lastModified = jXHR.getResponseHeader("Last-Modified"),
+ etag = jXHR.getResponseHeader("Etag");
+
+ if (lastModified) {
+ jQuery_lastModified[ s.url ] = lastModified;
+ }
+ if (etag) {
+ jQuery_etag[ s.url ] = etag;
+ }
}
- if ( documentElement.nodeName == "parsererror" ) {
- jQuery.error("parsererror");
+
+ if ( s.ifModified && statusText === "notmodified" ) {
+
+ success = null;
+ isSuccess = 1;
+
+ } else {
+ // Chain data conversions and determine the final value
+ // (if an exception is thrown in the process, it'll be notified as an error)
+ try {
+
+ var i,
+ current,
+ prev,
+ checker,
+ conv1,
+ conv2,
+ oneConv,
+ convertion,
+ dataTypes = s.dataTypes,
+ dataConverters = s.dataConverters,
+ responses = {
+ "xml": "XML",
+ "text": "Text"
+ };
+
+ for( i = 0 ; i < dataTypes.length ; i++ ) {
+
+ current = dataTypes[ i ];
+
+ if ( responses[ current ] ) {
+ jXHR[ "response" + responses[ current ] ] = response;
+ responses[ current ] = 0;
+ }
+
+ if ( i ) {
+
+ prev = dataTypes[ i - 1 ];
+
+ if ( prev !== "*" && current !== "*" && prev !== current ) {
+
+ oneConv = conv1 =
+ dataConverters[ ( conversion = prev + " " + current ) ] ||
+ dataConverters[ "* " + current ];
+
+ if ( oneConv !== true ) {
+
+ if ( ! oneConv && prev !== "text" && current !== "text" ) {
+ conv1 = dataConverters[ prev + " text" ] || dataConverters[ "* text" ];
+ conv2 = dataConverters[ "text " + current ];
+ }
+
+ if ( oneConv || conv1 && conv2 ) {
+ response = oneConv ? conv1( response ) : conv2( conv1( response ) );
+ } else {
+ throw "no " + conversion;
+ }
+ }
+ }
+ } else if ( s.dataFilter ) {
+
+ response = s.dataFilter( response );
+ dataTypes = s.dataTypes;
+ }
+ }
+
+ // We have a real success
+ success = response;
+ isSuccess = 1;
+
+ } catch(e) {
+
+ statusText = "parsererror";
+ error = "" + e;
+
+ }
}
+
+ } else { // if not success, mark it as an error
+
+ error = error || statusText;
}
- },
-
- // List of data converters
- // 1) key format is "source_type => destination_type" (spaces required)
- // 2) the catchall symbol "*" can be used for source_type
- dataConverters: {
-
- // Convert anything to text
- "* => text": function(data) {
- return "" + data;
- },
+
+ // Set data for the fake xhr object
+ jXHR.status = status;
+ jXHR.statusText = statusText;
- // Text to html (no transformation)
- "text => html": function(data) {
- return data;
- },
+ // Success/Error
+ if ( isSuccess ) {
+ deferred.fire( callbackContext , [ success , statusText , jXHR ] );
+ } else {
+ deferred.fireReject( callbackContext , [ jXHR , statusText , error ] );
+ }
- // Evaluate text as a json expression
- "text => json": jQuery.parseJSON,
+ if ( s.global ) {
+ globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ) ,
+ [ jXHR , s , isSuccess ? success : error ] );
+ }
- // Parse text as xml
- "text => xml": function(data) {
- var xml, parser;
- if ( window.DOMParser ) { // Standard
- parser = new DOMParser();
- xml = parser.parseFromString(data,"text/xml");
- } else { // IE
- xml = new ActiveXObject("Microsoft.XMLDOM");
- xml.async="false";
- xml.loadXML(data);
+ // Complete
+ completeDeferred.fire( callbackContext, [ jXHR , statusText ] );
+
+ if ( s.global ) {
+ globalEventContext.trigger( "ajaxComplete" , [ jXHR , s] );
+ // Handle the global AJAX counter
+ if ( ! --jQuery.active ) {
+ jQuery.event.trigger( "ajaxStop" );
}
- return xml;
}
}
- },
+
+ // Attach deferreds
+ jXHR.success = jXHR.then = deferred.then;
+ jXHR.error = jXHR.fail = deferred.fail;
+ jXHR.complete = completeDeferred.then;
- // Main method
- ajax: function( url , s ) {
+ // Remove hash character (#7531: and string promotion)
+ s.url = ( "" + s.url ).replace( rhash , "" );
- if ( arguments.length === 1 ) {
- s = url;
- url = s ? s.url : undefined;
+ // Uppercase the type
+ s.type = s.type.toUpperCase();
+
+ // Determine if request has content
+ s.hasContent = ! rnoContent.test( s.type );
+
+ // Extract dataTypes list
+ s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( /\s+/ );
+
+ // Determine if a cross-domain request is in order
+ var parts = rurl.exec( s.url.toLowerCase() ),
+ loc = location;
+ s.crossDomain = !!( parts && ( parts[ 1 ] && parts[ 1 ] != loc.protocol || parts[ 2 ] != loc.host ) );
+
+ // Convert data if not already a string
+ if ( s.data && s.processData && typeof s.data != "string" ) {
+ s.data = jQuery.param( s.data , s.traditional );
+ }
+
+ // Watch for a new set of requests
+ if ( s.global && jQuery.active++ === 0 ) {
+ jQuery.event.trigger( "ajaxStart" );
}
- return jQuery.xhr().open( s ? s.type : undefined , url ).send( undefined , s );
+ // Get transport
+ transport = jQuery.ajax.prefilter( s ).transport( s );
+ // If no transport, we auto-abort
+ if ( ! transport ) {
+
+ done( 0 , "transport not found" );
+ jXHR = false;
+
+ } else {
+
+ // More options handling for requests with no content
+ if ( ! s.hasContent ) {
+
+ // If data is available, append data to url
+ if ( s.data ) {
+ s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
+ }
+
+ // Add anti-cache in url if needed
+ if ( s.cache === false ) {
+
+ var ts = jQuery.now(),
+ // try replacing _= if it is there
+ ret = s.url.replace( rts , "$1_=" + ts );
+
+ // if nothing was replaced, add timestamp to the end
+ s.url = ret + ( (ret == s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "");
+ }
+ }
+
+ // Set the correct header, if data is being sent
+ if ( ( s.data && s.hasContent ) || options.contentType ) {
+ requestHeaders[ "content-type" ] = s.contentType;
+ }
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ if ( jQuery_lastModified[ s.url ] ) {
+ requestHeaders[ "if-modified-since" ] = jQuery_lastModified[ s.url ];
+ }
+ if ( jQuery_etag[ s.url ] ) {
+ requestHeaders[ "if-none-match" ] = jQuery_etag[ s.url ];
+ }
+ }
+
+ // Set the Accepts header for the server, depending on the dataType
+ requestHeaders.accept = s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
+ s.accepts[ s.dataTypes[ 0 ] ] + ( s.dataTypes[ 0 ] !== "*" ? ", */*; q=0.01" : "" ) :
+ s.accepts[ "*" ];
+
+ // Check for headers option
+ for ( i in s.headers ) {
+ requestHeaders[ i.toLowerCase() ] = s.headers[ i ];
+ }
+
+ // Allow custom headers/mimetypes and early abort
+ if ( s.beforeSend && ( s.beforeSend.call( callbackContext , jXHR , s ) === false || state === 2 ) ) {
+
+ // Abort if not done already
+ done( 0 , "abort" );
+ jXHR = false;
+
+ } else {
+
+ // Set state as sending
+ state = 1;
+ jXHR.readyState = 1;
+
+ // Install callbacks on deferreds
+ for ( i in { success:1, error:1, complete:1 } ) {
+ jXHR[ i ]( s[ i ] );
+ }
+
+ // Send global event
+ if ( s.global ) {
+ globalEventContext.trigger( "ajaxSend" , [ jXHR , s ] );
+ }
+
+ // Timeout
+ if ( s.async && s.timeout > 0 ) {
+ timeoutTimer = setTimeout(function(){
+ jXHR.abort( "timeout" );
+ }, s.timeout);
+ }
+
+ // Try to send
+ try {
+ transport.send(requestHeaders, done);
+ } catch (e) {
+ // Propagate exception as error if not done
+ if ( status === 1 ) {
+
+ done(0, "error", "" + e);
+ jXHR = false;
+
+ // Simply rethrow otherwise
+ } else {
+ jQuery.error(e);
+ }
+ }
+ }
+ }
+
+ return jXHR;
},
// Serialize an array of form elements or a set of
});
+//Execute or select from functions in a given structure of options
+function ajax_selectOrExecute( structure , s ) {
+
+ var dataTypes = s.dataTypes,
+ transportDataType,
+ list,
+ selected,
+ i,
+ length,
+ checked = {},
+ flag,
+ noSelect = structure !== "transports";
+
+ function initSearch( dataType ) {
+
+ flag = transportDataType !== dataType && ! checked[ dataType ];
+
+ if ( flag ) {
+
+ checked[ dataType ] = 1;
+ transportDataType = dataType;
+ list = s[ structure ][ dataType ];
+ i = -1;
+ length = list ? list.length : 0 ;
+ }
+
+ return flag;
+ }
+
+ initSearch( dataTypes[ 0 ] );
+
+ for ( i = 0 ; ( noSelect || ! selected ) && i <= length ; i++ ) {
+
+ if ( i === length ) {
+
+ initSearch( "*" );
+
+ } else {
+
+ selected = list[ i ]( s , determineDataType );
+
+ // If we got redirected to another dataType
+ // Search there (if not in progress or already tried)
+ if ( typeof( selected ) === "string" &&
+ initSearch( selected ) ) {
+
+ dataTypes.unshift( selected );
+ selected = 0;
+ }
+ }
+ }
+
+ return noSelect ? jQuery.ajax : selected;
+}
+
+// Add an element to one of the structures in ajaxSettings
+function ajax_addElement( structure , args ) {
+
+ var i,
+ start = 0,
+ length = args.length,
+ dataTypes = [ "*" ],
+ dLength = 1,
+ dataType,
+ functors = [],
+ first,
+ append,
+ list;
+
+ if ( length ) {
+
+ first = jQuery.type( args[ 0 ] );
+
+ if ( first === "object" ) {
+ return ajax_selectOrExecute( structure , args[ 0 ] );
+ }
+
+ structure = jQuery.ajaxSettings[ structure ];
+
+ if ( first !== "function" ) {
+
+ dataTypes = args[ 0 ].toLowerCase().split(/\s+/);
+ dLength = dataTypes.length;
+ start = 1;
+
+ }
+
+ if ( dLength && start < length ) {
+
+ functors = sliceFunc.call( args , start );
+
+ for( i = 0 ; i < dLength ; i++ ) {
+
+ dataType = dataTypes[ i ];
+
+ first = /^\+/.test( dataType );
+
+ if (first) {
+ dataType = dataType.substr(1);
+ }
+
+ if ( dataType !== "" ) {
+
+ append = Array.prototype[ first ? "unshift" : "push" ];
+ list = structure[ dataType ] = structure[ dataType ] || [];
+ append.apply( list , functors );
+ }
+ }
+ }
+ }
+
+ return jQuery.ajax;
+}
+
+// Install prefilter & transport methods
+jQuery.each( [ "prefilter" , "transport" ] , function( _ , name ) {
+ _ = name + "s";
+ jQuery.ajax[ name ] = function() {
+ return ajax_addElement( _ , arguments );
+ };
+} );
+
+// Utility function that handles dataType when response is received
+// (for those transports that can give text or xml responses)
+function determineDataType( s , ct , text , xml ) {
+
+ var autoDataType = s.autoDataType,
+ type,
+ regexp,
+ dataTypes = s.dataTypes,
+ transportDataType = dataTypes[0],
+ response;
+
+ // Auto (xml, json, script or text determined given headers)
+ if ( transportDataType === "*" ) {
+
+ for ( type in autoDataType ) {
+ if ( ( regexp = autoDataType[ type ] ) && regexp.test( ct ) ) {
+ transportDataType = dataTypes[0] = type;
+ break;
+ }
+ }
+ }
+
+ // xml and parsed as such
+ if ( transportDataType === "xml" &&
+ xml &&
+ xml.documentElement /* #4958 */ ) {
+
+ response = xml;
+
+ // Text response was provided
+ } else {
+
+ response = text;
+
+ // If it's not really text, defer to dataConverters
+ if ( transportDataType !== "text" ) {
+ dataTypes.unshift( "text" );
+ }
+
+ }
+
+ return response;
+}
+
/*
* Create the request object; Microsoft failed to properly
* implement the XMLHttpRequest in IE7 (can't request local files),
// Has the ready events already been bound?
readyBound = false,
- // The functions to execute on DOM ready
- readyList = [],
+ // The deferred used on DOM ready
+ readyList,
// The ready event handler
DOMContentLoaded,
indexOf = Array.prototype.indexOf,
// [[Class]] -> type pairs
- class2type = {};
+ class2type = {},
+
+ // Marker for deferred
+ deferredMarker = [];
jQuery.fn = jQuery.prototype = {
init: function( selector, context ) {
return jQuery.each( this, callback, args );
},
- ready: function( fn ) {
+ ready: function() {
// Attach the listeners
jQuery.bindReady();
-
- // If the DOM is already ready
- if ( jQuery.isReady ) {
- // Execute the function immediately
- fn.call( document, jQuery );
-
- // Otherwise, remember the function for later
- } else if ( readyList ) {
- // Add the function to the wait list
- readyList.push( fn );
- }
-
- return this;
+
+ // Change ready & apply
+ return ( jQuery.fn.ready = readyList.then ).apply( this , arguments );
},
eq: function( i ) {
}
// If there are functions bound, to execute
- if ( readyList ) {
- // Execute all of them
- var fn,
- i = 0,
- ready = readyList;
-
- // Reset the list of functions
- readyList = null;
-
- while ( (fn = ready[ i++ ]) ) {
- fn.call( document, jQuery );
- }
-
- // Trigger any bound ready events
- if ( jQuery.fn.trigger ) {
- jQuery( document ).trigger( "ready" ).unbind( "ready" );
- }
+ readyList.fire( document , [ jQuery ] );
+
+ // Trigger any bound ready events
+ if ( jQuery.fn.trigger ) {
+ jQuery( document ).trigger( "ready" ).unbind( "ready" );
}
}
},
jQuery.error( "Invalid JSON: " + data );
}
},
+
+ // Cross-browser xml parsing
+ // (xml & tmp used internally)
+ parseXML: function( data , xml , tmp ) {
+
+ if ( window.DOMParser ) { // Standard
+ tmp = new DOMParser();
+ xml = tmp.parseFromString( data , "text/xml" );
+ } else { // IE
+ xml = new ActiveXObject( "Microsoft.XMLDOM" );
+ xml.async = "false";
+ xml.loadXML( data );
+ }
+
+ tmp = xml.documentElement;
+
+ if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) {
+ jQuery.error( "Invalid XML: " + data );
+ }
+
+ return xml;
+ },
noop: function() {},
now: function() {
return (new Date()).getTime();
},
+
+ // Create a simple deferred (one callbacks list)
+ _Deferred: function() {
+
+ var // callbacks list
+ callbacks = [],
+ // stored [ context , args ]
+ fired,
+ // to avoid firing when already doing so
+ firing,
+ // flag to know if the deferred has been cancelled
+ cancelled,
+ // the deferred itself
+ deferred = {
+
+ // then( f1, f2, ...)
+ then: function () {
+
+ if ( ! cancelled ) {
+
+ var args = arguments,
+ i,
+ length,
+ elem,
+ type,
+ _fired;
+
+ if ( fired ) {
+ _fired = fired;
+ fired = 0;
+ }
+
+ for ( i = 0, length = args.length ; i < length ; i++ ) {
+ elem = args[ i ];
+ type = jQuery.type( elem );
+ if ( type === "array" ) {
+ deferred.then.apply( deferred , elem );
+ } else if ( type === "function" ) {
+ callbacks.push( elem );
+ }
+ }
+
+ if ( _fired ) {
+ deferred.fire( _fired[ 0 ] , _fired[ 1 ] );
+ }
+ }
+
+ return this;
+ },
+
+ // resolve with given context and args
+ fire: function( context , args ) {
+ if ( ! cancelled && ! fired && ! firing ) {
+
+ firing = 1;
+
+ try {
+ while( callbacks[ 0 ] ) {
+ callbacks.shift().apply( context , args );
+ }
+ }
+ finally {
+ fired = [ context , args ];
+ firing = 0;
+ }
+ }
+ return this;
+ },
+
+ // resolve with this as context and given arguments
+ resolve: function() {
+ deferred.fire( this , arguments );
+ return this;
+ },
+
+ // Has this deferred been resolved?
+ isResolved: function() {
+ return !!( firing || fired );
+ },
+
+ // Cancel
+ cancel: function() {
+ cancelled = 1;
+ callbacks = [];
+ return this;
+ },
+
+ // Has this deferred been cancelled?
+ isCancelled: function() {
+ return !!cancelled;
+ }
+ };
+
+ // Add the deferred marker
+ deferred.then._ = deferredMarker;
+
+ return deferred;
+ },
+
+ // Full fledged deferred (two callbacks list)
+ // Typical success/error system
+ Deferred: function( func ) {
+
+ var errorDeferred = jQuery._Deferred(),
+ deferred = jQuery._Deferred(),
+ successCancel = deferred.cancel;
+
+ // Add errorDeferred methods and redefine cancel
+ jQuery.extend( deferred , {
+
+ fail: errorDeferred.then,
+ fireReject: errorDeferred.fire,
+ reject: errorDeferred.resolve,
+ isRejected: errorDeferred.isResolved
+
+ } );
+
+ // Remove cancel related
+ delete deferred.cancel;
+ delete deferred.isCancelled;
+
+ // Make sure only one callback list will be used
+ deferred.then( errorDeferred.cancel ).fail( successCancel );
+
+ // Call given func if any
+ if ( func ) {
+ func.call( deferred , deferred );
+ }
+
+ return deferred;
+ },
+
+ // Check if an object is a deferred
+ isDeferred: function( object ) {
+ return !!( object && object.then && object.then._ === deferredMarker );
+ },
+
+ // Deferred helper
+ when: function( object ) {
+ object = jQuery.isDeferred( object ) ?
+ object :
+ jQuery.Deferred().resolve( object );
+ return object;
+ },
// Use of jQuery.browser is frowned upon.
// More details: http://docs.jquery.com/Utilities/jQuery.browser
browser: {}
});
+// Create readyList deferred
+// also force $.fn.ready to be recognized as a defer
+readyList = jQuery._Deferred();
+jQuery.fn.ready._ = deferredMarker;
+
// Populate the class2type map
jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
class2type[ "[object " + name + "]" ] = name.toLowerCase();
jQuery.ready();
}
+ // Expose jQuery as an Asynchronous Module
+ if ( typeof define !== "undefined" ) {
+ define( "jquery", [], function () { return jQuery; } );
+ }
+
// Expose jQuery to the global object
return (window.jQuery = window.$ = jQuery);
});
test("jQuery()", function() {
- expect(23);
+ expect(24);
+
+ strictEqual( commonJSDefined, jQuery, "CommonJS registered (Bug #7102)" );
// Basic constructor's behavior
test = jQuery("#main").eq(0);
equals( test.selector, "#main.slice(0,1)", "#main eq Selector" );
equals( test.context, document, "#main eq Context" );
-
+
var d = "<div />";
equals(
jQuery(d).appendTo(jQuery(d)).selector,
// The use case that we want to match
ok(jQuery.isPlainObject({}), "{}");
-
+
// Not objects shouldn't be matched
ok(!jQuery.isPlainObject(""), "string");
ok(!jQuery.isPlainObject(0) && !jQuery.isPlainObject(1), "number");
ok(!jQuery.isPlainObject(true) && !jQuery.isPlainObject(false), "boolean");
ok(!jQuery.isPlainObject(null), "null");
ok(!jQuery.isPlainObject(undefined), "undefined");
-
+
// Arrays shouldn't be matched
ok(!jQuery.isPlainObject([]), "array");
-
+
// Instantiated objects shouldn't be matched
ok(!jQuery.isPlainObject(new Date), "new Date");
-
+
var fn = function(){};
-
+
// Functions shouldn't be matched
ok(!jQuery.isPlainObject(fn), "fn");
-
+
// Again, instantiated objects shouldn't be matched
ok(!jQuery.isPlainObject(new fn), "new fn (no methods)");
-
+
// Makes the function a little more realistic
// (and harder to detect, incidentally)
fn.prototype = {someMethod: function(){}};
-
+
// Again, instantiated objects shouldn't be matched
ok(!jQuery.isPlainObject(new fn), "new fn");
// DOM Element
ok(!jQuery.isPlainObject(document.createElement("div")), "DOM Element");
-
+
// Window
ok(!jQuery.isPlainObject(window), "window");
document.body.removeChild( iframe );
start();
};
-
+
var doc = iframe.contentDocument || iframe.contentWindow.document;
doc.open();
doc.write("<body onload='window.parent.iframeDone(Object);'>");
// Fixed at [5998], #3641
same( parse([-2,-1], [0,1,2]), [-2,-1,0,1,2], "Second array including a zero (falsy)");
-
+
// After fixing #5527
same( parse([], [null, undefined]), [null, undefined], "Second array including null and undefined values");
same( parse({length:0}, [1,2]), {length:2, 0:1, 1:2}, "First array like");
equals( deep1.foo2, document, "Make sure that a deep clone was not attempted on the document" );
ok( jQuery.extend(true, {}, nestedarray).arr !== arr, "Deep extend of object must clone child array" );
-
+
// #5991
ok( jQuery.isArray( jQuery.extend(true, { arr: {} }, nestedarray).arr ), "Cloned array heve to be an Array" );
ok( jQuery.isPlainObject( jQuery.extend(true, { arr: arr }, { arr: {} }).arr ), "Cloned object heve to be an plain object" );
empty = {};
jQuery.extend(true, empty, optionsWithCustomObject);
ok( empty.foo && empty.foo.date === customObject, "Custom objects copy correctly (no methods)" );
-
+
// Makes the class a little more realistic
myKlass.prototype = { someMethod: function(){} };
empty = {};
jQuery.extend(true, empty, optionsWithCustomObject);
ok( empty.foo && empty.foo.date === customObject, "Custom objects copy correctly" );
-
+
var ret = jQuery.extend(true, { foo: 4 }, { foo: new Number(5) } );
ok( ret.foo == 5, "Wrapped numbers copy correctly" );
test("jQuery.isEmptyObject", function(){
expect(2);
-
+
equals(true, jQuery.isEmptyObject({}), "isEmptyObject on empty object literal" );
equals(false, jQuery.isEmptyObject({a:1}), "isEmptyObject on non-empty object literal" );
-
+
// What about this ?
// equals(true, jQuery.isEmptyObject(null), "isEmptyObject on null" );
});
test("jQuery.parseJSON", function(){
expect(8);
-
+
equals( jQuery.parseJSON(), null, "Nothing in, null out." );
equals( jQuery.parseJSON( null ), null, "Nothing in, null out." );
equals( jQuery.parseJSON( "" ), null, "Nothing in, null out." );
-
+
same( jQuery.parseJSON("{}"), {}, "Plain object parsing." );
same( jQuery.parseJSON('{"test":1}'), {"test":1}, "Plain object parsing." );
same( jQuery.parseJSON('\n{"test":1}'), {"test":1}, "Make sure leading whitespaces are handled." );
-
+
try {
jQuery.parseJSON("{a:1}");
ok( false, "Test malformed JSON string." );
} catch( e ) {
ok( true, "Test malformed JSON string." );
}
-
+
try {
jQuery.parseJSON("{'a':1}");
ok( false, "Test malformed JSON string." );
ok( true, "Test malformed JSON string." );
}
});
+
+test("jQuery._Deferred()", function() {
+
+ expect( 10 );
+
+ var deferred,
+ object,
+ test;
+
+ deferred = jQuery._Deferred();
+
+ test = false;
+
+ deferred.then( function( value ) {
+ equals( value , "value" , "Test pre-resolve callback" );
+ test = true;
+ } );
+
+ deferred.resolve( "value" );
+
+ ok( test , "Test pre-resolve callbacks called right away" );
+
+ test = false;
+
+ deferred.then( function( value ) {
+ equals( value , "value" , "Test post-resolve callback" );
+ test = true;
+ } );
+
+ ok( test , "Test post-resolve callbacks called right away" );
+
+ deferred.cancel();
+
+ test = true;
+
+ deferred.then( function() {
+ ok( false , "Cancel was ignored" );
+ test = false;
+ } );
+
+ ok( test , "Test cancel" );
+
+ deferred = jQuery._Deferred().resolve();
+
+ try {
+ deferred.then( function() {
+ throw "Error";
+ } , function() {
+ ok( true , "Test deferred do not cancel on exception" );
+ } );
+ } catch( e ) {
+ strictEqual( e , "Error" , "Test deferred propagates exceptions");
+ deferred.then();
+ }
+
+ test = "";
+ deferred = jQuery._Deferred().then( function() {
+
+ test += "A";
+
+ }, function() {
+
+ test += "B";
+
+ } ).resolve();
+
+ strictEqual( test , "AB" , "Test multiple then parameters" );
+
+ test = "";
+
+ deferred.then( function() {
+
+ deferred.then( function() {
+
+ test += "C";
+
+ } );
+
+ test += "A";
+
+ }, function() {
+
+ test += "B";
+ } );
+
+ strictEqual( test , "ABC" , "Test then callbacks order" );
+
+ deferred = jQuery._Deferred();
+
+ deferred.fire( jQuery , [ document ] ).then( function( doc ) {
+ ok( this === jQuery && arguments.length === 1 && doc === document , "Test fire context & args" );
+ });
+});
+
+test("jQuery.Deferred()", function() {
+
+ expect( 4 );
+
+ jQuery.Deferred( function( defer ) {
+ strictEqual( this , defer , "Defer passed as this & first argument" );
+ this.resolve( "done" );
+ }).then( function( value ) {
+ strictEqual( value , "done" , "Passed function executed" );
+ });
+
+ jQuery.Deferred().resolve().then( function() {
+ ok( true , "Success on resolve" );
+ }).fail( function() {
+ ok( false , "Error on resolve" );
+ });
+
+ jQuery.Deferred().reject().then( function() {
+ ok( false , "Success on reject" );
+ }).fail( function() {
+ ok( true , "Error on reject" );
+ });
+});
+
+test("jQuery.isDeferred()", function() {
+
+ expect( 10 );
+
+ var object1 = { then: function() { return this; } },
+ object2 = { then: function() { return this; } };
+
+ object2.then._ = [];
+
+ // The use case that we want to match
+ ok(jQuery.isDeferred(jQuery._Deferred()), "Simple deferred");
+ ok(jQuery.isDeferred(jQuery.Deferred()), "Failable deferred");
+
+ // Some other objects
+ ok(!jQuery.isDeferred(object1), "Object with then & no marker");
+ ok(!jQuery.isDeferred(object2), "Object with then & marker");
+
+ // Not objects shouldn't be matched
+ ok(!jQuery.isDeferred(""), "string");
+ ok(!jQuery.isDeferred(0) && !jQuery.isDeferred(1), "number");
+ ok(!jQuery.isDeferred(true) && !jQuery.isDeferred(false), "boolean");
+ ok(!jQuery.isDeferred(null), "null");
+ ok(!jQuery.isDeferred(undefined), "undefined");
+
+ object1 = {custom: jQuery._Deferred().then};
+
+ ok(!jQuery.isDeferred(object1) , "custom method name not found automagically");
+});
+
+test("jQuery.when()", function() {
+
+ expect( 2 );
+
+ var cache, i;
+
+ for( i = 1 ; i < 3 ; i++ ) {
+ jQuery.when( cache || jQuery.Deferred( function() {
+ this.resolve( i );
+ }) ).then( function( value ) {
+ strictEqual( value , 1 , "Function executed" + ( i > 1 ? " only once" : "" ) );
+ cache = value;
+ }).fail( function() {
+ ok( false , "Fail called" );
+ });
+ }
+});