form.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /**
  2. * Functions for manipulating web forms.
  3. *
  4. * @author David I. Lehn <dlehn@digitalbazaar.com>
  5. * @author Dave Longley
  6. * @author Mike Johnson
  7. *
  8. * Copyright (c) 2011-2014 Digital Bazaar, Inc. All rights reserved.
  9. */
  10. var forge = require('./forge');
  11. /* Form API */
  12. var form = module.exports = forge.form = forge.form || {};
  13. (function($) {
  14. /**
  15. * Regex for parsing a single name property (handles array brackets).
  16. */
  17. var _regex = /([^\[]*?)\[(.*?)\]/g;
  18. /**
  19. * Parses a single name property into an array with the name and any
  20. * array indices.
  21. *
  22. * @param name the name to parse.
  23. *
  24. * @return the array of the name and its array indices in order.
  25. */
  26. var _parseName = function(name) {
  27. var rval = [];
  28. var matches;
  29. while(!!(matches = _regex.exec(name))) {
  30. if(matches[1].length > 0) {
  31. rval.push(matches[1]);
  32. }
  33. if(matches.length >= 2) {
  34. rval.push(matches[2]);
  35. }
  36. }
  37. if(rval.length === 0) {
  38. rval.push(name);
  39. }
  40. return rval;
  41. };
  42. /**
  43. * Adds a field from the given form to the given object.
  44. *
  45. * @param obj the object.
  46. * @param names the field as an array of object property names.
  47. * @param value the value of the field.
  48. * @param dict a dictionary of names to replace.
  49. */
  50. var _addField = function(obj, names, value, dict) {
  51. // combine array names that fall within square brackets
  52. var tmp = [];
  53. for(var i = 0; i < names.length; ++i) {
  54. // check name for starting square bracket but no ending one
  55. var name = names[i];
  56. if(name.indexOf('[') !== -1 && name.indexOf(']') === -1 &&
  57. i < names.length - 1) {
  58. do {
  59. name += '.' + names[++i];
  60. } while(i < names.length - 1 && names[i].indexOf(']') === -1);
  61. }
  62. tmp.push(name);
  63. }
  64. names = tmp;
  65. // split out array indexes
  66. var tmp = [];
  67. $.each(names, function(n, name) {
  68. tmp = tmp.concat(_parseName(name));
  69. });
  70. names = tmp;
  71. // iterate over object property names until value is set
  72. $.each(names, function(n, name) {
  73. // do dictionary name replacement
  74. if(dict && name.length !== 0 && name in dict) {
  75. name = dict[name];
  76. }
  77. // blank name indicates appending to an array, set name to
  78. // new last index of array
  79. if(name.length === 0) {
  80. name = obj.length;
  81. }
  82. // value already exists, append value
  83. if(obj[name]) {
  84. // last name in the field
  85. if(n == names.length - 1) {
  86. // more than one value, so convert into an array
  87. if(!$.isArray(obj[name])) {
  88. obj[name] = [obj[name]];
  89. }
  90. obj[name].push(value);
  91. } else {
  92. // not last name, go deeper into object
  93. obj = obj[name];
  94. }
  95. } else if(n == names.length - 1) {
  96. // new value, last name in the field, set value
  97. obj[name] = value;
  98. } else {
  99. // new value, not last name, go deeper
  100. // get next name
  101. var next = names[n + 1];
  102. // blank next value indicates array-appending, so create array
  103. if(next.length === 0) {
  104. obj[name] = [];
  105. } else {
  106. // if next name is a number create an array, otherwise a map
  107. var isNum = ((next - 0) == next && next.length > 0);
  108. obj[name] = isNum ? [] : {};
  109. }
  110. obj = obj[name];
  111. }
  112. });
  113. };
  114. /**
  115. * Serializes a form to a JSON object. Object properties will be separated
  116. * using the given separator (defaults to '.') and by square brackets.
  117. *
  118. * @param input the jquery form to serialize.
  119. * @param sep the object-property separator (defaults to '.').
  120. * @param dict a dictionary of names to replace (name=replace).
  121. *
  122. * @return the JSON-serialized form.
  123. */
  124. form.serialize = function(input, sep, dict) {
  125. var rval = {};
  126. // add all fields in the form to the object
  127. sep = sep || '.';
  128. $.each(input.serializeArray(), function() {
  129. _addField(rval, this.name.split(sep), this.value || '', dict);
  130. });
  131. return rval;
  132. };
  133. })(jQuery);