Fix bug #7018.
[jquery.git] / src / ajax.js
index 97d4039..08dc443 100644 (file)
@@ -4,13 +4,14 @@ var jsc = jQuery.now(),
        rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
        rselectTextarea = /^(?:select|textarea)/i,
        rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
+       rnoContent = /^(?:GET|HEAD|DELETE)$/,
        rbracket = /\[\]$/,
        jsre = /\=\?(&|$)/,
        rquery = /\?/,
-       rts = /([?&])_=[^&]*(&?)/,
+       rts = /([?&])_=[^&]*/,
        rurl = /^(\w+:)?\/\/([^\/?#]+)/,
        r20 = /%20/g,
-       rhash = /#[^#]*$/,
+       rhash = /#.*$/,
 
        // Keep a copy of the old load method
        _load = jQuery.fn.load;
@@ -179,19 +180,10 @@ jQuery.extend({
                password: null,
                traditional: false,
                */
-               // Create the request object; Microsoft failed to properly
-               // implement the XMLHttpRequest in IE7 (can't request local files),
-               // so we use the ActiveXObject when it is available
                // This function can be overriden by calling jQuery.ajaxSetup
-               xhr: window.XMLHttpRequest && (window.location.protocol !== "file:" || !window.ActiveXObject) ?
-                       function() {
-                               return new window.XMLHttpRequest();
-                       } :
-                       function() {
-                               try {
-                                       return new window.ActiveXObject("Microsoft.XMLHTTP");
-                               } catch(e) {}
-                       },
+               xhr: function() {
+                       return new window.XMLHttpRequest();
+               },
                accepts: {
                        xml: "application/xml, text/xml",
                        html: "text/html",
@@ -204,10 +196,12 @@ jQuery.extend({
 
        ajax: function( origSettings ) {
                var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings),
-                       jsonp, status, data, type = s.type.toUpperCase();
+                       jsonp, status, data, type = s.type.toUpperCase(), noContent = rnoContent.test(type);
 
                s.url = s.url.replace( rhash, "" );
-               s.context = origSettings && origSettings.context || s;
+
+               // Use original (not extended) context object if it was provided
+               s.context = origSettings && origSettings.context != null ? origSettings.context : s;
 
                // convert data if not already a string
                if ( s.data && s.processData && typeof s.data !== "string" ) {
@@ -275,7 +269,7 @@ jQuery.extend({
                        var ts = jQuery.now();
 
                        // try replacing _= if it is there
-                       var ret = s.url.replace(rts, "$1_=" + ts + "$2");
+                       var 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 : "");
@@ -300,10 +294,10 @@ jQuery.extend({
                if ( s.dataType === "script" && type === "GET" && remote ) {
                        var head = document.getElementsByTagName("head")[0] || document.documentElement;
                        var script = document.createElement("script");
-                       script.src = s.url;
                        if ( s.scriptCharset ) {
                                script.charset = s.scriptCharset;
                        }
+                       script.src = s.url;
 
                        // Handle Script loading
                        if ( !jsonp ) {
@@ -353,8 +347,8 @@ jQuery.extend({
 
                // Need an extra try/catch for cross domain requests in Firefox 3
                try {
-                       // Set the correct header, if data is being sent
-                       if ( s.data || origSettings && origSettings.contentType ) {
+                       // Set content-type if data specified and content-body is valid for this type
+                       if ( (s.data != null && !noContent) || (origSettings && origSettings.contentType) ) {
                                xhr.setRequestHeader("Content-Type", s.contentType);
                        }
 
@@ -377,7 +371,7 @@ jQuery.extend({
 
                        // Set the Accepts header for the server, depending on the dataType
                        xhr.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
-                               s.accepts[ s.dataType ] + ", */*" :
+                               s.accepts[ s.dataType ] + ", */*; q=0.01" :
                                s.accepts._default );
                } catch( headerError ) {}
 
@@ -464,12 +458,14 @@ jQuery.extend({
                        }
                };
 
-               // Override the abort handler, if we can (IE doesn't allow it, but that's OK)
+               // Override the abort handler, if we can (IE 6 doesn't allow it, but that's OK)
                // Opera doesn't fire onreadystatechange at all on abort
                try {
                        var oldAbort = xhr.abort;
                        xhr.abort = function() {
-                               if ( xhr ) {
+                               // xhr.abort in IE7 is not a native JS function
+                               // and does not have a call property
+                               if ( xhr && oldAbort.call ) {
                                        oldAbort.call( xhr );
                                }
 
@@ -489,10 +485,10 @@ jQuery.extend({
 
                // Send the data
                try {
-                       xhr.send( (type !== "GET" && s.data) || null );
+                       xhr.send( noContent || s.data == null ? null : s.data );
 
                } catch( sendError ) {
-                       jQuery.ajax.handleError( s, xhr, null, e );
+                       jQuery.ajax.handleError( s, xhr, null, sendError );
 
                        // Fire the complete handlers
                        jQuery.ajax.handleComplete( s, xhr, status, data );
@@ -542,7 +538,7 @@ jQuery.extend({
 });
 
 function buildParams( prefix, obj, traditional, add ) {
-       if ( jQuery.isArray(obj) ) {
+       if ( jQuery.isArray(obj) && obj.length ) {
                // Serialize array item.
                jQuery.each( obj, function( i, v ) {
                        if ( traditional || rbracket.test( prefix ) ) {
@@ -562,10 +558,15 @@ function buildParams( prefix, obj, traditional, add ) {
                });
                        
        } else if ( !traditional && obj != null && typeof obj === "object" ) {
+               if ( jQuery.isEmptyObject( obj ) ) {
+                       add( prefix, "" );
+
                // Serialize object item.
-               jQuery.each( obj, function( k, v ) {
-                       buildParams( prefix + "[" + k + "]", v, traditional, add );
-               });
+               } else {
+                       jQuery.each( obj, function( k, v ) {
+                               buildParams( prefix + "[" + k + "]", v, traditional, add );
+                       });
+               }
                                        
        } else {
                // Serialize scalar item.
@@ -687,6 +688,27 @@ jQuery.extend( jQuery.ajax, {
 
 });
 
+/*
+ * Create the request object; Microsoft failed to properly
+ * implement the XMLHttpRequest in IE7 (can't request local files),
+ * so we use the ActiveXObject when it is available
+ * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
+ * we need a fallback.
+ */
+if ( window.ActiveXObject ) {
+       jQuery.ajaxSettings.xhr = function() {
+               if ( window.location.protocol !== "file:" ) {
+                       try {
+                               return new window.XMLHttpRequest();
+                       } catch(e) {}
+               }
+
+               try {
+                       return new window.ActiveXObject("Microsoft.XMLHTTP");
+               } catch(e) {}
+       };
+}
+
 // Does this browser support XHR requests?
 jQuery.support.ajax = !!jQuery.ajaxSettings.xhr();