Skip to content

Commit

Permalink
Extracts the serialization code from the ajax module so that alternat…
Browse files Browse the repository at this point in the history
…ive ajax implementations can use it without the need for the whole ajax module to be included in the build.
  • Loading branch information
jaubourg committed Jul 13, 2012
1 parent c29660c commit ced5e90
Show file tree
Hide file tree
Showing 6 changed files with 301 additions and 292 deletions.
1 change: 1 addition & 0 deletions grunt.js
Expand Up @@ -67,6 +67,7 @@ module.exports = function( grunt ) {

{ flag: "deprecated", src: "src/deprecated.js" },
{ flag: "css", src: "src/css.js" },
"src/serialize.js",
{ flag: "ajax", src: "src/ajax.js" },
{ flag: "ajax/jsonp", src: "src/ajax/jsonp.js", needs: [ "ajax", "ajax/script" ] },
{ flag: "ajax/script", src: "src/ajax/script.js", needs: ["ajax"] },
Expand Down
213 changes: 53 additions & 160 deletions src/ajax.js
Expand Up @@ -3,19 +3,14 @@ var // Document location
// Document location segments
ajaxLocParts,

r20 = /%20/g,
rbracket = /\[\]$/,
rCRLF = /\r?\n/g,
rhash = /#.*$/,
rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
// #7653, #8125, #8152: local protocol detection
rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,
rnoContent = /^(?:GET|HEAD)$/,
rprotocol = /^\/\//,
rquery = /\?/,
rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
rselectTextarea = /^(?:select|textarea)/i,
rts = /([?&])_=[^&]*/,
rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,

Expand Down Expand Up @@ -148,103 +143,75 @@ function ajaxExtend( target, src ) {
}
}

jQuery.fn.extend({
load: function( url, params, callback ) {
if ( typeof url !== "string" && _load ) {
return _load.apply( this, arguments );
}

// Don't do a request if no elements are being requested
if ( !this.length ) {
return this;
}
jQuery.fn.load = function( url, params, callback ) {
if ( typeof url !== "string" && _load ) {
return _load.apply( this, arguments );
}

var selector, type, response,
self = this,
off = url.indexOf(" ");
// Don't do a request if no elements are being requested
if ( !this.length ) {
return this;
}

if ( off >= 0 ) {
selector = url.slice( off, url.length );
url = url.slice( 0, off );
}
var selector, type, response,
self = this,
off = url.indexOf(" ");

// If it's a function
if ( jQuery.isFunction( params ) ) {
if ( off >= 0 ) {
selector = url.slice( off, url.length );
url = url.slice( 0, off );
}

// We assume that it's the callback
callback = params;
params = undefined;
// If it's a function
if ( jQuery.isFunction( params ) ) {

// Otherwise, build a param string
} else if ( typeof params === "object" ) {
type = "POST";
}
// We assume that it's the callback
callback = params;
params = undefined;

// Request the remote document
jQuery.ajax({
url: url,
// Otherwise, build a param string
} else if ( typeof params === "object" ) {
type = "POST";
}

// if "type" variable is undefined, then "GET" method will be used
type: type,
dataType: "html",
data: params,
complete: function( jqXHR, status ) {
if ( callback ) {
self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
}
// Request the remote document
jQuery.ajax({
url: url,

// if "type" variable is undefined, then "GET" method will be used
type: type,
dataType: "html",
data: params,
complete: function( jqXHR, status ) {
if ( callback ) {
self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
}
}).done(function( responseText ) {

// Save response for use in complete callback
response = arguments;

// See if a selector was specified
self.html( selector ?
}
}).done(function( responseText ) {

// Create a dummy div to hold the results
jQuery("<div>")
// Save response for use in complete callback
response = arguments;

// inject the contents of the document in, removing the scripts
// to avoid any 'Permission Denied' errors in IE
.append( responseText.replace( rscript, "" ) )
// See if a selector was specified
self.html( selector ?

// Locate the specified elements
.find( selector ) :
// Create a dummy div to hold the results
jQuery("<div>")

// If not, just inject the full result
responseText );
// inject the contents of the document in, removing the scripts
// to avoid any 'Permission Denied' errors in IE
.append( responseText.replace( rscript, "" ) )

});
// Locate the specified elements
.find( selector ) :

return this;
},
// If not, just inject the full result
responseText );

serialize: function() {
return jQuery.param( this.serializeArray() );
},
});

serializeArray: function() {
return this.map(function(){
return this.elements ? jQuery.makeArray( this.elements ) : this;
})
.filter(function(){
return this.name && !this.disabled &&
( this.checked || rselectTextarea.test( this.nodeName ) ||
rinput.test( this.type ) );
})
.map(function( i, elem ){
var val = jQuery( this ).val();

return val == null ?
null :
jQuery.isArray( val ) ?
jQuery.map( val, function( val, i ){
return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
}) :
{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
}).get();
}
});
return this;
};

// Attach a bunch of functions for handling common AJAX events
jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
Expand Down Expand Up @@ -753,80 +720,6 @@ jQuery.extend({
return jqXHR;
},

// Serialize an array of form elements or a set of
// key/values into a query string
param: function( a, traditional ) {
var prefix,
s = [],
add = function( key, value ) {
// If value is a function, invoke it and return its value
value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
};

// Set traditional to true for jQuery <= 1.3.2 behavior.
if ( traditional === undefined ) {
traditional = jQuery.ajaxSettings.traditional;
}

// If an array was passed in, assume that it is an array of form elements.
if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
// Serialize the form elements
jQuery.each( a, function() {
add( this.name, this.value );
});

} else {
// If traditional, encode the "old" way (the way 1.3.2 or older
// did it), otherwise encode params recursively.
for ( prefix in a ) {
buildParams( prefix, a[ prefix ], traditional, add );
}
}

// Return the resulting serialization
return s.join( "&" ).replace( r20, "+" );
}
});

