This commit is contained in:
scottjehl 2011-01-13 14:14:04 -05:00
commit 610ab137da
42 changed files with 2307 additions and 2069 deletions

View File

@ -1,4 +1,4 @@
Copyright (c) 2010 John Resig, http://jquery.com/ Copyright (c) 2011 John Resig, http://jquery.com/
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the

View File

@ -24,10 +24,9 @@ BASE_FILES = ${SRC_DIR}/core.js\
${SRC_DIR}/manipulation.js\ ${SRC_DIR}/manipulation.js\
${SRC_DIR}/css.js\ ${SRC_DIR}/css.js\
${SRC_DIR}/ajax.js\ ${SRC_DIR}/ajax.js\
${SRC_DIR}/xhr.js\ ${SRC_DIR}/ajax/jsonp.js\
${SRC_DIR}/transports/jsonp.js\ ${SRC_DIR}/ajax/script.js\
${SRC_DIR}/transports/script.js\ ${SRC_DIR}/ajax/xhr.js\
${SRC_DIR}/transports/xhr.js\
${SRC_DIR}/effects.js\ ${SRC_DIR}/effects.js\
${SRC_DIR}/offset.js\ ${SRC_DIR}/offset.js\
${SRC_DIR}/dimensions.js ${SRC_DIR}/dimensions.js
@ -79,13 +78,13 @@ init:
jquery: ${JQ} jquery: ${JQ}
jq: ${JQ} jq: ${JQ}
${JQ}: ${MODULES} ${DIST_DIR} ${JQ}: ${MODULES} | ${DIST_DIR}
@@echo "Building" ${JQ} @@echo "Building" ${JQ}
@@cat ${MODULES} | \ @@cat ${MODULES} | \
sed 's/.function..jQuery...{//' | \ sed 's/.function..jQuery...{//' | \
sed 's/}...jQuery..;//' | \ sed 's/}...jQuery..;//' | \
sed 's/Date:./&'"${DATE}"'/' | \ sed 's/@DATE/'"${DATE}"'/' | \
${VER} > ${JQ}; ${VER} > ${JQ};
${SRC_DIR}/selector.js: ${SIZZLE_DIR}/sizzle.js ${SRC_DIR}/selector.js: ${SIZZLE_DIR}/sizzle.js

View File

@ -9,7 +9,27 @@ test_dir = File.join( prefix, 'test' )
# setting DIST_DIR before calling rake # setting DIST_DIR before calling rake
dist_dir = ENV['DIST_DIR'] || File.join( prefix, 'dist' ) dist_dir = ENV['DIST_DIR'] || File.join( prefix, 'dist' )
base_files = %w{intro core support data queue attributes event selector traversing manipulation css ajax xhr transports/jsonp transports/script transports/xhr effects offset dimensions outro}.map { |js| File.join( src_dir, "#{js}.js" ) } base_files = %w{
intro
core
support
data
queue
attributes
event
selector
traversing
manipulation
css
ajax
ajax/jsonp
ajax/script
ajax/xhr
effects
offset
dimensions
outro
}.map { |js| File.join( src_dir, "#{js}.js" ) }
# Sizzle, QUnit and jQuery files/dirs # Sizzle, QUnit and jQuery files/dirs
sizzle_dir = File.join( src_dir, "sizzle" ) sizzle_dir = File.join( src_dir, "sizzle" )
@ -89,7 +109,11 @@ file jq => [dist_dir, base_files].flatten do
puts "Building jquery.js..." puts "Building jquery.js..."
File.open(jq, 'w') do |f| File.open(jq, 'w') do |f|
f.write cat(base_files).gsub(/(Date:.)/, "\\1#{date}" ).gsub(/@VERSION/, version) f.write cat(base_files).
gsub(/@DATE/, date).
gsub(/@VERSION/, version).
gsub(/.function..jQuery...\{/, '').
gsub(/\}...jQuery..;/, '')
end end
end end

View File

@ -63,10 +63,9 @@
<fileset file="src/manipulation.js" /> <fileset file="src/manipulation.js" />
<fileset file="src/css.js" /> <fileset file="src/css.js" />
<fileset file="src/ajax.js" /> <fileset file="src/ajax.js" />
<fileset file="src/xhr.js" /> <fileset file="src/ajax/jsonp.js" />
<fileset file="src/transports/jsonp.js" /> <fileset file="src/ajax/script.js" />
<fileset file="src/transports/script.js" /> <fileset file="src/ajax/xhr.js" />
<fileset file="src/transports/xhr.js" />
<fileset file="src/effects.js" /> <fileset file="src/effects.js" />
<fileset file="src/offset.js" /> <fileset file="src/offset.js" />
<fileset file="src/dimensions.js" /> <fileset file="src/dimensions.js" />
@ -77,7 +76,7 @@
<arg line="log -1 --pretty=format:%ad" /> <arg line="log -1 --pretty=format:%ad" />
</exec> </exec>
<replaceregexp match="(\(\s*function\s*\(\s*jQuery\s*\)\s*\{)|(\}\s*\)\s*\(\s*jQuery\s*\)\s*;)" flags="g" replace="" file="${JQ}" /> <replaceregexp match="(\(\s*function\s*\(\s*jQuery\s*\)\s*\{)|(\}\s*\)\s*\(\s*jQuery\s*\)\s*;)" flags="g" replace="" file="${JQ}" />
<replaceregexp match="Date: " replace="Date: ${date}" file="${JQ}" /> <replaceregexp match="@DATE" replace="${date}" file="${JQ}" />
<echo message="${JQ} built." /> <echo message="${JQ} built." />
</target> </target>

View File

