Integration of Mike Alsup's excellent form serialization code. The benefits are as follows:
- New method: .serializeArray() This returns an array of name/value pairs representing the contents of a form, or individual input elements. - Enhancement: .serialize() The results are correct now (as opposed to the mess from before), and allows you to serializes forms directly (rather than just the input elements). - Enhancement: .val() This now returns the correct value when dealing wih selects. Additionally, when dealing with multiple selects, it returns an array of values. Based upon Mike's code: http://malsup.com/jquery/form/comp/form.js and test suite: http://malsup.com/jquery/form/comp/test.html
This commit is contained in:
parent
f28f199dc0
commit
f96bf10415
|
@ -116,6 +116,39 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="fx-tests"></div>
|
<div id="fx-tests"></div>
|
||||||
|
|
||||||
|
<form id="testForm" action="#" method="get">
|
||||||
|
<textarea name="T3" rows="2" cols="15">?
|
||||||
|
Z</textarea>
|
||||||
|
<input type="hidden" name="H1" value="x" />
|
||||||
|
<input type="hidden" name="H2" />
|
||||||
|
<input name="PWD" type="password" value="" />
|
||||||
|
<input name="T1" type="text" />
|
||||||
|
<input name="T2" type="text" value="YES" readonly="readonly" />
|
||||||
|
<input type="checkbox" name="C1" value="1" />
|
||||||
|
<input type="checkbox" name="C2" />
|
||||||
|
<input type="radio" name="R1" value="1" />
|
||||||
|
<input type="radio" name="R1" value="2" />
|
||||||
|
<input type="text" name="My Name" value="me" />
|
||||||
|
<input type="reset" name="reset" value="NO" />
|
||||||
|
<select name="S1">
<option value="abc">ABC</option>
<option value="abc">ABC</option>
<option value="abc">ABC</option>
</select>
<select name="S2" multiple="multiple" size="3">
<option value="abc">ABC</option>
<option value="abc">ABC</option>
<option value="abc">ABC</option>
</select>
|
||||||
|
<select name="S3">
|
||||||
|
<option selected="selected">YES</option>
|
||||||
|
</select>
|
||||||
|
<select name="S4">
|
||||||
|
<option value="" selected="selected">NO</option>
|
||||||
|
</select>
|
||||||
|
<input type="submit" name="sub1" value="NO" />
|
||||||
|
<input type="submit" name="sub2" value="NO" />
|
||||||
|
<input type="image" name="sub3" value="NO" src="submit.gif" />
|
||||||
|
<button name="sub4" type="submit" value="NO">NO</button>
|
||||||
|
<input name="D1" type="text" value="NO" disabled="disabled" />
|
||||||
|
<input type="checkbox" checked="checked" disabled="disabled" name="D2" value="NO" />
|
||||||
|
<input type="radio" name="D3" value="NO" checked="checked" disabled="disabled" />
|
||||||
|
<select name="D4" disabled="disabled">
|
||||||
|
<option selected="selected" value="NO">NO</option>
|
||||||
|
</select>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
|
|
@ -62,9 +62,25 @@ jQuery.fn.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
serialize: function() {
|
serialize: function() {
|
||||||
return jQuery.param( this );
|
return jQuery.param(this.serializeArray());
|
||||||
}
|
},
|
||||||
|
serializeArray: function() {
|
||||||
|
return this.map(function(){
|
||||||
|
return jQuery.nodeName(this, "form") ?
|
||||||
|
jQuery.makeArray(this.elements) : this;
|
||||||
|
})
|
||||||
|
.filter(function(){
|
||||||
|
return this.name && !this.disabled &&
|
||||||
|
(this.checked || /select|textarea/i.test(this.nodeName) ||
|
||||||
|
/text|hidden|password/i.test(this.type));
|
||||||
|
})
|
||||||
|
.map(function(i, elem){
var val = jQuery(this).val();
|
||||||
|
return val == null ? null :
|
||||||
|
val.constructor == Array ?
|
||||||
|
jQuery.map( val, function(i, val){
return {name: elem.name, value: val};
|
||||||
|
}) :
|
||||||
|
{name: elem.name, value: val};
|
||||||
|
}).get();
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Attach a bunch of functions for handling common AJAX events
|
// Attach a bunch of functions for handling common AJAX events
|
||||||
|
@ -440,7 +456,7 @@ jQuery.extend({
|
||||||
s.push( encodeURIComponent(j) + "=" + encodeURIComponent( a[j] ) );
|
s.push( encodeURIComponent(j) + "=" + encodeURIComponent( a[j] ) );
|
||||||
|
|
||||||
// Return the resulting serialization
|
// Return the resulting serialization
|
||||||
return s.join("&");
|
return s.join("&").replace(/%20/g, "+");
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,7 +3,7 @@ module("ajax");
|
||||||
// Safari 3 randomly crashes when running these tests,
|
// Safari 3 randomly crashes when running these tests,
|
||||||
// but only in the full suite - you can run just the Ajax
|
// but only in the full suite - you can run just the Ajax
|
||||||
// tests and they'll pass
|
// tests and they'll pass
|
||||||
if ( !jQuery.browser.safari ) {
|
//if ( !jQuery.browser.safari ) {
|
||||||
|
|
||||||
test("$.ajax() - success callbacks", function() {
|
test("$.ajax() - success callbacks", function() {
|
||||||
expect( 8 );
|
expect( 8 );
|
||||||
|
@ -163,11 +163,31 @@ test("$.ajax - dataType html", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
test("serialize()", function() {
|
test("serialize()", function() {
|
||||||
expect(1);
|
expect(6);
|
||||||
// ignore button, IE takes text content as value, not relevant for this test
|
|
||||||
equals( $(':input').not('button').serialize(),
|
equals( $('#form').serialize(),
|
||||||
'action=Test&text2=Test&radio1=on&radio2=on&check=on&=on&hidden=&foo%5Bbar%5D=&name=name&=foobar&select1=&select2=3&select3=1&test=&id=',
|
"action=Test&radio2=on&check=on&hidden=&foo%5Bbar%5D=&name=name&select1=&select2=3&select3=0&select3=1",
|
||||||
'Check form serialization as query string');
|
'Check form serialization as query string');
|
||||||
|
|
||||||
|
equals( $('#form :input').serialize(),
|
||||||
|
"action=Test&radio2=on&check=on&hidden=&foo%5Bbar%5D=&name=name&select1=&select2=3&select3=0&select3=1",
|
||||||
|
'Check input serialization as query string');
|
||||||
|
|
||||||
|
equals( $('#testForm').serialize(),
|
||||||
|
'T3=%3F%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=',
|
||||||
|
'Check form serialization as query string');
|
||||||
|
|
||||||
|
equals( $('#testForm :input').serialize(),
|
||||||
|
'T3=%3F%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=',
|
||||||
|
'Check input serialization as query string');
|
||||||
|
|
||||||
|
equals( $('#form, #testForm').serialize(),
|
||||||
|
"action=Test&radio2=on&check=on&hidden=&foo%5Bbar%5D=&name=name&select1=&select2=3&select3=0&select3=1&T3=%3F%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=",
|
||||||
|
'Multiple form serialization as query string');
|
||||||
|
|
||||||
|
equals( $('#form, #testForm :input').serialize(),
|
||||||
|
"action=Test&radio2=on&check=on&hidden=&foo%5Bbar%5D=&name=name&select1=&select2=3&select3=0&select3=1&T3=%3F%0AZ&H1=x&H2=&PWD=&T1=&T2=YES&My+Name=me&S1=abc&S3=YES&S4=",
|
||||||
|
'Mixed form/input serialization as query string');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("$.param()", function() {
|
test("$.param()", function() {
|
||||||
|
@ -618,4 +638,4 @@ test("custom timeout does not set error message when timeout occurs, see #970",
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
//}
|
||||||
|
|
|
@ -42,7 +42,7 @@ test("bind()", function() {
|
||||||
function selectOnChange(event) {
|
function selectOnChange(event) {
|
||||||
equals( event.data, counter++, "Event.data is not a global event object" );
|
equals( event.data, counter++, "Event.data is not a global event object" );
|
||||||
};
|
};
|
||||||
$("select").each(function(i){
|
$("#form select").each(function(i){
|
||||||
$(this).bind('change', i, selectOnChange);
|
$(this).bind('change', i, selectOnChange);
|
||||||
}).trigger('change');
|
}).trigger('change');
|
||||||
|
|
||||||
|
|
4
src/jquery/coreTest.js
vendored
4
src/jquery/coreTest.js
vendored
|
@ -836,7 +836,7 @@ test("html(String)", function() {
|
||||||
|
|
||||||
test("filter()", function() {
|
test("filter()", function() {
|
||||||
expect(4);
|
expect(4);
|
||||||
isSet( $("input").filter(":checked").get(), q("radio2", "check1"), "filter(String)" );
|
isSet( $("#form input").filter(":checked").get(), q("radio2", "check1"), "filter(String)" );
|
||||||
isSet( $("p").filter("#ap, #sndp").get(), q("ap", "sndp"), "filter('String, String')" );
|
isSet( $("p").filter("#ap, #sndp").get(), q("ap", "sndp"), "filter('String, String')" );
|
||||||
isSet( $("p").filter("#ap,#sndp").get(), q("ap", "sndp"), "filter('String,String')" );
|
isSet( $("p").filter("#ap,#sndp").get(), q("ap", "sndp"), "filter('String,String')" );
|
||||||
isSet( $("p").filter(function() { return !$("a", this).length }).get(), q("sndp", "first"), "filter(Function)" );
|
isSet( $("p").filter(function() { return !$("a", this).length }).get(), q("sndp", "first"), "filter(Function)" );
|
||||||
|
@ -862,7 +862,7 @@ test("siblings([String])", function() {
|
||||||
isSet( $("#en").siblings().get(), q("sndp", "sap"), "Check for siblings" );
|
isSet( $("#en").siblings().get(), q("sndp", "sap"), "Check for siblings" );
|
||||||
isSet( $("#sndp").siblings(":has(code)").get(), q("sap"), "Check for filtered siblings (has code child element)" );
|
isSet( $("#sndp").siblings(":has(code)").get(), q("sap"), "Check for filtered siblings (has code child element)" );
|
||||||
isSet( $("#sndp").siblings(":has(a)").get(), q("en", "sap"), "Check for filtered siblings (has anchor child element)" );
|
isSet( $("#sndp").siblings(":has(a)").get(), q("en", "sap"), "Check for filtered siblings (has anchor child element)" );
|
||||||
isSet( $("#foo").siblings("form, b").get(), q("form", "lengthtest", "floatTest"), "Check for multiple filters" );
|
isSet( $("#foo").siblings("form, b").get(), q("form", "lengthtest", "testForm", "floatTest"), "Check for multiple filters" );
|
||||||
isSet( $("#en, #sndp").siblings().get(), q("sndp", "sap", "en"), "Check for unique results from siblings" );
|
isSet( $("#en, #sndp").siblings().get(), q("sndp", "sap", "en"), "Check for unique results from siblings" );
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
29
src/jquery/jquery.js
vendored
29
src/jquery/jquery.js
vendored
|
@ -306,9 +306,32 @@ jQuery.fn = jQuery.prototype = {
|
||||||
},
|
},
|
||||||
|
|
||||||
val: function( val ) {
|
val: function( val ) {
|
||||||
return val == undefined ?
|
if ( val == undefined ) {
|
||||||
( this.length ? this[0].value : null ) :
|
if ( this.length ) {
|
||||||
this.attr( "value", val );
|
var elem = this[0];
|
||||||
|
|
||||||
|
// We need to handle select boxes special
if ( jQuery.nodeName(elem, "select") ) {
var index = elem.selectedIndex,
|
||||||
|
a = [],
|
||||||
|
options = elem.options,
|
||||||
|
one = elem.type == "select-one";
|
||||||
|
|
||||||
|
// Nothing was selected
if ( index < 0 )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Loop through all the selected options
for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
|
||||||
|
var option = options[i];
if ( option.selected ) {
// Get the specifc value for the option
var val = jQuery.browser.msie && !option.attributes["value"].specified ? option.text : option.value;
|
||||||
|
|
||||||
|
// We don't need an array for one selects
if ( one )
|
||||||
|
return val;
|
||||||
|
|
||||||
|
// Multi-Selects return an array
a.push(val);
}
}
|
||||||
|
return a;
|
||||||
|
|
||||||
|
// Everything else, we just grab the value
} else
|
||||||
|
return this[0].value.replace(/\r/g, "");
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
return this.attr( "value", val );
|
||||||
},
|
},
|
||||||
|
|
||||||
html: function( val ) {
|
html: function( val ) {
|
||||||
|
|
|
@ -128,8 +128,8 @@ test("child and adjacent", function() {
|
||||||
t( "Last Child", "p:last-child", ["sap"] );
|
t( "Last Child", "p:last-child", ["sap"] );
|
||||||
t( "Last Child", "a:last-child", ["simon1","anchor1","mark","yahoo","anchor2","simon"] );
|
t( "Last Child", "a:last-child", ["simon1","anchor1","mark","yahoo","anchor2","simon"] );
|
||||||
|
|
||||||
t( "Nth-child", "#main form > *:nth-child(2)", ["text2","idTest"] );
|
t( "Nth-child", "#main form#form > *:nth-child(2)", ["text2"] );
|
||||||
t( "Nth-child", "#main form > :nth-child(2)", ["text2","idTest"] );
|
t( "Nth-child", "#main form#form > :nth-child(2)", ["text2"] );
|
||||||
});
|
});
|
||||||
|
|
||||||
test("attributes", function() {
|
test("attributes", function() {
|
||||||
|
@ -141,9 +141,9 @@ test("attributes", function() {
|
||||||
t( "Attribute Equals", "a[rel='bookmark']", ["simon1"] );
|
t( "Attribute Equals", "a[rel='bookmark']", ["simon1"] );
|
||||||
t( "Attribute Equals", 'a[rel="bookmark"]', ["simon1"] );
|
t( "Attribute Equals", 'a[rel="bookmark"]', ["simon1"] );
|
||||||
t( "Attribute Equals", "a[rel=bookmark]", ["simon1"] );
|
t( "Attribute Equals", "a[rel=bookmark]", ["simon1"] );
|
||||||
t( "Multiple Attribute Equals", "input[type='hidden'],input[type='radio']", ["hidden1","radio1","radio2"] );
|
t( "Multiple Attribute Equals", "#form input[type='hidden'],#form input[type='radio']", ["hidden1","radio1","radio2"] );
|
||||||
t( "Multiple Attribute Equals", "input[type=\"hidden\"],input[type='radio']", ["hidden1","radio1","radio2"] );
|
t( "Multiple Attribute Equals", "#form input[type=\"hidden\"],#form input[type='radio']", ["hidden1","radio1","radio2"] );
|
||||||
t( "Multiple Attribute Equals", "input[type=hidden],input[type=radio]", ["hidden1","radio1","radio2"] );
|
t( "Multiple Attribute Equals", "#form input[type=hidden],#form input[type=radio]", ["hidden1","radio1","radio2"] );
|
||||||
|
|
||||||
t( "Attribute selector using UTF8", "span[lang=中文]", ["台北"] );
|
t( "Attribute selector using UTF8", "span[lang=中文]", ["台北"] );
|
||||||
|
|
||||||
|
@ -157,9 +157,9 @@ test("attributes", function() {
|
||||||
|
|
||||||
t( "Grouped Form Elements", "input[name='foo[bar]']", ["hidden2"] );
|
t( "Grouped Form Elements", "input[name='foo[bar]']", ["hidden2"] );
|
||||||
|
|
||||||
t( ":not() Existing attribute", "select:not([multiple])", ["select1", "select2"]);
|
t( ":not() Existing attribute", "#form select:not([multiple])", ["select1", "select2"]);
|
||||||
t( ":not() Equals attribute", "select:not([name=select1])", ["select2", "select3"]);
|
t( ":not() Equals attribute", "#form select:not([name=select1])", ["select2", "select3"]);
|
||||||
t( ":not() Equals quoted attribute", "select:not([name='select1'])", ["select2", "select3"]);
|
t( ":not() Equals quoted attribute", "#form select:not([name='select1'])", ["select2", "select3"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("pseudo (:) selectors", function() {
|
test("pseudo (:) selectors", function() {
|
||||||
|
@ -168,10 +168,10 @@ test("pseudo (:) selectors", function() {
|
||||||
t( "Last Child", "p:last-child", ["sap"] );
|
t( "Last Child", "p:last-child", ["sap"] );
|
||||||
t( "Only Child", "a:only-child", ["simon1","anchor1","yahoo","anchor2"] );
|
t( "Only Child", "a:only-child", ["simon1","anchor1","yahoo","anchor2"] );
|
||||||
t( "Empty", "ul:empty", ["firstUL"] );
|
t( "Empty", "ul:empty", ["firstUL"] );
|
||||||
t( "Enabled UI Element", "input:enabled", ["text1","radio1","radio2","check1","check2","hidden1","hidden2","name","length","idTest"] );
|
t( "Enabled UI Element", "#form input:enabled", ["text1","radio1","radio2","check1","check2","hidden1","hidden2","name"] );
|
||||||
t( "Disabled UI Element", "input:disabled", ["text2"] );
|
t( "Disabled UI Element", "#form input:disabled", ["text2"] );
|
||||||
t( "Checked UI Element", "input:checked", ["radio2","check1"] );
|
t( "Checked UI Element", "#form input:checked", ["radio2","check1"] );
|
||||||
t( "Selected Option Element", "option:selected", ["option1a","option2d","option3b","option3c"] );
|
t( "Selected Option Element", "#form option:selected", ["option1a","option2d","option3b","option3c"] );
|
||||||
t( "Text Contains", "a:contains('Google')", ["google","groups"] );
|
t( "Text Contains", "a:contains('Google')", ["google","groups"] );
|
||||||
t( "Text Contains", "a:contains('Google Groups')", ["groups"] );
|
t( "Text Contains", "a:contains('Google Groups')", ["groups"] );
|
||||||
t( "Element Preceded By", "p ~ div", ["foo","fx-queue","fx-tests"] );
|
t( "Element Preceded By", "p ~ div", ["foo","fx-queue","fx-tests"] );
|
||||||
|
@ -186,16 +186,16 @@ test("pseudo (:) selectors", function() {
|
||||||
t( "Position Greater Than", "p:gt(0)", ["ap","sndp","en","sap","first"] );
|
t( "Position Greater Than", "p:gt(0)", ["ap","sndp","en","sap","first"] );
|
||||||
t( "Position Less Than", "p:lt(3)", ["firstp","ap","sndp"] );
|
t( "Position Less Than", "p:lt(3)", ["firstp","ap","sndp"] );
|
||||||
t( "Is A Parent", "p:parent", ["firstp","ap","sndp","en","sap","first"] );
|
t( "Is A Parent", "p:parent", ["firstp","ap","sndp","en","sap","first"] );
|
||||||
t( "Is Visible", "input:visible", ["text1","text2","radio1","radio2","check1","check2","name","length","idTest"] );
|
t( "Is Visible", "#form input:visible", ["text1","text2","radio1","radio2","check1","check2","name"] );
|
||||||
t( "Is Hidden", "input:hidden", ["hidden1","hidden2"] );
|
t( "Is Hidden", "#form input:hidden", ["hidden1","hidden2"] );
|
||||||
|
|
||||||
t( "Form element :input", ":input", ["text1", "text2", "radio1", "radio2", "check1", "check2", "hidden1", "hidden2", "name", "button", "area1", "select1", "select2", "select3", "length", "idTest"] );
|
t( "Form element :input", "#form :input", ["text1", "text2", "radio1", "radio2", "check1", "check2", "hidden1", "hidden2", "name", "button", "area1", "select1", "select2", "select3"] );
|
||||||
t( "Form element :radio", ":radio", ["radio1", "radio2"] );
|
t( "Form element :radio", "#form :radio", ["radio1", "radio2"] );
|
||||||
t( "Form element :checkbox", ":checkbox", ["check1", "check2"] );
|
t( "Form element :checkbox", "#form :checkbox", ["check1", "check2"] );
|
||||||
t( "Form element :text", ":text", ["text1", "text2", "hidden2", "name", "length", "idTest"] );
|
t( "Form element :text", "#form :text", ["text1", "text2", "hidden2", "name"] );
|
||||||
t( "Form element :radio:checked", ":radio:checked", ["radio2"] );
|
t( "Form element :radio:checked", "#form :radio:checked", ["radio2"] );
|
||||||
t( "Form element :checkbox:checked", ":checkbox:checked", ["check1"] );
|
t( "Form element :checkbox:checked", "#form :checkbox:checked", ["check1"] );
|
||||||
t( "Form element :checkbox:checked, :radio:checked", ":checkbox:checked, :radio:checked", ["check1", "radio2"] );
|
t( "Form element :checkbox:checked, :radio:checked", "#form :checkbox:checked, #form :radio:checked", ["check1", "radio2"] );
|
||||||
|
|
||||||
t( "Headers", ":header", ["header", "banner", "userAgent"] );
|
t( "Headers", ":header", ["header", "banner", "userAgent"] );
|
||||||
t( "Has Children - :has()", "p:has(a)", ["firstp","ap","en","sap"] );
|
t( "Has Children - :has()", "p:has(a)", ["firstp","ap","en","sap"] );
|
||||||
|
|
Loading…
Reference in a new issue