From: jeresig Date: Fri, 21 Jan 2011 16:20:05 +0000 (-0500) Subject: Merge branch '8013p' of https://github.com/rwldrn/jquery into rwldrn-8013p X-Git-Url: http://git.asbjorn.biz/?p=jquery.git;a=commitdiff_plain;h=61e80c55df9231c177d194ff075472898933c2c9;hp=33a67ffa9d85450f1edf1b1645b57f7641e2e2d2 Merge branch '8013p' of https://github.com/rwldrn/jquery into rwldrn-8013p --- diff --git a/Makefile b/Makefile index 2e6848d..c708db5 100644 --- a/Makefile +++ b/Makefile @@ -96,7 +96,10 @@ min: ${JQ_MIN} ${JQ_MIN}: ${JQ} @@echo "Building" ${JQ_MIN} - @@${COMPILER} ${JQ} > ${JQ_MIN} + @@${COMPILER} ${JQ} > ${JQ_MIN}.tmp + @@echo ";" >> ${JQ_MIN}.tmp + @@sed 's/\*\/(/*\/Ê©(/' ${JQ_MIN}.tmp | tr "Ê©" "\n" > ${JQ_MIN} + @@rm -rf ${JQ_MIN}.tmp clean: @@echo "Removing Distribution directory:" ${DIST_DIR} diff --git a/build/uglify.js b/build/uglify.js index cba0586..943ddd8 100644 --- a/build/uglify.js +++ b/build/uglify.js @@ -143,7 +143,7 @@ function show_copyright(comments) { if (c.type == "comment1") { ret += "//" + c.value + "\n"; } else { - ret += "/*" + c.value + "*/\n"; + ret += "/*" + c.value + "*/"; } } return ret; @@ -181,7 +181,7 @@ function squeeze_it(code) { }); if (options.ast) return sys.inspect(ast, null, null); - result += time_it("generate", function(){ return pro.gen_code(ast, options.beautify && options.beautify_options) }) + ";"; + result += time_it("generate", function(){ return pro.gen_code(ast, options.beautify && options.beautify_options) }); return result; } catch(ex) { sys.debug(ex.stack); diff --git a/src/ajax.js b/src/ajax.js index fc1ecfd..1872365 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -199,6 +199,11 @@ jQuery.extend({ json: /json/ }, + responseFields: { + xml: "responseXML", + text: "responseText" + }, + // Prefilters // 1) They are useful to introduce custom dataTypes (see transport/jsonp for an example) // 2) These are called: @@ -231,53 +236,7 @@ jQuery.extend({ // Parse text as xml "text xml": jQuery.parseXML - }, - - // Utility function that handles dataType when response is received - // (for those transports that can give text or xml responses) - determineDataType: function( ct , text , xml ) { - - var s = this, - contents = s.contents, - type, - regexp, - dataTypes = s.dataTypes, - transportDataType = dataTypes[0], - response; - - // Auto (xml, json, script or text determined given headers) - if ( transportDataType === "*" ) { - - for ( type in contents ) { - if ( ( regexp = contents[ type ] ) && regexp.test( ct ) ) { - transportDataType = dataTypes[0] = type; - break; - } - } - } - - // xml and parsed as such - if ( transportDataType === "xml" && - xml && - xml.documentElement /* #4958 */ ) { - - response = xml; - - // Text response was provided - } else { - - response = text; - - // If it's not really text, defer to converters - if ( transportDataType !== "text" ) { - dataTypes.unshift( "text" ); - } - - } - - return response; } - }, ajaxPrefilter: function( a , b ) { @@ -291,18 +250,16 @@ jQuery.extend({ // Main method ajax: function( url , options ) { - // Handle varargs - if ( arguments.length === 1 ) { + // If options is not an object, + // we simulate pre-1.5 signature + if ( typeof( options ) !== "object" ) { options = url; - url = options ? options.url : undefined; + url = undefined; } // Force options to be an object options = options || {}; - // Get the url if provided separately - options.url = url || options.url; - var // Create the final options object s = jQuery.extend( true , {} , jQuery.ajaxSettings , options ), // jQuery lists @@ -390,7 +347,7 @@ jQuery.extend({ // Callback for when everything is done // It is defined here because jslint complains if it is declared // at the end of the function (which would be more logical and readable) - function done( status , statusText , response , headers) { + function done( status , statusText , responses , headers) { // Called once if ( state === 2 ) { @@ -401,7 +358,7 @@ jQuery.extend({ state = 2; // Dereference transport for early garbage collection - // (no matter how long the jXHR transport will be used + // (no matter how long the jXHR object will be used) transport = undefined; // Set readyState @@ -415,22 +372,94 @@ jQuery.extend({ clearTimeout(timeoutTimer); } - var // Reference url - url = s.url, - // and ifModified status - ifModified = s.ifModified, + var // Reference dataTypes, converters and responseFields + dataTypes = s.dataTypes, + converters = s.converters, + responseFields = s.responseFields, + responseField, - // Is it a success? - isSuccess = 0, + // Flag to mark as success + isSuccess, // Stored success success, // Stored error error, - // Keep track of statusCode callbacks - oldStatusCode = statusCode; + // To keep track of statusCode based callbacks + oldStatusCode, - statusCode = undefined; + // Actual response + response; + + // If we got responses: + // - find the right one + // - update dataTypes accordingly + // - set responseXXX accordingly too + if ( responses ) { + + var contents = s.contents, + transportDataType = dataTypes[0], + ct, + type, + finalDataType, + firstDataType; + + // Auto (xml, json, script or text determined given headers) + if ( transportDataType === "*" ) { + + // Remove all auto types + while( dataTypes[0] === "*" ) { + dataTypes.shift(); + } + transportDataTypes = dataTypes[0]; + + // Get content type + ct = jXHR.getResponseHeader( "content-type" ); + + // Check if it's a known type + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( ( transportDataType = type ) ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( transportDataType in responses ) { + finalDataType = transportDataType; + } else { + // Try convertible dataTypes + for ( type in responses ) { + if ( ! firstDataType ) { + firstDataType = type; + } + if ( ! transportDataType || converters[ type + " " + transportDataType ] ) { + finalDataType = type; + break; + } + } + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We get the corresponding response + // and add the dataType to the list if needed + if ( finalDataType ) { + response = responses[ finalDataType ]; + if ( finalDataType !== transportDataType ) { + dataTypes.unshift( finalDataType ); + } + } + + // Fill responseXXX fields + for( type in responseFields ) { + if ( type in responses ) { + jXHR[ responseFields[ type ] ] = responses[ type ]; + } + } + } // If successful, handle type chaining if ( status >= 200 && status < 300 || status === 304 ) { @@ -452,15 +481,12 @@ jQuery.extend({ // 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 @@ -468,6 +494,7 @@ jQuery.extend({ try { var i, + tmp, // Current dataType current, // Previous dataType @@ -478,15 +505,7 @@ jQuery.extend({ conv, // Conversion functions (when text is used in-between) conv1, - conv2, - // Local references to dataTypes & converters - dataTypes = s.dataTypes, - converters = s.converters, - // DataType to responseXXX field mapping - responses = { - "xml": "XML", - "text": "Text" - }; + conv2; // For each dataType in the chain for( i = 0 ; i < dataTypes.length ; i++ ) { @@ -495,11 +514,9 @@ jQuery.extend({ // 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; + responseField = responseFields[ current ]; + if ( responseField && ! ( responseField in jXHR ) ) { + jXHR[ responseField ] = response; } // If this is not the first element @@ -508,26 +525,31 @@ jQuery.extend({ // Get the dataType to convert from prev = dataTypes[ i - 1 ]; - // If no catch-all and dataTypes are actually different + // If no auto and dataTypes are actually different if ( prev !== "*" && current !== "*" && prev !== current ) { // Get the converter conversion = prev + " " + current; conv = converters[ conversion ] || 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 there is no direct converter, search transitively + if ( ! conv ) { + conv1 = conv2 = undefined; + + for( conv1 in converters ) { + tmp = conv1.split( " " ); + if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) { + conv2 = converters[ tmp[ 1 ] + " " + current ]; + if ( conv2 ) { + conv1 = converters[ conv1 ]; + if ( conv1 === true ) { + conv = conv2; + } else if ( conv2 === true ) { + conv = conv1; + } + break; + } + } } } // If we found no converter, dispatch an error @@ -567,13 +589,7 @@ jQuery.extend({ // 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 @@ -582,12 +598,14 @@ jQuery.extend({ // Success/Error if ( isSuccess ) { - deferred.fire( callbackContext , [ success , statusText , jXHR ] ); + deferred.resolveWith( callbackContext , [ success , statusText , jXHR ] ); } else { - deferred.fireReject( callbackContext , [ jXHR , statusText , error ] ); + deferred.rejectWith( callbackContext , [ jXHR , statusText , error ] ); } // Status-dependent callbacks + oldStatusCode = statusCode; + statusCode = undefined; jXHR.statusCode( oldStatusCode ); if ( s.global ) { @@ -596,7 +614,7 @@ jQuery.extend({ } // Complete - completeDeferred.fire( callbackContext, [ jXHR , statusText ] ); + completeDeferred.resolveWith( callbackContext, [ jXHR , statusText ] ); if ( s.global ) { globalEventContext.trigger( "ajaxComplete" , [ jXHR , s] ); @@ -630,7 +648,8 @@ jQuery.extend({ }; // Remove hash character (#7531: and string promotion) - s.url = ( "" + s.url ).replace( rhash , "" ); + // We also use the url parameter if available + s.url = ( "" + ( url || s.url ) ).replace( rhash , "" ); // Extract dataTypes list s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( /\s+/ ); diff --git a/src/ajax/xhr.js b/src/ajax/xhr.js index 4acb700..7a4da2d 100644 --- a/src/ajax/xhr.js +++ b/src/ajax/xhr.js @@ -12,8 +12,8 @@ var // Next active xhr id // XHR used to determine supports properties testXHR; -// Create the request object; Microsoft failed to properly -// (This is still attached to ajaxSettings for backward compatibility reasons) +// Create the request object +// (This is still attached to ajaxSettings for backward compatibility) jQuery.ajaxSettings.xhr = window.ActiveXObject ? /* Microsoft failed to properly * implement the XMLHttpRequest in IE7 (can't request local files), @@ -128,7 +128,6 @@ if ( jQuery.support.ajax ) { callback = 0; // Do not keep as active anymore - // and store back into pool if (handle) { xhr.onreadystatechange = jQuery.noop; delete xhrs[ handle ]; @@ -146,8 +145,15 @@ if ( jQuery.support.ajax ) { // Get info var status = xhr.status, statusText, - response, - responseHeaders = xhr.getAllResponseHeaders(); + responseHeaders = xhr.getAllResponseHeaders(), + responses = {}, + xml = xhr.responseXML; + + // Construct response list + if ( xml && xml.documentElement /* #4958 */ ) { + responses.xml = xml; + } + responses.text = xhr.responseText; try { // Firefox throws an exception when accessing statusText for faulty cross-domain requests @@ -184,15 +190,8 @@ if ( jQuery.support.ajax ) { status ); - // Guess response & update dataType accordingly - response = - s.determineDataType( - xhr.getResponseHeader("content-type"), - xhr.responseText, - xhr.responseXML ); - // Call complete - complete(status,statusText,response,responseHeaders); + complete(status,statusText,responses,responseHeaders); } } }; diff --git a/src/core.js b/src/core.js index 9af2882..aa97202 100644 --- a/src/core.js +++ b/src/core.js @@ -134,7 +134,7 @@ jQuery.fn = jQuery.prototype = { } return jQuery.merge( this, selector ); - + // HANDLE: $("#id") } else { elem = document.getElementById( match[2] ); @@ -158,13 +158,6 @@ jQuery.fn = jQuery.prototype = { return this; } - // HANDLE: $("TAG") - } else if ( !context && !rnonword.test( selector ) ) { - this.selector = selector; - this.context = document; - selector = document.getElementsByTagName( selector ); - return jQuery.merge( this, selector ); - // HANDLE: $(expr, $(...)) } else if ( !context || context.jquery ) { return (context || rootjQuery).find( selector ); @@ -406,7 +399,7 @@ jQuery.extend({ } // If there are functions bound, to execute - readyList.fire( document , [ jQuery ] ); + readyList.resolveWith( document , [ jQuery ] ); // Trigger any bound ready events if ( jQuery.fn.trigger ) { @@ -844,7 +837,7 @@ jQuery.extend({ } if ( _fired ) { - deferred.fire( _fired[ 0 ] , _fired[ 1 ] ); + deferred.resolveWith( _fired[ 0 ] , _fired[ 1 ] ); } } @@ -852,7 +845,7 @@ jQuery.extend({ }, // resolve with given context and args - fire: function( context , args ) { + resolveWith: function( context , args ) { if ( ! cancelled && ! fired && ! firing ) { firing = 1; @@ -872,7 +865,7 @@ jQuery.extend({ // resolve with this as context and given arguments resolve: function() { - deferred.fire( jQuery.isFunction( this.promise ) ? this.promise() : this , arguments ); + deferred.resolveWith( jQuery.isFunction( this.promise ) ? this.promise() : this , arguments ); return this; }, @@ -908,7 +901,7 @@ jQuery.extend({ return this; }, fail: failDeferred.done, - fireReject: failDeferred.fire, + rejectWith: failDeferred.resolveWith, reject: failDeferred.resolve, isRejected: failDeferred.isResolved, // Get a promise for this deferred @@ -961,10 +954,10 @@ jQuery.extend({ args = arguments; resolveArray[ index ] = args.length > 1 ? slice.call( args , 0 ) : value; if( ! --length ) { - deferred.fire( promise, resolveArray ); + deferred.resolveWith( promise, resolveArray ); } }).fail( function() { - deferred.fireReject( promise, arguments ); + deferred.rejectWith( promise, arguments ); }); return !deferred.isRejected(); }); diff --git a/src/dimensions.js b/src/dimensions.js index 17b4f8f..e2d411d 100644 --- a/src/dimensions.js +++ b/src/dimensions.js @@ -35,8 +35,10 @@ jQuery.each([ "Height", "Width" ], function( i, name ) { if ( jQuery.isWindow( elem ) ) { // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode - return elem.document.compatMode === "CSS1Compat" && elem.document.documentElement[ "client" + name ] || - elem.document.body[ "client" + name ]; + // 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat + var docElemProp = elem.document.documentElement[ "client" + name ]; + return elem.document.compatMode === "CSS1Compat" && docElemProp || + elem.document.body[ "client" + name ] || docElemProp; // Get document width or height } else if ( elem.nodeType === 9 ) { diff --git a/src/event.js b/src/event.js index 2ddf288..2d53562 100644 --- a/src/event.js +++ b/src/event.js @@ -8,7 +8,6 @@ var rnamespaces = /\.(.*)$/, fcleanup = function( nm ) { return nm.replace(rescape, "\\$&"); }, - focusCounts = { focusin: 0, focusout: 0 }, eventKey = "events"; /* @@ -880,21 +879,17 @@ if ( document.addEventListener ) { jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { jQuery.event.special[ fix ] = { setup: function() { - if ( focusCounts[fix]++ === 0 ) { - document.addEventListener( orig, handler, true ); - } - }, - teardown: function() { - if ( --focusCounts[fix] === 0 ) { - document.removeEventListener( orig, handler, true ); - } + this.addEventListener( orig, handler, true ); + }, + teardown: function() { + this.removeEventListener( orig, handler, true ); } }; function handler( e ) { e = jQuery.event.fix( e ); e.type = fix; - return jQuery.event.trigger( e, null, e.target ); + return jQuery.event.handle.call( this, e ); } }); } diff --git a/src/traversing.js b/src/traversing.js index 929547c..90601df 100644 --- a/src/traversing.js +++ b/src/traversing.js @@ -141,7 +141,7 @@ jQuery.fn.extend({ add: function( selector, context ) { var set = typeof selector === "string" ? - jQuery( selector, context || this.context ) : + jQuery( selector, context ) : jQuery.makeArray( selector ), all = jQuery.merge( this.get(), set ); diff --git a/test/unit/ajax.js b/test/unit/ajax.js index d262988..b44f077 100644 --- a/test/unit/ajax.js +++ b/test/unit/ajax.js @@ -1911,9 +1911,9 @@ test( "jQuery.ajax - Location object as url (#7531)", 1, function () { test( "jQuery.ajax - statusCode" , function() { - var count = 10; + var count = 12; - expect( 16 ); + expect( 20 ); stop(); function countComplete() { @@ -1975,7 +1975,77 @@ test( "jQuery.ajax - statusCode" , function() { } }).statusCode( createStatusCodes( "all (immediately with method)" , isSuccess ) ); + var testString = ""; + + jQuery.ajax( url( uri ), { + success: function( a , b , jXHR ) { + ok( isSuccess , "success" ); + var statusCode = {}; + statusCode[ jXHR.status ] = function() { + testString += "B"; + }; + jXHR.statusCode( statusCode ); + testString += "A"; + }, + error: function( jXHR ) { + ok( ! isSuccess , "error" ); + var statusCode = {}; + statusCode[ jXHR.status ] = function() { + testString += "B"; + }; + jXHR.statusCode( statusCode ); + testString += "A"; + }, + complete: function() { + strictEqual( testString , "AB" , "Test statusCode callbacks are ordered like " + + ( isSuccess ? "success" : "error" ) + " callbacks" ); + countComplete(); + } + } ); + }); +}); + +test("jQuery.ajax - transitive conversions", function() { + + expect( 8 ); + + stop(); + + jQuery.when( + + jQuery.ajax( url("data/json.php") , { + converters: { + "json myjson": function( data ) { + ok( true , "converter called" ); + return data; + } + }, + dataType: "myjson", + success: function() { + ok( true , "Transitive conversion worked" ); + strictEqual( this.dataTypes[0] , "text" , "response was retrieved as text" ); + strictEqual( this.dataTypes[1] , "myjson" , "request expected myjson dataType" ); + } + }), + + jQuery.ajax( url("data/json.php") , { + converters: { + "json myjson": function( data ) { + ok( true , "converter called (*)" ); + return data; + } + }, + contents: false, /* headers are wrong so we ignore them */ + dataType: "* myjson", + success: function() { + ok( true , "Transitive conversion worked (*)" ); + strictEqual( this.dataTypes[0] , "text" , "response was retrieved as text (*)" ); + strictEqual( this.dataTypes[1] , "myjson" , "request expected myjson dataType (*)" ); + } + }) + + ).then( start , start ); }); diff --git a/test/unit/core.js b/test/unit/core.js index 8e57edf..30039bf 100644 --- a/test/unit/core.js +++ b/test/unit/core.js @@ -1002,7 +1002,7 @@ test("jQuery._Deferred()", function() { deferred = jQuery._Deferred(); - deferred.fire( jQuery , [ document ] ).done( function( doc ) { + deferred.resolveWith( jQuery , [ document ] ).done( function( doc ) { ok( this === jQuery && arguments.length === 1 && doc === document , "Test fire context & args" ); }); }); diff --git a/test/unit/event.js b/test/unit/event.js index 02824a9..e4caee8 100644 --- a/test/unit/event.js +++ b/test/unit/event.js @@ -1953,26 +1953,6 @@ test("window resize", function() { ok( !jQuery._data(window, "__events__"), "Make sure all the events are gone." ); }); -test("focusin bubbles", function() { - //create an input and focusin on it - var input = jQuery(""), order = 0; - - input.prependTo("body"); - - jQuery("body").bind("focusin.focusinBubblesTest",function(){ - equals(1,order++,"focusin on the body second") - }); - - input.bind("focusin.focusinBubblesTest",function(){ - equals(0,order++,"focusin on the element first") - }); - - input[0].focus(); - input.remove(); - - jQuery("body").unbind("focusin.focusinBubblesTest"); -}); - /* test("jQuery(function($) {})", function() { stop(); diff --git a/test/unit/traversing.js b/test/unit/traversing.js index f0471d7..56fed22 100644 --- a/test/unit/traversing.js +++ b/test/unit/traversing.js @@ -440,12 +440,13 @@ test("add(String|Element|Array|undefined)", function() { test("add(String, Context)", function() { expect(6); - - equals( jQuery(document).add("#form").length, 2, "Make sure that using regular context document still works." ); - equals( jQuery(document.body).add("#form").length, 2, "Using a body context." ); - equals( jQuery(document.body).add("#html").length, 1, "Using a body context." ); - - equals( jQuery(document).add("#form", document).length, 2, "Use a passed in document context." ); - equals( jQuery(document).add("#form", document.body).length, 2, "Use a passed in body context." ); - equals( jQuery(document).add("#html", document.body).length, 1, "Use a passed in body context." ); + + deepEqual( jQuery( "#firstp" ).add( "#ap" ).get(), q( "firstp", "ap" ), "Add selector to selector " ); + deepEqual( jQuery( document.getElementById("firstp") ).add( "#ap" ).get(), q( "firstp", "ap" ), "Add gEBId to selector" ); + deepEqual( jQuery( document.getElementById("firstp") ).add( document.getElementById("ap") ).get(), q( "firstp", "ap" ), "Add gEBId to gEBId" ); + + var ctx = document.getElementById("firstp"); + deepEqual( jQuery( "#firstp" ).add( "#ap", ctx ).get(), q( "firstp" ), "Add selector to selector " ); + deepEqual( jQuery( document.getElementById("firstp") ).add( "#ap", ctx ).get(), q( "firstp" ), "Add gEBId to selector, not in context" ); + deepEqual( jQuery( document.getElementById("firstp") ).add( "#ap", document.getElementsByTagName("body")[0] ).get(), q( "firstp", "ap" ), "Add gEBId to selector, in context" ); });