1
|
|
|
define( [ |
2
|
|
|
"./core", |
3
|
|
|
"./var/document", |
4
|
|
|
"./var/rnothtmlwhite", |
5
|
|
|
"./ajax/var/location", |
6
|
|
|
"./ajax/var/nonce", |
7
|
|
|
"./ajax/var/rquery", |
8
|
|
|
|
9
|
|
|
"./core/init", |
10
|
|
|
"./ajax/parseXML", |
11
|
|
|
"./event/trigger", |
12
|
|
|
"./deferred", |
13
|
|
|
"./serialize" // jQuery.param |
14
|
|
|
], function( jQuery, document, rnothtmlwhite, location, nonce, rquery ) { |
15
|
|
|
|
16
|
|
|
"use strict"; |
17
|
|
|
|
18
|
|
|
var |
19
|
|
|
r20 = /%20/g, |
20
|
|
|
rhash = /#.*$/, |
21
|
|
|
rantiCache = /([?&])_=[^&]*/, |
22
|
|
|
rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, |
23
|
|
|
|
24
|
|
|
// #7653, #8125, #8152: local protocol detection |
25
|
|
|
rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, |
26
|
|
|
rnoContent = /^(?:GET|HEAD)$/, |
27
|
|
|
rprotocol = /^\/\//, |
28
|
|
|
|
29
|
|
|
/* Prefilters |
30
|
|
|
* 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) |
31
|
|
|
* 2) These are called: |
32
|
|
|
* - BEFORE asking for a transport |
33
|
|
|
* - AFTER param serialization (s.data is a string if s.processData is true) |
34
|
|
|
* 3) key is the dataType |
35
|
|
|
* 4) the catchall symbol "*" can be used |
36
|
|
|
* 5) execution will start with transport dataType and THEN continue down to "*" if needed |
37
|
|
|
*/ |
38
|
|
|
prefilters = {}, |
39
|
|
|
|
40
|
|
|
/* Transports bindings |
41
|
|
|
* 1) key is the dataType |
42
|
|
|
* 2) the catchall symbol "*" can be used |
43
|
|
|
* 3) selection will start with transport dataType and THEN go to "*" if needed |
44
|
|
|
*/ |
45
|
|
|
transports = {}, |
46
|
|
|
|
47
|
|
|
// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression |
48
|
|
|
allTypes = "*/".concat( "*" ), |
49
|
|
|
|
50
|
|
|
// Anchor tag for parsing the document origin |
51
|
|
|
originAnchor = document.createElement( "a" ); |
52
|
|
|
originAnchor.href = location.href; |
53
|
|
|
|
54
|
|
|
// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport |
55
|
|
|
function addToPrefiltersOrTransports( structure ) { |
56
|
|
|
|
57
|
|
|
// dataTypeExpression is optional and defaults to "*" |
58
|
|
|
return function( dataTypeExpression, func ) { |
59
|
|
|
|
60
|
|
|
if ( typeof dataTypeExpression !== "string" ) { |
61
|
|
|
func = dataTypeExpression; |
62
|
|
|
dataTypeExpression = "*"; |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
var dataType, |
66
|
|
|
i = 0, |
67
|
|
|
dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; |
68
|
|
|
|
69
|
|
|
if ( jQuery.isFunction( func ) ) { |
70
|
|
|
|
71
|
|
|
// For each dataType in the dataTypeExpression |
72
|
|
|
while ( ( dataType = dataTypes[ i++ ] ) ) { |
73
|
|
|
|
74
|
|
|
// Prepend if requested |
75
|
|
|
if ( dataType[ 0 ] === "+" ) { |
76
|
|
|
dataType = dataType.slice( 1 ) || "*"; |
77
|
|
|
( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); |
78
|
|
|
|
79
|
|
|
// Otherwise append |
80
|
|
|
} else { |
81
|
|
|
( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); |
82
|
|
|
} |
83
|
|
|
} |
84
|
|
|
} |
85
|
|
|
}; |
86
|
|
|
} |
87
|
|
|
|
88
|
|
|
// Base inspection function for prefilters and transports |
89
|
|
|
function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { |
90
|
|
|
|
91
|
|
|
var inspected = {}, |
92
|
|
|
seekingTransport = ( structure === transports ); |
93
|
|
|
|
94
|
|
|
function inspect( dataType ) { |
95
|
|
|
var selected; |
96
|
|
|
inspected[ dataType ] = true; |
97
|
|
|
jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { |
98
|
|
|
var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); |
99
|
|
|
if ( typeof dataTypeOrTransport === "string" && |
100
|
|
|
!seekingTransport && !inspected[ dataTypeOrTransport ] ) { |
101
|
|
|
|
102
|
|
|
options.dataTypes.unshift( dataTypeOrTransport ); |
103
|
|
|
inspect( dataTypeOrTransport ); |
104
|
|
|
return false; |
105
|
|
|
} else if ( seekingTransport ) { |
106
|
|
|
return !( selected = dataTypeOrTransport ); |
107
|
|
|
} |
108
|
|
|
} ); |
109
|
|
|
return selected; |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
// A special extend for ajax options |
116
|
|
|
// that takes "flat" options (not to be deep extended) |
117
|
|
|
// Fixes #9887 |
118
|
|
|
function ajaxExtend( target, src ) { |
119
|
|
|
var key, deep, |
120
|
|
|
flatOptions = jQuery.ajaxSettings.flatOptions || {}; |
121
|
|
|
|
122
|
|
|
for ( key in src ) { |
123
|
|
|
if ( src[ key ] !== undefined ) { |
124
|
|
|
( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; |
125
|
|
|
} |
126
|
|
|
} |
127
|
|
|
if ( deep ) { |
128
|
|
|
jQuery.extend( true, target, deep ); |
129
|
|
|
} |
130
|
|
|
|
131
|
|
|
return target; |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
/* Handles responses to an ajax request: |
135
|
|
|
* - finds the right dataType (mediates between content-type and expected dataType) |
136
|
|
|
* - returns the corresponding response |
137
|
|
|
*/ |
138
|
|
|
function ajaxHandleResponses( s, jqXHR, responses ) { |
139
|
|
|
|
140
|
|
|
var ct, type, finalDataType, firstDataType, |
141
|
|
|
contents = s.contents, |
142
|
|
|
dataTypes = s.dataTypes; |
143
|
|
|
|
144
|
|
|
// Remove auto dataType and get content-type in the process |
145
|
|
|
while ( dataTypes[ 0 ] === "*" ) { |
146
|
|
|
dataTypes.shift(); |
147
|
|
|
if ( ct === undefined ) { |
148
|
|
|
ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); |
149
|
|
|
} |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
// Check if we're dealing with a known content-type |
153
|
|
|
if ( ct ) { |
154
|
|
|
for ( type in contents ) { |
155
|
|
|
if ( contents[ type ] && contents[ type ].test( ct ) ) { |
156
|
|
|
dataTypes.unshift( type ); |
157
|
|
|
break; |
158
|
|
|
} |
159
|
|
|
} |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
// Check to see if we have a response for the expected dataType |
163
|
|
|
if ( dataTypes[ 0 ] in responses ) { |
164
|
|
|
finalDataType = dataTypes[ 0 ]; |
165
|
|
|
} else { |
166
|
|
|
|
167
|
|
|
// Try convertible dataTypes |
168
|
|
|
for ( type in responses ) { |
169
|
|
|
if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { |
170
|
|
|
finalDataType = type; |
171
|
|
|
break; |
172
|
|
|
} |
173
|
|
|
if ( !firstDataType ) { |
174
|
|
|
firstDataType = type; |
175
|
|
|
} |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
// Or just use first one |
179
|
|
|
finalDataType = finalDataType || firstDataType; |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
// If we found a dataType |
183
|
|
|
// We add the dataType to the list if needed |
184
|
|
|
// and return the corresponding response |
185
|
|
|
if ( finalDataType ) { |
186
|
|
|
if ( finalDataType !== dataTypes[ 0 ] ) { |
187
|
|
|
dataTypes.unshift( finalDataType ); |
188
|
|
|
} |
189
|
|
|
return responses[ finalDataType ]; |
190
|
|
|
} |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
/* Chain conversions given the request and the original response |
194
|
|
|
* Also sets the responseXXX fields on the jqXHR instance |
195
|
|
|
*/ |
196
|
|
|
function ajaxConvert( s, response, jqXHR, isSuccess ) { |
197
|
|
|
var conv2, current, conv, tmp, prev, |
198
|
|
|
converters = {}, |
199
|
|
|
|
200
|
|
|
// Work with a copy of dataTypes in case we need to modify it for conversion |
201
|
|
|
dataTypes = s.dataTypes.slice(); |
202
|
|
|
|
203
|
|
|
// Create converters map with lowercased keys |
204
|
|
|
if ( dataTypes[ 1 ] ) { |
205
|
|
|
for ( conv in s.converters ) { |
206
|
|
|
converters[ conv.toLowerCase() ] = s.converters[ conv ]; |
207
|
|
|
} |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
current = dataTypes.shift(); |
211
|
|
|
|
212
|
|
|
// Convert to each sequential dataType |
213
|
|
|
while ( current ) { |
214
|
|
|
|
215
|
|
|
if ( s.responseFields[ current ] ) { |
216
|
|
|
jqXHR[ s.responseFields[ current ] ] = response; |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
// Apply the dataFilter if provided |
220
|
|
|
if ( !prev && isSuccess && s.dataFilter ) { |
221
|
|
|
response = s.dataFilter( response, s.dataType ); |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
prev = current; |
225
|
|
|
current = dataTypes.shift(); |
226
|
|
|
|
227
|
|
|
if ( current ) { |
228
|
|
|
|
229
|
|
|
// There's only work to do if current dataType is non-auto |
230
|
|
|
if ( current === "*" ) { |
231
|
|
|
|
232
|
|
|
current = prev; |
233
|
|
|
|
234
|
|
|
// Convert response if prev dataType is non-auto and differs from current |
235
|
|
|
} else if ( prev !== "*" && prev !== current ) { |
236
|
|
|
|
237
|
|
|
// Seek a direct converter |
238
|
|
|
conv = converters[ prev + " " + current ] || converters[ "* " + current ]; |
239
|
|
|
|
240
|
|
|
// If none found, seek a pair |
241
|
|
|
if ( !conv ) { |
242
|
|
|
for ( conv2 in converters ) { |
243
|
|
|
|
244
|
|
|
// If conv2 outputs current |
245
|
|
|
tmp = conv2.split( " " ); |
246
|
|
|
if ( tmp[ 1 ] === current ) { |
247
|
|
|
|
248
|
|
|
// If prev can be converted to accepted input |
249
|
|
|
conv = converters[ prev + " " + tmp[ 0 ] ] || |
250
|
|
|
converters[ "* " + tmp[ 0 ] ]; |
251
|
|
|
if ( conv ) { |
252
|
|
|
|
253
|
|
|
// Condense equivalence converters |
254
|
|
|
if ( conv === true ) { |
255
|
|
|
conv = converters[ conv2 ]; |
256
|
|
|
|
257
|
|
|
// Otherwise, insert the intermediate dataType |
258
|
|
|
} else if ( converters[ conv2 ] !== true ) { |
259
|
|
|
current = tmp[ 0 ]; |
260
|
|
|
dataTypes.unshift( tmp[ 1 ] ); |
261
|
|
|
} |
262
|
|
|
break; |
263
|
|
|
} |
264
|
|
|
} |
265
|
|
|
} |
266
|
|
|
} |
267
|
|
|
|
268
|
|
|
// Apply converter (if not an equivalence) |
269
|
|
|
if ( conv !== true ) { |
270
|
|
|
|
271
|
|
|
// Unless errors are allowed to bubble, catch and return them |
272
|
|
|
if ( conv && s.throws ) { |
273
|
|
|
response = conv( response ); |
274
|
|
|
} else { |
275
|
|
|
try { |
276
|
|
|
response = conv( response ); |
277
|
|
|
} catch ( e ) { |
278
|
|
|
return { |
279
|
|
|
state: "parsererror", |
280
|
|
|
error: conv ? e : "No conversion from " + prev + " to " + current |
281
|
|
|
}; |
282
|
|
|
} |
283
|
|
|
} |
284
|
|
|
} |
285
|
|
|
} |
286
|
|
|
} |
287
|
|
|
} |
288
|
|
|
|
289
|
|
|
return { state: "success", data: response }; |
290
|
|
|
} |
291
|
|
|
|
292
|
|
|
jQuery.extend( { |
293
|
|
|
|
294
|
|
|
// Counter for holding the number of active queries |
295
|
|
|
active: 0, |
296
|
|
|
|
297
|
|
|
// Last-Modified header cache for next request |
298
|
|
|
lastModified: {}, |
299
|
|
|
etag: {}, |
300
|
|
|
|
301
|
|
|
ajaxSettings: { |
302
|
|
|
url: location.href, |
303
|
|
|
type: "GET", |
304
|
|
|
isLocal: rlocalProtocol.test( location.protocol ), |
305
|
|
|
global: true, |
306
|
|
|
processData: true, |
307
|
|
|
async: true, |
308
|
|
|
contentType: "application/x-www-form-urlencoded; charset=UTF-8", |
309
|
|
|
|
310
|
|
|
/* |
311
|
|
|
timeout: 0, |
312
|
|
|
data: null, |
313
|
|
|
dataType: null, |
314
|
|
|
username: null, |
315
|
|
|
password: null, |
316
|
|
|
cache: null, |
317
|
|
|
throws: false, |
318
|
|
|
traditional: false, |
319
|
|
|
headers: {}, |
320
|
|
|
*/ |
321
|
|
|
|
322
|
|
|
accepts: { |
323
|
|
|
"*": allTypes, |
324
|
|
|
text: "text/plain", |
325
|
|
|
html: "text/html", |
326
|
|
|
xml: "application/xml, text/xml", |
327
|
|
|
json: "application/json, text/javascript" |
328
|
|
|
}, |
329
|
|
|
|
330
|
|
|
contents: { |
331
|
|
|
xml: /\bxml\b/, |
332
|
|
|
html: /\bhtml/, |
333
|
|
|
json: /\bjson\b/ |
334
|
|
|
}, |
335
|
|
|
|
336
|
|
|
responseFields: { |
337
|
|
|
xml: "responseXML", |
338
|
|
|
text: "responseText", |
339
|
|
|
json: "responseJSON" |
340
|
|
|
}, |
341
|
|
|
|
342
|
|
|
// Data converters |
343
|
|
|
// Keys separate source (or catchall "*") and destination types with a single space |
344
|
|
|
converters: { |
345
|
|
|
|
346
|
|
|
// Convert anything to text |
347
|
|
|
"* text": String, |
348
|
|
|
|
349
|
|
|
// Text to html (true = no transformation) |
350
|
|
|
"text html": true, |
351
|
|
|
|
352
|
|
|
// Evaluate text as a json expression |
353
|
|
|
"text json": JSON.parse, |
354
|
|
|
|
355
|
|
|
// Parse text as xml |
356
|
|
|
"text xml": jQuery.parseXML |
357
|
|
|
}, |
358
|
|
|
|
359
|
|
|
// For options that shouldn't be deep extended: |
360
|
|
|
// you can add your own custom options here if |
361
|
|
|
// and when you create one that shouldn't be |
362
|
|
|
// deep extended (see ajaxExtend) |
363
|
|
|
flatOptions: { |
364
|
|
|
url: true, |
365
|
|
|
context: true |
366
|
|
|
} |
367
|
|
|
}, |
368
|
|
|
|
369
|
|
|
// Creates a full fledged settings object into target |
370
|
|
|
// with both ajaxSettings and settings fields. |
371
|
|
|
// If target is omitted, writes into ajaxSettings. |
372
|
|
|
ajaxSetup: function( target, settings ) { |
373
|
|
|
return settings ? |
374
|
|
|
|
375
|
|
|
// Building a settings object |
376
|
|
|
ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : |
377
|
|
|
|
378
|
|
|
// Extending ajaxSettings |
379
|
|
|
ajaxExtend( jQuery.ajaxSettings, target ); |
380
|
|
|
}, |
381
|
|
|
|
382
|
|
|
ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), |
383
|
|
|
ajaxTransport: addToPrefiltersOrTransports( transports ), |
384
|
|
|
|
385
|
|
|
// Main method |
386
|
|
|
ajax: function( url, options ) { |
387
|
|
|
|
388
|
|
|
// If url is an object, simulate pre-1.5 signature |
389
|
|
|
if ( typeof url === "object" ) { |
390
|
|
|
options = url; |
391
|
|
|
url = undefined; |
392
|
|
|
} |
393
|
|
|
|
394
|
|
|
// Force options to be an object |
395
|
|
|
options = options || {}; |
396
|
|
|
|
397
|
|
|
var transport, |
398
|
|
|
|
399
|
|
|
// URL without anti-cache param |
400
|
|
|
cacheURL, |
401
|
|
|
|
402
|
|
|
// Response headers |
403
|
|
|
responseHeadersString, |
404
|
|
|
responseHeaders, |
405
|
|
|
|
406
|
|
|
// timeout handle |
407
|
|
|
timeoutTimer, |
408
|
|
|
|
409
|
|
|
// Url cleanup var |
410
|
|
|
urlAnchor, |
411
|
|
|
|
412
|
|
|
// Request state (becomes false upon send and true upon completion) |
413
|
|
|
completed, |
414
|
|
|
|
415
|
|
|
// To know if global events are to be dispatched |
416
|
|
|
fireGlobals, |
417
|
|
|
|
418
|
|
|
// Loop variable |
419
|
|
|
i, |
420
|
|
|
|
421
|
|
|
// uncached part of the url |
422
|
|
|
uncached, |
423
|
|
|
|
424
|
|
|
// Create the final options object |
425
|
|
|
s = jQuery.ajaxSetup( {}, options ), |
426
|
|
|
|
427
|
|
|
// Callbacks context |
428
|
|
|
callbackContext = s.context || s, |
429
|
|
|
|
430
|
|
|
// Context for global events is callbackContext if it is a DOM node or jQuery collection |
431
|
|
|
globalEventContext = s.context && |
432
|
|
|
( callbackContext.nodeType || callbackContext.jquery ) ? |
433
|
|
|
jQuery( callbackContext ) : |
434
|
|
|
jQuery.event, |
435
|
|
|
|
436
|
|
|
// Deferreds |
437
|
|
|
deferred = jQuery.Deferred(), |
438
|
|
|
completeDeferred = jQuery.Callbacks( "once memory" ), |
439
|
|
|
|
440
|
|
|
// Status-dependent callbacks |
441
|
|
|
statusCode = s.statusCode || {}, |
442
|
|
|
|
443
|
|
|
// Headers (they are sent all at once) |
444
|
|
|
requestHeaders = {}, |
445
|
|
|
requestHeadersNames = {}, |
446
|
|
|
|
447
|
|
|
// Default abort message |
448
|
|
|
strAbort = "canceled", |
449
|
|
|
|
450
|
|
|
// Fake xhr |
451
|
|
|
jqXHR = { |
452
|
|
|
readyState: 0, |
453
|
|
|
|
454
|
|
|
// Builds headers hashtable if needed |
455
|
|
|
getResponseHeader: function( key ) { |
456
|
|
|
var match; |
457
|
|
|
if ( completed ) { |
458
|
|
|
if ( !responseHeaders ) { |
459
|
|
|
responseHeaders = {}; |
460
|
|
|
while ( ( match = rheaders.exec( responseHeadersString ) ) ) { |
461
|
|
|
responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ]; |
462
|
|
|
} |
463
|
|
|
} |
464
|
|
|
match = responseHeaders[ key.toLowerCase() ]; |
465
|
|
|
} |
466
|
|
|
return match == null ? null : match; |
467
|
|
|
}, |
468
|
|
|
|
469
|
|
|
// Raw string |
470
|
|
|
getAllResponseHeaders: function() { |
471
|
|
|
return completed ? responseHeadersString : null; |
472
|
|
|
}, |
473
|
|
|
|
474
|
|
|
// Caches the header |
475
|
|
|
setRequestHeader: function( name, value ) { |
476
|
|
|
if ( completed == null ) { |
477
|
|
|
name = requestHeadersNames[ name.toLowerCase() ] = |
478
|
|
|
requestHeadersNames[ name.toLowerCase() ] || name; |
479
|
|
|
requestHeaders[ name ] = value; |
480
|
|
|
} |
481
|
|
|
return this; |
482
|
|
|
}, |
483
|
|
|
|
484
|
|
|
// Overrides response content-type header |
485
|
|
|
overrideMimeType: function( type ) { |
486
|
|
|
if ( completed == null ) { |
487
|
|
|
s.mimeType = type; |
488
|
|
|
} |
489
|
|
|
return this; |
490
|
|
|
}, |
491
|
|
|
|
492
|
|
|
// Status-dependent callbacks |
493
|
|
|
statusCode: function( map ) { |
494
|
|
|
var code; |
495
|
|
|
if ( map ) { |
496
|
|
|
if ( completed ) { |
497
|
|
|
|
498
|
|
|
// Execute the appropriate callbacks |
499
|
|
|
jqXHR.always( map[ jqXHR.status ] ); |
500
|
|
|
} else { |
501
|
|
|
|
502
|
|
|
// Lazy-add the new callbacks in a way that preserves old ones |
503
|
|
|
for ( code in map ) { |
504
|
|
|
statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; |
505
|
|
|
} |
506
|
|
|
} |
507
|
|
|
} |
508
|
|
|
return this; |
509
|
|
|
}, |
510
|
|
|
|
511
|
|
|
// Cancel the request |
512
|
|
|
abort: function( statusText ) { |
513
|
|
|
var finalText = statusText || strAbort; |
514
|
|
|
if ( transport ) { |
515
|
|
|
transport.abort( finalText ); |
516
|
|
|
} |
517
|
|
|
done( 0, finalText ); |
518
|
|
|
return this; |
519
|
|
|
} |
520
|
|
|
}; |
521
|
|
|
|
522
|
|
|
// Attach deferreds |
523
|
|
|
deferred.promise( jqXHR ); |
524
|
|
|
|
525
|
|
|
// Add protocol if not provided (prefilters might expect it) |
526
|
|
|
// Handle falsy url in the settings object (#10093: consistency with old signature) |
527
|
|
|
// We also use the url parameter if available |
528
|
|
|
s.url = ( ( url || s.url || location.href ) + "" ) |
529
|
|
|
.replace( rprotocol, location.protocol + "//" ); |
530
|
|
|
|
531
|
|
|
// Alias method option to type as per ticket #12004 |
532
|
|
|
s.type = options.method || options.type || s.method || s.type; |
533
|
|
|
|
534
|
|
|
// Extract dataTypes list |
535
|
|
|
s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; |
536
|
|
|
|
537
|
|
|
// A cross-domain request is in order when the origin doesn't match the current origin. |
538
|
|
|
if ( s.crossDomain == null ) { |
539
|
|
|
urlAnchor = document.createElement( "a" ); |
540
|
|
|
|
541
|
|
|
// Support: IE <=8 - 11, Edge 12 - 13 |
542
|
|
|
// IE throws exception on accessing the href property if url is malformed, |
543
|
|
|
// e.g. http://example.com:80x/ |
544
|
|
|
try { |
545
|
|
|
urlAnchor.href = s.url; |
546
|
|
|
|
547
|
|
|
// Support: IE <=8 - 11 only |
548
|
|
|
// Anchor's host property isn't correctly set when s.url is relative |
549
|
|
|
urlAnchor.href = urlAnchor.href; |
550
|
|
|
s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== |
551
|
|
|
urlAnchor.protocol + "//" + urlAnchor.host; |
552
|
|
|
} catch ( e ) { |
553
|
|
|
|
554
|
|
|
// If there is an error parsing the URL, assume it is crossDomain, |
555
|
|
|
// it can be rejected by the transport if it is invalid |
556
|
|
|
s.crossDomain = true; |
557
|
|
|
} |
558
|
|
|
} |
559
|
|
|
|
560
|
|
|
// Convert data if not already a string |
561
|
|
|
if ( s.data && s.processData && typeof s.data !== "string" ) { |
562
|
|
|
s.data = jQuery.param( s.data, s.traditional ); |
563
|
|
|
} |
564
|
|
|
|
565
|
|
|
// Apply prefilters |
566
|
|
|
inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); |
567
|
|
|
|
568
|
|
|
// If request was aborted inside a prefilter, stop there |
569
|
|
|
if ( completed ) { |
570
|
|
|
return jqXHR; |
571
|
|
|
} |
572
|
|
|
|
573
|
|
|
// We can fire global events as of now if asked to |
574
|
|
|
// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) |
575
|
|
|
fireGlobals = jQuery.event && s.global; |
576
|
|
|
|
577
|
|
|
// Watch for a new set of requests |
578
|
|
|
if ( fireGlobals && jQuery.active++ === 0 ) { |
579
|
|
|
jQuery.event.trigger( "ajaxStart" ); |
580
|
|
|
} |
581
|
|
|
|
582
|
|
|
// Uppercase the type |
583
|
|
|
s.type = s.type.toUpperCase(); |
584
|
|
|
|
585
|
|
|
// Determine if request has content |
586
|
|
|
s.hasContent = !rnoContent.test( s.type ); |
587
|
|
|
|
588
|
|
|
// Save the URL in case we're toying with the If-Modified-Since |
589
|
|
|
// and/or If-None-Match header later on |
590
|
|
|
// Remove hash to simplify url manipulation |
591
|
|
|
cacheURL = s.url.replace( rhash, "" ); |
592
|
|
|
|
593
|
|
|
// More options handling for requests with no content |
594
|
|
|
if ( !s.hasContent ) { |
595
|
|
|
|
596
|
|
|
// Remember the hash so we can put it back |
597
|
|
|
uncached = s.url.slice( cacheURL.length ); |
598
|
|
|
|
599
|
|
|
// If data is available, append data to url |
600
|
|
|
if ( s.data ) { |
601
|
|
|
cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; |
602
|
|
|
|
603
|
|
|
// #9682: remove data so that it's not used in an eventual retry |
604
|
|
|
delete s.data; |
605
|
|
|
} |
606
|
|
|
|
607
|
|
|
// Add or update anti-cache param if needed |
608
|
|
|
if ( s.cache === false ) { |
609
|
|
|
cacheURL = cacheURL.replace( rantiCache, "$1" ); |
610
|
|
|
uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached; |
611
|
|
|
} |
612
|
|
|
|
613
|
|
|
// Put hash and anti-cache on the URL that will be requested (gh-1732) |
614
|
|
|
s.url = cacheURL + uncached; |
615
|
|
|
|
616
|
|
|
// Change '%20' to '+' if this is encoded form body content (gh-2658) |
617
|
|
|
} else if ( s.data && s.processData && |
618
|
|
|
( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { |
619
|
|
|
s.data = s.data.replace( r20, "+" ); |
620
|
|
|
} |
621
|
|
|
|
622
|
|
|
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. |
623
|
|
|
if ( s.ifModified ) { |
624
|
|
|
if ( jQuery.lastModified[ cacheURL ] ) { |
625
|
|
|
jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); |
626
|
|
|
} |
627
|
|
|
if ( jQuery.etag[ cacheURL ] ) { |
628
|
|
|
jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); |
629
|
|
|
} |
630
|
|
|
} |
631
|
|
|
|
632
|
|
|
// Set the correct header, if data is being sent |
633
|
|
|
if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { |
634
|
|
|
jqXHR.setRequestHeader( "Content-Type", s.contentType ); |
635
|
|
|
} |
636
|
|
|
|
637
|
|
|
// Set the Accepts header for the server, depending on the dataType |
638
|
|
|
jqXHR.setRequestHeader( |
639
|
|
|
"Accept", |
640
|
|
|
s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? |
641
|
|
|
s.accepts[ s.dataTypes[ 0 ] ] + |
642
|
|
|
( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : |
643
|
|
|
s.accepts[ "*" ] |
644
|
|
|
); |
645
|
|
|
|
646
|
|
|
// Check for headers option |
647
|
|
|
for ( i in s.headers ) { |
648
|
|
|
jqXHR.setRequestHeader( i, s.headers[ i ] ); |
649
|
|
|
} |
650
|
|
|
|
651
|
|
|
// Allow custom headers/mimetypes and early abort |
652
|
|
|
if ( s.beforeSend && |
653
|
|
|
( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { |
654
|
|
|
|
655
|
|
|
// Abort if not done already and return |
656
|
|
|
return jqXHR.abort(); |
657
|
|
|
} |
658
|
|
|
|
659
|
|
|
// Aborting is no longer a cancellation |
660
|
|
|
strAbort = "abort"; |
661
|
|
|
|
662
|
|
|
// Install callbacks on deferreds |
663
|
|
|
completeDeferred.add( s.complete ); |
664
|
|
|
jqXHR.done( s.success ); |
665
|
|
|
jqXHR.fail( s.error ); |
666
|
|
|
|
667
|
|
|
// Get transport |
668
|
|
|
transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); |
669
|
|
|
|
670
|
|
|
// If no transport, we auto-abort |
671
|
|
|
if ( !transport ) { |
672
|
|
|
done( -1, "No Transport" ); |
673
|
|
|
} else { |
674
|
|
|
jqXHR.readyState = 1; |
675
|
|
|
|
676
|
|
|
// Send global event |
677
|
|
|
if ( fireGlobals ) { |
678
|
|
|
globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); |
679
|
|
|
} |
680
|
|
|
|
681
|
|
|
// If request was aborted inside ajaxSend, stop there |
682
|
|
|
if ( completed ) { |
683
|
|
|
return jqXHR; |
684
|
|
|
} |
685
|
|
|
|
686
|
|
|
// Timeout |
687
|
|
|
if ( s.async && s.timeout > 0 ) { |
688
|
|
|
timeoutTimer = window.setTimeout( function() { |
689
|
|
|
jqXHR.abort( "timeout" ); |
690
|
|
|
}, s.timeout ); |
691
|
|
|
} |
692
|
|
|
|
693
|
|
|
try { |
694
|
|
|
completed = false; |
695
|
|
|
transport.send( requestHeaders, done ); |
696
|
|
|
} catch ( e ) { |
697
|
|
|
|
698
|
|
|
// Rethrow post-completion exceptions |
699
|
|
|
if ( completed ) { |
700
|
|
|
throw e; |
701
|
|
|
} |
702
|
|
|
|
703
|
|
|
// Propagate others as results |
704
|
|
|
done( -1, e ); |
705
|
|
|
} |
706
|
|
|
} |
707
|
|
|
|
708
|
|
|
// Callback for when everything is done |
709
|
|
|
function done( status, nativeStatusText, responses, headers ) { |
710
|
|
|
var isSuccess, success, error, response, modified, |
711
|
|
|
statusText = nativeStatusText; |
712
|
|
|
|
713
|
|
|
// Ignore repeat invocations |
714
|
|
|
if ( completed ) { |
715
|
|
|
return; |
716
|
|
|
} |
717
|
|
|
|
718
|
|
|
completed = true; |
719
|
|
|
|
720
|
|
|
// Clear timeout if it exists |
721
|
|
|
if ( timeoutTimer ) { |
722
|
|
|
window.clearTimeout( timeoutTimer ); |
723
|
|
|
} |
724
|
|
|
|
725
|
|
|
// Dereference transport for early garbage collection |
726
|
|
|
// (no matter how long the jqXHR object will be used) |
727
|
|
|
transport = undefined; |
728
|
|
|
|
729
|
|
|
// Cache response headers |
730
|
|
|
responseHeadersString = headers || ""; |
731
|
|
|
|
732
|
|
|
// Set readyState |
733
|
|
|
jqXHR.readyState = status > 0 ? 4 : 0; |
734
|
|
|
|
735
|
|
|
// Determine if successful |
736
|
|
|
isSuccess = status >= 200 && status < 300 || status === 304; |
737
|
|
|
|
738
|
|
|
// Get response data |
739
|
|
|
if ( responses ) { |
740
|
|
|
response = ajaxHandleResponses( s, jqXHR, responses ); |
741
|
|
|
} |
742
|
|
|
|
743
|
|
|
// Convert no matter what (that way responseXXX fields are always set) |
744
|
|
|
response = ajaxConvert( s, response, jqXHR, isSuccess ); |
745
|
|
|
|
746
|
|
|
// If successful, handle type chaining |
747
|
|
|
if ( isSuccess ) { |
748
|
|
|
|
749
|
|
|
// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. |
750
|
|
|
if ( s.ifModified ) { |
751
|
|
|
modified = jqXHR.getResponseHeader( "Last-Modified" ); |
752
|
|
|
if ( modified ) { |
753
|
|
|
jQuery.lastModified[ cacheURL ] = modified; |
754
|
|
|
} |
755
|
|
|
modified = jqXHR.getResponseHeader( "etag" ); |
756
|
|
|
if ( modified ) { |
757
|
|
|
jQuery.etag[ cacheURL ] = modified; |
758
|
|
|
} |
759
|
|
|
} |
760
|
|
|
|
761
|
|
|
// if no content |
762
|
|
|
if ( status === 204 || s.type === "HEAD" ) { |
763
|
|
|
statusText = "nocontent"; |
764
|
|
|
|
765
|
|
|
// if not modified |
766
|
|
|
} else if ( status === 304 ) { |
767
|
|
|
statusText = "notmodified"; |
768
|
|
|
|
769
|
|
|
// If we have data, let's convert it |
770
|
|
|
} else { |
771
|
|
|
statusText = response.state; |
772
|
|
|
success = response.data; |
773
|
|
|
error = response.error; |
774
|
|
|
isSuccess = !error; |
775
|
|
|
} |
776
|
|
|
} else { |
777
|
|
|
|
778
|
|
|
// Extract error from statusText and normalize for non-aborts |
779
|
|
|
error = statusText; |
780
|
|
|
if ( status || !statusText ) { |
781
|
|
|
statusText = "error"; |
782
|
|
|
if ( status < 0 ) { |
783
|
|
|
status = 0; |
784
|
|
|
} |
785
|
|
|
} |
786
|
|
|
} |
787
|
|
|
|
788
|
|
|
// Set data for the fake xhr object |
789
|
|
|
jqXHR.status = status; |
790
|
|
|
jqXHR.statusText = ( nativeStatusText || statusText ) + ""; |
791
|
|
|
|
792
|
|
|
// Success/Error |
793
|
|
|
if ( isSuccess ) { |
794
|
|
|
deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); |
795
|
|
|
} else { |
796
|
|
|
deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); |
797
|
|
|
} |
798
|
|
|
|
799
|
|
|
// Status-dependent callbacks |
800
|
|
|
jqXHR.statusCode( statusCode ); |
801
|
|
|
statusCode = undefined; |
802
|
|
|
|
803
|
|
|
if ( fireGlobals ) { |
804
|
|
|
globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", |
805
|
|
|
[ jqXHR, s, isSuccess ? success : error ] ); |
806
|
|
|
} |
807
|
|
|
|
808
|
|
|
// Complete |
809
|
|
|
completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); |
810
|
|
|
|
811
|
|
|
if ( fireGlobals ) { |
812
|
|
|
globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); |
813
|
|
|
|
814
|
|
|
// Handle the global AJAX counter |
815
|
|
|
if ( !( --jQuery.active ) ) { |
816
|
|
|
jQuery.event.trigger( "ajaxStop" ); |
817
|
|
|
} |
818
|
|
|
} |
819
|
|
|
} |
820
|
|
|
|
821
|
|
|
return jqXHR; |
822
|
|
|
}, |
823
|
|
|
|
824
|
|
|
getJSON: function( url, data, callback ) { |
825
|
|
|
return jQuery.get( url, data, callback, "json" ); |
826
|
|
|
}, |
827
|
|
|
|
828
|
|
|
getScript: function( url, callback ) { |
829
|
|
|
return jQuery.get( url, undefined, callback, "script" ); |
830
|
|
|
} |
831
|
|
|
} ); |
832
|
|
|
|
833
|
|
|
jQuery.each( [ "get", "post" ], function( i, method ) { |
834
|
|
|
jQuery[ method ] = function( url, data, callback, type ) { |
835
|
|
|
|
836
|
|
|
// Shift arguments if data argument was omitted |
837
|
|
|
if ( jQuery.isFunction( data ) ) { |
838
|
|
|
type = type || callback; |
839
|
|
|
callback = data; |
840
|
|
|
data = undefined; |
841
|
|
|
} |
842
|
|
|
|
843
|
|
|
// The url can be an options object (which then must have .url) |
844
|
|
|
return jQuery.ajax( jQuery.extend( { |
845
|
|
|
url: url, |
846
|
|
|
type: method, |
847
|
|
|
dataType: type, |
848
|
|
|
data: data, |
849
|
|
|
success: callback |
850
|
|
|
}, jQuery.isPlainObject( url ) && url ) ); |
851
|
|
|
}; |
852
|
|
|
} ); |
853
|
|
|
|
854
|
|
|
return jQuery; |
855
|
|
|
} ); |
856
|
|
|
|