jam-cloud/web/app/assets/javascripts/jquery.formToObject.js

110 lines
3.9 KiB
JavaScript
Raw Permalink Normal View History

(function($) {
/**
* Go through the current JQuery match, and build a
* javascript object based on the name attributes of
* child elements. This is intended to be used for forms
* with inputs: var jsObj = $('#myform').formToObject();
*
* Using dots in the name attributes will build nested
* structures into the resulting object:
*
* <input name="foo.bar" value="x" />
* returns
* { foo: { bar:"x" } }
*
* The same name appearing twice will be returned as an array:
*
* <input type="checkbox" name="foo" value="a" checked="true"/>
* <input type="checkbox" name="foo" value="b" checked="true"/>
* returns
* { foo: ['a','b'] }
*
* Checkboxes and Radio inputs which are not checked will not
* appear at all, nor will any inputs which are disabled.
*
* Form fields which are optional can be omitted from the resulting
* object by providing a value for that field of "__OMIT__".
*
*/
"use strict";
$.fn.formToObject = function() {
// don't want to depend on other libs. Provide our own size to check
// length of an associative array:
function _size(obj) {
var key, size=0;
for (key in obj) {
if (obj.hasOwnProperty(key)) size++;
}
return size;
}
var formObject = {},
a = this.serializeArray();
$.each(a, function() {
var data = $('[name="' + this.name + '"]').first().data(),
current = formObject,
childKey,
path = this.name.split('.'),
key = path.pop(),
val = (data && data.parseInt !== undefined && data.parseInt) ? parseInt(this.value, 10) : (
(this.value.toLowerCase() == 'true') ? true : (
(this.value.toLowerCase() == 'false') ? false : (
(this.value.toLowerCase() == 'null') ? null : (
(typeof this.value == 'undefined') ? '' : this.value
)
)
)
);
while (path.length > 0) {
// Shift the front element from path into childKey
childKey = path.shift();
if (!(childKey in current)) {
current[childKey] = {};
}
// Move down and start working with the child object
current = current[childKey];
}
// We're at the right level in hierarchy. Define property next.
if (key in current) { // already exists.
if ($.isPlainObject(current[key])) { // about to overwrite obj with property!
throw "Can't overwrite named structure";
}
if (!current[key].push) { // convert property to array
current[key] = [current[key]];
}
current[key].push(val);
} else { // doesn't exist. Just set.
if (val !== '__OMIT__') {
current[key] = val;
}
}
});
// Trim any keys who hold nothing but empty objects: {}
var removeEmptyObjects = function(o) {
var k;
var trimlist = [];
for (k in o) {
if ($.isPlainObject(o[k])) { // recurse: deep first
removeEmptyObjects(o[k]);
}
if ($.isPlainObject(o[k]) && _size(o[k]) === 0) {
trimlist.push(k);
}
}
$.each(trimlist, function() {
delete o[this];
});
};
removeEmptyObjects(formObject);
return (_size(formObject) === 0) ? null : formObject;
};
})(jQuery);