Skip to content

Commit 4458bc7

Browse files
Integrate readCheckboxUncheckedValues into the new serializeArray method to simplify the serialization process for unchecked checkboxes
1 parent 5d0c68d commit 4458bc7

File tree

3 files changed

+48
-45
lines changed

3 files changed

+48
-45
lines changed

README.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ $('form').serializeJSON();
4040
}
4141
```
4242

43-
Form input, textarea and select tags are supported. Nested attributes and arrays can be specified by using the `attr[nested][nested]` syntax.
43+
Form input, textarea and select tags are supported. Nested attributes and arrays can be specified by naming fields with the syntax: `name="attr[nested][nested]"`.
4444

4545
HTML form:
4646
```html
@@ -114,7 +114,7 @@ $('#my-profile').serializeJSON();
114114
}
115115
```
116116

117-
The `serializeJSON` function returns a JavaScript object, not a JSON String. The plugin should probably have been called `serializeObject` or similar, but those plugins already existed.
117+
The `serializeJSON` function returns a JavaScript object, not a JSON String. The plugin should probably have been called `serializeObject` or similar, but that plugin name was already taken.
118118

119119
To convert into a JSON String, use the `JSON.stringify` method, that is available on all major [new browsers](http://caniuse.com/json).
120120
If you need to support very old browsers, just include the [json2.js](https://github.com/douglascrockford/JSON-js) polyfill (as described on [stackoverfow](http://stackoverflow.com/questions/191881/serializing-to-json-in-jquery)).
@@ -471,7 +471,8 @@ Contributions are awesome. Feature branch *pull requests* are the preferred meth
471471
Changelog
472472
---------
473473

474-
* *3.1.1* (Dev 30, 2020): Update #114 (Allow to use new versions of jQuery by avoiding calls to the deprecated method `jQuery.isArray`).
474+
* *3.2.0* (draft): ... TODO: update comment: https://github.com/marioizquierdo/jquery.serializeJSON/issues/67
475+
* *3.1.1* (Dec 30, 2020): Update #114 (Allow to use new versions of jQuery by avoiding calls to the deprecated method `jQuery.isArray`).
475476
* *3.1.1* (Nov 09, 2020): Bugfix #110 (Allow unindexed arrays with multiple levels of nested objects).
476477
* *3.1.0* (Sep 13, 2020): Rename option `disableColonTypes` that was mistakenly named `disableSemicolonTypes`. Fix typos in README.
477478
* *3.0.0* (Sep 06, 2020): Improve types (PR #105) and remove parsing options (PR #104). The type system with `:type` suffixes, `data-value-type` attributes, and a combination of the options `customTypes`, `disableColonTypes` and `defaultType`, are safer and easier to use than the previous options `parseNumbers`, `parseAll`, etc. Thanks [Laykou](https://github.com/Laykou) for suggesting [PR #102] that pointed the problems of inputs with colons in their names.

jquery.serializejson.js

+32-39
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,11 @@
3333
var typeFunctions = $.extend({}, opts.defaultTypes, opts.customTypes);
3434

3535
// Make a list with {name, value, el} for each matched element.
36-
var formAsArray = f.serializeArray($form);
37-
f.readCheckboxUncheckedValues(formAsArray, opts, $form); // add objects to the array from unchecked checkboxes if needed
36+
var serializedArray = f.serializeArray($form, opts);
3837

39-
// Convert the formAsArray into a serializedObject with nested keys
38+
// Convert the serializedArray into a serializedObject with nested keys
4039
var serializedObject = {};
41-
$.each(formAsArray, function (_i, obj) {
40+
$.each(serializedArray, function (_i, obj) {
4241
var ogName = obj.name; // original input name
4342
var ogValue = obj.value; // original input value
4443

@@ -123,26 +122,39 @@
123122
return $.extend({}, f.defaultBaseOptions, f.defaultOptions, options);
124123
},
125124

126-
// Similar to jQuery serializeArray, returns an array of objects with name and value,
127-
// but in addition has the dom element, so it can be referenced later for configuration data attrs.
128-
serializeArray: function($form) {
125+
// Just like jQuery's serializeArray method, returns an array of objects with name and value.
126+
// but also includes the dom element (el) and is handles unchecked checkboxes if the option or data attribute are provided.
127+
serializeArray: function($form, opts) {
128+
if (opts == null) { opts = {}; }
129+
var f = $.serializeJSON;
130+
129131
return $form.map(function() {
130132
var elements = $.prop(this, "elements"); // handle propHook "elements" to filter or add form elements
131133
return elements ? $.makeArray(elements) : this;
132134

133135
}).filter(function() {
136+
var $el = $(this);
134137
var type = this.type;
135-
return this.name &&
136-
!$( this ).is(":disabled") && // .is(":disabled") so that fieldset[disabled] works
137-
rsubmittable.test(this.nodeName) && !rsubmitterTypes.test(type) && // only form fields
138-
(this.checked || !rcheckableType.test(type)); // remove unchecked checkboxes
138+
139+
// Filter with the standard W3C rules for successful controls: http://www.w3.org/TR/html401/interact/forms.html#h-17.13.2
140+
return this.name && // must contain a name attribute
141+
!$el.is(":disabled") && // must not be disable (use .is(":disabled") so that fieldset[disabled] works)
142+
rsubmittable.test(this.nodeName) && !rsubmitterTypes.test(type) && // only serialize submittable fields (and not buttons)
143+
(this.checked || !rcheckableType.test(type) || f.getCheckboxUncheckedValue($el, opts) != null); // skip unchecked checkboxes (unless using opts)
139144

140145
}).map(function(_i, el) {
141-
var val = $(this).val();
146+
var $el = $(this);
147+
var val = $el.val();
148+
var type = this.type;
149+
142150
if (val == null) {
143151
return null;
144152
}
145153

154+
if (rcheckableType.test(type) && !this.checked) {
155+
val = f.getCheckboxUncheckedValue($el, opts);
156+
}
157+
146158
if (isArray(val)) {
147159
return $.map(val, function(val) {
148160
return { name: el.name, value: val.replace(rCRLF, "\r\n"), el: el };
@@ -154,6 +166,14 @@
154166
}).get();
155167
},
156168

169+
getCheckboxUncheckedValue: function($el, opts) {
170+
var val = $el.attr("data-unchecked-value");
171+
if (val == null) {
172+
val = opts.checkboxUncheckedValue;
173+
}
174+
return val
175+
},
176+
157177
// Parse value with type function
158178
applyTypeFunc: function(name, valStr, type, typeFunctions) {
159179
var typeFunc = typeFunctions[type];
@@ -163,33 +183,6 @@
163183
return typeFunc(valStr);
164184
},
165185

166-
// Fill the formAsArray object with values for the unchecked checkbox inputs,
167-
// using the same format as the jquery.serializeArray function.
168-
// The value of the unchecked values is determined from the opts.checkboxUncheckedValue
169-
// and/or the data-unchecked-value attribute of the inputs.
170-
readCheckboxUncheckedValues: function (formAsArray, opts, $form) {
171-
if (opts == null) { opts = {}; }
172-
173-
var selector = "input[type=checkbox][name]:not(:checked):not([disabled])";
174-
var $uncheckedCheckboxes = $form.find(selector).add($form.filter(selector));
175-
$uncheckedCheckboxes.each(function (_i, el) {
176-
// Check data attr first, then the option
177-
var $el = $(el);
178-
var uncheckedValue = $el.attr("data-unchecked-value");
179-
if (uncheckedValue == null) {
180-
uncheckedValue = opts.checkboxUncheckedValue;
181-
}
182-
183-
// If there's an uncheckedValue, push it into the serialized formAsArray
184-
if (uncheckedValue != null) {
185-
if (el.name && el.name.indexOf("[][") !== -1) { // identify a non-supported
186-
throw new Error("serializeJSON ERROR: checkbox unchecked values are not supported on nested arrays of objects like '"+el.name+"'. See https://github.com/marioizquierdo/jquery.serializeJSON/issues/67");
187-
}
188-
formAsArray.push({name: el.name, value: uncheckedValue});
189-
}
190-
});
191-
},
192-
193186
// Splits a field name into the name and the type. Examples:
194187
// "foo" => ["foo", ""]
195188
// "foo:boolean" => ["foo", "boolean"]

spec/spec.js

+12-3
Original file line numberDiff line numberDiff line change
@@ -825,16 +825,25 @@ describe("$.serializeJSON", function() {
825825
});
826826
});
827827

828-
it("does not work on a nested list of objects", function() {
828+
it("works on a nested list of objects", function() {
829829
$form = form([
830830
inputCheckbox("answers[][correct]:boolean", "true").attr("data-unchecked-value", "false"),
831831
inputText("answers[][text]", "Blue"),
832832

833833
inputCheckbox("answers[][correct]:boolean", "true").attr("data-unchecked-value", "false"),
834834
inputText("answers[][text]", "Green"),
835-
]);
836835

837-
expect(function(){$form.serializeJSON();}).toThrow(); // it throws a descriptive error for the user
836+
inputCheckbox("answers[][correct]:boolean", "true").attr("data-unchecked-value", "false").prop("checked", true),
837+
inputText("answers[][text]", "Red"),
838+
]);
839+
obj = $form.serializeJSON({checkboxUncheckedValue: "false"});
840+
expect(obj).toEqual({
841+
answers: [
842+
{correct: false, text: "Blue"},
843+
{correct: false, text: "Green"},
844+
{correct: true, text: "Red"},
845+
],
846+
});
838847
});
839848

840849
it("does not serialize disabled checkboxes", function() {

0 commit comments

Comments
 (0)