@ -1,11 +1,20 @@
(function( jQuery ) { (function( jQuery ) {
var rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, var r20 = /%20/g,
rselectTextarea = /^(?:select|textarea)/i,
rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
rbracket = /\[\]$/, 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 = /\?/, rquery = /\?/,
r20 = /%20/g, rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
rselectTextarea = /^(?:select|textarea)/i,
rts = /([?&])_=[^&]*/,
rurl = /^(\w+:)?\/\/([^\/?#:]+)(?::(\d+))?/,
rCRLF = /\r?\n/g,
// Slice function
sliceFunc = Array.prototype.slice,
// Keep a copy of the old load method // Keep a copy of the old load method
_load = jQuery.fn.load; _load = jQuery.fn.load;
@ -52,26 +61,34 @@ jQuery.fn.extend({
type: type, type: type,
dataType: "html", dataType: "html",
data: params, data: params,
complete: function( res, status ) { // Complete callback (responseText is used internally)
complete: function( jXHR, status, responseText ) {
// Store the response as specified by the jXHR object
responseText = jXHR.responseText;
// If successful, inject the HTML into all the matched elements // If successful, inject the HTML into all the matched elements
if ( status === "success" || status === "notmodified" ) { if ( jXHR.isResolved() ) {
// #4825: Get the actual response in case
// a dataFilter is present in ajaxSettings
jXHR.done(function( r ) {
responseText = r;
});
// See if a selector was specified // See if a selector was specified
self.html( selector ? self.html( selector ?
// Create a dummy div to hold the results // Create a dummy div to hold the results
jQuery("<div>") jQuery("<div>")
// inject the contents of the document in, removing the scripts // inject the contents of the document in, removing the scripts
// to avoid any 'Permission Denied' errors in IE // to avoid any 'Permission Denied' errors in IE
.append(res.responseText.replace(rscript, "")) .append(responseText.replace(rscript, ""))
// Locate the specified elements // Locate the specified elements
.find(selector) : .find(selector) :
// If not, just inject the full result // If not, just inject the full result
res.responseText ); responseText );
} }
if ( callback ) { if ( callback ) {
self.each( callback, [res.responseText, status, res] ); self.each( callback, [responseText, status, jXHR] );
} }
} }
}); });
@ -99,9 +116,9 @@ jQuery.fn.extend({
null : null :
jQuery.isArray(val) ? jQuery.isArray(val) ?
jQuery.map( val, function(val, i){ jQuery.map( val, function(val, i){
return {name: elem.name, value: val}; return { name: elem.name, value: val.replace(rCRLF, "\r\n") };
}) : }) :
{name: elem.name, value: val}; { name: elem.name, value: val.replace(rCRLF, "\r\n") };
}).get(); }).get();
} }
}); });
@ -113,9 +130,8 @@ jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".sp
}; };
}); });
jQuery.extend({ jQuery.each( [ "get", "post" ], function( i, method ) {
jQuery[ method ] = function( url, data, callback, type ) {
get: function( url, data, callback, type ) {
// shift arguments if data argument was omited // shift arguments if data argument was omited
if ( jQuery.isFunction( data ) ) { if ( jQuery.isFunction( data ) ) {
type = type || callback; type = type || callback;
@ -124,13 +140,16 @@ jQuery.extend({
} }
return jQuery.ajax({ return jQuery.ajax({
type: "GET", type: method,
url: url, url: url,
data: data, data: data,
success: callback, success: callback,
dataType: type dataType: type
}); });
}, };
});
jQuery.extend({
getScript: function( url, callback ) { getScript: function( url, callback ) {
return jQuery.get(url, null, callback, "script"); return jQuery.get(url, null, callback, "script");
@ -140,25 +159,9 @@ jQuery.extend({
return jQuery.get(url, data, callback, "json"); 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 ) { ajaxSetup: function( settings ) {
jQuery.extend( jQuery.ajaxSettings, settings ); jQuery.extend( true, jQuery.ajaxSettings, settings );
return this;
}, },
ajaxSettings: { ajaxSettings: {
@ -181,11 +184,6 @@ jQuery.extend({
xhr: function() { xhr: function() {
return new window.XMLHttpRequest(); return new window.XMLHttpRequest();
}, },
xhrResponseFields: {
xml: "XML",
text: "Text",
json: "JSON"
},
accepts: { accepts: {
xml: "application/xml, text/xml", xml: "application/xml, text/xml",
@ -195,7 +193,7 @@ jQuery.extend({
"*": "*/*" "*": "*/*"
}, },
autoDataType: { contents: {
xml: /xml/, xml: /xml/,
html: /html/, html: /html/,
json: /json/ json: /json/
@ -206,85 +204,511 @@ jQuery.extend({
// 2) These are called: // 2) These are called:
// * BEFORE asking for a transport // * BEFORE asking for a transport
// * AFTER param serialization (s.data is a string if s.processData is true) // * AFTER param serialization (s.data is a string if s.processData is true)
// 3) They MUST be order agnostic // 3) key is the dataType
prefilters: [], // 4) the catchall symbol "*" can be used
// 5) execution will start with transport dataType and THEN continue down to "*" if needed
prefilters: {},
// Transports bindings // Transports bindings
// 1) key is the dataType // 1) key is the dataType
// 2) the catchall symbol "*" can be used // 2) the catchall symbol "*" can be used
// 3) selection will start with transport dataType and THEN go to "*" if needed // 3) selection will start with transport dataType and THEN go to "*" if needed
transports: { transports: {},
},
// 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");
}
},
// Check if xml has been properly parsed
"xml": function(data) {
var documentElement = data ? data.documentElement : data;
if ( ! documentElement || ! documentElement.nodeName ) {
jQuery.error("typeerror");
}
if ( documentElement.nodeName == "parsererror" ) {
jQuery.error("parsererror");
}
}
},
// List of data converters // List of data converters
// 1) key format is "source_type => destination_type" (spaces required) // 1) key format is "source_type destination_type" (a single space in-between)
// 2) the catchall symbol "*" can be used for source_type // 2) the catchall symbol "*" can be used for source_type
dataConverters: { converters: {
// Convert anything to text // Convert anything to text
"* => text": function(data) { "* text": window.String,
return "" + data;
},
// Text to html (no transformation) // Text to html (true = no transformation)
"text => html": function(data) { "text html": true,
return data;
},
// Evaluate text as a json expression // Evaluate text as a json expression
"text => json": jQuery.parseJSON, "text json": jQuery.parseJSON,
// Parse text as xml // Parse text as xml
"text => xml": function(data) { "text xml": jQuery.parseXML
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);
}
return xml;
}
} }
}, },
// Main method // Main method
ajax: function( url , s ) { // (s is used internally)
ajax: function( url , options , s ) {
// Handle varargs
if ( arguments.length === 1 ) { if ( arguments.length === 1 ) {
s = url; options = url;
url = s ? s.url : undefined; url = options ? options.url : undefined;
} }
return jQuery.xhr().open( s ? s.type : undefined , url ).send( undefined , s ); // 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(),
// Status-dependent callbacks
statusCode = s.statusCode || {},
// Headers (they are sent all at once)
requestHeaders = {},
// Response headers
responseHeadersString,
responseHeaders,
// transport
transport,
// timeout handle
timeoutTimer,
// Cross-domain detection vars
loc = document.location,
parts,
// 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;
}
};
// 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;
// If successful, handle type chaining
if ( status >= 200 && status < 300 || status === 304 ) {
// 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 not modified
if ( status === 304 ) {
// Set the statusText accordingly
statusText = "notmodified";
// Mark as a success
isSuccess = 1;
// If we have data
} else {
// Set the statusText accordingly
statusText = "success";
// 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 dataType
current,
// Previous dataType
prev,
// Conversion function
conv,
// Conversion functions (when text is used in-between)
conv1,
conv2,
// Local references to dataTypes & converters
dataTypes = s.dataTypes,
converters = s.converters,
// DataType to responseXXX field mapping
responses = {
"xml": "XML",
"text": "Text"
};
// For each dataType in the chain
for( i = 0 ; i < dataTypes.length ; i++ ) {
current = dataTypes[ i ];
// If a responseXXX field for this dataType exists
// and if it hasn't been set yet
if ( responses[ current ] ) {
// Set it
jXHR[ "response" + responses[ current ] ] = response;
// Mark it as set
responses[ current ] = 0;
}
// If this is not the first element
if ( i ) {
// Get the dataType to convert from
prev = dataTypes[ i - 1 ];
// If no catch-all and dataTypes are actually different
if ( prev !== "*" && current !== "*" && prev !== current ) {
// Get the converter
conv = converters[ prev + " " + current ] ||
converters[ "* " + current ];
conv1 = conv2 = 0;
// If there is no direct converter and none of the dataTypes is text
if ( ! conv && prev !== "text" && current !== "text" ) {
// Try with text in-between
conv1 = converters[ prev + " text" ] || converters[ "* text" ];
conv2 = converters[ "text " + current ];
// Revert back to a single converter
// if one of the converter is an equivalence
if ( conv1 === true ) {
conv = conv2;
} else if ( conv2 === true ) {
conv = conv1;
}
}
// If we found no converter, dispatch an error
if ( ! ( conv || conv1 && conv2 ) ) {
throw conversion;
}
// If found converter is not an equivalence
if ( conv !== true ) {
// Convert with 1 or 2 converters accordingly
response = conv ? conv( response ) : conv2( conv1( response ) );
}
}
// If it is the first element of the chain
// and we have a dataFilter
} else if ( s.dataFilter ) {
// Apply the dataFilter
response = s.dataFilter( response , current );
// Get dataTypes again in case the filter changed them
dataTypes = s.dataTypes;
}
}
// End of loop
// We have a real success
success = response;
isSuccess = 1;
// If an exception was thrown
} catch(e) {
// We have a parsererror
statusText = "parsererror";
error = "" + e;
}
}
// if not success, mark it as an error
} else {
error = statusText = statusText || "error";
// Set responseText if needed
if ( response ) {
jXHR.responseText = response;
}
}
// Set data for the fake xhr object
jXHR.status = status;
jXHR.statusText = statusText;
// Success/Error
if ( isSuccess ) {
deferred.fire( callbackContext , [ success , statusText , jXHR ] );
} else {
deferred.fireReject( callbackContext , [ jXHR , statusText , error ] );
}
// Status-dependent callbacks
jXHR.statusCode( statusCode );
if ( s.global ) {
globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ) ,
[ jXHR , s , isSuccess ? success : error ] );
}
// 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" );
}
}
}
// Attach deferreds
deferred.promise( jXHR );
jXHR.success = jXHR.done;
jXHR.error = jXHR.fail;
jXHR.complete = completeDeferred.done;
// Status-dependent callbacks
jXHR.statusCode = function( map ) {
if ( map ) {
var resolved = jXHR.isResolved(),
tmp;
if ( resolved || jXHR.isRejected() ) {
tmp = map[ jXHR.status ];
if ( tmp ) {
if ( map === statusCode ) {
delete statusCode[ jXHR.status ];
}
jXHR[ resolved ? "done" : "fail" ]( tmp );
}
} else {
for( tmp in map ) {
statusCode[ tmp ] = [ statusCode[ tmp ] , map[ tmp ] ];
}
}
}
return this;
};
// Remove hash character (#7531: and string promotion)
s.url = ( "" + s.url ).replace( rhash , "" );
// 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
if ( ! s.crossDomain ) {
parts = rurl.exec( s.url.toLowerCase() );
s.crossDomain = !!(
parts &&
( parts[ 1 ] && parts[ 1 ] != loc.protocol ||
parts[ 2 ] != loc.hostname ||
( parts[ 3 ] || 80 ) != ( loc.port || 80 ) )
);
}
// Convert data if not already a string
if ( s.data && s.processData && typeof s.data != "string" ) {
s.data = jQuery.param( s.data , s.traditional );
}
// Get transport
transport = jQuery.ajaxPrefilter( s , options ).ajaxTransport( s );
// Watch for a new set of requests
if ( s.global && jQuery.active++ === 0 ) {
jQuery.event.trigger( "ajaxStart" );
}
// 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 && s.contentType !== false || 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 // Serialize an array of form elements or a set of
@ -343,7 +767,9 @@ function buildParams( prefix, obj, traditional, add ) {
}); });
} else if ( !traditional && obj != null && typeof obj === "object" ) { } else if ( !traditional && obj != null && typeof obj === "object" ) {
if ( jQuery.isEmptyObject( obj ) ) { // If we see an array here, it is empty and should be treated as an empty
// object
if ( jQuery.isArray( obj ) || jQuery.isEmptyObject( obj ) ) {
add( prefix, "" ); add( prefix, "" );
// Serialize object item. // Serialize object item.
@ -372,6 +798,172 @@ jQuery.extend({
}); });
//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 : 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;
}
// Install prefilter & transport methods
jQuery.each( [ "Prefilter" , "Transport" ] , function( _ , name ) {
_ = name.toLowerCase() + "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 contents = s.contents,
type,
regexp,
dataTypes = s.dataTypes,
transportDataType = dataTypes[0],
response;
// Auto (xml, json, script or text determined given headers)
if ( transportDataType === "*" ) {
for ( type in contents ) {
if ( ( regexp = contents[ 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 converters
if ( transportDataType !== "text" ) {
dataTypes.unshift( "text" );
}
}
return response;
}
/* /*
* Create the request object; Microsoft failed to properly * Create the request object; Microsoft failed to properly
* implement the XMLHttpRequest in IE7 (can't request local files), * implement the XMLHttpRequest in IE7 (can't request local files),

83
src/ajax/jsonp.js Normal file
View File

@ -0,0 +1,83 @@
(function( jQuery ) {
var jsc = jQuery.now(),
jsre = /(\=)(?:\?|%3F)(&|$)|()(?:\?\?|%3F%3F)()/i,
rquery_jsonp = /\?/;
// Default jsonp settings
jQuery.ajaxSetup({
jsonp: "callback",
jsonpCallback: function() {
return "jsonp" + jsc++;
}
// Normalize jsonp queries
// 1) put callback parameter in url or data
// 2) sneakily ensure transportDataType is always jsonp for jsonp requests
}).ajaxPrefilter("json jsonp", function(s, originalSettings) {
if ( s.dataTypes[ 0 ] === "jsonp" ||
originalSettings.jsonp ||
originalSettings.jsonpCallback ||
jsre.test(s.url) ||
typeof(s.data) === "string" && jsre.test(s.data) ) {
var jsonpCallback = s.jsonpCallback =
jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
url = s.url.replace(jsre, "$1" + jsonpCallback + "$2"),
data = s.url === url && typeof(s.data) === "string" ? s.data.replace(jsre, "$1" + jsonpCallback + "$2") : s.data;
if ( url === s.url && data === s.data ) {
url += (rquery_jsonp.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
}
s.url = url;
s.data = data;
s.dataTypes[ 0 ] = "jsonp";
}
// Bind transport to jsonp dataType
}).ajaxTransport("jsonp", function(s) {
// Put callback in place
var responseContainer,
jsonpCallback = s.jsonpCallback,
previous = window[ jsonpCallback ];
window [ jsonpCallback ] = function( response ) {
responseContainer = [response];
};
s.complete = [function() {
// Set callback back to previous value
window[ jsonpCallback ] = previous;
// Call if it was a function and we have a response
if ( previous) {
if ( responseContainer && jQuery.isFunction ( previous ) ) {
window[ jsonpCallback ] ( responseContainer[0] );
}
} else {
// else, more memory leak avoidance
try{ delete window[ jsonpCallback ]; } catch(e){}
}
}, s.complete ];
// Sneakily ensure this will be handled as json
s.dataTypes[ 0 ] = "json";
// Use data converter to retrieve json after script execution
s.converters["script json"] = function() {
if ( ! responseContainer ) {
jQuery.error( jsonpCallback + " was not called" );
}
return responseContainer[ 0 ];
};
// Delegate to script transport
return "script";
});
})( jQuery );

View File

@ -1,23 +1,22 @@
(function( jQuery ) { (function( jQuery ) {
// Install text to script executor // Install script dataType
jQuery.extend( true, jQuery.ajaxSettings , { jQuery.ajaxSetup({
accepts: { accepts: {
script: "text/javascript, application/javascript" script: "text/javascript, application/javascript"
}, },
autoDataType: { contents: {
script: /javascript/ script: /javascript/
}, },
dataConverters: { converters: {
"text => script": jQuery.globalEval "text script": jQuery.globalEval
} }
} );
// Bind script tag hack transport // Bind script tag hack transport
jQuery.xhr.bindTransport("script", function(s) { }).ajaxTransport("script", function(s) {
// Handle cache special case // Handle cache special case
if ( s.cache === undefined ) { if ( s.cache === undefined ) {
@ -47,10 +46,9 @@ jQuery.xhr.bindTransport("script", function(s) {
script.src = s.url; script.src = s.url;
// Attach handlers for all browsers // Attach handlers for all browsers
script.onload = script.onreadystatechange = function(statusText) { script.onload = script.onreadystatechange = function( _ , isAbort ) {
if ( (!script.readyState || if ( ! script.readyState || /loaded|complete/.test( script.readyState ) ) {
script.readyState === "loaded" || script.readyState === "complete") ) {
// Handle memory leak in IE // Handle memory leak in IE
script.onload = script.onreadystatechange = null; script.onload = script.onreadystatechange = null;
@ -60,10 +58,13 @@ jQuery.xhr.bindTransport("script", function(s) {
head.removeChild( script ); head.removeChild( script );
} }
script = undefined; // Dereference the script
script = 0;
// Callback & dereference // Callback if not abort
callback(statusText ? 0 : 200, statusText || "success"); if ( ! isAbort ) {
callback( 200, "success" );
}
} }
}; };
// Use insertBefore instead of appendChild to circumvent an IE6 bug. // Use insertBefore instead of appendChild to circumvent an IE6 bug.
@ -71,9 +72,9 @@ jQuery.xhr.bindTransport("script", function(s) {
head.insertBefore( script, head.firstChild ); head.insertBefore( script, head.firstChild );
}, },
abort: function(statusText) { abort: function() {
if ( script ) { if ( script ) {
script.onload(statusText); script.onload(0,1);
} }
} }
}; };

View File

@ -1,16 +1,16 @@
(function( jQuery ) { (function( jQuery ) {
var // Next fake timer id var // Next active xhr id
xhrPollingId = jQuery.now(), xhrId = jQuery.now(),
// Callbacks hashtable // active xhrs
xhrs = {}, xhrs = {},
// #5280: see end of file // #5280: see below
xhrUnloadAbortMarker = []; xhrUnloadAbortInstalled;
jQuery.xhr.bindTransport( function( s , determineDataType ) { jQuery.ajaxTransport( function( s , determineDataType ) {
// Cross domain only allowed if supported through XMLHttpRequest // Cross domain only allowed if supported through XMLHttpRequest
if ( ! s.crossDomain || jQuery.support.cors ) { if ( ! s.crossDomain || jQuery.support.cors ) {
@ -21,6 +21,24 @@ jQuery.xhr.bindTransport( function( s , determineDataType ) {
send: function(headers, complete) { send: function(headers, complete) {
// #5280: we need to abort on unload or IE will keep connections alive
if ( ! xhrUnloadAbortInstalled ) {
xhrUnloadAbortInstalled = 1;
jQuery(window).bind( "unload" , function() {
// Abort all pending requests
jQuery.each(xhrs, function(_, xhr) {
if ( xhr.onreadystatechange ) {
xhr.onreadystatechange( 1 );
}
});
});
}
// Get a new xhr
var xhr = s.xhr(), var xhr = s.xhr(),
handle; handle;
@ -35,7 +53,7 @@ jQuery.xhr.bindTransport( function( s , determineDataType ) {
// Requested-With header // Requested-With header
// Not set for crossDomain requests with no content // Not set for crossDomain requests with no content
// (see why at http://trac.dojotoolkit.org/ticket/9486) // (see why at http://trac.dojotoolkit.org/ticket/9486)
// Won't change header if already provided in beforeSend // Won't change header if already provided
if ( ! ( s.crossDomain && ! s.hasContent ) && ! headers["x-requested-with"] ) { if ( ! ( s.crossDomain && ! s.hasContent ) && ! headers["x-requested-with"] ) {
headers["x-requested-with"] = "XMLHttpRequest"; headers["x-requested-with"] = "XMLHttpRequest";
} }
@ -58,40 +76,35 @@ jQuery.xhr.bindTransport( function( s , determineDataType ) {
} }
// Listener // Listener
callback = function ( abortStatusText ) { callback = function( _ , isAbort ) {
// Was never called and is aborted or complete // Was never called and is aborted or complete
if ( callback && ( abortStatusText || xhr.readyState === 4 ) ) { if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
// Do not listen anymore // Only called once
callback = 0;
// Do not keep as active anymore
// and store back into pool
if (handle) { if (handle) {
xhr.onreadystatechange = jQuery.noop; xhr.onreadystatechange = jQuery.noop;
delete xhrs[ handle ]; delete xhrs[ handle ];
handle = undefined;
} }
callback = 0; // If it's an abort
if ( isAbort ) {
// Get info
var status, statusText, response, responseHeaders;
if ( abortStatusText ) {
// Abort it manually if needed
if ( xhr.readyState !== 4 ) { if ( xhr.readyState !== 4 ) {
xhr.abort(); xhr.abort();
} }
// Stop here if unloadAbort
if ( abortStatusText === xhrUnloadAbortMarker ) {
return;
}
status = 0;
statusText = abortStatusText;
} else { } else {
status = xhr.status; // Get info
var status = xhr.status,
statusText,
response,
responseHeaders = xhr.getAllResponseHeaders();
try { // Firefox throws an exception when accessing statusText for faulty cross-domain requests try { // Firefox throws an exception when accessing statusText for faulty cross-domain requests
@ -103,8 +116,6 @@ jQuery.xhr.bindTransport( function( s , determineDataType ) {
} }
responseHeaders = xhr.getAllResponseHeaders();
// Filter status for non standard behaviours // Filter status for non standard behaviours
// (so many they seem to be the actual "standard") // (so many they seem to be the actual "standard")
status = status =
@ -130,19 +141,17 @@ jQuery.xhr.bindTransport( function( s , determineDataType ) {
status status
); );
// Guess response if needed & update datatype accordingly // Guess response & update dataType accordingly
if ( status >= 200 && status < 300 ) { response =
response = determineDataType(
determineDataType( s,
s, xhr.getResponseHeader("content-type"),
xhr.getResponseHeader("content-type"), xhr.responseText,
xhr.responseText, xhr.responseXML );
xhr.responseXML );
}
}
// Call complete // Call complete
complete(status,statusText,response,responseHeaders); complete(status,statusText,response,responseHeaders);
}
} }
}; };
@ -155,37 +164,20 @@ jQuery.xhr.bindTransport( function( s , determineDataType ) {
} else { } else {
// Listener is externalized to handle abort on unload // Add to list of active xhrs
handle = xhrPollingId++; handle = xhrId++;
xhrs[ handle ] = xhr; xhrs[ handle ] = xhr;
xhr.onreadystatechange = function() { xhr.onreadystatechange = callback;
callback();
};
} }
}, },
abort: function(statusText) { abort: function() {
if ( callback ) { if ( callback ) {
callback(statusText); callback(0,1);
} }
} }
}; };
} }
}); });
// #5280: we need to abort on unload or IE will keep connections alive
jQuery(window).bind( "unload" , function() {
// Abort all pending requests
jQuery.each(xhrs, function(_, xhr) {
if ( xhr.onreadystatechange ) {
xhr.onreadystatechange( xhrUnloadAbortMarker );
}
});
// Resest polling structure to be safe
xhrs = {};
});
})( jQuery ); })( jQuery );

View File

@ -60,8 +60,8 @@ var jQuery = function( selector, context ) {
// Has the ready events already been bound? // Has the ready events already been bound?
readyBound = false, readyBound = false,
// The functions to execute on DOM ready // The deferred used on DOM ready
readyList = [], readyList,
// The ready event handler // The ready event handler
DOMContentLoaded, DOMContentLoaded,
@ -129,7 +129,7 @@ jQuery.fn = jQuery.prototype = {
} else { } else {
ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes; selector = (ret.cacheable ? jQuery(ret.fragment).clone()[0] : ret.fragment).childNodes;
} }
return jQuery.merge( this, selector ); return jQuery.merge( this, selector );
@ -253,22 +253,12 @@ jQuery.fn = jQuery.prototype = {
return jQuery.each( this, callback, args ); return jQuery.each( this, callback, args );
}, },
ready: function( fn ) { ready: function() {
// Attach the listeners // Attach the listeners
jQuery.bindReady(); jQuery.bindReady();
// If the DOM is already ready // Change ready & apply
if ( jQuery.isReady ) { return ( jQuery.fn.ready = readyList.done ).apply( this , arguments );
// 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;
}, },
eq: function( i ) { eq: function( i ) {
@ -415,23 +405,11 @@ jQuery.extend({
} }
// If there are functions bound, to execute // If there are functions bound, to execute
if ( readyList ) { readyList.fire( document , [ jQuery ] );
// Execute all of them
var fn,
i = 0,
ready = readyList;
// Reset the list of functions // Trigger any bound ready events
readyList = null; if ( jQuery.fn.trigger ) {
jQuery( document ).trigger( "ready" ).unbind( "ready" );
while ( (fn = ready[ i++ ]) ) {
fn.call( document, jQuery );
}
// Trigger any bound ready events
if ( jQuery.fn.trigger ) {
jQuery( document ).trigger( "ready" ).unbind( "ready" );
}
} }
} }
}, },
@ -566,6 +544,28 @@ jQuery.extend({
} }
}, },
// 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() {}, noop: function() {},
// Evalulates a script in a global context // Evalulates a script in a global context
@ -801,6 +801,151 @@ jQuery.extend({
return (new Date()).getTime(); 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 = {
// done( f1, f2, ...)
done: 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.done.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( jQuery.isFunction( this.promise ) ? this.promise() : this , arguments );
return this;
},
// Has this deferred been resolved?
isResolved: function() {
return !!( firing || fired );
},
// Cancel
cancel: function() {
cancelled = 1;
callbacks = [];
return this;
}
};
return deferred;
},
// Full fledged deferred (two callbacks list)
// Typical success/error system
Deferred: function( func ) {
var deferred = jQuery._Deferred(),
failDeferred = jQuery._Deferred();
// Add errorDeferred methods and redefine cancel
jQuery.extend( deferred , {
then: function( doneCallbacks , failCallbacks ) {
deferred.done( doneCallbacks ).fail( failCallbacks );
return this;
},
fail: failDeferred.done,
fireReject: failDeferred.fire,
reject: failDeferred.resolve,
isRejected: failDeferred.isResolved,
// Get a promise for this deferred
// If obj is provided, the promise aspect is added to the object
promise: function( obj ) {
obj = obj || {};
jQuery.each( "then done fail isResolved isRejected".split( " " ) , function( _ , method ) {
obj[ method ] = deferred[ method ];
});
obj.promise = function() {
return obj;
};
return obj;
}
} );
// Make sure only one callback list will be used
deferred.then( failDeferred.cancel , deferred.cancel );
// Unexpose cancel
delete deferred.cancel;
// Call given func if any
if ( func ) {
func.call( deferred , deferred );
}
return deferred;
},
// Deferred helper
when: function( object ) {
object = object && jQuery.isFunction( object.promise ) ?
object :
jQuery.Deferred().resolve( object );
return object.promise();
},
// Use of jQuery.browser is frowned upon. // Use of jQuery.browser is frowned upon.
// More details: http://docs.jquery.com/Utilities/jQuery.browser // More details: http://docs.jquery.com/Utilities/jQuery.browser
uaMatch: function( ua ) { uaMatch: function( ua ) {
@ -818,6 +963,9 @@ jQuery.extend({
browser: {} browser: {}
}); });
// Create readyList deferred
readyList = jQuery._Deferred();
// Populate the class2type map // Populate the class2type map
jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
class2type[ "[object " + name + "]" ] = name.toLowerCase(); class2type[ "[object " + name + "]" ] = name.toLowerCase();

View File

@ -12,9 +12,6 @@ var ralpha = /alpha\([^)]*\)/i,
cssHeight = [ "Top", "Bottom" ], cssHeight = [ "Top", "Bottom" ],
curCSS, curCSS,
getComputedStyle,
currentStyle,
fcamelCase = function( all, letter ) { fcamelCase = function( all, letter ) {
return letter.toUpperCase(); return letter.toUpperCase();
}; };
@ -172,10 +169,6 @@ jQuery.each(["height", "width"], function( i, name ) {
if ( val <= 0 ) { if ( val <= 0 ) {
val = curCSS( elem, name, name ); val = curCSS( elem, name, name );
if ( val === "0px" && currentStyle ) {
val = currentStyle( elem, name, name );
}
if ( val != null ) { if ( val != null ) {
// Should return "auto" instead of 0, use 0 for // Should return "auto" instead of 0, use 0 for
// temporary backwards-compat // temporary backwards-compat
@ -241,7 +234,7 @@ if ( !jQuery.support.opacity ) {
} }
if ( document.defaultView && document.defaultView.getComputedStyle ) { if ( document.defaultView && document.defaultView.getComputedStyle ) {
getComputedStyle = function( elem, newName, name ) { curCSS = function( elem, newName, name ) {
var ret, defaultView, computedStyle; var ret, defaultView, computedStyle;
name = name.replace( rupper, "-$1" ).toLowerCase(); name = name.replace( rupper, "-$1" ).toLowerCase();
@ -259,10 +252,8 @@ if ( document.defaultView && document.defaultView.getComputedStyle ) {
return ret; return ret;
}; };
} } else if ( document.documentElement.currentStyle ) {
curCSS = function( elem, name ) {
if ( document.documentElement.currentStyle ) {
currentStyle = function( elem, name ) {
var left, rsLeft, var left, rsLeft,
ret = elem.currentStyle && elem.currentStyle[ name ], ret = elem.currentStyle && elem.currentStyle[ name ],
style = elem.style; style = elem.style;
@ -291,8 +282,6 @@ if ( document.documentElement.currentStyle ) {
}; };
} }
curCSS = getComputedStyle || currentStyle;
function getWH( elem, name, extra ) { function getWH( elem, name, extra ) {
var which = name === "width" ? cssWidth : cssHeight, var which = name === "width" ? cssWidth : cssHeight,
val = name === "width" ? elem.offsetWidth : elem.offsetHeight; val = name === "width" ? elem.offsetWidth : elem.offsetHeight;

View File

@ -10,7 +10,8 @@ jQuery.extend({
uuid: 0, uuid: 0,
// Unique for each copy of jQuery on the page // Unique for each copy of jQuery on the page
expando: "jQuery" + jQuery.now(), // Non-digits removed to match rinlinejQuery
expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
// The following elements throw uncatchable exceptions if you // The following elements throw uncatchable exceptions if you
// attempt to add expando properties to them. // attempt to add expando properties to them.
@ -21,6 +22,14 @@ jQuery.extend({
"applet": true "applet": true
}, },
hasData: function( elem ) {
if ( elem.nodeType ) {
elem = jQuery.cache[ elem[jQuery.expando] ];
}
return !!elem && !jQuery.isEmptyObject(elem);
},
data: function( elem, name, data ) { data: function( elem, name, data ) {
if ( !jQuery.acceptData( elem ) ) { if ( !jQuery.acceptData( elem ) ) {
return; return;

2
src/effects.js vendored
View File

@ -337,7 +337,7 @@ jQuery.fx.prototype = {
} }
var r = parseFloat( jQuery.css( this.elem, this.prop ) ); var r = parseFloat( jQuery.css( this.elem, this.prop ) );
return r && r > -10000 ? r : 0; return r || 0;
}, },
// Start an animation from one number to another // Start an animation from one number to another

View File

@ -600,6 +600,12 @@ jQuery.Event = function( src ) {
if ( src && src.type ) { if ( src && src.type ) {
this.originalEvent = src; this.originalEvent = src;
this.type = src.type; this.type = src.type;
// Events bubbling up the document may have been marked as prevented
// by a handler lower down the tree; reflect the correct value.
this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||
src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;
// Event type // Event type
} else { } else {
this.type = src; this.type = src;
@ -1177,21 +1183,4 @@ jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblcl
} }
}); });
// Prevent memory leaks in IE
// Window isn't included so as not to unbind existing unload events
// More info:
// - http://isaacschlueter.com/2006/10/msie-memory-leaks/
if ( window.attachEvent && !window.addEventListener ) {
jQuery(window).bind("unload", function() {
for ( var id in jQuery.cache ) {
if ( jQuery.cache[ id ].handle ) {
// Try/Catch is to handle iframes being unloaded, see #4280
try {
jQuery.event.remove( jQuery.cache[ id ].handle.elem );
} catch(e) {}
}
}
});
}
})( jQuery ); })( jQuery );

View File

@ -11,7 +11,7 @@
* Copyright 2010, The Dojo Foundation * Copyright 2010, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses. * Released under the MIT, BSD, and GPL Licenses.
* *
* Date: * Date: @DATE
*/ */
(function( window, undefined ) { (function( window, undefined ) {

View File

@ -370,14 +370,18 @@ function root( elem, cur ) {
} }
function cloneCopyEvent(orig, ret) { function cloneCopyEvent(orig, ret) {
var i = 0; ret.each(function (nodeIndex) {
if ( this.nodeType !== 1 || !jQuery.hasData(orig[nodeIndex]) ) {
ret.each(function() {
if ( this.nodeType !== 1 || this.nodeName !== (orig[i] && orig[i].nodeName) ) {
return; return;
} }
var oldData = jQuery.data( orig[i++] ), // XXX remove for 1.5 RC or merge back in if there is actually a reason for this check that has been
// unexposed by unit tests
if ( this.nodeName !== (orig[nodeIndex] && orig[nodeIndex].nodeName) ) {
throw "Cloned data mismatch";
}
var oldData = jQuery.data( orig[nodeIndex] ),
curData = jQuery.data( this, oldData ), curData = jQuery.data( this, oldData ),
events = oldData && oldData.events; events = oldData && oldData.events;
@ -386,8 +390,8 @@ function cloneCopyEvent(orig, ret) {
curData.events = {}; curData.events = {};
for ( var type in events ) { for ( var type in events ) {
for ( var handler in events[ type ] ) { for ( var i = 0, l = events[ type ].length; i < l; i++ ) {
jQuery.event.add( this, type, events[ type ][ handler ], events[ type ][ handler ].data ); jQuery.event.add( this, type, events[ type ][ i ], events[ type ][ i ].data );
} }
} }
} }
@ -416,15 +420,29 @@ function cloneFixAttributes(src, dest) {
if ( nodeName === "object" ) { if ( nodeName === "object" ) {
dest.outerHTML = src.outerHTML; dest.outerHTML = src.outerHTML;
// IE6-8 fails to persist the checked state of a cloned checkbox } else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
// or radio button // IE6-8 fails to persist the checked state of a cloned checkbox
} else if ( nodeName === "input" && src.checked ) { // or radio button. Worse, IE6-7 fail to give the cloned element
dest.defaultChecked = dest.checked = src.checked; // a checked appearance if the defaultChecked value isn't also set
if ( src.checked ) {
dest.defaultChecked = dest.checked = src.checked;
}
// IE6-7 get confused and end up setting the value of a cloned
// checkbox/radio button to an empty string instead of "on"
if ( dest.value !== src.value ) {
dest.value = src.value;
}
// IE6-8 fails to return the selected option to the default selected // IE6-8 fails to return the selected option to the default selected
// state when cloning options // state when cloning options
} else if ( nodeName === "option" ) { } else if ( nodeName === "option" ) {
dest.selected = src.defaultSelected; dest.selected = src.defaultSelected;
// IE6-8 fails to set the defaultValue to the correct value when
// cloning other types of input fields
} else if ( nodeName === "input" || nodeName === "textarea" ) {
dest.defaultValue = src.defaultValue;
} }
// Event data gets referenced instead of copied if the expando // Event data gets referenced instead of copied if the expando
@ -436,12 +454,12 @@ jQuery.buildFragment = function( args, nodes, scripts ) {
var fragment, cacheable, cacheresults, var fragment, cacheable, cacheresults,
doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document); doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
// Only cache "small" (1/2 KB) strings that are associated with the main document // Only cache "small" (1/2 KB) HTML strings that are associated with the main document
// Cloning options loses the selected state, so don't cache them // Cloning options loses the selected state, so don't cache them
// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document && if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document &&
!rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) { args[0].charAt(0) === "<" && !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
cacheable = true; cacheable = true;
cacheresults = jQuery.fragments[ args[0] ]; cacheresults = jQuery.fragments[ args[0] ];
@ -613,6 +631,11 @@ jQuery.extend({
jQuery.removeEvent( elem, type, data.handle ); jQuery.removeEvent( elem, type, data.handle );
} }
} }
// Null the DOM reference to avoid IE6/7/8 leak (#7054)
if ( data.handle ) {
data.handle.elem = null;
}
} }
if ( deleteExpando ) { if ( deleteExpando ) {

View File

@ -147,7 +147,7 @@
jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2; jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2;
} }
div.innerHTML = "<table><tr><td style='padding:0;display:none'></td><td>t</td></tr></table>"; div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
var tds = div.getElementsByTagName("td"); var tds = div.getElementsByTagName("td");
// Check if table cells still have offsetWidth/Height when they are set // Check if table cells still have offsetWidth/Height when they are set

View File

@ -1,89 +0,0 @@
(function( jQuery ) {
var jsc = jQuery.now(),
jsre = /\=\?(&|$)/,
rquery_jsonp = /\?/;
// Default jsonp callback name
jQuery.ajaxSettings.jsonpCallback = function() {
return "jsonp" + jsc++;
};
// Normalize jsonp queries
// 1) put callback parameter in url or data
// 2) ensure transportDataType is json
// 3) ensure options jsonp is always provided so that jsonp requests are always
// json request with the jsonp option set
jQuery.xhr.prefilter( function(s) {
var transportDataType = s.dataTypes[0];
if ( s.jsonp ||
transportDataType === "jsonp" ||
transportDataType === "json" && ( jsre.test(s.url) || typeof(s.data) === "string" && jsre.test(s.data) ) ) {
var jsonp = s.jsonp = s.jsonp || "callback",
jsonpCallback = s.jsonpCallback =
jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
url = s.url.replace(jsre, "=" + jsonpCallback + "$1"),
data = s.url == url && typeof(s.data) === "string" ? s.data.replace(jsre, "=" + jsonpCallback + "$1") : s.data;
if ( url == s.url && data == s.data ) {
url = url += (rquery_jsonp.test( url ) ? "&" : "?") + jsonp + "=" + jsonpCallback;
}
s.url = url;
s.data = data;
s.dataTypes[0] = "json";
}
});
// Bind transport to json dataType
jQuery.xhr.bindTransport("json", function(s) {
if ( s.jsonp ) {
// Put callback in place
var responseContainer,
jsonpCallback = s.jsonpCallback,
previous = window[ jsonpCallback ];
window [ jsonpCallback ] = function( response ) {
responseContainer = [response];
};
s.complete = [function() {
// Set callback back to previous value
window[ jsonpCallback ] = previous;
// Call if it was a function and we have a response
if ( previous) {
if ( responseContainer && jQuery.isFunction ( previous ) ) {
window[ jsonpCallback ] ( responseContainer[0] );
}
} else {
// else, more memory leak avoidance
try{ delete window[ jsonpCallback ]; } catch(e){}
}
}, s.complete ];
// Use data converter to retrieve json after script execution
s.dataConverters["script => json"] = function() {
if ( ! responseContainer ) {
jQuery.error("Callback '" + jsonpCallback + "' was not called");
}
return responseContainer[ 0 ];
};
// Delegate to script transport
return "script";
}
});
})( jQuery );

View File

@ -1,909 +0,0 @@
(function( jQuery ) {
var rquery_xhr = /\?/,
rhash = /#.*$/,
rheaders = /^(.*?):\s*(.*?)\r?$/mg, // IE leaves an \r character at EOL
rnoContent = /^(?:GET|HEAD)$/,
rts = /([?&])_=[^&]*/,
rurl = /^(\w+:)?\/\/([^\/?#]+)/,
sliceFunc = Array.prototype.slice,
isFunction = jQuery.isFunction;
// Creates a jQuery xhr object
jQuery.xhr = function( _native ) {
if ( _native ) {
return jQuery.ajaxSettings.xhr();
}
function reset(force) {
// We only need to reset if we went through the init phase
// (with the exception of object creation)
if ( force || internal ) {
// Reset callbacks lists
callbacksLists = {
success: createCBList(),
error: createCBList(),
complete: createCBList()
};
// Reset private variables
requestHeaders = {};
responseHeadersString = responseHeaders = internal = done = timeoutTimer = s = undefined;
// Reset state
xhr.readyState = 0;
sendFlag = 0;
// Remove responseX fields
for ( var name in xhr ) {
if ( /^response/.test(name) ) {
delete xhr[name];
}
}
}
}
function init() {
var // Options extraction
// Remove hash character (#7531: first for string promotion)
url = s.url = ( "" + s.url ).replace( rhash , "" ),
// Uppercase the type
type = s.type = s.type.toUpperCase(),
// Determine if request has content
hasContent = s.hasContent = ! rnoContent.test( type ),
// Extract dataTypes list
dataType = s.dataType,
dataTypes = s.dataTypes = dataType ? jQuery.trim(dataType).toLowerCase().split(/\s+/) : ["*"],
// Determine if a cross-domain request is in order
parts = rurl.exec( url.toLowerCase() ),
loc = location,
crossDomain = s.crossDomain = !!( parts && ( parts[1] && parts[1] != loc.protocol || parts[2] != loc.host ) ),
// Get other options locally
data = s.data,
originalContentType = s.contentType,
prefilters = s.prefilters,
accepts = s.accepts,
headers = s.headers,
// Other Variables
transportDataType,
i;
// Convert data if not already a string
if ( data && s.processData && typeof data != "string" ) {
data = s.data = jQuery.param( data , s.traditional );
}
// Apply option prefilters
for (i in prefilters) {
prefilters[i](s);
}
// Get internal
internal = selectTransport( s );
// Re-actualize url & data
url = s.url;
data = s.data;
// If internal was found
if ( internal ) {
// Get transportDataType
transportDataType = dataTypes[0];
// More options handling for requests with no content
if ( ! hasContent ) {
// If data is available, append data to url
if ( data ) {
url += (rquery_xhr.test(url) ? "&" : "?") + data;
}
// Add anti-cache in url if needed
if ( s.cache === false ) {
var ts = jQuery.now(),
// try replacing _= if it is there
ret = url.replace(rts, "$1_=" + ts );
// if nothing was replaced, add timestamp to the end
url = ret + ((ret == url) ? (rquery_xhr.test(url) ? "&" : "?") + "_=" + ts : "");
}
s.url = url;
}
// Set the correct header, if data is being sent
if ( ( data && hasContent ) || originalContentType ) {
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[url] ) {
requestHeaders["if-modified-since"] = jQuery_lastModified[url];
}
if ( jQuery_etag[url] ) {
requestHeaders["if-none-match"] = jQuery_etag[url];
}
}
// Set the Accepts header for the server, depending on the dataType
requestHeaders.accept = transportDataType && accepts[ transportDataType ] ?
accepts[ transportDataType ] + ( transportDataType !== "*" ? ", */*; q=0.01" : "" ) :
accepts[ "*" ];
// Check for headers option
for ( i in headers ) {
requestHeaders[ i.toLowerCase() ] = headers[ i ];
}
}
callbackContext = s.context || s;
globalEventContext = s.context ? jQuery(s.context) : jQuery.event;
for ( i in callbacksLists ) {
callbacksLists[i].bind(s[i]);
}
// Watch for a new set of requests
if ( s.global && jQuery.active++ === 0 ) {
jQuery.event.trigger( "ajaxStart" );
}
done = whenDone;
}
function whenDone(status, statusText, response, headers) {
// Called once
done = undefined;
// Reset sendFlag
sendFlag = 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 ( ifModified ) {
var lastModified = xhr.getResponseHeader("Last-Modified"),
etag = xhr.getResponseHeader("Etag");
if (lastModified) {
jQuery_lastModified[url] = lastModified;
}
if (etag) {
jQuery_etag[url] = etag;
}
}
if ( 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 {
function checkData(data) {
if ( data !== undefined ) {
var testFunction = s.dataCheckers[srcDataType];
if ( isFunction( testFunction ) ) {
testFunction(data);
}
}
}
function convertData (data) {
var conversionFunction = dataConverters[srcDataType+" => "+destDataType] ||
dataConverters["* => "+destDataType],
noFunction = ! isFunction( conversionFunction );
if ( noFunction ) {
if ( srcDataType != "text" && destDataType != "text" ) {
// We try to put text inbetween
var first = dataConverters[srcDataType+" => text"] ||
dataConverters["* => text"],
second = dataConverters["text => "+destDataType] ||
dataConverters["* => "+destDataType],
areFunctions = isFunction( first ) && isFunction( second );
if ( areFunctions ) {
conversionFunction = function (data) {
return second( first ( data ) );
};
}
noFunction = ! areFunctions;
}
if ( noFunction ) {
jQuery.error( "no data converter between " + srcDataType + " and " + destDataType );
}
}
return conversionFunction(data);
}
var dataTypes = s.dataTypes,
i,
length,
data = response,
dataConverters = s.dataConverters,
srcDataType,
destDataType,
responseTypes = s.xhrResponseFields;
for ( i = 0, length = dataTypes.length ; i < length ; i++ ) {
destDataType = dataTypes[i];
if ( !srcDataType ) { // First time
// Copy type
srcDataType = destDataType;
// Check
checkData(data);
// Apply dataFilter
if ( isFunction( s.dataFilter ) ) {
data = s.dataFilter(data, s.dataType);
// Recheck data
checkData(data);
}
} else { // Subsequent times
// handle auto
// JULIAN: for reasons unknown to me === doesn't work here
if (destDataType == "*") {
destDataType = srcDataType;
} else if ( srcDataType != destDataType ) {
// Convert
data = convertData(data);
// Copy type & check
srcDataType = destDataType;
checkData(data);
}
}
// Copy response into the xhr if it hasn't been already
var responseDataType,
responseType = responseTypes[srcDataType];
if ( responseType ) {
responseDataType = srcDataType;
} else {
responseType = responseTypes[ responseDataType = "text" ];
}
if ( responseType !== 1 ) {
xhr[ "response" + responseType ] = data;
responseTypes[ responseType ] = 1;
}
}
// We have a real success
success = data;
isSuccess = 1;
} catch(e) {
statusText = "parsererror";
error = "" + e;
}
}
} else { // if not success, mark it as an error
error = error || statusText;
}
// Set data for the fake xhr object
xhr.status = status;
xhr.statusText = statusText;
// Keep local copies of vars in case callbacks re-use the xhr
var _s = s,
_callbacksLists = callbacksLists,
_callbackContext = callbackContext,
_globalEventContext = globalEventContext;
// Set state if the xhr hasn't been re-used
function _setState( value ) {
if ( xhr.readyState && s === _s ) {
setState( value );
}
}
// Really completed?
if ( status && s.async ) {
setState( 2 );
_setState( 3 );
}
// We're done
_setState( 4 );
// Success
_callbacksLists.success.fire( isSuccess , _callbackContext , success, statusText, xhr);
if ( isSuccess && _s.global ) {
_globalEventContext.trigger( "ajaxSuccess", [xhr, _s, success] );
}
// Error
_callbacksLists.error.fire( ! isSuccess , _callbackContext , xhr, statusText, error);
if ( !isSuccess && _s.global ) {
_globalEventContext.trigger( "ajaxError", [xhr, _s, error] );
}
// Complete
_callbacksLists.complete.fire( 1 , _callbackContext, xhr, statusText);
if ( _s.global ) {
_globalEventContext.trigger( "ajaxComplete", [xhr, _s] );
// Handle the global AJAX counter
if ( ! --jQuery.active ) {
jQuery.event.trigger( "ajaxStop" );
}
}
}
// Ready state control
function checkState( expected , test ) {
if ( expected !== true && ( expected === false || test === false || xhr.readyState !== expected ) ) {
jQuery.error("INVALID_STATE_ERR");
}
}
// Ready state change
function setState( value ) {
xhr.readyState = value;
if ( isFunction( xhr.onreadystatechange ) ) {
xhr.onreadystatechange();
}
}
var // jQuery lists
jQuery_lastModified = jQuery.lastModified,
jQuery_etag = jQuery.etag,
// Options object
s,
// Callback stuff
callbackContext,
globalEventContext,
callbacksLists,
// Headers (they are sent all at once)
requestHeaders,
// Response headers
responseHeadersString,
responseHeaders,
// Done callback
done,
// transport
internal,
// timeout handle
timeoutTimer,
// The send flag
sendFlag,
// Fake xhr
xhr = {
// state
readyState: 0,
// Callback
onreadystatechange: null,
// Open
open: function(type, url, async, username, password) {
xhr.abort();
reset();
s = {
type: type,
url: url,
async: async,
username: username,
password: password
};
setState(1);
return xhr;
},
// Send
send: function(data, moreOptions) {
checkState(1 , !sendFlag);
s.data = data;
s = jQuery.extend( true,
{},
jQuery.ajaxSettings,
s,
moreOptions || ( moreOptions === false ? { global: false } : {} ) );
if ( moreOptions ) {
// We force the original context
// (plain objects used as context get extended)
s.context = moreOptions.context;
}
init();
// If not internal, abort
if ( ! internal ) {
done( 0 , "transport not found" );
return false;
}
// Allow custom headers/mimetypes and early abort
if ( s.beforeSend ) {
var _s = s;
if ( s.beforeSend.call(callbackContext, xhr, s) === false || ! xhr.readyState || _s !== s ) {
// Abort if not done
if ( xhr.readyState && _s === s ) {
xhr.abort();
}
// Handle the global AJAX counter
if ( _s.global && ! --jQuery.active ) {
jQuery.event.trigger( "ajaxStop" );
}
return false;
}
}
sendFlag = 1;
// Send global event
if ( s.global ) {
globalEventContext.trigger("ajaxSend", [xhr, s]);
}
// Timeout
if ( s.async && s.timeout > 0 ) {
timeoutTimer = setTimeout(function(){
xhr.abort("timeout");
}, s.timeout);
}
if ( s.async ) {
setState(1);
}
try {
internal.send(requestHeaders, done);
return xhr;
} catch (e) {
if ( done ) {
done(0, "error", "" + e);
} else {
jQuery.error(e);
}
}
return false;
},
// Caches the header
setRequestHeader: function(name,value) {
checkState(1, !sendFlag);
requestHeaders[ name.toLowerCase() ] = value;
return xhr;
},
// Raw string
getAllResponseHeaders: function() {
return xhr.readyState <= 1 ? "" : responseHeadersString;
},
// Builds headers hashtable if needed
getResponseHeader: function( key ) {
if ( xhr.readyState <= 1 ) {
return null;
}
if ( responseHeaders === undefined ) {
responseHeaders = {};
if ( typeof responseHeadersString === "string" ) {
var match;
while( ( match = rheaders.exec( responseHeadersString ) ) ) {
responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
}
}
}
return responseHeaders[ key.toLowerCase() ];
},
// Cancel the request
abort: function(statusText) {
if (internal) {
internal.abort( statusText || "abort" );
}
xhr.readyState = 0;
}
};
// Init data (so that we can bind callbacks early
reset(1);
// Install callbacks related methods
jQuery.each(callbacksLists, function(name) {
var list;
xhr[name] = function() {
list = callbacksLists[name];
if ( list ) {
list.bind.apply(list, arguments );
}
return this;
};
});
// Return the xhr emulation
return xhr;
};
// Create a callback list
function createCBList() {
var functors = [],
autoFire = 0,
fireArgs,
list = {
fire: function( flag , context ) {
// Save info for later bindings
fireArgs = arguments;
// Remove autoFire to keep bindings in order
autoFire = 0;
var args = sliceFunc.call( fireArgs , 2 );
// Execute callbacks
while ( flag && functors.length ) {
flag = functors.shift().apply( context , args ) !== false;
}
// Clean if asked to stop
if ( ! flag ) {
clean();
}
// Set autoFire
autoFire = 1;
},
bind: function() {
var args = arguments,
i = 0,
length = args.length,
func;
for ( ; i < length ; i++ ) {
func = args[ i ];
if ( jQuery.isArray(func) ) {
list.bind.apply( list , func );
} else if ( isFunction(func) ) {
// Add if not already in
if ( ! pos( func ) ) {
functors.push( func );
}
}
}
if ( autoFire ) {
list.fire.apply( list , fireArgs );
}
},
unbind: function() {
var i = 0,
args = arguments,
length = args.length,
func,
position;
if ( length ) {
for( ; i < length ; i++ ) {
func = args[i];
if ( jQuery.isArray(func) ) {
list.unbind.apply(list,func);
} else if ( isFunction(func) ) {
position = pos(func);
if ( position ) {
functors.splice(position-1,1);
}
}
}
} else {
functors = [];
}
}
};
// Get the index of the functor in the list (1-based)
function pos( func ) {
for (var i = 0, length = functors.length; i < length && functors[i] !== func; i++) {
}
return i < length ? ( i + 1 ) : 0;
}
// Clean the object
function clean() {
// Empty callbacks list
functors = [];
// Inhibit methods
for (var i in list) {
list[i] = jQuery.noop;
}
}
return list;
}
jQuery.extend(jQuery.xhr, {
// Add new prefilter
prefilter: function (functor) {
if ( isFunction(functor) ) {
jQuery.ajaxSettings.prefilters.push( functor );
}
return this;
},
// Bind a transport to one or more dataTypes
bindTransport: function () {
var args = arguments,
i,
start = 0,
length = args.length,
dataTypes = [ "*" ],
functors = [],
functor,
first,
append,
list,
transports = jQuery.ajaxSettings.transports;
if ( length ) {
if ( ! isFunction( args[ 0 ] ) ) {
dataTypes = args[ 0 ].toLowerCase().split(/\s+/);
start = 1;
}
if ( dataTypes.length && start < length ) {
for ( i = start; i < length; i++ ) {
functor = args[i];
if ( isFunction(functor) ) {
functors.push( functor );
}
}
if ( functors.length ) {
jQuery.each ( dataTypes, function( _ , dataType ) {
first = /^\+/.test( dataType );
if (first) {
dataType = dataType.substr(1);
}
if ( dataType !== "" ) {
append = Array.prototype[ first ? "unshift" : "push" ];
list = transports[ dataType ];
jQuery.each ( functors, function( _ , functor ) {
if ( ! list ) {
list = transports[ dataType ] = [ functor ];
} else {
append.call( list , functor );
}
} );
}
} );
}
}
}
return this;
}
});
// Select a transport given options
function selectTransport( s ) {
var dataTypes = s.dataTypes,
transportDataType,
transportsList,
transport,
i,
length,
checked = {},
flag;
function initSearch( dataType ) {
flag = transportDataType !== dataType && ! checked[ dataType ];
if ( flag ) {
checked[ dataType ] = 1;
transportDataType = dataType;
transportsList = s.transports[ dataType ];
i = -1;
length = transportsList ? transportsList.length : 0 ;
}
return flag;
}
initSearch( dataTypes[ 0 ] );
for ( i = 0 ; ! transport && i <= length ; i++ ) {
if ( i === length ) {
initSearch( "*" );
} else {
transport = transportsList[ i ]( s , determineDataType );
// If we got redirected to another dataType
// Search there (if not in progress or already tried)
if ( typeof( transport ) === "string" &&
initSearch( transport ) ) {
dataTypes.unshift( transport );
transport = 0;
}
}
}
return transport;
}
// 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;
}
})( jQuery );

View File

@ -0,0 +1,5 @@
<?php
header("HTTP/1.0 400 Bad Request");
echo "plain text message";

View File

@ -6,15 +6,11 @@ $headers = array();
foreach( $_SERVER as $key => $value ) { foreach( $_SERVER as $key => $value ) {
if ( substr( $key , 0 , 5 ) == "HTTP_" ) { $key = str_replace( "_" , "-" , substr( $key , 0 , 5 ) == "HTTP_" ? substr( $key , 5 ) : $key );
$headers[ $key ] = $value;
$key = str_replace( "_" , "-" , substr( $key , 5) );
$headers[ $key ] = $value;
}
} }
foreach( explode( "_" , $_GET[ "keys" ] ) as $key ) { foreach( explode( "_" , $_GET[ "keys" ] ) as $key ) {
echo "$key: " . $headers[ strtoupper( $key ) ] . "\n"; echo "$key: " . @$headers[ strtoupper( $key ) ] . "\n";
} }

View File

@ -1,6 +1,10 @@
<?php <?php
error_reporting(0); error_reporting(0);
$callback = $_REQUEST['callback']; $callback = $_REQUEST['callback'];
if ( ! $callback ) {
$callback = explode("?",end(explode("/",$_SERVER['REQUEST_URI'])));
$callback = $callback[0];
}
$json = $_REQUEST['json']; $json = $_REQUEST['json'];
if($json) { if($json) {
echo $callback . '([ {"name": "John", "age": 21}, {"name": "Peter", "age": 25 } ])'; echo $callback . '([ {"name": "John", "age": 21}, {"name": "Peter", "age": 25 } ])';

View File

@ -20,10 +20,9 @@
<script src="../src/manipulation.js"></script> <script src="../src/manipulation.js"></script>
<script src="../src/css.js"></script> <script src="../src/css.js"></script>
<script src="../src/ajax.js"></script> <script src="../src/ajax.js"></script>
<script src="../src/xhr.js"></script> <script src="../src/ajax/jsonp.js"></script>
<script src="../src/transports/jsonp.js"></script> <script src="../src/ajax/script.js"></script>
<script src="../src/transports/script.js"></script> <script src="../src/ajax/xhr.js"></script>
<script src="../src/transports/xhr.js"></script>
<script src="../src/effects.js"></script> <script src="../src/effects.js"></script>
<script src="../src/offset.js"></script> <script src="../src/offset.js"></script>
<script src="../src/dimensions.js"></script> <script src="../src/dimensions.js"></script>

View File

@ -70,44 +70,6 @@ test("jQuery.ajax() - success callbacks - (url, options) syntax", function() {
}, 13); }, 13);
}); });
test("jQuery.ajax() - success/error callbacks (remote)", function() {
var supports = jQuery.support.cors;
expect( supports ? 9 : 6 );
jQuery.ajaxSetup({ timeout: 0 });
stop();
setTimeout(function(){
jQuery('#foo').ajaxStart(function(){
ok( true, "ajaxStart" );
}).ajaxStop(function(){
ok( true, "ajaxStop" );
start();
}).ajaxSend(function(){
ok( supports , "ajaxSend" );
}).ajaxComplete(function(){
ok( true, "ajaxComplete" );
}).ajaxError(function(){
ok( ! supports, "ajaxError" );
}).ajaxSuccess(function(){
ok( supports, "ajaxSuccess" );
});
jQuery.ajax({
// JULIAN TODO: Get an url especially for jQuery
url: "http://rockstarapps.com/test.php",
dataType: "text",
beforeSend: function(){ ok(supports, "beforeSend"); },
success: function( val ){ ok(supports, "success"); ok(supports && val.length, "data received"); },
error: function(_ , a , b ){ ok(!supports, "error"); },
complete: function(){ ok(true, "complete"); }
});
}, 13);
});
test("jQuery.ajax() - success callbacks (late binding)", function() { test("jQuery.ajax() - success callbacks (late binding)", function() {
expect( 8 ); expect( 8 );
@ -173,7 +135,7 @@ test("jQuery.ajax() - success callbacks (oncomplete binding)", function() {
.error(function(){ ok(false, "error"); }) .error(function(){ ok(false, "error"); })
.complete(function(){ start(); }); .complete(function(){ start(); });
} }
}) });
}, 13); }, 13);
}); });
@ -211,7 +173,7 @@ test("jQuery.ajax() - success callbacks (very late binding)", function() {
.complete(function(){ start(); }); .complete(function(){ start(); });
},100); },100);
} }
}) });
}, 13); }, 13);
}); });
@ -278,6 +240,46 @@ test("jQuery.ajax() - error callbacks", function() {
}); });
}); });
test("jQuery.ajax() - responseText on error", function() {
expect( 1 );
stop();
jQuery.ajax({
url: url("data/errorWithText.php"),
error: function(xhr) {
strictEqual( xhr.responseText , "plain text message" , "Test jXHR.responseText is filled for HTTP errors" );
},
complete: function() {
start();
}
});
});
test(".ajax() - retry with jQuery.ajax( this )", function() {
expect( 1 );
stop();
var firstTime = 1;
jQuery.ajax({
url: url("data/errorWithText.php"),
error: function() {
if ( firstTime ) {
firstTime = 0;
jQuery.ajax( this );
} else {
ok( true , "Test retrying with jQuery.ajax(this) works" );
start();
}
}
});
});
test(".ajax() - headers" , function() { test(".ajax() - headers" , function() {
expect( 2 ); expect( 2 );
@ -314,6 +316,64 @@ test(".ajax() - headers" , function() {
}); });
test(".ajax() - Accept header" , function() {
expect( 1 );
stop();
jQuery.ajax(url("data/headers.php?keys=accept"), {
headers: {
Accept: "very wrong accept value"
},
beforeSend: function( xhr ) {
xhr.setRequestHeader( "Accept", "*/*" );
},
success: function( data ) {
strictEqual( data , "accept: */*\n" , "Test Accept header is set to last value provided" );
start();
},
error: function(){ ok(false, "error"); }
});
});
test(".ajax() - contentType" , function() {
expect( 2 );
stop();
var count = 2;
function restart() {
if ( ! --count ) {
start();
}
}
jQuery.ajax(url("data/headers.php?keys=content-type" ), {
contentType: "test",
success: function( data ) {
strictEqual( data , "content-type: test\n" , "Test content-type is sent when options.contentType is set" );
},
complete: function() {
restart();
}
});
jQuery.ajax(url("data/headers.php?keys=content-type" ), {
contentType: false,
success: function( data ) {
strictEqual( data , "content-type: \n" , "Test content-type is not sent when options.contentType===false" );
},
complete: function() {
restart();
}
});
});
test(".ajax() - hash", function() { test(".ajax() - hash", function() {
expect(3); expect(3);
@ -343,6 +403,53 @@ test(".ajax() - hash", function() {
}); });
}); });
test("jQuery ajax - cross-domain detection", function() {
expect( 4 );
var loc = document.location,
otherPort = loc.port === 666 ? 667 : 666,
otherProtocol = loc.protocol === "http:" ? "https:" : "http:";
jQuery.ajax({
dataType: "jsonp",
url: otherProtocol + "//" + loc.host,
beforeSend: function( _ , s ) {
ok( s.crossDomain , "Test different protocols are detected as cross-domain" );
return false;
}
});
jQuery.ajax({
dataType: "jsonp",
url: loc.protocol + '//somewebsitethatdoesnotexist-656329477541.com:' + ( loc.port || 80 ),
beforeSend: function( _ , s ) {
ok( s.crossDomain , "Test different hostnames are detected as cross-domain" );
return false;
}
});
jQuery.ajax({
dataType: "jsonp",
url: loc.protocol + "//" + loc.hostname + ":" + otherPort,
beforeSend: function( _ , s ) {
ok( s.crossDomain , "Test different ports are detected as cross-domain" );
return false;
}
});
jQuery.ajax({
dataType: "jsonp",
url: loc.protocol + "//" + loc.host,
crossDomain: true,
beforeSend: function( _ , s ) {
ok( s.crossDomain , "Test forced crossDomain is detected as cross-domain" );
return false;
}
});
});
test(".ajax() - 304", function() { test(".ajax() - 304", function() {
expect( 1 ); expect( 1 );
stop(); stop();
@ -409,136 +516,6 @@ test("jQuery.ajax() - abort", function() {
equals( xhr.readyState, 0, "XHR readyState indicates successful abortion" ); equals( xhr.readyState, 0, "XHR readyState indicates successful abortion" );
}); });
test("jQuery.ajax() - readyState (success)", function() {
expect( 1 );
jQuery.ajaxSetup({ timeout: 0 });
stop();
var control = "";
setTimeout(function(){
jQuery.ajax({
url: url("data/name.html"),
beforeSend: function( xhr ) {
xhr.onreadystatechange = function() {
control += xhr.readyState;
}
},
complete: function(){
setTimeout( function() {
equals( control , "1234" , "onreadystatechange was properly called" );
}, 13 );
start();
}
});
}, 13);
});
test("jQuery.ajax() - readyState (abort)", function() {
expect( 2 );
jQuery.ajaxSetup({ timeout: 0 });
stop();
var control = "";
setTimeout(function(){
jQuery.ajaxSetup({ timeout: 500 });
jQuery.ajax({
url: url("data/name.php?wait=5"),
beforeSend: function( xhr ) {
xhr.onreadystatechange = function() {
control += xhr.readyState;
}
},
complete: function( xhr ){
setTimeout( function() {
equals( control , "14" , "onreadystatechange was properly called" );
equals( xhr.readyState, 0 , "readyState is 0" );
}, 13 );
start();
}
});
}, 13);
});
test("jQuery.xhr() - reuse", function() {
expect( 15 );
jQuery.ajaxSetup({ timeout: 0 });
stop();
var number = 0;
setTimeout(function(){
jQuery('#foo').ajaxStart(function(){
ok( true, "ajaxStart" );
}).ajaxStop(function(){
ok( true, "ajaxStop" );
start();
}).ajaxSend(function(){
number++;
ok( true, "ajaxSend (" + number +")" );
}).ajaxComplete(function(){
ok( true, "ajaxComplete (" + number +")" );
}).ajaxError(function(){
ok( false, "ajaxError (" + number +")" );
}).ajaxSuccess(function(){
ok( true, "ajaxSuccess (" + number +")" );
});
jQuery.ajax({
url: url("data/name.html"),
beforeSend: function(){ ok(true, "beforeSend (1)"); },
success: function( _1 , _2 , xhr ){
ok(true, "success (1)");
xhr.complete(function() {
ok(true, "complete (1bis)");
});
xhr.open( "GET", url("data/name.html") );
xhr.success( function(){ ok(true, "beforeSend (2)"); } )
xhr.send( null, {
success: function(){ ok(true, "success (2)"); },
error: function(){ ok(false, "error (2)"); },
complete: function(){ ok(true, "complete (2)"); }
} );
},
error: function(){ ok(false, "error (1)"); },
complete: function(){ ok(true, "complete (1)"); }
});
}, 13);
});
test("jQuery.xhr() - early binding", function() {
expect( 2 );
jQuery.ajaxSetup({ timeout: 0 });
stop();
jQuery.xhr()
.success( function(){ ok(true, "success"); } )
.error( function(){ ok(false, "error"); } )
.complete( function(){ ok(true, "complete"); start(); } )
.open( "GET", url("data/name.html") )
.send();
});
test("jQuery.xhr() - get native implementation", function() {
var xhr = jQuery.xhr(true);
ok( xhr.readyState !== undefined , "implements XMLHttpRequest" );
ok( ! jQuery.isFunction( xhr.success ) , "is not jQuery's abstraction" );
});
test("Ajax events with context", function() { test("Ajax events with context", function() {
expect(14); expect(14);
@ -606,7 +583,7 @@ test("jQuery.ajax context modification", function() {
stop(); stop();
var obj = {} var obj = {};
jQuery.ajax({ jQuery.ajax({
url: url("data/name.html"), url: url("data/name.html"),
@ -653,34 +630,6 @@ test("jQuery.ajax() - disabled globals", function() {
}); });
}); });
test("jQuery.xhr() - disabled globals through xhr.send(data , false)", function() {
expect( 2 );
stop();
jQuery('#foo').ajaxStart(function(){
ok( false, "ajaxStart" );
}).ajaxStop(function(){
ok( false, "ajaxStop" );
}).ajaxSend(function(){
ok( false, "ajaxSend" );
}).ajaxComplete(function(){
ok( false, "ajaxComplete" );
}).ajaxError(function(){
ok( false, "ajaxError" );
}).ajaxSuccess(function(){
ok( false, "ajaxSuccess" );
});
jQuery.xhr()
.success(function(){ ok(true, "success"); })
.error(function(){ ok(false, "error"); })
.complete(function(){
ok(true, "complete");
setTimeout(function(){ start(); }, 13);
})
.open("GET", url("data/name.html")).send(undefined, false);
});
test("jQuery.ajax - xml: non-namespace elements inside namespaced elements", function() { test("jQuery.ajax - xml: non-namespace elements inside namespaced elements", function() {
expect(3); expect(3);
stop(); stop();
@ -707,6 +656,10 @@ test("jQuery.ajax - xml: non-namespace elements inside namespaced elements (over
equals( jQuery("jsconf", resp).length, 1, 'jsconf in responseXML' ); equals( jQuery("jsconf", resp).length, 1, 'jsconf in responseXML' );
equals( jQuery("thing", resp).length, 2, 'things in responseXML' ); equals( jQuery("thing", resp).length, 2, 'things in responseXML' );
start(); start();
},
error: function(_1,_2,error) {
ok( false, error );
start();
} }
}); });
}); });
@ -842,20 +795,20 @@ test("serialize()", function() {
'Check input serialization as query string'); 'Check input serialization as query string');
equals( jQuery('#testForm').serialize(), equals( jQuery('#testForm').serialize(),
'T3=%3F%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=', 'T3=%3F%0D%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=',
'Check form serialization as query string'); 'Check form serialization as query string');
equals( jQuery('#testForm :input').serialize(), equals( jQuery('#testForm :input').serialize(),
'T3=%3F%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=', 'T3=%3F%0D%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=',
'Check input serialization as query string'); 'Check input serialization as query string');
equals( jQuery('#form, #testForm').serialize(), equals( jQuery('#form, #testForm').serialize(),
"action=Test&radio2=on&check=on&hidden=&foo%5Bbar%5D=&name=name&search=search&email=dave%40jquery.com&number=43&select1=&select2=3&select3=1&select3=2&select5=3&T3=%3F%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=", "action=Test&radio2=on&check=on&hidden=&foo%5Bbar%5D=&name=name&search=search&email=dave%40jquery.com&number=43&select1=&select2=3&select3=1&select3=2&select5=3&T3=%3F%0D%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=",
'Multiple form serialization as query string'); 'Multiple form serialization as query string');
/* Temporarily disabled. Opera 10 has problems with form serialization. /* Temporarily disabled. Opera 10 has problems with form serialization.
equals( jQuery('#form, #testForm :input').serialize(), equals( jQuery('#form, #testForm :input').serialize(),
"action=Test&radio2=on&check=on&hidden=&foo%5Bbar%5D=&name=name&search=search&email=dave%40jquery.com&number=43&select1=&select2=3&select3=1&select3=2&T3=%3F%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=", "action=Test&radio2=on&check=on&hidden=&foo%5Bbar%5D=&name=name&search=search&email=dave%40jquery.com&number=43&select1=&select2=3&select3=1&select3=2&T3=%3F%0D%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=",
'Mixed form/input serialization as query string'); 'Mixed form/input serialization as query string');
*/ */
jQuery("#html5email, #html5number").remove(); jQuery("#html5email, #html5number").remove();
@ -1094,6 +1047,18 @@ test("load(String, Function) - check file with only a script tag", function() {
}); });
}); });
test("load(String, Function) - dataFilter in ajaxSettings", function() {
expect(2);
stop();
jQuery.ajaxSetup({ dataFilter: function() { return "Hello World"; } });
var div = jQuery("<div/>").load(url("data/name.html"), function(responseText) {
strictEqual( div.html(), "Hello World" , "Test div was filled with filtered data" );
strictEqual( responseText, "Hello World" , "Test callback receives filtered data" );
jQuery.ajaxSetup({ dataFilter: 0 });
start();
});
});
test("load(String, Object, Function)", function() { test("load(String, Object, Function)", function() {
expect(2); expect(2);
stop(); stop();
@ -1150,10 +1115,10 @@ test("jQuery.getScript(String, Function) - no callback", function() {
}); });
test("jQuery.ajax() - JSONP, Local", function() { test("jQuery.ajax() - JSONP, Local", function() {
expect(9); expect(14);
var count = 0; var count = 0;
function plus(){ if ( ++count == 9 ) start(); } function plus(){ if ( ++count == 14 ) start(); }
stop(); stop();
@ -1197,6 +1162,75 @@ test("jQuery.ajax() - JSONP, Local", function() {
} }
}); });
jQuery.ajax({
url: "data/jsonp.php?callback=??",
dataType: "jsonp",
success: function(data){
ok( data.data, "JSON results returned (GET, url context-free callback)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (GET, url context-free callback)" );
plus();
}
});
jQuery.ajax({
url: "data/jsonp.php",
dataType: "jsonp",
data: "callback=??",
success: function(data){
ok( data.data, "JSON results returned (GET, data context-free callback)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (GET, data context-free callback)" );
plus();
}
});
jQuery.ajax({
url: "data/jsonp.php/??",
dataType: "jsonp",
success: function(data){
ok( data.data, "JSON results returned (GET, REST-like)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (GET, REST-like)" );
plus();
}
});
jQuery.ajax({
url: "data/jsonp.php/???json=1",
dataType: "jsonp",
success: function(data){
strictEqual( jQuery.type(data), "array", "JSON results returned (GET, REST-like with param)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (GET, REST-like with param)" );
plus();
}
});
jQuery.ajax({
url: "data/jsonp.php",
dataType: "jsonp",
data: {
callback: "?"
},
success: function(data){
ok( data.data, "JSON results returned (GET, processed data callback)" );
plus();
},
error: function(data){
ok( false, "Ajax error JSON (GET, processed data callback)" );
plus();
}
});
jQuery.ajax({ jQuery.ajax({
url: "data/jsonp.php", url: "data/jsonp.php",
dataType: "jsonp", dataType: "jsonp",
@ -1482,12 +1516,12 @@ test("jQuery.ajax() - json by content-type disabled with options", function() {
jQuery.ajax({ jQuery.ajax({
url: url("data/json.php"), url: url("data/json.php"),
data: { header: "json", json: "array" }, data: { header: "json", json: "array" },
autoDataType: { contents: {
json: false json: false
}, },
success: function( text ) { success: function( text ) {
equals( typeof text , "string" , "json wasn't auto-determined" ); equals( typeof text , "string" , "json wasn't auto-determined" );
var json = this.dataConverters["text => json"]( text ); var json = jQuery.parseJSON( text );
ok( json.length >= 2, "Check length"); ok( json.length >= 2, "Check length");
equals( json[0].name, 'John', 'Check JSON: first, name' ); equals( json[0].name, 'John', 'Check JSON: first, name' );
equals( json[0].age, 21, 'Check JSON: first, age' ); equals( json[0].age, 21, 'Check JSON: first, age' );
@ -1714,7 +1748,7 @@ test("data option: evaluate function values (#2806)", function() {
equals( result, "key=value" ); equals( result, "key=value" );
start(); start();
} }
}) });
}); });
test("data option: empty bodies for non-GET requests", function() { test("data option: empty bodies for non-GET requests", function() {
@ -1727,7 +1761,7 @@ test("data option: empty bodies for non-GET requests", function() {
equals( result, "" ); equals( result, "" );
start(); start();
} }
}) });
}); });
test("jQuery.ajax - If-Modified-Since support", function() { test("jQuery.ajax - If-Modified-Since support", function() {
@ -1752,7 +1786,7 @@ test("jQuery.ajax - If-Modified-Since support", function() {
ok(true, "Opera is incapable of doing .setRequestHeader('If-Modified-Since')."); ok(true, "Opera is incapable of doing .setRequestHeader('If-Modified-Since').");
} else { } else {
equals(status, "notmodified"); equals(status, "notmodified");
ok(data == null, "response body should be empty") ok(data == null, "response body should be empty");
} }
start(); start();
}, },
@ -1799,7 +1833,7 @@ test("jQuery.ajax - Etag support", function() {
ok(true, "Opera is incapable of doing .setRequestHeader('If-None-Match')."); ok(true, "Opera is incapable of doing .setRequestHeader('If-None-Match').");
} else { } else {
equals(status, "notmodified"); equals(status, "notmodified");
ok(data == null, "response body should be empty") ok(data == null, "response body should be empty");
} }
start(); start();
}, },
@ -1831,19 +1865,25 @@ test("jQuery ajax - failing cross-domain", function() {
var i = 2; var i = 2;
jQuery.ajax({ if ( jQuery.ajax({
url: 'http://somewebsitethatdoesnotexist.com', url: 'http://somewebsitethatdoesnotexist-67864863574657654.com',
success: function(){ ok( false , "success" ); }, success: function(){ ok( false , "success" ); },
error: function(xhr,_,e){ ok( true , "file not found: " + xhr.status + " => " + e ); }, error: function(xhr,_,e){ ok( true , "file not found: " + xhr.status + " => " + e ); },
complete: function() { if ( ! --i ) start(); } complete: function() { if ( ! --i ) start(); }
}); }) === false ) {
ok( true , "no transport" );
if ( ! --i ) start();
}
jQuery.ajax({ if ( jQuery.ajax({
url: 'http://www.google.com', url: 'http://www.google.com',
success: function(){ ok( false , "success" ); }, success: function(){ ok( false , "success" ); },
error: function(xhr,_,e){ ok( true , "access denied: " + xhr.status + " => " + e ); }, error: function(xhr,_,e){ ok( true , "access denied: " + xhr.status + " => " + e ); },
complete: function() { if ( ! --i ) start(); } complete: function() { if ( ! --i ) start(); }
}); }) === false ) {
ok( true , "no transport" );
if ( ! --i ) start();
}
}); });
@ -1875,6 +1915,76 @@ test( "jQuery.ajax - Location object as url (#7531)", 1, function () {
ok( success, "document.location did not generate exception" ); ok( success, "document.location did not generate exception" );
}); });
test( "jQuery.ajax - statusCode" , function() {
var count = 10;
expect( 16 );
stop();
function countComplete() {
if ( ! --count ) {
start();
}
}
function createStatusCodes( name , isSuccess ) {
name = "Test " + name + " " + ( isSuccess ? "success" : "error" );
return {
200: function() {
ok( isSuccess , name );
},
404: function() {
ok( ! isSuccess , name );
}
}
}
jQuery.each( {
"data/name.html": true,
"data/someFileThatDoesNotExist.html": false
} , function( uri , isSuccess ) {
jQuery.ajax( url( uri ) , {
statusCode: createStatusCodes( "in options" , isSuccess ),
complete: countComplete
});
jQuery.ajax( url( uri ) , {
complete: countComplete
}).statusCode( createStatusCodes( "immediately with method" , isSuccess ) );
jQuery.ajax( url( uri ) , {
complete: function(jXHR) {
jXHR.statusCode( createStatusCodes( "on complete" , isSuccess ) );
countComplete();
}
});
jQuery.ajax( url( uri ) , {
complete: function(jXHR) {
setTimeout( function() {
jXHR.statusCode( createStatusCodes( "very late binding" , isSuccess ) );
countComplete();
} , 100 );
}
});
jQuery.ajax( url( uri ) , {
statusCode: createStatusCodes( "all (options)" , isSuccess ),
complete: function(jXHR) {
jXHR.statusCode( createStatusCodes( "all (on complete)" , isSuccess ) );
setTimeout( function() {
jXHR.statusCode( createStatusCodes( "all (very late binding)" , isSuccess ) );
countComplete();
} , 100 );
}
}).statusCode( createStatusCodes( "all (immediately with method)" , isSuccess ) );
});
});
} }
//} //}

