1 import jQuery
from "./core.js";
2 import document
from "./var/document.js";
3 import rnothtmlwhite
from "./var/rnothtmlwhite.js";
4 import location
from "./ajax/var/location.js";
5 import nonce
from "./ajax/var/nonce.js";
6 import rquery
from "./ajax/var/rquery.js";
8 import "./core/init.js";
9 import "./core/parseXML.js";
10 import "./event/trigger.js";
11 import "./deferred.js";
12 import "./serialize.js"; // jQuery.param
17 rantiCache
= /([?&])_=[^&]*/,
18 rheaders
= /^(.*?):[ \t]*([^\r\n]*)$/mg,
20 // trac-7653, trac-8125, trac-8152: local protocol detection
21 rlocalProtocol
= /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
22 rnoContent
= /^(?:GET|HEAD)$/,
26 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
27 * 2) These are called:
28 * - BEFORE asking for a transport
29 * - AFTER param serialization (s.data is a string if s.processData is true)
30 * 3) key is the dataType
31 * 4) the catchall symbol "*" can be used
32 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
36 /* Transports bindings
37 * 1) key is the dataType
38 * 2) the catchall symbol "*" can be used
39 * 3) selection will start with transport dataType and THEN go to "*" if needed
43 // Avoid comment-prolog char sequence (trac-10098); must appease lint and evade compression
44 allTypes
= "*/".concat( "*" ),
46 // Anchor tag for parsing the document origin
47 originAnchor
= document
.createElement( "a" );
49 originAnchor
.href
= location
.href
;
51 // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
52 function addToPrefiltersOrTransports( structure
) {
54 // dataTypeExpression is optional and defaults to "*"
55 return function( dataTypeExpression
, func
) {
57 if ( typeof dataTypeExpression
!== "string" ) {
58 func
= dataTypeExpression
;
59 dataTypeExpression
= "*";
64 dataTypes
= dataTypeExpression
.toLowerCase().match( rnothtmlwhite
) || [];
66 if ( typeof func
=== "function" ) {
68 // For each dataType in the dataTypeExpression
69 while ( ( dataType
= dataTypes
[ i
++ ] ) ) {
71 // Prepend if requested
72 if ( dataType
[ 0 ] === "+" ) {
73 dataType
= dataType
.slice( 1 ) || "*";
74 ( structure
[ dataType
] = structure
[ dataType
] || [] ).unshift( func
);
78 ( structure
[ dataType
] = structure
[ dataType
] || [] ).push( func
);
85 // Base inspection function for prefilters and transports
86 function inspectPrefiltersOrTransports( structure
, options
, originalOptions
, jqXHR
) {
89 seekingTransport
= ( structure
=== transports
);
91 function inspect( dataType
) {
93 inspected
[ dataType
] = true;
94 jQuery
.each( structure
[ dataType
] || [], function( _
, prefilterOrFactory
) {
95 var dataTypeOrTransport
= prefilterOrFactory( options
, originalOptions
, jqXHR
);
96 if ( typeof dataTypeOrTransport
=== "string" &&
97 !seekingTransport
&& !inspected
[ dataTypeOrTransport
] ) {
99 options
.dataTypes
.unshift( dataTypeOrTransport
);
100 inspect( dataTypeOrTransport
);
102 } else if ( seekingTransport
) {
103 return !( selected
= dataTypeOrTransport
);
109 return inspect( options
.dataTypes
[ 0 ] ) || !inspected
[ "*" ] && inspect( "*" );
112 // A special extend for ajax options
113 // that takes "flat" options (not to be deep extended)
115 function ajaxExtend( target
, src
) {
117 flatOptions
= jQuery
.ajaxSettings
.flatOptions
|| {};
120 if ( src
[ key
] !== undefined ) {
121 ( flatOptions
[ key
] ? target
: ( deep
|| ( deep
= {} ) ) )[ key
] = src
[ key
];
125 jQuery
.extend( true, target
, deep
);
131 /* Handles responses to an ajax request:
132 * - finds the right dataType (mediates between content-type and expected dataType)
133 * - returns the corresponding response
135 function ajaxHandleResponses( s
, jqXHR
, responses
) {
137 var ct
, type
, finalDataType
, firstDataType
,
138 contents
= s
.contents
,
139 dataTypes
= s
.dataTypes
;
141 // Remove auto dataType and get content-type in the process
142 while ( dataTypes
[ 0 ] === "*" ) {
144 if ( ct
=== undefined ) {
145 ct
= s
.mimeType
|| jqXHR
.getResponseHeader( "Content-Type" );
149 // Check if we're dealing with a known content-type
151 for ( type
in contents
) {
152 if ( contents
[ type
] && contents
[ type
].test( ct
) ) {
153 dataTypes
.unshift( type
);
159 // Check to see if we have a response for the expected dataType
160 if ( dataTypes
[ 0 ] in responses
) {
161 finalDataType
= dataTypes
[ 0 ];
164 // Try convertible dataTypes
165 for ( type
in responses
) {
166 if ( !dataTypes
[ 0 ] || s
.converters
[ type
+ " " + dataTypes
[ 0 ] ] ) {
167 finalDataType
= type
;
170 if ( !firstDataType
) {
171 firstDataType
= type
;
175 // Or just use first one
176 finalDataType
= finalDataType
|| firstDataType
;
179 // If we found a dataType
180 // We add the dataType to the list if needed
181 // and return the corresponding response
182 if ( finalDataType
) {
183 if ( finalDataType
!== dataTypes
[ 0 ] ) {
184 dataTypes
.unshift( finalDataType
);
186 return responses
[ finalDataType
];
190 /* Chain conversions given the request and the original response
191 * Also sets the responseXXX fields on the jqXHR instance
193 function ajaxConvert( s
, response
, jqXHR
, isSuccess
) {
194 var conv2
, current
, conv
, tmp
, prev
,
197 // Work with a copy of dataTypes in case we need to modify it for conversion
198 dataTypes
= s
.dataTypes
.slice();
200 // Create converters map with lowercased keys
201 if ( dataTypes
[ 1 ] ) {
202 for ( conv
in s
.converters
) {
203 converters
[ conv
.toLowerCase() ] = s
.converters
[ conv
];
207 current
= dataTypes
.shift();
209 // Convert to each sequential dataType
212 if ( s
.responseFields
[ current
] ) {
213 jqXHR
[ s
.responseFields
[ current
] ] = response
;
216 // Apply the dataFilter if provided
217 if ( !prev
&& isSuccess
&& s
.dataFilter
) {
218 response
= s
.dataFilter( response
, s
.dataType
);
222 current
= dataTypes
.shift();
226 // There's only work to do if current dataType is non-auto
227 if ( current
=== "*" ) {
231 // Convert response if prev dataType is non-auto and differs from current
232 } else if ( prev
!== "*" && prev
!== current
) {
234 // Seek a direct converter
235 conv
= converters
[ prev
+ " " + current
] || converters
[ "* " + current
];
237 // If none found, seek a pair
239 for ( conv2
in converters
) {
241 // If conv2 outputs current
242 tmp
= conv2
.split( " " );
243 if ( tmp
[ 1 ] === current
) {
245 // If prev can be converted to accepted input
246 conv
= converters
[ prev
+ " " + tmp
[ 0 ] ] ||
247 converters
[ "* " + tmp
[ 0 ] ];
250 // Condense equivalence converters
251 if ( conv
=== true ) {
252 conv
= converters
[ conv2
];
254 // Otherwise, insert the intermediate dataType
255 } else if ( converters
[ conv2
] !== true ) {
257 dataTypes
.unshift( tmp
[ 1 ] );
265 // Apply converter (if not an equivalence)
266 if ( conv
!== true ) {
268 // Unless errors are allowed to bubble, catch and return them
269 if ( conv
&& s
.throws ) {
270 response
= conv( response
);
273 response
= conv( response
);
276 state
: "parsererror",
277 error
: conv
? e
: "No conversion from " + prev
+ " to " + current
286 return { state
: "success", data
: response
};
291 // Counter for holding the number of active queries
294 // Last-Modified header cache for next request
301 isLocal
: rlocalProtocol
.test( location
.protocol
),
305 contentType
: "application/x-www-form-urlencoded; charset=UTF-8",
323 xml
: "application/xml, text/xml",
324 json
: "application/json, text/javascript"
335 text
: "responseText",
340 // Keys separate source (or catchall "*") and destination types with a single space
343 // Convert anything to text
346 // Text to html (true = no transformation)
349 // Evaluate text as a json expression
350 "text json": JSON
.parse
,
353 "text xml": jQuery
.parseXML
356 // For options that shouldn't be deep extended:
357 // you can add your own custom options here if
358 // and when you create one that shouldn't be
359 // deep extended (see ajaxExtend)
366 // Creates a full fledged settings object into target
367 // with both ajaxSettings and settings fields.
368 // If target is omitted, writes into ajaxSettings.
369 ajaxSetup: function( target
, settings
) {
372 // Building a settings object
373 ajaxExtend( ajaxExtend( target
, jQuery
.ajaxSettings
), settings
) :
375 // Extending ajaxSettings
376 ajaxExtend( jQuery
.ajaxSettings
, target
);
379 ajaxPrefilter
: addToPrefiltersOrTransports( prefilters
),
380 ajaxTransport
: addToPrefiltersOrTransports( transports
),
383 ajax: function( url
, options
) {
385 // If url is an object, simulate pre-1.5 signature
386 if ( typeof url
=== "object" ) {
391 // Force options to be an object
392 options
= options
|| {};
396 // URL without anti-cache param
400 responseHeadersString
,
409 // Request state (becomes false upon send and true upon completion)
412 // To know if global events are to be dispatched
418 // uncached part of the url
421 // Create the final options object
422 s
= jQuery
.ajaxSetup( {}, options
),
425 callbackContext
= s
.context
|| s
,
427 // Context for global events is callbackContext if it is a DOM node or jQuery collection
428 globalEventContext
= s
.context
&&
429 ( callbackContext
.nodeType
|| callbackContext
.jquery
) ?
430 jQuery( callbackContext
) :
434 deferred
= jQuery
.Deferred(),
435 completeDeferred
= jQuery
.Callbacks( "once memory" ),
437 // Status-dependent callbacks
438 statusCode
= s
.statusCode
|| {},
440 // Headers (they are sent all at once)
442 requestHeadersNames
= {},
444 // Default abort message
445 strAbort
= "canceled",
451 // Builds headers hashtable if needed
452 getResponseHeader: function( key
) {
455 if ( !responseHeaders
) {
456 responseHeaders
= {};
457 while ( ( match
= rheaders
.exec( responseHeadersString
) ) ) {
460 // `getResponseHeader( key )` in IE doesn't combine all header
461 // values for the provided key into a single result with values
462 // joined by commas as other browsers do. Instead, it returns
463 // them on separate lines.
464 responseHeaders
[ match
[ 1 ].toLowerCase() + " " ] =
465 ( responseHeaders
[ match
[ 1 ].toLowerCase() + " " ] || [] )
466 .concat( match
[ 2 ] );
469 match
= responseHeaders
[ key
.toLowerCase() + " " ];
471 return match
== null ? null : match
.join( ", " );
475 getAllResponseHeaders: function() {
476 return completed
? responseHeadersString
: null;
480 setRequestHeader: function( name
, value
) {
481 if ( completed
== null ) {
482 name
= requestHeadersNames
[ name
.toLowerCase() ] =
483 requestHeadersNames
[ name
.toLowerCase() ] || name
;
484 requestHeaders
[ name
] = value
;
489 // Overrides response content-type header
490 overrideMimeType: function( type
) {
491 if ( completed
== null ) {
497 // Status-dependent callbacks
498 statusCode: function( map
) {
503 // Execute the appropriate callbacks
504 jqXHR
.always( map
[ jqXHR
.status
] );
507 // Lazy-add the new callbacks in a way that preserves old ones
508 for ( code
in map
) {
509 statusCode
[ code
] = [ statusCode
[ code
], map
[ code
] ];
516 // Cancel the request
517 abort: function( statusText
) {
518 var finalText
= statusText
|| strAbort
;
520 transport
.abort( finalText
);
522 done( 0, finalText
);
528 deferred
.promise( jqXHR
);
530 // Add protocol if not provided (prefilters might expect it)
531 // Handle falsy url in the settings object (trac-10093: consistency with old signature)
532 // We also use the url parameter if available
533 s
.url
= ( ( url
|| s
.url
|| location
.href
) + "" )
534 .replace( rprotocol
, location
.protocol
+ "//" );
536 // Alias method option to type as per ticket trac-12004
537 s
.type
= options
.method
|| options
.type
|| s
.method
|| s
.type
;
539 // Extract dataTypes list
540 s
.dataTypes
= ( s
.dataType
|| "*" ).toLowerCase().match( rnothtmlwhite
) || [ "" ];
542 // A cross-domain request is in order when the origin doesn't match the current origin.
543 if ( s
.crossDomain
== null ) {
544 urlAnchor
= document
.createElement( "a" );
546 // Support: IE <=8 - 11+
547 // IE throws exception on accessing the href property if url is malformed,
548 // e.g. http://example.com:80x/
550 urlAnchor
.href
= s
.url
;
552 // Support: IE <=8 - 11+
553 // Anchor's host property isn't correctly set when s.url is relative
554 urlAnchor
.href
= urlAnchor
.href
;
555 s
.crossDomain
= originAnchor
.protocol
+ "//" + originAnchor
.host
!==
556 urlAnchor
.protocol
+ "//" + urlAnchor
.host
;
559 // If there is an error parsing the URL, assume it is crossDomain,
560 // it can be rejected by the transport if it is invalid
561 s
.crossDomain
= true;
566 inspectPrefiltersOrTransports( prefilters
, s
, options
, jqXHR
);
568 // Convert data if not already a string
569 if ( s
.data
&& s
.processData
&& typeof s
.data
!== "string" ) {
570 s
.data
= jQuery
.param( s
.data
, s
.traditional
);
573 // If request was aborted inside a prefilter, stop there
578 // We can fire global events as of now if asked to
579 // Don't fire events if jQuery.event is undefined in an ESM-usage scenario (trac-15118)
580 fireGlobals
= jQuery
.event
&& s
.global
;
582 // Watch for a new set of requests
583 if ( fireGlobals
&& jQuery
.active
++ === 0 ) {
584 jQuery
.event
.trigger( "ajaxStart" );
587 // Uppercase the type
588 s
.type
= s
.type
.toUpperCase();
590 // Determine if request has content
591 s
.hasContent
= !rnoContent
.test( s
.type
);
593 // Save the URL in case we're toying with the If-Modified-Since
594 // and/or If-None-Match header later on
595 // Remove hash to simplify url manipulation
596 cacheURL
= s
.url
.replace( rhash
, "" );
598 // More options handling for requests with no content
599 if ( !s
.hasContent
) {
601 // Remember the hash so we can put it back
602 uncached
= s
.url
.slice( cacheURL
.length
);
604 // If data is available and should be processed, append data to url
605 if ( s
.data
&& ( s
.processData
|| typeof s
.data
=== "string" ) ) {
606 cacheURL
+= ( rquery
.test( cacheURL
) ? "&" : "?" ) + s
.data
;
608 // trac-9682: remove data so that it's not used in an eventual retry
612 // Add or update anti-cache param if needed
613 if ( s
.cache
=== false ) {
614 cacheURL
= cacheURL
.replace( rantiCache
, "$1" );
615 uncached
= ( rquery
.test( cacheURL
) ? "&" : "?" ) + "_=" +
616 ( nonce
.guid
++ ) + uncached
;
619 // Put hash and anti-cache on the URL that will be requested (gh-1732)
620 s
.url
= cacheURL
+ uncached
;
622 // Change '%20' to '+' if this is encoded form body content (gh-2658)
623 } else if ( s
.data
&& s
.processData
&&
624 ( s
.contentType
|| "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) {
625 s
.data
= s
.data
.replace( r20
, "+" );
628 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
629 if ( s
.ifModified
) {
630 if ( jQuery
.lastModified
[ cacheURL
] ) {
631 jqXHR
.setRequestHeader( "If-Modified-Since", jQuery
.lastModified
[ cacheURL
] );
633 if ( jQuery
.etag
[ cacheURL
] ) {
634 jqXHR
.setRequestHeader( "If-None-Match", jQuery
.etag
[ cacheURL
] );
638 // Set the correct header, if data is being sent
639 if ( s
.data
&& s
.hasContent
&& s
.contentType
!== false || options
.contentType
) {
640 jqXHR
.setRequestHeader( "Content-Type", s
.contentType
);
643 // Set the Accepts header for the server, depending on the dataType
644 jqXHR
.setRequestHeader(
646 s
.dataTypes
[ 0 ] && s
.accepts
[ s
.dataTypes
[ 0 ] ] ?
647 s
.accepts
[ s
.dataTypes
[ 0 ] ] +
648 ( s
.dataTypes
[ 0 ] !== "*" ? ", " + allTypes
+ "; q=0.01" : "" ) :
652 // Check for headers option
653 for ( i
in s
.headers
) {
654 jqXHR
.setRequestHeader( i
, s
.headers
[ i
] );
657 // Allow custom headers/mimetypes and early abort
659 ( s
.beforeSend
.call( callbackContext
, jqXHR
, s
) === false || completed
) ) {
661 // Abort if not done already and return
662 return jqXHR
.abort();
665 // Aborting is no longer a cancellation
668 // Install callbacks on deferreds
669 completeDeferred
.add( s
.complete
);
670 jqXHR
.done( s
.success
);
671 jqXHR
.fail( s
.error
);
674 transport
= inspectPrefiltersOrTransports( transports
, s
, options
, jqXHR
);
676 // If no transport, we auto-abort
678 done( -1, "No Transport" );
680 jqXHR
.readyState
= 1;
684 globalEventContext
.trigger( "ajaxSend", [ jqXHR
, s
] );
687 // If request was aborted inside ajaxSend, stop there
693 if ( s
.async
&& s
.timeout
> 0 ) {
694 timeoutTimer
= window
.setTimeout( function() {
695 jqXHR
.abort( "timeout" );
701 transport
.send( requestHeaders
, done
);
704 // Rethrow post-completion exceptions
709 // Propagate others as results
714 // Callback for when everything is done
715 function done( status
, nativeStatusText
, responses
, headers
) {
716 var isSuccess
, success
, error
, response
, modified
,
717 statusText
= nativeStatusText
;
719 // Ignore repeat invocations
726 // Clear timeout if it exists
727 if ( timeoutTimer
) {
728 window
.clearTimeout( timeoutTimer
);
731 // Dereference transport for early garbage collection
732 // (no matter how long the jqXHR object will be used)
733 transport
= undefined;
735 // Cache response headers
736 responseHeadersString
= headers
|| "";
739 jqXHR
.readyState
= status
> 0 ? 4 : 0;
741 // Determine if successful
742 isSuccess
= status
>= 200 && status
< 300 || status
=== 304;
746 response
= ajaxHandleResponses( s
, jqXHR
, responses
);
749 // Use a noop converter for missing script but not if jsonp
751 jQuery
.inArray( "script", s
.dataTypes
) > -1 &&
752 jQuery
.inArray( "json", s
.dataTypes
) < 0 ) {
753 s
.converters
[ "text script" ] = function() {};
756 // Convert no matter what (that way responseXXX fields are always set)
757 response
= ajaxConvert( s
, response
, jqXHR
, isSuccess
);
759 // If successful, handle type chaining
762 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
763 if ( s
.ifModified
) {
764 modified
= jqXHR
.getResponseHeader( "Last-Modified" );
766 jQuery
.lastModified
[ cacheURL
] = modified
;
768 modified
= jqXHR
.getResponseHeader( "etag" );
770 jQuery
.etag
[ cacheURL
] = modified
;
775 if ( status
=== 204 || s
.type
=== "HEAD" ) {
776 statusText
= "nocontent";
779 } else if ( status
=== 304 ) {
780 statusText
= "notmodified";
782 // If we have data, let's convert it
784 statusText
= response
.state
;
785 success
= response
.data
;
786 error
= response
.error
;
791 // Extract error from statusText and normalize for non-aborts
793 if ( status
|| !statusText
) {
794 statusText
= "error";
801 // Set data for the fake xhr object
802 jqXHR
.status
= status
;
803 jqXHR
.statusText
= ( nativeStatusText
|| statusText
) + "";
807 deferred
.resolveWith( callbackContext
, [ success
, statusText
, jqXHR
] );
809 deferred
.rejectWith( callbackContext
, [ jqXHR
, statusText
, error
] );
812 // Status-dependent callbacks
813 jqXHR
.statusCode( statusCode
);
814 statusCode
= undefined;
817 globalEventContext
.trigger( isSuccess
? "ajaxSuccess" : "ajaxError",
818 [ jqXHR
, s
, isSuccess
? success
: error
] );
822 completeDeferred
.fireWith( callbackContext
, [ jqXHR
, statusText
] );
825 globalEventContext
.trigger( "ajaxComplete", [ jqXHR
, s
] );
827 // Handle the global AJAX counter
828 if ( !( --jQuery
.active
) ) {
829 jQuery
.event
.trigger( "ajaxStop" );
837 getJSON: function( url
, data
, callback
) {
838 return jQuery
.get( url
, data
, callback
, "json" );
841 getScript: function( url
, callback
) {
842 return jQuery
.get( url
, undefined, callback
, "script" );
846 jQuery
.each( [ "get", "post" ], function( _i
, method
) {
847 jQuery
[ method
] = function( url
, data
, callback
, type
) {
849 // Shift arguments if data argument was omitted.
850 // Handle the null callback placeholder.
851 if ( typeof data
=== "function" || data
=== null ) {
852 type
= type
|| callback
;
857 // The url can be an options object (which then must have .url)
858 return jQuery
.ajax( jQuery
.extend( {
864 }, jQuery
.isPlainObject( url
) && url
) );
868 jQuery
.ajaxPrefilter( function( s
) {
870 for ( i
in s
.headers
) {
871 if ( i
.toLowerCase() === "content-type" ) {
872 s
.contentType
= s
.headers
[ i
] || "";
877 export default jQuery
;