form_field.js 7.8 KB

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