(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: * * * returns * { foo: { bar:"x" } } * * The same name appearing twice will be returned as an array: * * * * 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);