150 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			150 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/**
 | 
						|
 * Functions for manipulating web forms.
 | 
						|
 *
 | 
						|
 * @author David I. Lehn <dlehn@digitalbazaar.com>
 | 
						|
 * @author Dave Longley
 | 
						|
 * @author Mike Johnson
 | 
						|
 *
 | 
						|
 * Copyright (c) 2011-2014 Digital Bazaar, Inc. All rights reserved.
 | 
						|
 */
 | 
						|
var forge = require('./forge');
 | 
						|
 | 
						|
/* Form API */
 | 
						|
var form = module.exports = forge.form = forge.form || {};
 | 
						|
 | 
						|
(function($) {
 | 
						|
 | 
						|
/**
 | 
						|
 * Regex for parsing a single name property (handles array brackets).
 | 
						|
 */
 | 
						|
var _regex = /([^\[]*?)\[(.*?)\]/g;
 | 
						|
 | 
						|
/**
 | 
						|
 * Parses a single name property into an array with the name and any
 | 
						|
 * array indices.
 | 
						|
 *
 | 
						|
 * @param name the name to parse.
 | 
						|
 *
 | 
						|
 * @return the array of the name and its array indices in order.
 | 
						|
 */
 | 
						|
var _parseName = function(name) {
 | 
						|
  var rval = [];
 | 
						|
 | 
						|
  var matches;
 | 
						|
  while(!!(matches = _regex.exec(name))) {
 | 
						|
    if(matches[1].length > 0) {
 | 
						|
      rval.push(matches[1]);
 | 
						|
    }
 | 
						|
    if(matches.length >= 2) {
 | 
						|
      rval.push(matches[2]);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if(rval.length === 0) {
 | 
						|
    rval.push(name);
 | 
						|
  }
 | 
						|
 | 
						|
  return rval;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * Adds a field from the given form to the given object.
 | 
						|
 *
 | 
						|
 * @param obj the object.
 | 
						|
 * @param names the field as an array of object property names.
 | 
						|
 * @param value the value of the field.
 | 
						|
 * @param dict a dictionary of names to replace.
 | 
						|
 */
 | 
						|
var _addField = function(obj, names, value, dict) {
 | 
						|
  // combine array names that fall within square brackets
 | 
						|
  var tmp = [];
 | 
						|
  for(var i = 0; i < names.length; ++i) {
 | 
						|
    // check name for starting square bracket but no ending one
 | 
						|
    var name = names[i];
 | 
						|
    if(name.indexOf('[') !== -1 && name.indexOf(']') === -1 &&
 | 
						|
      i < names.length - 1) {
 | 
						|
      do {
 | 
						|
        name += '.' + names[++i];
 | 
						|
      } while(i < names.length - 1 && names[i].indexOf(']') === -1);
 | 
						|
    }
 | 
						|
    tmp.push(name);
 | 
						|
  }
 | 
						|
  names = tmp;
 | 
						|
 | 
						|
  // split out array indexes
 | 
						|
  var tmp = [];
 | 
						|
  $.each(names, function(n, name) {
 | 
						|
    tmp = tmp.concat(_parseName(name));
 | 
						|
  });
 | 
						|
  names = tmp;
 | 
						|
 | 
						|
  // iterate over object property names until value is set
 | 
						|
  $.each(names, function(n, name) {
 | 
						|
    // do dictionary name replacement
 | 
						|
    if(dict && name.length !== 0 && name in dict) {
 | 
						|
       name = dict[name];
 | 
						|
    }
 | 
						|
 | 
						|
    // blank name indicates appending to an array, set name to
 | 
						|
    // new last index of array
 | 
						|
    if(name.length === 0) {
 | 
						|
       name = obj.length;
 | 
						|
    }
 | 
						|
 | 
						|
    // value already exists, append value
 | 
						|
    if(obj[name]) {
 | 
						|
      // last name in the field
 | 
						|
      if(n == names.length - 1) {
 | 
						|
        // more than one value, so convert into an array
 | 
						|
        if(!$.isArray(obj[name])) {
 | 
						|
          obj[name] = [obj[name]];
 | 
						|
        }
 | 
						|
        obj[name].push(value);
 | 
						|
      } else {
 | 
						|
        // not last name, go deeper into object
 | 
						|
        obj = obj[name];
 | 
						|
      }
 | 
						|
    } else if(n == names.length - 1) {
 | 
						|
      // new value, last name in the field, set value
 | 
						|
      obj[name] = value;
 | 
						|
    } else {
 | 
						|
      // new value, not last name, go deeper
 | 
						|
      // get next name
 | 
						|
      var next = names[n + 1];
 | 
						|
 | 
						|
      // blank next value indicates array-appending, so create array
 | 
						|
      if(next.length === 0) {
 | 
						|
         obj[name] = [];
 | 
						|
      } else {
 | 
						|
        // if next name is a number create an array, otherwise a map
 | 
						|
        var isNum = ((next - 0) == next && next.length > 0);
 | 
						|
        obj[name] = isNum ? [] : {};
 | 
						|
      }
 | 
						|
      obj = obj[name];
 | 
						|
    }
 | 
						|
  });
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * Serializes a form to a JSON object. Object properties will be separated
 | 
						|
 * using the given separator (defaults to '.') and by square brackets.
 | 
						|
 *
 | 
						|
 * @param input the jquery form to serialize.
 | 
						|
 * @param sep the object-property separator (defaults to '.').
 | 
						|
 * @param dict a dictionary of names to replace (name=replace).
 | 
						|
 *
 | 
						|
 * @return the JSON-serialized form.
 | 
						|
 */
 | 
						|
form.serialize = function(input, sep, dict) {
 | 
						|
  var rval = {};
 | 
						|
 | 
						|
  // add all fields in the form to the object
 | 
						|
  sep = sep || '.';
 | 
						|
  $.each(input.serializeArray(), function() {
 | 
						|
    _addField(rval, this.name.split(sep), this.value || '', dict);
 | 
						|
  });
 | 
						|
 | 
						|
  return rval;
 | 
						|
};
 | 
						|
 | 
						|
})(jQuery);
 |