Merge branch '7608' of https://github.com/rwldrn/jquery into rwldrn-7608
authorjeresig <jeresig@gmail.com>
Mon, 17 Jan 2011 20:50:20 +0000 (15:50 -0500)
committerjeresig <jeresig@gmail.com>
Mon, 17 Jan 2011 20:50:20 +0000 (15:50 -0500)
22 files changed:
Makefile
Rakefile
build.xml
src/ajax.js
src/ajax/jsonp.js [new file with mode: 0644]
src/ajax/script.js [moved from src/transports/script.js with 67% similarity]
src/ajax/xhr.js [moved from src/transports/xhr.js with 58% similarity]
src/core.js
src/event.js
src/manipulation.js
src/transports/jsonp.js [deleted file]
src/traversing.js
test/data/errorWithText.php [new file with mode: 0644]
test/data/headers.php
test/data/jsonp.php
test/data/testinit.js
test/index.html
test/unit/ajax.js
test/unit/core.js
test/unit/event.js
test/unit/manipulation.js
version.txt

index cf98554..6a71722 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -24,9 +24,9 @@ BASE_FILES = ${SRC_DIR}/core.js\
        ${SRC_DIR}/manipulation.js\
        ${SRC_DIR}/css.js\
        ${SRC_DIR}/ajax.js\
-       ${SRC_DIR}/transports/jsonp.js\
-       ${SRC_DIR}/transports/script.js\
-       ${SRC_DIR}/transports/xhr.js\
+       ${SRC_DIR}/ajax/jsonp.js\
+       ${SRC_DIR}/ajax/script.js\
+       ${SRC_DIR}/ajax/xhr.js\
        ${SRC_DIR}/effects.js\
        ${SRC_DIR}/offset.js\
        ${SRC_DIR}/dimensions.js