function buildParams( prefix, obj, traditional, add ) {
var name;

if ( jQuery.isArray( obj ) ) {
// Serialize array item.
jQuery.each( obj, function( i, v ) {
if ( traditional || rbracket.test( prefix ) ) {
// Treat each array item as a scalar.
add( prefix, v );

} else {
// If array item is non-scalar (array or object), encode its
// numeric index to resolve deserialization ambiguity issues.
// Note that rack (as of 1.0.0) can't currently deserialize
// nested arrays properly, and attempting to do so may cause
// a server error. Possible fixes are to modify rack's
// deserialization algorithm or to provide an option or flag
// to force array serialization to be shallow.
buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
}
});

} else if ( !traditional && jQuery.type( obj ) === "object" ) {
// Serialize object item.
for ( name in obj ) {
buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
}

} else {
// Serialize scalar item.
add( prefix, obj );
}
}

// This is still on the jQuery object... for now
// Want to move this to jQuery.ajax some day
jQuery.extend({

// Counter for holding the number of active queries
active: 0,

Expand Down
101 changes: 101 additions & 0 deletions src/serialize.js
@@ -0,0 +1,101 @@
var r20 = /%20/g,
rbracket = /\[\]$/,
rCRLF = /\r?\n/g,
rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
rselectTextarea = /^(?:select|textarea)/i;

jQuery.fn.extend({
serialize: function() {
return jQuery.param( this.serializeArray() );
},
serializeArray: function() {
return this.map(function(){
return this.elements ? jQuery.makeArray( this.elements ) : this;
})
.filter(function(){
return this.name && !this.disabled &&
( this.checked || rselectTextarea.test( this.nodeName ) ||
rinput.test( this.type ) );
})
.map(function( i, elem ){
var val = jQuery( this ).val();

return val == null ?
null :
jQuery.isArray( val ) ?
jQuery.map( val, function( val, i ){
return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
}) :
{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
}).get();
}
});

//Serialize an array of form elements or a set of
//key/values into a query string
jQuery.param = function( a, traditional ) {
var prefix,
s = [],
add = function( key, value ) {
// If value is a function, invoke it and return its value
value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
};

// Set traditional to true for jQuery <= 1.3.2 behavior.
if ( traditional === undefined ) {
traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
}

// If an array was passed in, assume that it is an array of form elements.
if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
// Serialize the form elements
jQuery.each( a, function() {
add( this.name, this.value );
});

} else {
// If traditional, encode the "old" way (the way 1.3.2 or older
// did it), otherwise encode params recursively.
for ( prefix in a ) {
buildParams( prefix, a[ prefix ], traditional, add );
}
}

// Return the resulting serialization
return s.join( "&" ).replace( r20, "+" );
};

function buildParams( prefix, obj, traditional, add ) {
var name;

if ( jQuery.isArray( obj ) ) {
// Serialize array item.
jQuery.each( obj, function( i, v ) {
if ( traditional || rbracket.test( prefix ) ) {
// Treat each array item as a scalar.
add( prefix, v );

} else {
// If array item is non-scalar (array or object), encode its
// numeric index to resolve deserialization ambiguity issues.
// Note that rack (as of 1.0.0) can't currently deserialize
// nested arrays properly, and attempting to do so may cause
// a server error. Possible fixes are to modify rack's
// deserialization algorithm or to provide an option or flag
// to force array serialization to be shallow.
buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
}
});

} else if ( !traditional && jQuery.type( obj ) === "object" ) {
// Serialize object item.
for ( name in obj ) {
buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
}

} else {
// Serialize scalar item.
add( prefix, obj );
}
}
1 change: 1 addition & 0 deletions test/index.html
Expand Up @@ -46,6 +46,7 @@
<script src="unit/traversing.js"></script>
<script src="unit/manipulation.js"></script>
<script src="unit/css.js"></script>
<script src="unit/serialize.js"></script>
<script src="unit/ajax.js"></script>
<script src="unit/effects.js"></script>
<script src="unit/offset.js"></script>
Expand Down

0 comments on commit ced5e90

Please sign in to comment.