form_field.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. //iTop Form field
  2. ;
  3. $(function()
  4. {
  5. // the widget definition, where 'itop' is the namespace,
  6. // 'form_field' the widget name
  7. $.widget( 'itop.form_field',
  8. {
  9. // default options
  10. options:
  11. {
  12. validators: null,
  13. validate_callback: 'validate', // When using an anonymous function, use the 'me' parameter to acces the current widget : function(me){ return me.validate(); },
  14. get_current_value_callback: 'getCurrentValue'
  15. },
  16. // the constructor
  17. _create: function()
  18. {
  19. var me = this;
  20. this.element
  21. .addClass('form_field');
  22. this.element
  23. .bind('set_validators', function(event, data){
  24. me.options.validators = data;
  25. });
  26. this.element
  27. .bind('validate get_current_value', function(event, data){
  28. var callback = me.options[event.type+'_callback'];
  29. if(typeof callback === 'string')
  30. {
  31. return me[callback]();
  32. }
  33. else if(typeof callback === 'function')
  34. {
  35. return callback(me);
  36. }
  37. else
  38. {
  39. console.log('Form field : callback type must be a function or a existing function name of the widget');
  40. return false;
  41. }
  42. });
  43. },
  44. // called when created, and later when changing options
  45. _refresh: function()
  46. {
  47. },
  48. // events bound via _bind are removed automatically
  49. // revert other modifications here
  50. _destroy: function()
  51. {
  52. this.element
  53. .removeClass('form_field');
  54. },
  55. // _setOptions is called with a hash of all options that are changing
  56. // always refresh when changing options
  57. _setOptions: function()
  58. {
  59. this._superApply(arguments);
  60. },
  61. // _setOption is called for each individual option that is changing
  62. _setOption: function( key, value )
  63. {
  64. this._super( key, value );
  65. },
  66. getCurrentValue: function()
  67. {
  68. var value = {};
  69. this.element.find(':input').each(function(index, elem){
  70. if($(elem).is(':hidden') || $(elem).is(':text') || $(elem).is('textarea'))
  71. {
  72. value[$(elem).attr('name')] = $(elem).val();
  73. }
  74. else if($(elem).is('select'))
  75. {
  76. value[$(elem).attr('name')] = [];
  77. $(elem).find('option:selected').each(function(){
  78. value[$(elem).attr('name')].push($(this).val());
  79. });
  80. }
  81. else if($(elem).is(':checkbox') || $(elem).is(':radio'))
  82. {
  83. if(value[$(elem).attr('name')] === undefined)
  84. {
  85. value[$(elem).attr('name')] = [];
  86. }
  87. if($(elem).is(':checked'))
  88. {
  89. value[$(elem).attr('name')].push($(elem).val());
  90. }
  91. }
  92. else
  93. {
  94. console.log('Form field : Input type not handle yet.');
  95. }
  96. });
  97. return value;
  98. },
  99. validate: function()
  100. {
  101. var oResult = { is_valid: true, error_messages: [] };
  102. // Doing data validation
  103. if(this.options.validators !== null)
  104. {
  105. var bMandatory = (this.options.validators.mandatory !== undefined);
  106. // Extracting value for the field
  107. var oValue = this.getCurrentValue();
  108. var aValueKeys = Object.keys(oValue);
  109. // This is just a safety check in case a field doesn't always return an object when no value assigned, so we have to check the mandatory validator here...
  110. // ... But this should never happen.
  111. if( (aValueKeys.length === 0) && bMandatory )
  112. {
  113. oResult.is_valid = false;
  114. oResult.error_messages.push(this.options.validators.mandatory.message);
  115. }
  116. // ... Otherwise, we check every validators
  117. else if(aValueKeys.length > 0)
  118. {
  119. var value = oValue[aValueKeys[0]];
  120. for(var sValidatorType in this.options.validators)
  121. {
  122. var oValidator = this.options.validators[sValidatorType];
  123. if(sValidatorType === 'mandatory')
  124. {
  125. // Works for string, array, object
  126. if($.isEmptyObject(value))
  127. {
  128. oResult.is_valid = false;
  129. oResult.error_messages.push(oValidator.message);
  130. }
  131. // ... In case of none empty array, we have to check is the value is not null
  132. else if($.isArray(value))
  133. {
  134. for(var i in value)
  135. {
  136. if(typeof value[i] === 'string')
  137. {
  138. if($.isEmptyObject(value[i]))
  139. {
  140. oResult.is_valid = false;
  141. oResult.error_messages.push(oValidator.message);
  142. }
  143. }
  144. else
  145. {
  146. console.log('Form field: mandatory validation not supported yet for the type "' + (typeof value[i]) +'"');
  147. }
  148. }
  149. }
  150. }
  151. else
  152. {
  153. var oRegExp = new RegExp(oValidator.reg_exp, "g");
  154. if(typeof value === 'string')
  155. {
  156. if(!oRegExp.test(value))
  157. {
  158. oResult.is_valid = false;
  159. oResult.error_messages.push(oValidator.message);
  160. }
  161. }
  162. else if($.isArray(value))
  163. {
  164. for(var i in value)
  165. {
  166. if(value[i] === 'string' && !oRegExp.test(value))
  167. {
  168. oResult.is_valid = false;
  169. oResult.error_messages.push(oValidator.message);
  170. }
  171. }
  172. }
  173. else
  174. {
  175. console.log('Form field: validation not supported yet for the type "' + (typeof value) +'"');
  176. }
  177. }
  178. }
  179. }
  180. }
  181. // Rendering visual feedback on the field
  182. this.element.removeClass('has-success has-warning has-error')
  183. this.element.find('.help-block').html('');
  184. if(!oResult.is_valid)
  185. {
  186. this.element.addClass('has-error');
  187. for(var i in oResult.error_messages)
  188. {
  189. this.element.find('.help-block').append($('<p>' + oResult.error_messages[i] + '</p>'));
  190. }
  191. }
  192. return oResult;
  193. },
  194. showOptions: function()
  195. {
  196. return this.options;
  197. }
  198. });
  199. });