View File

@ -12,7 +12,7 @@ test("Basic requirements", function() {
}); });
test("jQuery()", function() { test("jQuery()", function() {
expect(23); expect(24);
// Basic constructor's behavior // Basic constructor's behavior
@ -84,6 +84,11 @@ test("jQuery()", function() {
exec = true; exec = true;
elem.click(); elem.click();
for ( var i = 0; i < 3; ++i ) {
elem = jQuery("<input type='text' value='TEST' />");
}
equals( elem[0].defaultValue, "TEST", "Ensure cached nodes are cloned properly (Bug #6655)" );
}); });
test("selector state", function() { test("selector state", function() {
@ -902,3 +907,159 @@ test("jQuery.parseJSON", function(){
ok( true, "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.done( 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.done( 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.done( function() {
ok( false , "Cancel was ignored" );
test = false;
} );
ok( test , "Test cancel" );
deferred = jQuery._Deferred().resolve();
try {
deferred.done( function() {
throw "Error";
} , function() {
ok( true , "Test deferred do not cancel on exception" );
} );
} catch( e ) {
strictEqual( e , "Error" , "Test deferred propagates exceptions");
deferred.done();
}
test = "";
deferred = jQuery._Deferred().done( function() {
test += "A";
}, function() {
test += "B";
} ).resolve();
strictEqual( test , "AB" , "Test multiple done parameters" );
test = "";
deferred.done( function() {
deferred.done( function() {
test += "C";
} );
test += "A";
}, function() {
test += "B";
} );
strictEqual( test , "ABC" , "Test done callbacks order" );
deferred = jQuery._Deferred();
deferred.fire( jQuery , [ document ] ).done( 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" );
}, function() {
ok( false , "Error on resolve" );
});
jQuery.Deferred().reject().then( function() {
ok( false , "Success on reject" );
}, function() {
ok( true , "Error on reject" );
});
});
test("jQuery.when()", function() {
expect( 21 );
// Some other objects
jQuery.each( {
"an empty string": "",
"a non-empty string": "some string",
"zero": 0,
"a number other than zero": 1,
"true": true,
"false": false,
"null": null,
"undefined": undefined,
"a plain object": {}
} , function( message , value ) {
ok( jQuery.isFunction( jQuery.when( value ).then( function( resolveValue ) {
strictEqual( resolveValue , value , "Test the promise was resolved with " + message );
} ).promise ) , "Test " + message + " triggers the creation of a new Promise" );
} );
var cache, i;
for( i = 1 ; i < 4 ; i++ ) {
jQuery.when( cache || jQuery.Deferred( function() {
this.resolve( i );
}) ).then( function( value ) {
strictEqual( value , 1 , "Function executed" + ( i > 1 ? " only once" : "" ) );
cache = value;
}, function() {
ok( false , "Fail called" );
});
}
});

View File

@ -78,6 +78,21 @@ test("jQuery.data", function() {
ok( jQuery.data( window, "BAD" ), "Make sure that the value was set." ); ok( jQuery.data( window, "BAD" ), "Make sure that the value was set." );
}); });
test("jQuery.hasData", function() {
expect(6);
function testData(obj) {
equals( jQuery.hasData(obj), false, "No data exists" );
jQuery.data( obj, "foo", "bar" );
equals( jQuery.hasData(obj), true, "Data exists" );
jQuery.removeData( obj, "foo" );
equals( jQuery.hasData(obj), false, "Data was removed" );
}
testData(document.createElement('div'));
testData({});
});
test(".data()", function() { test(".data()", function() {
expect(5); expect(5);

17
test/unit/effects.js vendored
View File

@ -560,6 +560,23 @@ jQuery.checkOverflowDisplay = function(){
start(); start();
} }
test("support negative values < -10000 (bug #7193)", function () {
expect(1);
stop();
jQuery.extend(jQuery.fx.step, {
"marginBottom": function(fx) {
equals( fx.cur(), -11000, "Element has margin-bottom of -11000" );
delete jQuery.fx.step.marginBottom;
}
});
jQuery("#main").css("marginBottom", "-11000px").animate({ marginBottom: "-11001px" }, {
duration: 1,
complete: start
});
});
test("JS Overflow and Display", function() { test("JS Overflow and Display", function() {
expect(2); expect(2);
stop(); stop();

View File

@ -295,6 +295,41 @@ test("live/delegate immediate propagation", function() {
$p.undelegate( "click" ); $p.undelegate( "click" );
}); });
test("bind/delegate bubbling, isDefaultPrevented (Bug #7793)", function() {
expect(2);
var $anchor2 = jQuery( "#anchor2" ),
$main = jQuery( "#main" ),
fakeClick = function($jq) {
// Use a native click so we don't get jQuery simulated bubbling
if ( document.createEvent ) {
var e = document.createEvent( "MouseEvents" );
e.initEvent( "click", true, true );
$jq[0].dispatchEvent(e);
}
else if ( $jq[0].click ) {
$jq[0].click(); // IE
}
};
$anchor2.click(function(e) {
e.preventDefault();
});
$main.delegate("#foo", "click", function(e) {
equals( e.isDefaultPrevented(), true, "isDefaultPrevented true passed to bubbled event" );
});
fakeClick( $anchor2 );
$anchor2.unbind( "click" );
$main.undelegate( "click" );
$anchor2.click(function(e) {
// Let the default action occur
});
$main.delegate("#foo", "click", function(e) {
equals( e.isDefaultPrevented(), false, "isDefaultPrevented false passed to bubbled event" );
});
fakeClick( $anchor2 );
$anchor2.unbind( "click" );
$main.undelegate( "click" );
});
test("bind(), iframes", function() { test("bind(), iframes", function() {
// events don't work with iframes, see #939 - this test fails in IE because of contentDocument // events don't work with iframes, see #939 - this test fails in IE because of contentDocument
var doc = jQuery("#loadediframe").contents(); var doc = jQuery("#loadediframe").contents();

View File

@ -1,5 +1,8 @@
module("manipulation"); module("manipulation");
// Ensure that an extended Array prototype doesn't break jQuery
Array.prototype.arrayProtoFn = function(arg) { throw("arrayProtoFn should not be called"); };
var bareObj = function(value) { return value; }; var bareObj = function(value) { return value; };
var functionReturningObj = function(value) { return (function() { return value; }); }; var functionReturningObj = function(value) { return (function() { return value; }); };
@ -51,7 +54,7 @@ test("text(Function) with incoming value", function() {
}); });
var testWrap = function(val) { var testWrap = function(val) {
expect(18); expect(19);
var defaultText = 'Try them out:' var defaultText = 'Try them out:'
var result = jQuery('#first').wrap(val( '<div class="red"><span></span></div>' )).text(); var result = jQuery('#first').wrap(val( '<div class="red"><span></span></div>' )).text();
equals( defaultText, result, 'Check for wrapping of on-the-fly html' ); equals( defaultText, result, 'Check for wrapping of on-the-fly html' );
@ -80,10 +83,20 @@ var testWrap = function(val) {
equals( jQuery("#nonnodes > i").text(), j.text(), "Check node,textnode,comment wraps doesn't hurt text" ); equals( jQuery("#nonnodes > i").text(), j.text(), "Check node,textnode,comment wraps doesn't hurt text" );
// Try wrapping a disconnected node // Try wrapping a disconnected node
var cacheLength = 0;
for (var i in jQuery.cache) {
cacheLength++;
}
j = jQuery("<label/>").wrap(val( "<li/>" )); j = jQuery("<label/>").wrap(val( "<li/>" ));
equals( j[0].nodeName.toUpperCase(), "LABEL", "Element is a label" ); equals( j[0].nodeName.toUpperCase(), "LABEL", "Element is a label" );
equals( j[0].parentNode.nodeName.toUpperCase(), "LI", "Element has been wrapped" ); equals( j[0].parentNode.nodeName.toUpperCase(), "LI", "Element has been wrapped" );
for (i in jQuery.cache) {
cacheLength--;
}
equals(cacheLength, 0, "No memory leak in jQuery.cache (bug #7165)");
// Wrap an element containing a text node // Wrap an element containing a text node
j = jQuery("<span/>").wrap("<div>test</div>"); j = jQuery("<span/>").wrap("<div>test</div>");
equals( j[0].previousSibling.nodeType, 3, "Make sure the previous node is a text element" ); equals( j[0].previousSibling.nodeType, 3, "Make sure the previous node is a text element" );
@ -382,7 +395,7 @@ test("append(Function) with incoming value", function() {
}); });
test("append the same fragment with events (Bug #6997, 5566)", function () { test("append the same fragment with events (Bug #6997, 5566)", function () {
expect(4 + (document.fireEvent ? 1 : 0)); expect(2 + (document.fireEvent ? 1 : 0));
stop(1000); stop(1000);
var element; var element;
@ -413,14 +426,6 @@ test("append the same fragment with events (Bug #6997, 5566)", function () {
jQuery("#listWithTabIndex li").before(element); jQuery("#listWithTabIndex li").before(element);
jQuery("#listWithTabIndex li.test6997").eq(1).click(); jQuery("#listWithTabIndex li.test6997").eq(1).click();
element = jQuery("<select><option>Foo</option><option selected>Bar</option></select>");
equals( element.clone().find("option:selected").val(), element.find("option:selected").val(), "Selected option cloned correctly" );
element = jQuery("<input type='checkbox'>").attr('checked', 'checked');
equals( element.clone().is(":checked"), element.is(":checked"), "Checked input cloned correctly" );
}); });
test("appendTo(String|Element|Array&lt;Element&gt;|jQuery)", function() { test("appendTo(String|Element|Array&lt;Element&gt;|jQuery)", function() {
@ -856,7 +861,7 @@ test("replaceAll(String|Element|Array&lt;Element&gt;|jQuery)", function() {
}); });
test("clone()", function() { test("clone()", function() {
expect(36); expect(37);
equals( 'This is a normal link: Yahoo', jQuery('#en').text(), 'Assert text for #en' ); equals( 'This is a normal link: Yahoo', jQuery('#en').text(), 'Assert text for #en' );
var clone = jQuery('#yahoo').clone(); var clone = jQuery('#yahoo').clone();
equals( 'Try them out:Yahoo', jQuery('#first').append(clone).text(), 'Check for clone' ); equals( 'Try them out:Yahoo', jQuery('#first').append(clone).text(), 'Check for clone' );
@ -914,10 +919,12 @@ test("clone()", function() {
equals( clone.html(), div.html(), "Element contents cloned" ); equals( clone.html(), div.html(), "Element contents cloned" );
equals( clone[0].nodeName.toUpperCase(), "DIV", "DIV element cloned" ); equals( clone[0].nodeName.toUpperCase(), "DIV", "DIV element cloned" );
div = jQuery("<div/>").data({ a: true, b: true }); div = jQuery("<div/>").data({ a: true });
div = div.clone(true); var div2 = div.clone(true);
equals( div.data("a"), true, "Data cloned." ); equals( div2.data("a"), true, "Data cloned." );
equals( div.data("b"), true, "Data cloned." ); div2.data("a", false);
equals( div2.data("a"), false, "Ensure cloned element data object was correctly modified" );
equals( div.data("a"), true, "Ensure cloned element data object is copied, not referenced" );
var form = document.createElement("form"); var form = document.createElement("form");
form.action = "/test/"; form.action = "/test/";
@ -930,6 +937,28 @@ test("clone()", function() {
equal( jQuery("body").clone().children()[0].id, "qunit-header", "Make sure cloning body works" ); equal( jQuery("body").clone().children()[0].id, "qunit-header", "Make sure cloning body works" );
}); });
test("clone(form element) (Bug #3879, #6655)", function() {
expect(6);
element = jQuery("<select><option>Foo</option><option selected>Bar</option></select>");
equals( element.clone().find("option:selected").val(), element.find("option:selected").val(), "Selected option cloned correctly" );
element = jQuery("<input type='checkbox' value='foo'>").attr('checked', 'checked');
clone = element.clone();
equals( clone.is(":checked"), element.is(":checked"), "Checked input cloned correctly" );
equals( clone[0].defaultValue, "foo", "Checked input defaultValue cloned correctly" );
equals( clone[0].defaultChecked, !jQuery.support.noCloneEvent, "Checked input defaultChecked cloned correctly" );
element = jQuery("<input type='text' value='foo'>");
clone = element.clone();
equals( clone[0].defaultValue, "foo", "Text input defaultValue cloned correctly" );
element = jQuery("<textarea>foo</textarea>");
clone = element.clone();
equals( clone[0].defaultValue, "foo", "Textarea defaultValue cloned correctly" );
});
if (!isLocal) { if (!isLocal) {
test("clone() on XML nodes", function() { test("clone() on XML nodes", function() {
expect(2); expect(2);
@ -1232,3 +1261,20 @@ test("jQuery.cleanData", function() {
return div; return div;
} }
}); });
test("jQuery.buildFragment - no plain-text caching (Bug #6779)", function() {
expect(1);
// DOM manipulation fails if added text matches an Object method
var $f = jQuery( "<div />" ).appendTo( "#main" ),
bad = [ "start-", "toString", "hasOwnProperty", "append", "here&there!", "-end" ];
for ( var i=0; i < bad.length; i++ ) {
try {
$f.append( bad[i] );
}
catch(e) {}
}
equals($f.text(), bad.join(''), "Cached strings that match Object properties");
$f.remove();
});