index fd5fc18..bf7ee2b 100644 (file)
--- a/Rakefile
+++ b/Rakefile
@@ -22,9 +22,9 @@ base_files = %w{
   manipulation
   css
   ajax
-  transports/jsonp
-  transports/script
-  transports/xhr
+  ajax/jsonp
+  ajax/script
+  ajax/xhr
   effects
   offset
   dimensions
index d4cd39d..87b31e1 100644 (file)
--- a/build.xml
+++ b/build.xml
@@ -63,9 +63,9 @@
                        <fileset file="src/manipulation.js" />
                        <fileset file="src/css.js" />
                        <fileset file="src/ajax.js" />
-                       <fileset file="src/transports/jsonp.js" />
-                       <fileset file="src/transports/script.js" />
-                       <fileset file="src/transports/xhr.js" />
+                       <fileset file="src/ajax/jsonp.js" />
+                       <fileset file="src/ajax/script.js" />
+                       <fileset file="src/ajax/xhr.js" />
                        <fileset file="src/effects.js" />
                        <fileset file="src/offset.js" />
                        <fileset file="src/dimensions.js" />
index 32f75f6..871481d 100644 (file)
@@ -1,5 +1,5 @@
 (function( jQuery ) {
-       
+
 var r20 = /%20/g,
        rbracket = /\[\]$/,
        rhash = /#.*$/,
@@ -10,11 +10,12 @@ var r20 = /%20/g,
        rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
        rselectTextarea = /^(?:select|textarea)/i,
        rts = /([?&])_=[^&]*/,
-       rurl = /^(\w+:)?\/\/([^\/?#]+)/,
+       rurl = /^(\w+:)?\/\/([^\/?#:]+)(?::(\d+))?/,
+       rCRLF = /\r?\n/g,
 
        // Slice function
        sliceFunc = Array.prototype.slice,
-       
+
        // Keep a copy of the old load method
        _load = jQuery.fn.load;
 
@@ -60,26 +61,34 @@ jQuery.fn.extend({
                        type: type,
                        dataType: "html",
                        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 ( 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
                                        self.html( selector ?
                                                // Create a dummy div to hold the results
                                                jQuery("<div>")
                                                        // inject the contents of the document in, removing the scripts
                                                        // to avoid any 'Permission Denied' errors in IE
-                                                       .append(res.responseText.replace(rscript, ""))
+                                                       .append(responseText.replace(rscript, ""))
 
                                                        // Locate the specified elements
                                                        .find(selector) :
 
                                                // If not, just inject the full result
-                                               res.responseText );
+                                               responseText );
                                }
 
                                if ( callback ) {
-                                       self.each( callback, [res.responseText, status, res] );
+                                       self.each( callback, [responseText, status, jXHR] );
                                }
                        }
                });
@@ -107,9 +116,9 @@ jQuery.fn.extend({
                                null :
                                jQuery.isArray(val) ?
                                        jQuery.map( val, function(val, i){
-                                               return {name: elem.name, value: val.replace(/\r?\n/g, "\r\n")};
+                                               return { name: elem.name, value: val.replace(rCRLF, "\r\n") };
                                        }) :
-                                       {name: elem.name, value: val.replace(/\r?\n/g, "\r\n")};
+                                       { name: elem.name, value: val.replace(rCRLF, "\r\n") };
                }).get();
        }
 });
@@ -151,7 +160,8 @@ jQuery.extend({
        },
 
        ajaxSetup: function( settings ) {
-               jQuery.extend( jQuery.ajaxSettings, settings );
+               jQuery.extend( true, jQuery.ajaxSettings, settings );
+               return this;
        },
 
        ajaxSettings: {
@@ -165,11 +175,12 @@ jQuery.extend({
                timeout: 0,
                data: null,
                dataType: null,
-               dataTypes: null,
                username: null,
                password: null,
                cache: null,
                traditional: false,
+               headers: {},
+               crossDomain: null,
                */
                xhr: function() {
                        return new window.XMLHttpRequest();
@@ -227,26 +238,26 @@ jQuery.extend({
        // Main method
        // (s is used internally)
        ajax: function( url , options , s ) {
-               
+
                // Handle varargs
                if ( arguments.length === 1 ) {
                        options = url;
                        url = options ? options.url : undefined;
                }
-               
+
                // Force options to be an object
                options = options || {};
-               
+
                // Get the url if provided separately
                options.url = url || options.url;
-               
+
                // Create the final options object
                s = jQuery.extend( true , {} , jQuery.ajaxSettings , options );
-               
+
                // We force the original context
                // (plain objects used as context get extended)
                s.context = options.context;
-               
+
                var // jQuery lists
                        jQuery_lastModified = jQuery.lastModified,
                        jQuery_etag = jQuery.etag,
@@ -256,6 +267,8 @@ jQuery.extend({
                        // Deferreds
                        deferred = jQuery.Deferred(),
                        completeDeferred = jQuery._Deferred(),
+                       // Status-dependent callbacks
+                       statusCode = s.statusCode || {},
                        // Headers (they are sent all at once)
                        requestHeaders = {},
                        // Response headers
@@ -265,15 +278,18 @@ jQuery.extend({
                        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 ) {
@@ -281,40 +297,45 @@ jQuery.extend({
                                        }
                                        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 ];
+
+                                       if ( state === 2 ) {
+
+                                               if ( responseHeaders === undefined ) {
+
+                                                       responseHeaders = {};
+
+                                                       if ( typeof responseHeadersString === "string" ) {
+
+                                                               while( ( match = rheaders.exec( responseHeadersString ) ) ) {
+                                                                       responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
+                                                               }
                                                        }
                                                }
+                                               match = responseHeaders[ key.toLowerCase() ];
+
+                                       } else {
+
+                                               match = null;
                                        }
-                                       return responseHeaders[ key.toLowerCase() ];
+
+                                       return match;
                                },
-                               
+
                                // Cancel the request
                                abort: function( statusText ) {
-                                       if ( transport && state !== 2 ) {
+                                       if ( transport ) {
                                                transport.abort( statusText || "abort" );
-                                               done( 0 , statusText );
                                        }
+                                       done( 0 , statusText );
                                        return this;
                                }
                        };
@@ -323,15 +344,19 @@ jQuery.extend({
                // 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;
-                       
+
+                       // Dereference transport for early garbage collection
+                       // (no matter how long the jXHR transport will be used
+                       transport = 0;
+
                        // Set readyState
                        jXHR.readyState = status ? 4 : 0;
 
@@ -342,35 +367,28 @@ jQuery.extend({
                        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" );
-                       }
-                       
+                               error;
+
                        // If successful, handle type chaining
-                       if ( statusText === "success" || statusText === "notmodified" ) {
-                               
+                       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;
                                        }
@@ -378,113 +396,154 @@ jQuery.extend({
                                                jQuery_etag[ s.url ] = etag;
                                        }
                                }
-                               
-                               if ( s.ifModified && statusText === "notmodified" ) {
-                                       
-                                       success = null;
+
+                               // 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,
-                                                       checker,
+                                                       // Conversion function
                                                        conv,
+                                                       // Conversion functions (when text is used in-between)
                                                        conv1,
                                                        conv2,
-                                                       convertion,
+                                                       // 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 ) {
-                                                               
-                                                                       conv = converters[ ( conversion = 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 ) {
-                                                               
-                                                               response = s.dataFilter( response );
+                                                               // 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;
-                                               
+
                                        }
                                }
-                               
-                       } else { // if not success, mark it as an error
-                               
-                                       error = error || statusText;
+
+                       // 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
@@ -493,126 +552,157 @@ jQuery.extend({
                                }
                        }
                }
-               
+
                // Attach deferreds
                deferred.promise( jXHR );
-               jXHR.success = jXHR.complete;
+               jXHR.success = jXHR.done;
                jXHR.error = jXHR.fail;
-               jXHR.complete = completeDeferred.complete;
+               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
-               var parts = rurl.exec( s.url.toLowerCase() ),
-                       loc = location;
-               s.crossDomain = !!( parts && ( parts[ 1 ] && parts[ 1 ] != loc.protocol || parts[ 2 ] != loc.host ) );
+               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" ) {
+               if ( s.data && s.processData && typeof s.data !== "string" ) {
                        s.data = jQuery.param( s.data , s.traditional );
                }
 
+               // Apply prefilters
+               jQuery.ajaxPrefilter( s , options );
+
+               // Uppercase the type
+               s.type = s.type.toUpperCase();
+
+               // Determine if request has content
+               s.hasContent = ! rnoContent.test( s.type );
+
                // Watch for a new set of requests
                if ( s.global && jQuery.active++ === 0 ) {
                        jQuery.event.trigger( "ajaxStart" );
                }
-               
-               // Get transport
-               transport = jQuery.ajax.prefilter( s ).transport( s );
-               
-               // If no transport, we auto-abort
-               if ( ! transport ) {
-                       
-                       done( 0 , "transport not found" );
-                       jXHR = false;
-                       
-               } else {
-                       
-                       // More options handling for requests with no content
-                       if ( ! s.hasContent ) {
-                               
-                               // If data is available, append data to url
-                               if ( s.data ) {
-                                       s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
-                               }
-                                                               
-                               // Add anti-cache in url if needed
-                               if ( s.cache === false ) {
-                                       
-                                       var ts = jQuery.now(),
-                                               // try replacing _= if it is there
-                                               ret = s.url.replace( rts , "$1_=" + ts );
-                                               
-                                       // if nothing was replaced, add timestamp to the end
-                                       s.url = ret + ( (ret == s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "");
-                               }
+
+               // 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;
                        }
-                       
-                       // Set the correct header, if data is being sent
-                       if ( ( s.data && s.hasContent ) || options.contentType ) {
-                               requestHeaders[ "content-type" ] = s.contentType;
+
+                       // 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 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 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 ];
+               }
+
+               // 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" );
+
+                               // Return false
+                               jXHR = false;
+
+               } else {
+
+                       // Install callbacks on deferreds
+                       for ( i in { success:1, error:1, complete:1 } ) {
+                               jXHR[ i ]( s[ 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;
-                                       
+
+                       // Get transport
+                       transport = jQuery.ajaxTransport( s );
+
+                       // If no transport, we auto-abort
+                       if ( ! transport ) {
+
+                               done( 0 , "notransport" );
+
                        } 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 ] );
-                               }
-                               
+                               state = jXHR.readyState = 1;
+
                                // 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);
@@ -622,7 +712,7 @@ jQuery.extend({
 
                                                done(0, "error", "" + e);
                                                jXHR = false;
-                                               
+
                                        // Simply rethrow otherwise
                                        } else {
                                                jQuery.error(e);
@@ -630,7 +720,7 @@ jQuery.extend({
                                }
                        }
                }
-               
+
                return jXHR;
        },
 
@@ -733,13 +823,13 @@ function ajax_selectOrExecute( structure , s ) {
                checked = {},
                flag,
                noSelect = structure !== "transports";
-               
+
        function initSearch( dataType ) {
 
                flag = transportDataType !== dataType && ! checked[ dataType ];
-               
+
                if ( flag ) {
-                       
+
                        checked[ dataType ] = 1;
                        transportDataType = dataType;
                        list = s[ structure ][ dataType ];
@@ -749,15 +839,15 @@ function ajax_selectOrExecute( structure , s ) {
 
                return flag;
        }
-       
+
        initSearch( dataTypes[ 0 ] );
 
        for ( i = 0 ; ( noSelect || ! selected ) && i <= length ; i++ ) {
-               
+
                if ( i === length ) {
-                       
+
                        initSearch( "*" );
-                       
+
                } else {
 
                        selected = list[ i ]( s , determineDataType );
@@ -773,12 +863,12 @@ function ajax_selectOrExecute( structure , s ) {
                }
        }
 
-       return noSelect ? jQuery.ajax : selected;
+       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,
@@ -789,41 +879,41 @@ function ajax_addElement( structure , args ) {
                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 );
@@ -831,29 +921,29 @@ function ajax_addElement( structure , args ) {
                        }
                }
        }
-       
-       return jQuery.ajax;
+
+       return jQuery;
 }
 
 // Install prefilter & transport methods
-jQuery.each( [ "prefilter" , "transport" ] , function( _ , name ) {
-       _ = name + "s";
-       jQuery.ajax[ name ] = function() {
+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 === "*" ) {
 
@@ -862,30 +952,30 @@ function determineDataType( s , ct , text , xml ) {
                                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
diff --git a/src/ajax/jsonp.js b/src/ajax/jsonp.js
new file mode 100644 (file)
index 0000000..883876f
--- /dev/null
@@ -0,0 +1,86 @@
+(function( jQuery ) {
+
+var jsc = jQuery.now(),
+       jsre = /(\=)(?:\?|%3F)(&|$)|()(?:\?\?|%3F%3F)()/i;
+
+// Default jsonp settings
+jQuery.ajaxSetup({
+       jsonp: "callback",
+       jsonpCallback: function() {
+               return "jsonp" + jsc++;
+       }
+
+// Detect, normalize options and install callbacks for jsonp requests
+// (dataIsString is used internally)
+}).ajaxPrefilter("json jsonp", function(s, originalSettings, dataIsString) {
+
+       dataIsString = ( typeof(s.data) === "string" );
+
+       if ( s.dataTypes[ 0 ] === "jsonp" ||
+               originalSettings.jsonpCallback ||
+               originalSettings.jsonp != null ||
+               s.jsonp !== false && ( jsre.test( s.url ) ||
+                               dataIsString && jsre.test( s.data ) ) ) {
+
+               var responseContainer,
+                       jsonpCallback = s.jsonpCallback =
+                               jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
+                       previous = window[ jsonpCallback ],
+                       url = s.url,
+                       data = s.data,
+                       replace = "$1" + jsonpCallback + "$2";
+
+               if ( s.jsonp !== false ) {
+                       url = url.replace( jsre, replace );
+                       if ( s.url === url ) {
+                               if ( dataIsString ) {
+                                       data = data.replace( jsre, replace );
+                               }
+                               if ( s.data === data ) {
+                                       // Add callback manually
+                                       url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
+                               }
+                       }
+               }
+
+               s.url = url;
+               s.data = data;
+
+               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.converters["script json"] = function() {
+                       if ( ! responseContainer ) {
+                               jQuery.error( jsonpCallback + " was not called" );
+                       }
+                       return responseContainer[ 0 ];
+               };
+
+               // force json dataType
+               s.dataTypes[ 0 ] = "json";
+
+               // Delegate to script
+               return "script";
+       }
+});
+
+})( jQuery );
similarity index 67%
rename from src/transports/script.js
rename to src/ajax/script.js
index d18f4d7..b0e576f 100644 (file)
@@ -1,39 +1,43 @@
 (function( jQuery ) {
 
-// Install text to script executor
-jQuery.extend( true, jQuery.ajaxSettings , {
+// Install script dataType
+jQuery.ajaxSetup({
 
        accepts: {
                script: "text/javascript, application/javascript"
        },
-       
+
        contents: {
                script: /javascript/
        },
-               
+
        converters: {
                "text script": jQuery.globalEval
        }
-} );
 
-// Bind script tag hack transport
-jQuery.ajax.transport("script", function(s) {
-       
-       // Handle cache special case
+// Handle cache's special case and global
+}).ajaxPrefilter("script", function(s) {
+
        if ( s.cache === undefined ) {
                s.cache = false;
        }
-       
-       // This transport only deals with cross domain get requests
-       if ( s.crossDomain && s.async && ( s.type === "GET" || ! s.data ) ) {
-               
+
+       if ( s.crossDomain ) {
+               s.type = "GET";
                s.global = false;
-               
+       }
+
+// Bind script tag hack transport
+}).ajaxTransport("script", function(s) {
+
+       // This transport only deals with cross domain requests
+       if ( s.crossDomain ) {
+
                var script,
                        head = document.getElementsByTagName("head")[0] || document.documentElement;
-               
+
                return {
-                       
+
                        send: function(_, callback) {
 
                                script = document.createElement("script");
@@ -43,36 +47,39 @@ jQuery.ajax.transport("script", function(s) {
                                if ( s.scriptCharset ) {
                                        script.charset = s.scriptCharset;
                                }
-                               
+
                                script.src = s.url;
-                               
+
                                // Attach handlers for all browsers
-                               script.onload = script.onreadystatechange = function( _ , statusText) {
-                                       
+                               script.onload = script.onreadystatechange = function( _ , isAbort ) {
+
                                        if ( ! script.readyState || /loaded|complete/.test( script.readyState ) ) {
-                                                               
+
                                                // Handle memory leak in IE
                                                script.onload = script.onreadystatechange = null;
-                                               
+
                                                // Remove the script
                                                if ( head && script.parentNode ) {
                                                        head.removeChild( script );
                                                }
-                                               
+
+                                               // Dereference the script
                                                script = 0;
-                                               
-                                               // Callback
-                                               callback( statusText ? 0 : 200, statusText || "success" );
+
+                                               // Callback if not abort
+                                               if ( ! isAbort ) {
+                                                       callback( 200, "success" );
+                                               }
                                        }
                                };
                                // Use insertBefore instead of appendChild  to circumvent an IE6 bug.
                                // This arises when a base node is used (#2709 and #4378).
                                head.insertBefore( script, head.firstChild );
                        },
-                       
-                       abort: function(statusText) {
+
+                       abort: function() {
                                if ( script ) {
-                                       script.onload( 0 , statusText );
+                                       script.onload(0,1);
                                }
                        }
                };
similarity index 58%
rename from src/transports/xhr.js
rename to src/ajax/xhr.js
index 5845087..34aa832 100644 (file)
@@ -1,29 +1,47 @@
 (function( jQuery ) {
 
-var // Next fake timer id
-       xhrPollingId = jQuery.now(),
-       
-       // Callbacks hashtable
+var // Next active xhr id
+       xhrId = jQuery.now(),
+
+       // active xhrs
        xhrs = {},
 
-       // #5280: see end of file
-       xhrUnloadAbortMarker = [];
+       // #5280: see below
+       xhrUnloadAbortInstalled;
+
+
+jQuery.ajaxTransport( function( s , determineDataType ) {
 
-       
-jQuery.ajax.transport( function( s , determineDataType ) {
-       
        // Cross domain only allowed if supported through XMLHttpRequest
        if ( ! s.crossDomain || jQuery.support.cors ) {
-               
+
                var callback;
-               
+
                return {
-                       
+
                        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(),
                                        handle;
-                               
+
                                // Open the socket
                                // Passing null username, generates a login popup on Opera (#2865)
                                if ( s.username ) {
@@ -31,24 +49,24 @@ jQuery.ajax.transport( function( s , determineDataType ) {
                                } else {
                                        xhr.open(s.type, s.url, s.async);
                                }
-                               
+
                                // Requested-With header
                                // Not set for crossDomain requests with no content
                                // (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"] ) {
                                        headers["x-requested-with"] = "XMLHttpRequest";
                                }
-                               
+
                                // Need an extra try/catch for cross domain requests in Firefox 3
                                try {
-                                       
+
                                        jQuery.each(headers, function(key,value) {
                                                xhr.setRequestHeader(key,value);
                                        });
-                                       
+
                                } catch(_) {}
-                               
+
                                // Do send the request
                                try {
                                        xhr.send( ( s.hasContent && s.data ) || null );
@@ -56,55 +74,48 @@ jQuery.ajax.transport( function( s , determineDataType ) {
                                        complete(0, "error", "" + e);
                                        return;
                                }
-                               
+
                                // Listener
-                               callback = function ( abortStatusText ) {
-                                       
+                               callback = function( _ , isAbort ) {
+
                                        // Was never called and is aborted or complete
-                                       if ( callback && ( abortStatusText || xhr.readyState === 4 ) ) {
-                                       
-                                               // Do not listen anymore
+                                       if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
+
+                                               // Only called once
+                                               callback = 0;
+
+                                               // Do not keep as active anymore
+                                               // and store back into pool
                                                if (handle) {
                                                        xhr.onreadystatechange = jQuery.noop;
                                                        delete xhrs[ handle ];
-                                                       handle = undefined;
                                                }
-                                               
-                                               callback = 0;
-                                               
-                                               // Get info
-                                               var status, statusText, response, responseHeaders;
-                                                       
-                                               if ( abortStatusText ) {
-                                                       
+
+                                               // If it's an abort
+                                               if ( isAbort ) {
+
+                                                       // Abort it manually if needed
                                                        if ( xhr.readyState !== 4 ) {
                                                                xhr.abort();
                                                        }
-                                                       
-                                                       // Stop here if unloadAbort
-                                                       if ( abortStatusText === xhrUnloadAbortMarker ) {
-                                                               return;
-                                                       }
-                                                       
-                                                       status = 0;
-                                                       statusText = abortStatusText;
-                                                       
                                                } 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
-                                                               
+
                                                                statusText = xhr.statusText;
-                                                               
+
                                                        } catch( e ) {
-                                                               
+
                                                                statusText = ""; // We normalize with Webkit giving an empty statusText
-                                                               
+
                                                        }
-                                                       
-                                                       responseHeaders = xhr.getAllResponseHeaders();
-                                                       
+
                                                        // Filter status for non standard behaviours
                                                        // (so many they seem to be the actual "standard")
                                                        status =
@@ -129,63 +140,44 @@ jQuery.ajax.transport( function( s , determineDataType ) {
                                                                                        :
                                                                                        status
                                                                        );
-                                                                       
-                                                       // Guess response if needed & update datatype accordingly
-                                                       if ( status >= 200 && status < 300 ) {
-                                                               response = 
-                                                                       determineDataType(
-                                                                               s,
-                                                                               xhr.getResponseHeader("content-type"),
-                                                                               xhr.responseText,
-                                                                               xhr.responseXML );
-                                                       }
+
+                                                       // Guess response & update dataType accordingly
+                                                       response =
+                                                               determineDataType(
+                                                                       s,
+                                                                       xhr.getResponseHeader("content-type"),
+                                                                       xhr.responseText,
+                                                                       xhr.responseXML );
+
+                                                       // Call complete
+                                                       complete(status,statusText,response,responseHeaders);
                                                }
-                                               
-                                               // Call complete
-                                               complete(status,statusText,response,responseHeaders);
                                        }
                                };
-                               
+
                                // if we're in sync mode
                                // or it's in cache and has been retrieved directly (IE6 & IE7)
                                // we need to manually fire the callback
                                if ( ! s.async || xhr.readyState === 4 ) {
-                                       
+
                                        callback();
-                                       
+
                                } else {
-                                       
-                                       // Listener is externalized to handle abort on unload
-                                       handle = xhrPollingId++;
+
+                                       // Add to list of active xhrs
+                                       handle = xhrId++;
                                        xhrs[ handle ] = xhr;
-                                       xhr.onreadystatechange = function() {
-                                               callback();
-                                       };
-                               }                                       
+                                       xhr.onreadystatechange = callback;
+                               }
                        },
-                       
-                       abort: function(statusText) {
+
+                       abort: function() {
                                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 );
index edd2c94..fbf6491 100644 (file)
@@ -3,7 +3,7 @@ var jQuery = (function() {
 // Define a local copy of jQuery
 var jQuery = function( selector, context ) {
                // The jQuery object is actually just the init constructor 'enhanced'
-               return new jQuery.fn.init( selector, context );
+               return new jQuery.fn.init( selector, context, rootjQuery );
        },
 
        // Map over jQuery in case of overwrite
@@ -59,10 +59,13 @@ var jQuery = function( selector, context ) {
 
        // Has the ready events already been bound?
        readyBound = false,
-       
+
        // The deferred used on DOM ready
        readyList,
 
+       // Promise methods
+       promiseMethods = "then done fail isResolved isRejected promise".split( " " ),
+
        // The ready event handler
        DOMContentLoaded,
 
@@ -78,7 +81,8 @@ var jQuery = function( selector, context ) {
        class2type = {};
 
 jQuery.fn = jQuery.prototype = {
-       init: function( selector, context ) {
+       constructor: jQuery,
+       init: function( selector, context, rootjQuery ) {
                var match, elem, ret, doc;
 
                // Handle $(""), $(null), or $(undefined)
@@ -112,6 +116,7 @@ jQuery.fn = jQuery.prototype = {
 
                                // HANDLE: $(html) -> $(array)
                                if ( match[1] ) {
+                                       context = context instanceof jQuery ? context[0] : context;
                                        doc = (context ? context.ownerDocument || context : document);
 
                                        // If a single string is passed in and it's a single tag
@@ -129,7 +134,7 @@ jQuery.fn = jQuery.prototype = {
 
                                        } else {
                                                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 );
@@ -171,7 +176,7 @@ jQuery.fn = jQuery.prototype = {
                        // HANDLE: $(expr, context)
                        // (which is just equivalent to: $(context).find(expr)
                        } else {
-                               return jQuery( context ).find( selector );
+                               return this.constructor( context ).find( selector );
                        }
 
                // HANDLE: $(function)
@@ -222,7 +227,7 @@ jQuery.fn = jQuery.prototype = {
        // (returning the new matched element set)
        pushStack: function( elems, name, selector ) {
                // Build a new jQuery matched element set
-               var ret = jQuery();
+               var ret = this.constructor();
 
                if ( jQuery.isArray( elems ) ) {
                        push.apply( ret, elems );
@@ -252,13 +257,13 @@ jQuery.fn = jQuery.prototype = {
        each: function( callback, args ) {
                return jQuery.each( this, callback, args );
        },
-       
+
        ready: function() {
                // Attach the listeners
                jQuery.bindReady();
-               
+
                // Change ready & apply
-               return ( jQuery.fn.ready = readyList.complete ).apply( this , arguments );
+               return ( jQuery.fn.ready = readyList.done ).apply( this , arguments );
        },
 
        eq: function( i ) {
@@ -287,7 +292,7 @@ jQuery.fn = jQuery.prototype = {
        },
 
        end: function() {
-               return this.prevObject || jQuery(null);
+               return this.prevObject || this.constructor(null);
        },
 
        // For internal use only.
@@ -406,7 +411,7 @@ jQuery.extend({
 
                        // If there are functions bound, to execute
                        readyList.fire( document , [ jQuery ] );
-                       
+
                        // Trigger any bound ready events
                        if ( jQuery.fn.trigger ) {
                                jQuery( document ).trigger( "ready" ).unbind( "ready" );
@@ -543,7 +548,7 @@ jQuery.extend({
                        jQuery.error( "Invalid JSON: " + data );
                }
        },
-       
+
        // Cross-browser xml parsing
        // (xml & tmp used internally)
        parseXML: function( data , xml , tmp ) {
@@ -556,13 +561,13 @@ jQuery.extend({
                        xml.async = "false";
                        xml.loadXML( data );
                }
-               
+
                tmp = xml.documentElement;
-               
+
                if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) {
                        jQuery.error( "Invalid XML: " + data );
                }
-               
+
                return xml;
        },
 
@@ -800,10 +805,10 @@ jQuery.extend({
        now: function() {
                return (new Date()).getTime();
        },
-       
+
        // Create a simple deferred (one callbacks list)
        _Deferred: function() {
-               
+
                var // callbacks list
                        callbacks = [],
                        // stored [ context , args ]
@@ -814,48 +819,48 @@ jQuery.extend({
                        cancelled,
                        // the deferred itself
                        deferred  = {
-                               
-                               // complete( f1, f2, ...)
-                               complete: function () {
-                                       
+
+                               // 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.complete.apply( deferred , elem );
+                                                               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 );
@@ -868,18 +873,18 @@ jQuery.extend({
                                        }
                                        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;
@@ -887,63 +892,90 @@ jQuery.extend({
                                        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                        
+                       failDeferred = jQuery._Deferred(),
+                       promise;
+
+               // Add errorDeferred methods, then and promise
                jQuery.extend( deferred , {
 
-                   then: function( completeCallbacks , failCallbacks ) {
-                       deferred.complete( completeCallbacks ).fail( failCallbacks );
-                       return this;
-                   },
-                       fail: failDeferred.complete,
+                       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 complete fail isResolved isRejected".split( " " ) , function( _ , method ) {
-                                       obj[ method ] = deferred[ method ];
-                               });
-                               obj.promise = function() {
-                                       return obj;
-                               };
+                       // (i is used internally)
+                       promise: function( obj , i ) {
+                               if ( obj == null ) {
+                                       if ( promise ) {
+                                               return promise;
+                                       }
+                                       promise = obj = {};
+                               }
+                               i = promiseMethods.length;
+                               while( i-- ) {
+                                       obj[ promiseMethods[ i ] ] = deferred[ promiseMethods[ i ] ];
+                               }
                                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();
+               var args = arguments,
+                       length = args.length,
+                       deferred = length <= 1 && object && jQuery.isFunction( object.promise ) ?
+                               object :
+                               jQuery.Deferred(),
+                       promise = deferred.promise(),
+                       resolveArray;
+
+               if ( length > 1 ) {
+                       resolveArray = new Array( length );
+                       jQuery.each( args, function( index, element, args ) {
+                               jQuery.when( element ).done( function( value ) {
+                                       args = arguments;
+                                       resolveArray[ index ] = args.length > 1 ? slice.call( args , 0 ) : value;
+                                       if( ! --length ) {
+                                               deferred.fire( promise, resolveArray );
+                                       }
+                               }).fail( function() {
+                                       deferred.fireReject( promise, arguments );
+                               });
+                               return !deferred.isRejected();
+                       });
+               } else if ( deferred !== object ) {
+                       deferred.resolve( object );
+               }
+               return promise;
        },
 
        // Use of jQuery.browser is frowned upon.
@@ -960,6 +992,25 @@ jQuery.extend({
                return { browser: match[1] || "", version: match[2] || "0" };
        },
 
+       subclass: function(){
+               function jQuerySubclass( selector, context ) {
+                       return new jQuerySubclass.fn.init( selector, context );
+               }
+               jQuerySubclass.superclass = this;
+               jQuerySubclass.fn = jQuerySubclass.prototype = this();
+               jQuerySubclass.fn.constructor = jQuerySubclass;
+               jQuerySubclass.subclass = this.subclass;
+               jQuerySubclass.fn.init = function init( selector, context ) {
+                       if (context && context instanceof jQuery && !(context instanceof jQuerySubclass)){
+                               context = jQuerySubclass(context);
+                       }
+                       return jQuery.fn.init.call( this, selector, context, rootjQuerySubclass );
+               };
+               jQuerySubclass.fn.init.prototype = jQuerySubclass.fn;
+               var rootjQuerySubclass = jQuerySubclass(document);
+               return jQuerySubclass;
+       },
+
        browser: {}
 });
 
@@ -1034,11 +1085,6 @@ function doScrollCheck() {
        jQuery.ready();
 }
 
-// Expose jQuery as an Asynchronous Module
-if ( typeof define === "function" ) {
-       define( "jquery", [], function () { return jQuery; } );
-}
-
 // Expose jQuery to the global object
 return (window.jQuery = window.$ = jQuery);
 
index 675e5ff..34cd91b 100644 (file)
@@ -603,7 +603,7 @@ jQuery.Event = function( src ) {
 
                // 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 ||
+               this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || 
                        src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;
 
        // Event type
index 96caa02..cf533c8 100644 (file)
@@ -420,15 +420,29 @@ function cloneFixAttributes(src, dest) {
        if ( nodeName === "object" ) {
                dest.outerHTML = src.outerHTML;
 
-       // IE6-8 fails to persist the checked state of a cloned checkbox
-       // or radio button
-       } else if ( nodeName === "input" && src.checked ) {
-               dest.defaultChecked = dest.checked = src.checked;
+       } else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
+               // IE6-8 fails to persist the checked state of a cloned checkbox
+               // or radio button. Worse, IE6-7 fail to give the cloned element
+               // 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
        // state when cloning options
        } else if ( nodeName === "option" ) {
                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
@@ -617,6 +631,11 @@ jQuery.extend({
                                                        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 ) {
diff --git a/src/transports/jsonp.js b/src/transports/jsonp.js
deleted file mode 100644 (file)
index aa30b5d..0000000
+++ /dev/null
@@ -1,85 +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) sneakily 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.ajax.prefilter("json jsonp", function(s) {
-       
-       var transportDataType = s.dataTypes[ 0 ];
-       
-       s.dataTypes[ 0 ] = "json";
-       
-       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;
-       }
-       
-// Bind transport to json dataType
-}).transport("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.converters["script json"] = function() {
-                       if ( ! responseContainer ) {
-                               jQuery.error( jsonpCallback + " was not called" );
-                       }
-                       return responseContainer[ 0 ];
-               };
-               
-               // Delegate to script transport
-               return "script";
-       }
-});
-
-})( jQuery );
index 689e901..b36ce3d 100644 (file)
@@ -6,7 +6,14 @@ var runtil = /Until$/,
        rmultiselector = /,/,
        isSimple = /^.[^:#\[\.,]*$/,
        slice = Array.prototype.slice,
-       POS = jQuery.expr.match.POS;
+       POS = jQuery.expr.match.POS,
+       // methods guaranteed to produce a unique set when starting from a unique set
+       guaranteedUnique = {
+               children: true,
+               contents: true,
+               next: true,
+               prev: true
+       };
 
 jQuery.fn.extend({
        find: function( selector ) {
@@ -196,7 +203,8 @@ jQuery.each({
        }
 }, function( name, fn ) {
        jQuery.fn[ name ] = function( until, selector ) {
-               var ret = jQuery.map( this, fn, until );
+               var ret = jQuery.map( this, fn, until ),
+        args = slice.call(arguments);
 
                if ( !runtil.test( name ) ) {
                        selector = until;
@@ -206,13 +214,13 @@ jQuery.each({
                        ret = jQuery.filter( selector, ret );
                }
 
-               ret = this.length > 1 ? jQuery.unique( ret ) : ret;
+               ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
 
                if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
                        ret = ret.reverse();
                }
 
-               return this.pushStack( ret, name, slice.call(arguments).join(",") );
+               return this.pushStack( ret, name, args.join(",") );
        };
 });
 
diff --git a/test/data/errorWithText.php b/test/data/errorWithText.php
new file mode 100644 (file)
index 0000000..abd8732
--- /dev/null
@@ -0,0 +1,5 @@
+<?php
+
+header("HTTP/1.0 400 Bad Request");
+
+echo "plain text message";
\ No newline at end of file
index c3cb729..d500b16 100644 (file)
@@ -6,15 +6,11 @@ $headers = array();
 
 foreach( $_SERVER as $key => $value ) {
 
-       if ( substr( $key , 0 , 5 ) == "HTTP_" ) {
-
-               $key = str_replace( "_" , "-" , substr( $key , 5) );
-               $headers[ $key ] = $value;
-
-       }
+       $key = str_replace( "_" , "-" , substr( $key , 0 , 5 ) == "HTTP_" ? substr( $key , 5 ) : $key );
+       $headers[ $key ] = $value;
 
 }
 
 foreach( explode( "_" , $_GET[ "keys" ] ) as $key ) {
-       echo "$key: " . $headers[ strtoupper( $key ) ] . "\n";
+       echo "$key: " . @$headers[ strtoupper( $key ) ] . "\n";
 }
index 9ae1d84..6c13d72 100644 (file)
@@ -1,6 +1,10 @@
 <?php
 error_reporting(0);
 $callback = $_REQUEST['callback'];
+if ( ! $callback ) {
+       $callback = explode("?",end(explode("/",$_SERVER['REQUEST_URI'])));
+       $callback = $callback[0];
+}
 $json = $_REQUEST['json'];
 if($json) {
        echo $callback . '([ {"name": "John", "age": 21}, {"name": "Peter", "age": 25 } ])';
index 8f431fb..a66f71d 100644 (file)
@@ -1,12 +1,7 @@
 var jQuery = this.jQuery || "jQuery", // For testing .noConflict()
        $ = this.$ || "$",
        originaljQuery = jQuery,
-       original$ = $,
-       commonJSDefined;
-
-function define(module, dependencies, callback) {
-       commonJSDefined = callback();
-}
+       original$ = $;
 
 /**
  * Returns an array of elements with the given IDs, eg.
index accd349..bbeda63 100644 (file)
@@ -20,9 +20,9 @@
        <script src="../src/manipulation.js"></script>
        <script src="../src/css.js"></script>
        <script src="../src/ajax.js"></script>
-       <script src="../src/transports/jsonp.js"></script>
-       <script src="../src/transports/script.js"></script>
-       <script src="../src/transports/xhr.js"></script>
+       <script src="../src/ajax/jsonp.js"></script>
+       <script src="../src/ajax/script.js"></script>
+       <script src="../src/ajax/xhr.js"></script>
        <script src="../src/effects.js"></script>
        <script src="../src/offset.js"></script>
        <script src="../src/dimensions.js"></script>
index 270d32f..f26ebad 100644 (file)
@@ -135,7 +135,7 @@ test("jQuery.ajax() - success callbacks (oncomplete binding)", function() {
                                .error(function(){ ok(false, "error"); })
                                .complete(function(){ start(); });
                        }
-               })
+               });
        }, 13);
 });
 
@@ -173,7 +173,7 @@ test("jQuery.ajax() - success callbacks (very late binding)", function() {
                                        .complete(function(){ start(); });
                                },100);
                        }
-               })
+               });
        }, 13);
 });
 
@@ -240,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() {
 
        expect( 2 );
@@ -276,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() {
        expect(3);
 
@@ -305,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() {
        expect( 1 );
        stop();
@@ -438,7 +583,7 @@ test("jQuery.ajax context modification", function() {
 
        stop();
 
-       var obj = {}
+       var obj = {};
 
        jQuery.ajax({
                url: url("data/name.html"),
@@ -902,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() {
        expect(2);
        stop();
@@ -957,217 +1114,249 @@ test("jQuery.getScript(String, Function) - no callback", function() {
        });
 });
 
-test("jQuery.ajax() - JSONP, Local", function() {
-       expect(9);
+jQuery.each( [ "Same Domain", "Cross Domain" ] , function( crossDomain , label ) {
 
-       var count = 0;
-       function plus(){ if ( ++count == 9 ) start(); }
-
-       stop();
-
-       jQuery.ajax({
-               url: "data/jsonp.php",
-               dataType: "jsonp",
-               success: function(data){
-                       ok( data.data, "JSON results returned (GET, no callback)" );
-                       plus();
-               },
-               error: function(data){
-                       ok( false, "Ajax error JSON (GET, no callback)" );
-                       plus();
-               }
-       });
+       test("jQuery.ajax() - JSONP, " + label, function() {
+               expect(17);
 
-       jQuery.ajax({
-               url: "data/jsonp.php?callback=?",
-               dataType: "jsonp",
-               success: function(data){
-                       ok( data.data, "JSON results returned (GET, url callback)" );
-                       plus();
-               },
-               error: function(data){
-                       ok( false, "Ajax error JSON (GET, url callback)" );
-                       plus();
-               }
-       });
+               var count = 0;
+               function plus(){ if ( ++count == 17 ) start(); }
 
-       jQuery.ajax({
-               url: "data/jsonp.php",
-               dataType: "jsonp",
-               data: "callback=?",
-               success: function(data){
-                       ok( data.data, "JSON results returned (GET, data callback)" );
-                       plus();
-               },
-               error: function(data){
-                       ok( false, "Ajax error JSON (GET, data callback)" );
-                       plus();
-               }
-       });
+               stop();
 
-       jQuery.ajax({
-               url: "data/jsonp.php",
-               dataType: "jsonp",
-               jsonp: "callback",
-               success: function(data){
-                       ok( data.data, "JSON results returned (GET, data obj callback)" );
-                       plus();
-               },
-               error: function(data){
-                       ok( false, "Ajax error JSON (GET, data obj callback)" );
-                       plus();
-               }
-       });
+               jQuery.ajax({
+                       url: "data/jsonp.php",
+                       dataType: "jsonp",
+                       crossDomain: crossDomain,
+                       success: function(data){
+                               ok( data.data, "JSON results returned (GET, no callback)" );
+                               plus();
+                       },
+                       error: function(data){
+                               ok( false, "Ajax error JSON (GET, no callback)" );
+                               plus();
+                       }
+               });
 
-       jQuery.ajax({
-               url: "data/jsonp.php",
-               dataType: "jsonp",
-               jsonpCallback: "jsonpResults",
-               success: function(data){
-                       ok( data.data, "JSON results returned (GET, custom callback name)" );
-                       plus();
-               },
-               error: function(data){
-                       ok( false, "Ajax error JSON (GET, custom callback name)" );
-                       plus();
-               }
-       });
+               jQuery.ajax({
+                       url: "data/jsonp.php?callback=?",
+                       dataType: "jsonp",
+                       crossDomain: crossDomain,
+                       success: function(data){
+                               ok( data.data, "JSON results returned (GET, url callback)" );
+                               plus();
+                       },
+                       error: function(data){
+                               ok( false, "Ajax error JSON (GET, url callback)" );
+                               plus();
+                       }
+               });
 
-       jQuery.ajax({
-               type: "POST",
-               url: "data/jsonp.php",
-               dataType: "jsonp",
-               success: function(data){
-                       ok( data.data, "JSON results returned (POST, no callback)" );
-                       plus();
-               },
-               error: function(data){
-                       ok( false, "Ajax error JSON (GET, data obj callback)" );
-                       plus();
-               }
-       });
+               jQuery.ajax({
+                       url: "data/jsonp.php",
+                       dataType: "jsonp",
+                       crossDomain: crossDomain,
+                       data: "callback=?",
+                       success: function(data){
+                               ok( data.data, "JSON results returned (GET, data callback)" );
+                               plus();
+                       },
+                       error: function(data){
+                               ok( false, "Ajax error JSON (GET, data callback)" );
+                               plus();
+                       }
+               });
 
-       jQuery.ajax({
-               type: "POST",
-               url: "data/jsonp.php",
-               data: "callback=?",
-               dataType: "jsonp",
-               success: function(data){
-                       ok( data.data, "JSON results returned (POST, data callback)" );
-                       plus();
-               },
-               error: function(data){
-                       ok( false, "Ajax error JSON (POST, data callback)" );
-                       plus();
-               }
-       });
+               jQuery.ajax({
+                       url: "data/jsonp.php?callback=??",
+                       dataType: "jsonp",
+                       crossDomain: crossDomain,
+                       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({
-               type: "POST",
-               url: "data/jsonp.php",
-               jsonp: "callback",
-               dataType: "jsonp",
-               success: function(data){
-                       ok( data.data, "JSON results returned (POST, data obj callback)" );
-                       plus();
-               },
-               error: function(data){
-                       ok( false, "Ajax error JSON (POST, data obj callback)" );
-                       plus();
-               }
-       });
+               jQuery.ajax({
+                       url: "data/jsonp.php",
+                       dataType: "jsonp",
+                       crossDomain: crossDomain,
+                       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();
+                       }
+               });
 
-       //#7578
-       jQuery.ajax({
-               url: "data/jsonp.php",
-               dataType: "jsonp",
-               beforeSend: function(){
-                       strictEqual( this.cache, false, "cache must be false on JSON request" );
-                       plus();
-                       return false;
-               }
-       });
-});
+               jQuery.ajax({
+                       url: "data/jsonp.php/??",
+                       dataType: "jsonp",
+                       crossDomain: crossDomain,
+                       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();
+                       }
+               });
 
-test("jQuery.ajax() - JSONP - Custom JSONP Callback", function() {
-       expect(1);
-       stop();
+               jQuery.ajax({
+                       url: "data/jsonp.php/???json=1",
+                       dataType: "jsonp",
+                       crossDomain: crossDomain,
+                       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();
+                       }
+               });
 
-       window.jsonpResults = function(data) {
-               ok( data.data, "JSON results returned (GET, custom callback function)" );
-               window.jsonpResults = undefined;
-               start();
-       };
+               jQuery.ajax({
+                       url: "data/jsonp.php",
+                       dataType: "jsonp",
+                       crossDomain: crossDomain,
+                       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({
-               url: "data/jsonp.php",
-               dataType: "jsonp",
-               jsonpCallback: "jsonpResults"
-       });
-});
+               jQuery.ajax({
+                       url: "data/jsonp.php",
+                       dataType: "jsonp",
+                       crossDomain: crossDomain,
+                       jsonp: "callback",
+                       success: function(data){
+                               ok( data.data, "JSON results returned (GET, data obj callback)" );
+                               plus();
+                       },
+                       error: function(data){
+                               ok( false, "Ajax error JSON (GET, data obj callback)" );
+                               plus();
+                       }
+               });
 
-test("jQuery.ajax() - JSONP, Remote", function() {
-       expect(4);
+               window.jsonpResults = function(data) {
+                       ok( data.data, "JSON results returned (GET, custom callback function)" );
+                       window.jsonpResults = undefined;
+                       plus();
+               };
 
-       var count = 0;
-       function plus(){ if ( ++count == 4 ) start(); }
+               jQuery.ajax({
+                       url: "data/jsonp.php",
+                       dataType: "jsonp",
+                       crossDomain: crossDomain,
+                       jsonpCallback: "jsonpResults",
+                       success: function(data){
+                               ok( data.data, "JSON results returned (GET, custom callback name)" );
+                               plus();
+                       },
+                       error: function(data){
+                               ok( false, "Ajax error JSON (GET, custom callback name)" );
+                               plus();
+                       }
+               });
 
-       var base = window.location.href.replace(/[^\/]*$/, "");
+               jQuery.ajax({
+                       type: "POST",
+                       url: "data/jsonp.php",
+                       dataType: "jsonp",
+                       crossDomain: crossDomain,
+                       success: function(data){
+                               ok( data.data, "JSON results returned (POST, no callback)" );
+                               plus();
+                       },
+                       error: function(data){
+                               ok( false, "Ajax error JSON (GET, data obj callback)" );
+                               plus();
+                       }
+               });
 
-       stop();
+               jQuery.ajax({
+                       type: "POST",
+                       url: "data/jsonp.php",
+                       data: "callback=?",
+                       dataType: "jsonp",
+                       crossDomain: crossDomain,
+                       success: function(data){
+                               ok( data.data, "JSON results returned (POST, data callback)" );
+                               plus();
+                       },
+                       error: function(data){
+                               ok( false, "Ajax error JSON (POST, data callback)" );
+                               plus();
+                       }
+               });
 
-       jQuery.ajax({
-               url: base + "data/jsonp.php",
-               dataType: "jsonp",
-               success: function(data){
-                       ok( data.data, "JSON results returned (GET, no callback)" );
-                       plus();
-               },
-               error: function(data){
-                       ok( false, "Ajax error JSON (GET, no callback)" );
-                       plus();
-               }
-       });
+               jQuery.ajax({
+                       type: "POST",
+                       url: "data/jsonp.php",
+                       jsonp: "callback",
+                       dataType: "jsonp",
+                       crossDomain: crossDomain,
+                       success: function(data){
+                               ok( data.data, "JSON results returned (POST, data obj callback)" );
+                               plus();
+                       },
+                       error: function(data){
+                               ok( false, "Ajax error JSON (POST, data obj callback)" );
+                               plus();
+                       }
+               });
 
-       jQuery.ajax({
-               url: base + "data/jsonp.php?callback=?",
-               dataType: "jsonp",
-               success: function(data){
-                       ok( data.data, "JSON results returned (GET, url callback)" );
-                       plus();
-               },
-               error: function(data){
-                       ok( false, "Ajax error JSON (GET, url callback)" );
-                       plus();
-               }
-       });
+               //#7578
+               jQuery.ajax({
+                       url: "data/jsonp.php",
+                       dataType: "jsonp",
+                       crossDomain: crossDomain,
+                       beforeSend: function(){
+                               strictEqual( this.cache, false, "cache must be false on JSON request" );
+                               plus();
+                               return false;
+                       }
+               });
 
-       jQuery.ajax({
-               url: base + "data/jsonp.php",
-               dataType: "jsonp",
-               data: "callback=?",
-               success: function(data){
-                       ok( data.data, "JSON results returned (GET, data callback)" );
-                       plus();
-               },
-               error: function(data){
-                       ok( false, "Ajax error JSON (GET, data callback)" );
-                       plus();
-               }
-       });
+               jQuery.ajax({
+                       url: "data/jsonp.php?callback=XXX",
+                       dataType: "jsonp",
+                       jsonp: false,
+                       jsonpCallback: "XXX",
+                       crossDomain: crossDomain,
+                       beforeSend: function() {
+                               ok( /^data\/jsonp.php\?callback=XXX&_=\d+$/.test( this.url ) ,
+                                       "The URL wasn't messed with (GET, custom callback name with no url manipulation)" );
+                               plus();
+                       },
+                       success: function(data){
+                               ok( data.data, "JSON results returned (GET, custom callback name with no url manipulation)" );
+                               plus();
+                       },
+                       error: function(data){
+                               ok( false, "Ajax error JSON (GET, custom callback name with no url manipulation)" );
+                               plus();
+                       }
+               });
 
-       jQuery.ajax({
-               url: base + "data/jsonp.php",
-               dataType: "jsonp",
-               jsonp: "callback",
-               success: function(data){
-                       ok( data.data, "JSON results returned (GET, data obj callback)" );
-                       plus();
-               },
-               error: function(data){
-                       ok( false, "Ajax error JSON (GET, data obj callback)" );
-                       plus();
-               }
        });
 });
 
@@ -1522,7 +1711,7 @@ test("data option: evaluate function values (#2806)", function() {
                        equals( result, "key=value" );
                        start();
                }
-       })
+       });
 });
 
 test("data option: empty bodies for non-GET requests", function() {
@@ -1535,7 +1724,7 @@ test("data option: empty bodies for non-GET requests", function() {
                        equals( result, "" );
                        start();
                }
-       })
+       });
 });
 
 test("jQuery.ajax - If-Modified-Since support", function() {
@@ -1560,7 +1749,7 @@ test("jQuery.ajax - If-Modified-Since support", function() {
                                                ok(true, "Opera is incapable of doing .setRequestHeader('If-Modified-Since').");
                                        } else {
                                                equals(status, "notmodified");
-                                               ok(data == null, "response body should be empty")
+                                               ok(data == null, "response body should be empty");
                                        }
                                        start();
                        },
@@ -1607,7 +1796,7 @@ test("jQuery.ajax - Etag support", function() {
                                                ok(true, "Opera is incapable of doing .setRequestHeader('If-None-Match').");
                                        } else {
                                                equals(status, "notmodified");
-                                               ok(data == null, "response body should be empty")
+                                               ok(data == null, "response body should be empty");
                                        }
                                        start();
                        },
@@ -1638,27 +1827,21 @@ test("jQuery ajax - failing cross-domain", function() {
        stop();
 
        var i = 2;
-       
-       if ( jQuery.ajax({
+
+       jQuery.ajax({
                url: 'http://somewebsitethatdoesnotexist-67864863574657654.com',
                success: function(){ ok( false , "success" ); },
                error: function(xhr,_,e){ ok( true , "file not found: " + xhr.status + " => " + e ); },
                complete: function() { if ( ! --i ) start(); }
-       }) === false ) {
-               ok( true , "no transport" );
-               if ( ! --i ) start();
-       }
-       
-       if ( jQuery.ajax({
+       });
+
+       jQuery.ajax({
                url: 'http://www.google.com',
                success: function(){ ok( false , "success" ); },
                error: function(xhr,_,e){ ok( true , "access denied: " + xhr.status + " => " + e ); },
                complete: function() { if ( ! --i ) start(); }
-       }) === false ) {
-               ok( true , "no transport" );
-               if ( ! --i ) start();
-       }
-       
+       });
+
 });
 
 test("jQuery ajax - atom+xml", function() {
@@ -1689,6 +1872,76 @@ test( "jQuery.ajax - Location object as url (#7531)", 1, function () {
        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 ) );
+
+       });
+
+});
+
 }
 
 //}
\ No newline at end of file
index 1fc2a4a..88f7609 100644 (file)
@@ -14,8 +14,6 @@ test("Basic requirements", function() {
 test("jQuery()", function() {
        expect(24);
 
-       strictEqual( commonJSDefined, jQuery, "CommonJS registered (Bug #7102)" );
-
        // Basic constructor's behavior
 
        equals( jQuery().length, 0, "jQuery() === jQuery([])" );
@@ -23,7 +21,7 @@ test("jQuery()", function() {
        equals( jQuery(null).length, 0, "jQuery(null) === jQuery([])" );
        equals( jQuery("").length, 0, "jQuery('') === jQuery([])" );
 
-       var obj = jQuery("div")
+       var obj = jQuery("div");
        equals( jQuery(obj).selector, "div", "jQuery(jQueryObj) == jQueryObj" );
 
                // can actually yield more than one, when iframes are included, the window is an array as well
@@ -86,6 +84,11 @@ test("jQuery()", function() {
 
        exec = true;
        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() {
@@ -906,129 +909,153 @@ test("jQuery.parseJSON", function(){
 });
 
 test("jQuery._Deferred()", function() {
-       
+
        expect( 10 );
-       
+
        var deferred,
                object,
                test;
-       
+
        deferred = jQuery._Deferred();
-               
+
        test = false;
-               
-       deferred.complete( function( value ) {
+
+       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.complete( function( value ) {
+
+       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.complete( function() {
+
+       deferred.done( function() {
                ok( false , "Cancel was ignored" );
                test = false;
        } );
-       
+
        ok( test , "Test cancel" );
-       
+
        deferred = jQuery._Deferred().resolve();
-       
+
        try {
-               deferred.complete( function() {
+               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.complete();
+               deferred.done();
        }
-       
+
        test = "";
-       deferred = jQuery._Deferred().complete( function() {
-               
+       deferred = jQuery._Deferred().done( function() {
+
                test += "A";
-               
+
        }, function() {
-               
+
                test += "B";
-               
+
        } ).resolve();
-       
-       strictEqual( test , "AB" , "Test multiple complete parameters" );
-       
+
+       strictEqual( test , "AB" , "Test multiple done parameters" );
+
        test = "";
-       
-       deferred.complete( function() {
-               
-               deferred.complete( function() {
-                       
+
+       deferred.done( function() {
+
+               deferred.done( function() {
+
                        test += "C";
-                       
+
                } );
-               
+
                test += "A";
-               
+
        }, function() {
-               
+
                test += "B";
        } );
-       
-       strictEqual( test , "ABC" , "Test complete callbacks order" );
-       
+
+       strictEqual( test , "ABC" , "Test done callbacks order" );
+
        deferred = jQuery._Deferred();
-       
-       deferred.fire( jQuery , [ document ] ).complete( function( doc ) {
+
+       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 );
-       
+
+       expect( 10 );
+
        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" );
        });
+
+       ( new jQuery.Deferred( function( defer ) {
+               strictEqual( this , defer , "Defer passed as this & first argument (new)" );
+               this.resolve( "done" );
+       }) ).then( function( value ) {
+               strictEqual( value , "done" , "Passed function executed (new)" );
+       });
+
+       ( new jQuery.Deferred() ).resolve().then( function() {
+               ok( true , "Success on resolve (new)" );
+       }, function() {
+               ok( false , "Error on resolve (new)" );
+       });
+
+       ( new jQuery.Deferred() ).reject().then( function() {
+               ok( false , "Success on reject (new)" );
+       }, function() {
+               ok( true , "Error on reject (new)" );
+       });
+
+       var tmp = jQuery.Deferred();
+
+       strictEqual( tmp.promise() , tmp.promise() , "Test deferred always return same promise" );
+       strictEqual( tmp.promise() , tmp.promise().promise() , "Test deferred's promise always return same promise as deferred" );
 });
-       
+
 test("jQuery.when()", function() {
-       
-       expect( 21 );
-       
+
+       expect( 23 );
+
        // Some other objects
        jQuery.each( {
-               
+
                "an empty string": "",
                "a non-empty string": "some string",
                "zero": 0,
@@ -1038,17 +1065,21 @@ test("jQuery.when()", function() {
                "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" );
-               
+
        } );
-       
+
+       ok( jQuery.isFunction( jQuery.when().then( function( resolveValue ) {
+               strictEqual( resolveValue , undefined , "Test the promise was resolved with no parameter" );
+       } ).promise ) , "Test calling when with no parameter 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 );
@@ -1060,3 +1091,106 @@ test("jQuery.when()", function() {
                });
        }
 });
+
+test("jQuery.when() - joined", function() {
+
+       expect(8);
+
+       jQuery.when( 1, 2, 3 ).done( function( a, b, c ) {
+               strictEqual( a , 1 , "Test first param is first resolved value - non-observables" );
+               strictEqual( b , 2 , "Test second param is second resolved value - non-observables" );
+               strictEqual( c , 3 , "Test third param is third resolved value - non-observables" );
+       }).fail( function() {
+               ok( false , "Test the created deferred was resolved - non-observables");
+       });
+
+       var successDeferred = jQuery.Deferred().resolve( 1 , 2 , 3 ),
+               errorDeferred = jQuery.Deferred().reject( "error" , "errorParam" );
+
+       jQuery.when( 1 , successDeferred , 3 ).done( function( a, b, c ) {
+               strictEqual( a , 1 , "Test first param is first resolved value - resolved observable" );
+               same( b , [ 1 , 2 , 3 ] , "Test second param is second resolved value - resolved observable" );
+               strictEqual( c , 3 , "Test third param is third resolved value - resolved observable" );
+       }).fail( function() {
+               ok( false , "Test the created deferred was resolved - resolved observable");
+       });
+
+       jQuery.when( 1 , errorDeferred , 3 ).done( function() {
+               ok( false , "Test the created deferred was rejected - rejected observable");
+       }).fail( function( error , errorParam ) {
+               strictEqual( error , "error" , "Test first param is first rejected value - rejected observable" );
+               strictEqual( errorParam , "errorParam" , "Test second param is second rejected value - rejected observable" );
+       });
+});
+
+test("jQuery.subclass", function(){
+       expect(378);
+
+       var Subclass = jQuery.subclass(),
+                       SubclassSubclass = Subclass.subclass(),
+                       jQueryDocument = jQuery(document),
+                       selectors, contexts, methods, method, arg, description;
+
+       jQueryDocument.toString = function(){ return 'jQueryDocument'; };
+
+       Subclass.fn.subclassMethod = function(){};
+       SubclassSubclass.fn.subclassSubclassMethod = function(){};
+
+       selectors = [
+               'body',
+               'html, body',
+               '<div></div>'
+       ];
+
+       methods = [ // all methods that return a new jQuery instance
+               ['eq', 1],
+               ['add', document],
+               ['end'],
+               ['has'],
+               ['closest', 'div'],
+               ['filter', document],
+               ['find', 'div']
+       ];
+
+       contexts = [undefined, document, jQueryDocument];
+
+       jQuery.each(selectors, function(i, selector){
+
+               jQuery.each(methods, function(){
+                       method = this[0];
+                       arg = this[1];
+
+                       jQuery.each(contexts, function(i, context){
+
+                               description = '("'+selector+'", '+context+').'+method+'('+(arg||'')+')';
+
+                               same(
+                                       jQuery(selector, context)[method](arg).subclassMethod, undefined,
+                                       'jQuery'+description+' doesnt have Subclass methods'
+                               );
+                               same(
+                                       jQuery(selector, context)[method](arg).subclassSubclassMethod, undefined,
+                                       'jQuery'+description+' doesnt have SubclassSubclass methods'
+                               );
+                               same(
+                                       Subclass(selector, context)[method](arg).subclassMethod, Subclass.fn.subclassMethod,
+                                       'Subclass'+description+' has Subclass methods'
+                               );
+                               same(
+                                       Subclass(selector, context)[method](arg).subclassSubclassMethod, undefined,
+                                       'Subclass'+description+' doesnt have SubclassSubclass methods'
+                               );
+                               same(
+                                       SubclassSubclass(selector, context)[method](arg).subclassMethod, Subclass.fn.subclassMethod,
+                                       'SubclassSubclass'+description+' has Subclass methods'
+                               );
+                               same(
+                                       SubclassSubclass(selector, context)[method](arg).subclassSubclassMethod, SubclassSubclass.fn.subclassSubclassMethod,
+                                       'SubclassSubclass'+description+' has SubclassSubclass methods'
+                               );
+
+                       });
+               });
+       });
+
+});
index b4672a8..80b7650 100644 (file)
@@ -295,15 +295,15 @@ test("live/delegate immediate propagation", function() {
        $p.undelegate( "click" );
 });
 
-test("bind/delegate bubbling, isDefaultPrevented (Bug #7793)", function() {
+test("bind/delegate bubbling, isDefaultPrevented", 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 );
+                               var e = document.createEvent( 'MouseEvents' );
+                               e.initEvent( "click", true, true ); 
                                $jq[0].dispatchEvent(e);
                        }
                        else if ( $jq[0].click ) {
@@ -314,7 +314,15 @@ test("bind/delegate bubbling, isDefaultPrevented (Bug #7793)", function() {
                e.preventDefault();
        });
        $main.delegate("#foo", "click", function(e) {
-               equals( e.isDefaultPrevented(), true, "isDefaultPrevented true passed to bubbled event" );
+               var orig = e.originalEvent;
+
+               if ( typeof(orig.defaultPrevented) === "boolean" || typeof(orig.returnValue) === "boolean" || orig.getPreventDefault ) {
+                       equals( e.isDefaultPrevented(), true, "isDefaultPrevented true passed to bubbled event" );
+
+               } else {
+                       // Opera < 11 doesn't implement any interface we can use, so give it a pass
+                       ok( true, "isDefaultPrevented not supported by this browser, test skipped" );
+               }
        });
        fakeClick( $anchor2 );
        $anchor2.unbind( "click" );
index e273cf0..559a076 100644 (file)
@@ -395,7 +395,7 @@ test("append(Function) with incoming value", 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);
 
        var element;
@@ -426,14 +426,6 @@ test("append the same fragment with events (Bug #6997, 5566)", function () {
 
        jQuery("#listWithTabIndex li").before(element);
        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() {
@@ -945,6 +937,28 @@ test("clone()", function() {
        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) {
 test("clone() on XML nodes", function() {
        expect(2);
index 7810cd6..574f968 100644 (file)
@@ -1 +1 @@
-1.4.5pre
\ No newline at end of file
+1.5pre
\ No newline at end of file