X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=src%2Fxhr.js;h=9df512b4cb26d8d419e830c1d7742e6549529ccc;hb=2d4001b82c6325ac6a767294e96a8af8f920f7cd;hp=51bd3dfd00a64c7e6b92500a5ab7ff56994bb8e6;hpb=5bacb53866dbc3fbb36202a25c756a4ea2fd5965;p=jquery.git diff --git a/src/xhr.js b/src/xhr.js index 51bd3df..9df512b 100644 --- a/src/xhr.js +++ b/src/xhr.js @@ -6,11 +6,9 @@ var rquery_xhr = /\?/, rnoContent = /^(?:GET|HEAD)$/, rts = /([?&])_=[^&]*/, rurl = /^(\w+:)?\/\/([^\/?#]+)/, - - sliceFunc = Array.prototype.slice, - - isFunction = jQuery.isFunction; - + + sliceFunc = Array.prototype.slice; + // Creates a jQuery xhr object jQuery.xhr = function( _native ) { @@ -25,8 +23,8 @@ jQuery.xhr = function( _native ) { if ( force || internal ) { // Reset callbacks lists - deferred = jQuery.deferred(); - completeDeferred = jQuery._deferred(); + deferred = jQuery.Deferred(); + completeDeferred = jQuery._Deferred(); xhr.success = xhr.then = deferred.then; xhr.error = xhr.fail = deferred.fail; @@ -87,14 +85,9 @@ jQuery.xhr = function( _native ) { data = s.data = jQuery.param( data , s.traditional ); } - // Apply option prefilters - for ( i = 0; i < prefilters.length; i++ ) { - prefilters[i](s); - } - // Get internal - internal = selectTransport( s ); - + internal = jQuery.xhr.prefilter( s ).transport( s ); + // Re-actualize url & data url = s.url; data = s.data; @@ -152,7 +145,7 @@ jQuery.xhr = function( _native ) { requestHeaders[ i.toLowerCase() ] = headers[ i ]; } } - + callbackContext = s.context || s; globalEventContext = s.context ? jQuery(s.context) : jQuery.event; @@ -228,112 +221,79 @@ jQuery.xhr = function( _native ) { // Chain data conversions and determine the final value // (if an exception is thrown in the process, it'll be notified as an error) try { - - function checkData(data) { - if ( data !== undefined ) { - var testFunction = s.dataCheckers[srcDataType]; - if ( isFunction( testFunction ) ) { - testFunction(data); - } - } - } - - function convertData (data) { - var conversionFunction = dataConverters[srcDataType+" => "+destDataType] || - dataConverters["* => "+destDataType], - noFunction = ! isFunction( conversionFunction ); - if ( noFunction ) { - if ( srcDataType != "text" && destDataType != "text" ) { - // We try to put text inbetween - var first = dataConverters[srcDataType+" => text"] || - dataConverters["* => text"], - second = dataConverters["text => "+destDataType] || - dataConverters["* => "+destDataType], - areFunctions = isFunction( first ) && isFunction( second ); - if ( areFunctions ) { - conversionFunction = function (data) { - return second( first ( data ) ); - }; + + var i, + current, + prev, + checker, + conv1, + conv2, + oneConv, + convertion, + dataTypes = s.dataTypes, + dataCheckers = s.dataCheckers, + dataConverters = s.dataConverters, + dataFilter = s.dataFilter, + responses = { + "xml": "XML", + "text": "Text" + }; + + for( i = 0 ; i < dataTypes.length ; i++ ) { + + current = dataTypes[ i ]; + + if ( i ) { + + prev = dataTypes[ i - 1 ]; + + if ( prev === "*" ) { + + prev = current; + + } else if ( current !== "*" && prev !== current ) { + + oneConv = conv1 = + dataConverters[ ( conversion = prev + " " + current ) ] || + dataConverters[ "* " + current ]; + + console.log( conversion ); + + if ( ! oneConv && prev !== "text" && current !== "text" ) { + conv1 = dataConverters[ prev + " text" ] || dataConverters[ "* text" ]; + conv2 = dataConverters[ "text " + current ]; + } + if ( oneConv || conv1 && conv2 ) { + response = oneConv ? conv1( response ) : conv2( conv1( response ) ); + } else { + throw "no " + conversion; } - noFunction = ! areFunctions; - } - if ( noFunction ) { - jQuery.error( "no data converter between " + srcDataType + " and " + destDataType ); } - } - return conversionFunction(data); - } - - var dataTypes = s.dataTypes, - i, - length, - data = response, - dataConverters = s.dataConverters, - srcDataType, - destDataType, - responseTypes = s.xhrResponseFields; - - for ( i = 0, length = dataTypes.length ; i < length ; i++ ) { - - destDataType = dataTypes[i]; - - if ( !srcDataType ) { // First time - - // Copy type - srcDataType = destDataType; - // Check - checkData(data); - // Apply dataFilter - if ( isFunction( s.dataFilter ) ) { - data = s.dataFilter(data, s.dataType); - // Recheck data - checkData(data); - } - - } else { // Subsequent times - - // handle auto - // JULIAN: for reasons unknown to me === doesn't work here - if (destDataType == "*") { - - destDataType = srcDataType; - - } else if ( srcDataType != destDataType ) { - - // Convert - data = convertData(data); - // Copy type & check - srcDataType = destDataType; - checkData(data); - - } - + + checker = dataCheckers[ current ]; + + if ( response != null && checker ) { + checker( response ); } - - // Copy response into the xhr if it hasn't been already - var responseDataType, - responseType = responseTypes[srcDataType]; - - if ( responseType ) { - - responseDataType = srcDataType; - - } else { - - responseType = responseTypes[ responseDataType = "text" ]; - + + if ( responses[ current ] ) { + xhr[ "response" + responses[ current ] ] = response; + responses[ current ] = 0; } - - if ( responseType !== 1 ) { - xhr[ "response" + responseType ] = data; - responseTypes[ responseType ] = 1; + + if ( ! i && dataFilter ) { + + response = dataFilter( response ); + + dataTypes = s.dataTypes; + dataFilter = 0; + i--; } - } // We have a real success - success = data; + success = response; isSuccess = 1; } catch(e) { @@ -411,7 +371,7 @@ jQuery.xhr = function( _native ) { // Ready state change function setState( value ) { xhr.readyState = value; - if ( isFunction( xhr.onreadystatechange ) ) { + if ( jQuery.isFunction( xhr.onreadystatechange ) ) { xhr.onreadystatechange(); } } @@ -606,101 +566,19 @@ jQuery.xhr = function( _native ) { return xhr; }; -jQuery.extend(jQuery.xhr, { - - // Add new prefilter - prefilter: function (functor) { - if ( isFunction(functor) ) { - jQuery.ajaxSettings.prefilters.push( functor ); - } - return this; - }, - - // Bind a transport to one or more dataTypes - bindTransport: function () { - - var args = arguments, - i, - start = 0, - length = args.length, - dataTypes = [ "*" ], - functors = [], - functor, - first, - append, - list, - transports = jQuery.ajaxSettings.transports; - - if ( length ) { - - if ( ! isFunction( args[ 0 ] ) ) { - - dataTypes = args[ 0 ].toLowerCase().split(/\s+/); - start = 1; - - } - - if ( dataTypes.length && start < length ) { - - for ( i = start; i < length; i++ ) { - functor = args[i]; - if ( isFunction(functor) ) { - functors.push( functor ); - } - } - - if ( functors.length ) { - - jQuery.each ( dataTypes, function( _ , dataType ) { - - first = /^\+/.test( dataType ); - - if (first) { - dataType = dataType.substr(1); - } - - if ( dataType !== "" ) { - - append = Array.prototype[ first ? "unshift" : "push" ]; - - list = transports[ dataType ]; - - jQuery.each ( functors, function( _ , functor ) { - - if ( ! list ) { - - list = transports[ dataType ] = [ functor ]; - - } else { - - append.call( list , functor ); - } - } ); - } - - } ); - } - } - } - - return this; - } - - -}); - -// Select a transport given options -function selectTransport( s ) { +// Execute or select from functions in a given structure of options +function xhr_selectOrExecute( structure , s ) { var dataTypes = s.dataTypes, transportDataType, - transportsList, - transport, + list, + selected, i, length, checked = {}, - flag; - + flag, + noSelect = structure !== "transports"; + function initSearch( dataType ) { flag = transportDataType !== dataType && ! checked[ dataType ]; @@ -709,9 +587,9 @@ function selectTransport( s ) { checked[ dataType ] = 1; transportDataType = dataType; - transportsList = s.transports[ dataType ]; + list = s[ structure ][ dataType ]; i = -1; - length = transportsList ? transportsList.length : 0 ; + length = list ? list.length : 0 ; } return flag; @@ -719,30 +597,104 @@ function selectTransport( s ) { initSearch( dataTypes[ 0 ] ); - for ( i = 0 ; ! transport && i <= length ; i++ ) { - + for ( i = 0 ; ( noSelect || ! selected ) && i <= length ; i++ ) { + if ( i === length ) { initSearch( "*" ); } else { - transport = transportsList[ i ]( s , determineDataType ); + selected = list[ i ]( s , determineDataType ); // If we got redirected to another dataType // Search there (if not in progress or already tried) - if ( typeof( transport ) === "string" && - initSearch( transport ) ) { + if ( typeof( selected ) === "string" && + initSearch( selected ) ) { - dataTypes.unshift( transport ); - transport = 0; + dataTypes.unshift( selected ); + selected = 0; } } } - return transport; + return noSelect ? jQuery.xhr : selected; } +// Add an element to one of the xhr structures in ajaxSettings +function xhr_addElement( structure , args ) { + + var i, + j, + start = 0, + length = args.length, + dataTypes = [ "*" ], + dLength = 1, + dataType, + functors = [], + first, + append, + list; + + if ( length ) { + + first = jQuery.type( args[ 0 ] ); + + if ( first === "object" ) { + return xhr_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 ); + + length -= 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 ] || []; + + for ( j = 0; j < length; j++ ) { + append.call( list , functors[ j ] ); + } + } + } + } + } + + return jQuery.xhr; +} + +// Install prefilter & transport methods +jQuery.each( [ "prefilter" , "transport" ] , function( _ , name ) { + _ = name + "s"; + jQuery.xhr[ name ] = function() { + return xhr_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 ) {