form-render.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /*
  2. formBuilder - git@github.com:kevinchappell/formBuilder.git
  3. Version: 1.6.2
  4. Author: Kevin Chappell <kevin.b.chappell@gmail.com>
  5. */
  6. 'use strict';
  7. (function($) {
  8. 'use strict';
  9. var Toggle = function Toggle(element, options) {
  10. var defaults = {
  11. theme: 'fresh',
  12. labels: {
  13. off: 'Off',
  14. on: 'On'
  15. }
  16. };
  17. var opts = $.extend(defaults, options),
  18. $kcToggle = $('<div class="kc-toggle"/>').insertAfter(element).append(element);
  19. $kcToggle.toggleClass('on', element.is(':checked'));
  20. var kctOn = '<div class="kct-on">' + opts.labels.on + '</div>',
  21. kctOff = '<div class="kct-off">' + opts.labels.off + '</div>',
  22. kctHandle = '<div class="kct-handle"></div>',
  23. kctInner = '<div class="kct-inner">' + kctOn + kctHandle + kctOff + '</div>';
  24. $kcToggle.append(kctInner);
  25. $kcToggle.click(function() {
  26. element.attr('checked', !element.attr('checked'));
  27. $(this).toggleClass('on');
  28. });
  29. };
  30. $.fn.kcToggle = function(options) {
  31. var toggle = this;
  32. return toggle.each(function() {
  33. var element = $(this);
  34. if (element.data('kcToggle')) {
  35. return;
  36. }
  37. var kcToggle = new Toggle(element, options);
  38. element.data('kcToggle', kcToggle);
  39. });
  40. };
  41. })(jQuery);
  42. // render the formBuilder XML into html
  43. 'use strict';
  44. (function($) {
  45. 'use strict';
  46. $.fn.formRender = function(options) {
  47. var $template = $(this),
  48. defaults = {
  49. destroyTemplate: true,
  50. // @todo
  51. container: false
  52. },
  53. _helpers = {};
  54. var opts = $.extend(defaults, options);
  55. /**
  56. * Generate markup wrapper where needed
  57. * @param {string} type
  58. * @param {object} attrs
  59. * @param {string} content we wrap this
  60. * @return {string}
  61. */
  62. _helpers.markup = function(type) {
  63. var attrs = arguments.length <= 1 || arguments[1] === undefined ? {}: arguments[1];
  64. var content = arguments.length <= 2 || arguments[2] === undefined ? '': arguments[2];
  65. attrs = _helpers.attrString(attrs);
  66. content = Array.isArray(content) ? content.join('') : content;
  67. var inlineElems = ['input'],
  68. template = inlineElems.indexOf(type) === -1 ? '<' + type + ' ' + attrs + '>' + content + '</' + type + '>': '<' + type + ' ' + attrs + '/>';
  69. return template;
  70. };
  71. /**
  72. * Generate preview markup
  73. * @param {object} field
  74. * @return {string} preview markup for field
  75. * @todo
  76. */
  77. _helpers.fieldRender = function(field) {
  78. var fieldMarkup = '',
  79. fieldLabel = '',
  80. optionsMarkup = '';
  81. var fieldAttrs = _helpers.parseAttrs(field.attributes),
  82. fieldDesc = fieldAttrs.description,
  83. // @todo
  84. fieldOptions = $('option', field);
  85. fieldAttrs.id = fieldAttrs.name;
  86. console.log(fieldAttrs);
  87. var defaultVal = typeof fieldAttrs.defaultVal != 'undefined' ? fieldAttrs.defaultVal : '';
  88. if (fieldAttrs.type !== 'checkbox') {
  89. fieldAttrs['class'] = 'form-control';
  90. }
  91. if (fieldAttrs.type !== 'hidden') {
  92. fieldLabel = '<label for="' + fieldAttrs.id + '">' + fieldAttrs.label + '</label>';
  93. }
  94. if (fieldAttrs.required === 'false') {
  95. delete fieldAttrs.required;
  96. } else {
  97. fieldAttrs.required = null;
  98. fieldAttrs['aria-required'] = 'true';
  99. }
  100. delete fieldAttrs.label;
  101. delete fieldAttrs.description;
  102. var fieldAttrsString = _helpers.attrString(fieldAttrs);
  103. switch (fieldAttrs.type) {
  104. case 'textarea':
  105. case 'rich-text':
  106. delete fieldAttrs.type;
  107. delete fieldAttrs.value;
  108. fieldMarkup = fieldLabel + '<textarea ' + fieldAttrsString + '></textarea>';
  109. break;
  110. case 'select':
  111. fieldAttrs.type = fieldAttrs.type.replace('-group', '');
  112. if (fieldOptions.length) {
  113. fieldOptions.each(function(index, el) {
  114. var optionAttrs = _helpers.parseAttrs(el.attributes),
  115. optionAttrsString = _helpers.attrString(optionAttrs),
  116. optionText = el.innerHTML || el.innerContent || el.innerText || el.childNodes[0].nodeValue || el.value;
  117. optionsMarkup += '<option ' + optionAttrsString + '>' + optionText + '</option>';
  118. });
  119. }
  120. fieldMarkup = fieldLabel + '<select ' + fieldAttrsString + '>' + optionsMarkup + '</select>';
  121. break;
  122. case 'checkbox-group':
  123. case 'radio-group':
  124. fieldAttrs.type = fieldAttrs.type.replace('-group', '');
  125. delete fieldAttrs['class'];
  126. if (fieldOptions.length) { (function() {
  127. var optionName = fieldAttrs.name + '[]';
  128. fieldOptions.each(function(index, el) {
  129. var optionAttrs = $.extend(fieldAttrs, _helpers.parseAttrs(el.attributes));
  130. optionAttrs.name = optionName;
  131. optionAttrs.id = fieldAttrs.id + '-' + index;
  132. var optionAttrsString = _helpers.attrString(optionAttrs),
  133. optionText = el.innerHTML || el.innerContent || el.innerText || el.childNodes[0].nodeValue || el.value;
  134. optionsMarkup += '<div class="inner-checkbox"><input ' + optionAttrsString + ' /> <label for="' + optionAttrs.id + '">' + optionText + '</label></div>';
  135. });
  136. })();
  137. }
  138. fieldMarkup = fieldLabel + '<div class="' + fieldAttrs.type + '-group">' + optionsMarkup + '</div>';
  139. break;
  140. case 'text':
  141. case 'password':
  142. case 'email':
  143. case 'hidden':
  144. case 'date':
  145. case 'autocomplete':
  146. fieldMarkup = fieldLabel + ' <input ' + fieldAttrsString + ' value="'+defaultVal+'">';
  147. break;
  148. case 'checkbox':
  149. fieldMarkup = '<input ' + fieldAttrsString + '> ' + fieldLabel;
  150. if (fieldAttrs.toggle) {
  151. setTimeout(function() {
  152. $(document.getElementById(fieldAttrs.id)).kcToggle();
  153. },
  154. 100);
  155. }
  156. break;
  157. case 'text-label':
  158. fieldMarkup = fieldLabel + '<div class="frm-fld"><label class="field-introduce">' + fieldAttrs.introduce + '</label></div>';
  159. break;
  160. default:
  161. fieldMarkup = '<' + fieldAttrs.type + '></' + fieldAttrs.type + '>';
  162. }
  163. if (fieldAttrs.type !== 'hidden') {
  164. fieldMarkup = _helpers.markup('div', {
  165. 'class': 'form-group'
  166. },
  167. fieldMarkup);
  168. }
  169. return fieldMarkup;
  170. };
  171. _helpers.attrString = function(attrs) {
  172. var attributes = [];
  173. for (var attr in attrs) {
  174. if (attrs.hasOwnProperty(attr)) {
  175. var attrVal = attrs[attr] ? '="' + attrs[attr] + '"': '';
  176. attributes.push(attr + attrVal);
  177. }
  178. }
  179. return attributes.join(' ');
  180. };
  181. _helpers.parseAttrs = function(attrNodes) {
  182. var fieldAttrs = {};
  183. for (var attr in attrNodes) {
  184. if (attrNodes.hasOwnProperty(attr)) {
  185. fieldAttrs[attrNodes[attr]['nodeName']] = attrNodes[attr]['nodeValue'];
  186. }
  187. }
  188. return fieldAttrs;
  189. };
  190. // Begin the core plugin
  191. this.each(function() {
  192. var rendered = [];
  193. var formData = $.parseXML($template.val()),
  194. fields = $('field', formData),
  195. settings = $('settings', formData); // @todo
  196. if (!formData) {
  197. alert('No formData. Add some fields and try again');
  198. return false;
  199. }
  200. // generate field markup if we have fields
  201. if (fields.length) {
  202. fields.each(function(index, field) {
  203. index = index;
  204. rendered.push(_helpers.fieldRender(field));
  205. });
  206. }
  207. var output = rendered.join('');
  208. if (opts.container && opts.container.length) {
  209. opts.container.html(output);
  210. } else {
  211. $template.replaceWith(output);
  212. }
  213. });
  214. };
  215. })(jQuery);