1 var // Document location
3 // Document location segments
7 rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
8 // #7653, #8125, #8152: local protocol detection
9 rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,
10 rnoContent = /^(?:GET|HEAD|DELETE)$/,
13 rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
14 rts = /([?&])_=[^&]*/,
15 rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,
17 // Keep a copy of the old load method
18 _load = jQuery.fn.load,
21 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
22 * 2) These are called:
23 * - BEFORE asking for a transport
24 * - AFTER param serialization (s.data is a string if s.processData is true)
25 * 3) key is the dataType
26 * 4) the catchall symbol "*" can be used
27 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
31 /* Transports bindings
32 * 1) key is the dataType
33 * 2) the catchall symbol "*" can be used
34 * 3) selection will start with transport dataType and THEN go to "*" if needed
38 // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
39 allTypes = ["*/"] + ["*"];
41 // #8138, IE may throw an exception when accessing
42 // a field from window.location if document.domain has been set
44 ajaxLocation = location.href;
46 // Use the href attribute of an A element
47 // since IE will modify it given document.location
48 ajaxLocation = document.createElement( "a" );
49 ajaxLocation.href = "";
50 ajaxLocation = ajaxLocation.href;
53 // Segment location into parts
54 ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
56 // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
57 function addToPrefiltersOrTransports( structure ) {
59 // dataTypeExpression is optional and defaults to "*"
60 return function( dataTypeExpression, func ) {
62 if ( typeof dataTypeExpression !== "string" ) {
63 func = dataTypeExpression;
64 dataTypeExpression = "*";
67 var dataType, list, placeBefore,
68 dataTypes = dataTypeExpression.toLowerCase().split( core_rspace ),
70 length = dataTypes.length;
72 if ( jQuery.isFunction( func ) ) {
73 // For each dataType in the dataTypeExpression
74 for ( ; i < length; i++ ) {
75 dataType = dataTypes[ i ];
76 // We control if we're asked to add before
77 // any existing element
78 placeBefore = /^\+/.test( dataType );
80 dataType = dataType.substr( 1 ) || "*";
82 list = structure[ dataType ] = structure[ dataType ] || [];
83 // then we add to the structure accordingly
84 list[ placeBefore ? "unshift" : "push" ]( func );
90 // Base inspection function for prefilters and transports
91 function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
92 dataType /* internal */, inspected /* internal */ ) {
94 dataType = dataType || options.dataTypes[ 0 ];
95 inspected = inspected || {};
97 inspected[ dataType ] = true;
100 list = structure[ dataType ],
102 length = list ? list.length : 0,
103 executeOnly = ( structure === prefilters );
105 for ( ; i < length && ( executeOnly || !selection ); i++ ) {
106 selection = list[ i ]( options, originalOptions, jqXHR );
107 // If we got redirected to another dataType
108 // we try there if executing only and not done already
109 if ( typeof selection === "string" ) {
110 if ( !executeOnly || inspected[ selection ] ) {
111 selection = undefined;
113 options.dataTypes.unshift( selection );
114 selection = inspectPrefiltersOrTransports(
115 structure, options, originalOptions, jqXHR, selection, inspected );
119 // If we're only executing or nothing was selected
120 // we try the catchall dataType if not done already
121 if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
122 selection = inspectPrefiltersOrTransports(
123 structure, options, originalOptions, jqXHR, "*", inspected );
125 // unnecessary when only executing (prefilters)
126 // but it'll be ignored by the caller in that case
130 // A special extend for ajax options
131 // that takes "flat" options (not to be deep extended)
133 function ajaxExtend( target, src ) {
135 flatOptions = jQuery.ajaxSettings.flatOptions || {};
137 if ( src[ key ] !== undefined ) {
138 ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
142 jQuery.extend( true, target, deep );
146 jQuery.fn.load = function( url, params, callback ) {
147 if ( typeof url !== "string" && _load ) {
148 return _load.apply( this, arguments );
151 // Don't do a request if no elements are being requested
152 if ( !this.length ) {
156 var selector, type, response,
158 off = url.indexOf(" ");
161 selector = url.slice( off, url.length );
162 url = url.slice( 0, off );
165 // If it's a function
166 if ( jQuery.isFunction( params ) ) {
168 // We assume that it's the callback
172 // Otherwise, build a param string
173 } else if ( params && typeof params === "object" ) {
177 // Request the remote document
181 // if "type" variable is undefined, then "GET" method will be used
185 complete: function( jqXHR, status ) {
187 self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
190 }).done(function( responseText ) {
192 // Save response for use in complete callback
193 response = arguments;
195 // See if a selector was specified
196 self.html( selector ?
198 // Create a dummy div to hold the results
201 // inject the contents of the document in, removing the scripts
202 // to avoid any 'Permission Denied' errors in IE
203 .append( responseText.replace( rscript, "" ) )
205 // Locate the specified elements
208 // If not, just inject the full result
216 // Attach a bunch of functions for handling common AJAX events
217 jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
218 jQuery.fn[ o ] = function( f ){
219 return this.on( o, f );
223 jQuery.each( [ "get", "post" ], function( i, method ) {
224 jQuery[ method ] = function( url, data, callback, type ) {
225 // shift arguments if data argument was omitted
226 if ( jQuery.isFunction( data ) ) {
227 type = type || callback;
244 getScript: function( url, callback ) {
245 return jQuery.get( url, undefined, callback, "script" );
248 getJSON: function( url, data, callback ) {
249 return jQuery.get( url, data, callback, "json" );
252 // Creates a full fledged settings object into target
253 // with both ajaxSettings and settings fields.
254 // If target is omitted, writes into ajaxSettings.
255 ajaxSetup: function( target, settings ) {
257 // Building a settings object
258 ajaxExtend( target, jQuery.ajaxSettings );
260 // Extending ajaxSettings
262 target = jQuery.ajaxSettings;
264 ajaxExtend( target, settings );
270 isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
273 contentType: "application/x-www-form-urlencoded; charset=UTF-8",
289 xml: "application/xml, text/xml",
292 json: "application/json, text/javascript",
307 // List of data converters
308 // 1) key format is "source_type destination_type" (a single space in-between)
309 // 2) the catchall symbol "*" can be used for source_type
312 // Convert anything to text
313 "* text": window.String,
315 // Text to html (true = no transformation)
318 // Evaluate text as a json expression
319 "text json": jQuery.parseJSON,
322 "text xml": jQuery.parseXML
325 // For options that shouldn't be deep extended:
326 // you can add your own custom options here if
327 // and when you create one that shouldn't be
328 // deep extended (see ajaxExtend)
335 ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
336 ajaxTransport: addToPrefiltersOrTransports( transports ),
339 ajax: function( url, options ) {
341 // If url is an object, simulate pre-1.5 signature
342 if ( typeof url === "object" ) {
347 // Force options to be an object
348 options = options || {};
350 var // ifModified key
353 responseHeadersString,
359 // Cross-domain detection vars
361 // To know if global events are to be dispatched
365 // Create the final options object
366 s = jQuery.ajaxSetup( {}, options ),
368 callbackContext = s.context || s,
369 // Context for global events
370 // It's the callbackContext if one was provided in the options
371 // and if it's a DOM node or a jQuery collection
372 globalEventContext = callbackContext !== s &&
373 ( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
374 jQuery( callbackContext ) : jQuery.event,
376 deferred = jQuery.Deferred(),
377 completeDeferred = jQuery.Callbacks( "once memory" ),
378 // Status-dependent callbacks
379 statusCode = s.statusCode || {},
380 // Headers (they are sent all at once)
382 requestHeadersNames = {},
385 // Default abort message
386 strAbort = "canceled",
393 setRequestHeader: function( name, value ) {
395 var lname = name.toLowerCase();
396 name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
397 requestHeaders[ name ] = value;
403 getAllResponseHeaders: function() {
404 return state === 2 ? responseHeadersString : null;
407 // Builds headers hashtable if needed
408 getResponseHeader: function( key ) {
411 if ( !responseHeaders ) {
412 responseHeaders = {};
413 while( ( match = rheaders.exec( responseHeadersString ) ) ) {
414 responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
417 match = responseHeaders[ key.toLowerCase() ];
419 return match === undefined ? null : match;
422 // Overrides response content-type header
423 overrideMimeType: function( type ) {
430 // Cancel the request
431 abort: function( statusText ) {
432 statusText = statusText || strAbort;
434 transport.abort( statusText );
436 done( 0, statusText );
441 // Callback for when everything is done
442 // It is defined here because jslint complains if it is declared
443 // at the end of the function (which would be more logical and readable)
444 function done( status, nativeStatusText, responses, headers ) {
445 var isSuccess, success, error, response, modified,
446 statusText = nativeStatusText;
453 // State is "done" now
456 // Clear timeout if it exists
457 if ( timeoutTimer ) {
458 clearTimeout( timeoutTimer );
461 // Dereference transport for early garbage collection
462 // (no matter how long the jqXHR object will be used)
463 transport = undefined;
465 // Cache response headers
466 responseHeadersString = headers || "";
469 jqXHR.readyState = status > 0 ? 4 : 0;
473 response = ajaxHandleResponses( s, jqXHR, responses );
476 // If successful, handle type chaining
477 if ( status >= 200 && status < 300 || status === 304 ) {
479 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
480 if ( s.ifModified ) {
482 modified = jqXHR.getResponseHeader("Last-Modified");
484 jQuery.lastModified[ ifModifiedKey ] = modified;
486 modified = jqXHR.getResponseHeader("Etag");
488 jQuery.etag[ ifModifiedKey ] = modified;
493 if ( status === 304 ) {
495 statusText = "notmodified";
501 isSuccess = ajaxConvert( s, response );
502 statusText = isSuccess.state;
503 success = isSuccess.data;
504 error = isSuccess.error;
508 // We extract error from statusText
509 // then normalize statusText and status for non-aborts
511 if ( !statusText || status ) {
512 statusText = "error";
519 // Set data for the fake xhr object
520 jqXHR.status = status;
521 jqXHR.statusText = "" + ( nativeStatusText || statusText );
525 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
527 deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
530 // Status-dependent callbacks
531 jqXHR.statusCode( statusCode );
532 statusCode = undefined;
535 globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
536 [ jqXHR, s, isSuccess ? success : error ] );
540 completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
543 globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
544 // Handle the global AJAX counter
545 if ( !( --jQuery.active ) ) {
546 jQuery.event.trigger( "ajaxStop" );
552 deferred.promise( jqXHR );
553 jqXHR.success = jqXHR.done;
554 jqXHR.error = jqXHR.fail;
555 jqXHR.complete = completeDeferred.add;
557 // Status-dependent callbacks
558 jqXHR.statusCode = function( map ) {
563 statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
566 tmp = map[ jqXHR.status ];
573 // Remove hash character (#7531: and string promotion)
574 // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
575 // We also use the url parameter if available
576 s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
578 // Extract dataTypes list
579 s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( core_rspace );
581 // Determine if a cross-domain request is in order
582 if ( s.crossDomain == null ) {
583 parts = rurl.exec( s.url.toLowerCase() );
584 s.crossDomain = !!( parts &&
585 ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||
586 ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
587 ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
591 // Convert data if not already a string
592 if ( s.data && s.processData && typeof s.data !== "string" ) {
593 s.data = jQuery.param( s.data, s.traditional );
597 inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
599 // If request was aborted inside a prefilter, stop there
604 // We can fire global events as of now if asked to
605 fireGlobals = s.global;
607 // Uppercase the type
608 s.type = s.type.toUpperCase();
610 // Determine if request has content
611 s.hasContent = !rnoContent.test( s.type );
613 // Watch for a new set of requests
614 if ( fireGlobals && jQuery.active++ === 0 ) {
615 jQuery.event.trigger( "ajaxStart" );
618 // More options handling for requests with no content
619 if ( !s.hasContent ) {
621 // If data is available, append data to url
623 s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
624 // #9682: remove data so that it's not used in an eventual retry
628 // Get ifModifiedKey before adding the anti-cache parameter
629 ifModifiedKey = s.url;
631 // Add anti-cache in url if needed
632 if ( s.cache === false ) {
634 var ts = jQuery.now(),
635 // try replacing _= if it is there
636 ret = s.url.replace( rts, "$1_=" + ts );
638 // if nothing was replaced, add timestamp to the end
639 s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
643 // Set the correct header, if data is being sent
644 if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
645 jqXHR.setRequestHeader( "Content-Type", s.contentType );
648 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
649 if ( s.ifModified ) {
650 ifModifiedKey = ifModifiedKey || s.url;
651 if ( jQuery.lastModified[ ifModifiedKey ] ) {
652 jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
654 if ( jQuery.etag[ ifModifiedKey ] ) {
655 jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
659 // Set the Accepts header for the server, depending on the dataType
660 jqXHR.setRequestHeader(
662 s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
663 s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
667 // Check for headers option
668 for ( i in s.headers ) {
669 jqXHR.setRequestHeader( i, s.headers[ i ] );
672 // Allow custom headers/mimetypes and early abort
673 if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
674 // Abort if not done already and return
675 return jqXHR.abort();
679 // aborting is no longer a cancellation
682 // Install callbacks on deferreds
683 for ( i in { success: 1, error: 1, complete: 1 } ) {
684 jqXHR[ i ]( s[ i ] );
688 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
690 // If no transport, we auto-abort
692 done( -1, "No Transport" );
694 jqXHR.readyState = 1;
697 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
700 if ( s.async && s.timeout > 0 ) {
701 timeoutTimer = setTimeout( function(){
702 jqXHR.abort( "timeout" );
708 transport.send( requestHeaders, done );
710 // Propagate exception as error if not done
713 // Simply rethrow otherwise
723 // Counter for holding the number of active queries
726 // Last-Modified header cache for next request
732 /* Handles responses to an ajax request:
733 * - sets all responseXXX fields accordingly
734 * - finds the right dataType (mediates between content-type and expected dataType)
735 * - returns the corresponding response
737 function ajaxHandleResponses( s, jqXHR, responses ) {
739 var ct, type, finalDataType, firstDataType,
740 contents = s.contents,
741 dataTypes = s.dataTypes,
742 responseFields = s.responseFields;
744 // Fill responseXXX fields
745 for ( type in responseFields ) {
746 if ( type in responses ) {
747 jqXHR[ responseFields[type] ] = responses[ type ];
751 // Remove auto dataType and get content-type in the process
752 while( dataTypes[ 0 ] === "*" ) {
754 if ( ct === undefined ) {
755 ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
759 // Check if we're dealing with a known content-type
761 for ( type in contents ) {
762 if ( contents[ type ] && contents[ type ].test( ct ) ) {
763 dataTypes.unshift( type );
769 // Check to see if we have a response for the expected dataType
770 if ( dataTypes[ 0 ] in responses ) {
771 finalDataType = dataTypes[ 0 ];
773 // Try convertible dataTypes
774 for ( type in responses ) {
775 if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
776 finalDataType = type;
779 if ( !firstDataType ) {
780 firstDataType = type;
783 // Or just use first one
784 finalDataType = finalDataType || firstDataType;
787 // If we found a dataType
788 // We add the dataType to the list if needed
789 // and return the corresponding response
790 if ( finalDataType ) {
791 if ( finalDataType !== dataTypes[ 0 ] ) {
792 dataTypes.unshift( finalDataType );
794 return responses[ finalDataType ];
798 // Chain conversions given the request and the original response
799 function ajaxConvert( s, response ) {
801 var conv, conv2, current, tmp,
802 // Work with a copy of dataTypes in case we need to modify it for conversion
803 dataTypes = s.dataTypes.slice(),
804 prev = dataTypes[ 0 ],
808 // Apply the dataFilter if provided
809 if ( s.dataFilter ) {
810 response = s.dataFilter( response, s.dataType );
813 // Create converters map with lowercased keys
814 if ( dataTypes[ 1 ] ) {
815 for ( conv in s.converters ) {
816 converters[ conv.toLowerCase() ] = s.converters[ conv ];
820 // Convert to each sequential dataType, tolerating list modification
821 for ( ; (current = dataTypes[++i]); ) {
823 // There's only work to do if current dataType is non-auto
824 if ( current !== "*" ) {
826 // Convert response if prev dataType is non-auto and differs from current
827 if ( prev !== "*" && prev !== current ) {
829 // Seek a direct converter
830 conv = converters[ prev + " " + current ] || converters[ "* " + current ];
832 // If none found, seek a pair
834 for ( conv2 in converters ) {
836 // If conv2 outputs current
837 tmp = conv2.split(" ");
838 if ( tmp[ 1 ] === current ) {
840 // If prev can be converted to accepted input
841 conv = converters[ prev + " " + tmp[ 0 ] ] ||
842 converters[ "* " + tmp[ 0 ] ];
844 // Condense equivalence converters
845 if ( conv === true ) {
846 conv = converters[ conv2 ];
848 // Otherwise, insert the intermediate dataType
849 } else if ( converters[ conv2 ] !== true ) {
851 dataTypes.splice( i--, 0, current );
860 // Apply converter (if not an equivalence)
861 if ( conv !== true ) {
863 // Unless errors are allowed to bubble, catch and return them
864 if ( conv && s["throws"] ) {
865 response = conv( response );
868 response = conv( response );
870 return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
876 // Update prev for next iteration
881 return { state: "success", data: response };