jquery-form-validator-rails 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,144 @@
1
+ /**
2
+ * jQuery Form Validator Module: html5
3
+ * ------------------------------------------
4
+ * Created by Victor Jonsson <http://www.victorjonsson.se>
5
+ *
6
+ * The following module will make this jQuery plugin serve as a
7
+ * html5 fallback. It makes older browsers support the following
8
+ * - validation when type="email"
9
+ * - validation when type="url"
10
+ * - validation when type="time"
11
+ * - validation when type="date"
12
+ * - validation when type="number" and max="" min=""
13
+ * - validation when pattern="REGEXP"
14
+ * - validation when using maxlength
15
+ * - Using datalist element for creating suggestions
16
+ * - placeholders
17
+ *
18
+ * @website http://formvalidator.net/
19
+ * @license Dual licensed under the MIT or GPL Version 2 licenses
20
+ * @version 2.2.beta.50
21
+ */
22
+ (function($, window) {
23
+
24
+ "use strict";
25
+
26
+ var SUPPORTS_PLACEHOLDER = 'placeholder' in document.createElement('INPUT'),
27
+ SUPPORTS_DATALIST = 'options' in document.createElement('DATALIST');
28
+
29
+ $(window).bind('validatorsLoaded formValidationSetup', function(evt, $form) {
30
+
31
+ if( !$form ) {
32
+ $form = $('form');
33
+ }
34
+
35
+ var hasLoadedDateModule = false;
36
+
37
+ $form.each(function() {
38
+ var $f = $(this),
39
+ $formInputs = $f.find('input,textarea,select'),
40
+ foundHtml5Rule = false;
41
+
42
+ $formInputs.each(function() {
43
+ var validation = [],
44
+ $input = $(this),
45
+ isRequired = $input.attr('required'),
46
+ attrs = {};
47
+
48
+ switch ( ($input.attr('type') || '').toLowerCase() ) {
49
+ case 'time':
50
+ validation.push('time');
51
+ if( !$.formUtils.validators.validate_date && !hasLoadedDateModule ) {
52
+ hasLoadedDateModule = true;
53
+ $.formUtils.loadModules('date');
54
+ }
55
+ break;
56
+ case 'url':
57
+ validation.push('url');
58
+ break;
59
+ case 'email':
60
+ validation.push('email');
61
+ break;
62
+ case 'date':
63
+ validation.push('date');
64
+ break;
65
+ case 'number':
66
+ validation.push('number');
67
+ var max = $input.attr('max'),
68
+ min = $input.attr('min');
69
+ if( min || max ) {
70
+ if( !min )
71
+ min = 0;
72
+ if( !max )
73
+ max = 9007199254740992; // js max int
74
+
75
+ attrs['data-validation-allowing'] = 'range['+min+';'+max+']';
76
+ if( min.indexOf('-') === 0 || max.indexOf('-') === 0 ) {
77
+ attrs['data-validation-allowing'] += ',negative';
78
+ }
79
+ if( min.indexOf('.') > -1 || max.indexOf('.') > -1 ) {
80
+ attrs['data-validation-allowing'] += ',float';
81
+ }
82
+ }
83
+ break;
84
+ }
85
+
86
+ if( $input.attr('pattern') ) {
87
+ validation.push('custom');
88
+ attrs['data-validation-regexp'] = $input.attr('pattern');
89
+ }
90
+ if( $input.attr('maxlength') ) {
91
+ validation.push('length');
92
+ attrs['data-validation-length'] = 'max'+$input.attr('maxlength');
93
+ }
94
+
95
+ if( !SUPPORTS_DATALIST && $input.attr('list') ) {
96
+ var suggestions = [];
97
+ $('#'+$input.attr('list')+' option').each(function() {
98
+ var $opt = $(this);
99
+ suggestions.push($opt.attr('value') || $opt.text());
100
+ });
101
+ $.formUtils.suggest( $input, suggestions );
102
+ }
103
+
104
+ if( validation.length ) {
105
+ if( !isRequired ) {
106
+ attrs['data-validation-optional'] = 'true';
107
+ }
108
+
109
+ foundHtml5Rule = true;
110
+ $input.attr('data-validation', validation.join(' '));
111
+
112
+ $.each(attrs, function(attrName, attrVal) {
113
+ $input.attr(attrName, attrVal);
114
+ });
115
+ }
116
+ });
117
+
118
+ if( foundHtml5Rule ) {
119
+ $f.trigger('html5ValidationAttrsFound');
120
+ }
121
+
122
+ if( !SUPPORTS_PLACEHOLDER ) {
123
+ $formInputs.filter('input[placeholder]').each(function() {
124
+ this.defaultValue = this.getAttribute('placeholder');
125
+ $(this)
126
+ .bind('focus', function() {
127
+ if(this.value == this.defaultValue) {
128
+ this.value = '';
129
+ $(this).removeClass('showing-placeholder');
130
+ }
131
+ })
132
+ .bind('blur', function() {
133
+ if($.trim(this.value) == '') {
134
+ this.value = this.defaultValue;
135
+ $(this).addClass('showing-placeholder');
136
+ }
137
+ });
138
+ });
139
+ }
140
+
141
+ });
142
+ });
143
+
144
+ })(jQuery, window);
@@ -1 +1 @@
1
- (function($,window){"use strict";var SUPPORTS_PLACEHOLDER="placeholder"in document.createElement("INPUT"),SUPPORTS_DATALIST="options"in document.createElement("DATALIST");$(window).bind("validatorsLoaded formValidationSetup",function(evt,$form){if(!$form){$form=$("form")}var hasLoadedDateModule=false;$form.each(function(){var $f=$(this),$formInputs=$f.find("input,textarea,select"),foundHtml5Rule=false;$formInputs.each(function(){var validation=[],$input=$(this),isRequired=$input.attr("required"),attrs={};switch(($input.attr("type")||"").toLowerCase()){case"time":validation.push("time");if(!$.formUtils.validators.validate_date&&!hasLoadedDateModule){hasLoadedDateModule=true;$.formUtils.loadModules("date")}break;case"url":validation.push("url");break;case"email":validation.push("email");break;case"date":validation.push("date");break;case"number":validation.push("number");var max=$input.attr("max"),min=$input.attr("min");if(min||max){if(!min)min=0;if(!max)max=9007199254740992;attrs["data-validation-allowing"]="range["+min+";"+max+"]";if(min.indexOf("-")===0||max.indexOf("-")===0){attrs["data-validation-allowing"]+=",negative"}if(min.indexOf(".")>-1||max.indexOf(".")>-1){attrs["data-validation-allowing"]+=",float"}}break}if($input.attr("pattern")){validation.push("custom");attrs["data-validation-regexp"]=$input.attr("pattern")}if($input.attr("maxlength")){validation.push("length");attrs["data-validation-length"]="max"+$input.attr("maxlength")}console.log($input.html());if(!SUPPORTS_DATALIST&&$input.attr("list")){console.log($input.attr("list"));var suggestions=[];$("#"+$input.attr("list")+" option").each(function(){var $opt=$(this);suggestions.push($opt.attr("value")||$opt.text())});$.formUtils.suggest($input,suggestions)}if(validation.length){if(!isRequired){attrs["data-validation-optional"]="true"}foundHtml5Rule=true;$input.attr("data-validation",validation.join(" "));$.each(attrs,function(attrName,attrVal){$input.attr(attrName,attrVal)})}});if(foundHtml5Rule){$f.trigger("html5ValidationAttrsFound")}if(!SUPPORTS_PLACEHOLDER){$formInputs.filter("input[placeholder]").each(function(){this.defaultValue=this.getAttribute("placeholder");$(this).bind("focus",function(){if(this.value==this.defaultValue){this.value="";$(this).removeClass("showing-placeholder")}}).bind("blur",function(){if($.trim(this.value)==""){this.value=this.defaultValue;$(this).addClass("showing-placeholder")}})})}})})})(jQuery,window);
1
+ (function($,window){"use strict";var SUPPORTS_PLACEHOLDER="placeholder"in document.createElement("INPUT"),SUPPORTS_DATALIST="options"in document.createElement("DATALIST");$(window).bind("validatorsLoaded formValidationSetup",function(evt,$form){if(!$form){$form=$("form")}var hasLoadedDateModule=false;$form.each(function(){var $f=$(this),$formInputs=$f.find("input,textarea,select"),foundHtml5Rule=false;$formInputs.each(function(){var validation=[],$input=$(this),isRequired=$input.attr("required"),attrs={};switch(($input.attr("type")||"").toLowerCase()){case"time":validation.push("time");if(!$.formUtils.validators.validate_date&&!hasLoadedDateModule){hasLoadedDateModule=true;$.formUtils.loadModules("date")}break;case"url":validation.push("url");break;case"email":validation.push("email");break;case"date":validation.push("date");break;case"number":validation.push("number");var max=$input.attr("max"),min=$input.attr("min");if(min||max){if(!min)min=0;if(!max)max=9007199254740992;attrs["data-validation-allowing"]="range["+min+";"+max+"]";if(min.indexOf("-")===0||max.indexOf("-")===0){attrs["data-validation-allowing"]+=",negative"}if(min.indexOf(".")>-1||max.indexOf(".")>-1){attrs["data-validation-allowing"]+=",float"}}break}if($input.attr("pattern")){validation.push("custom");attrs["data-validation-regexp"]=$input.attr("pattern")}if($input.attr("maxlength")){validation.push("length");attrs["data-validation-length"]="max"+$input.attr("maxlength")}if(!SUPPORTS_DATALIST&&$input.attr("list")){var suggestions=[];$("#"+$input.attr("list")+" option").each(function(){var $opt=$(this);suggestions.push($opt.attr("value")||$opt.text())});$.formUtils.suggest($input,suggestions)}if(validation.length){if(!isRequired){attrs["data-validation-optional"]="true"}foundHtml5Rule=true;$input.attr("data-validation",validation.join(" "));$.each(attrs,function(attrName,attrVal){$input.attr(attrName,attrVal)})}});if(foundHtml5Rule){$f.trigger("html5ValidationAttrsFound")}if(!SUPPORTS_PLACEHOLDER){$formInputs.filter("input[placeholder]").each(function(){this.defaultValue=this.getAttribute("placeholder");$(this).bind("focus",function(){if(this.value==this.defaultValue){this.value="";$(this).removeClass("showing-placeholder")}}).bind("blur",function(){if($.trim(this.value)==""){this.value=this.defaultValue;$(this).addClass("showing-placeholder")}})})}})})})(jQuery,window);
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * @website http://formvalidator.net/
7
7
  * @license Dual licensed under the MIT or GPL Version 2 licenses
8
- * @version 2.1.66
8
+ * @version 2.2.beta.50
9
9
  */
10
10
  (function($) {
11
11
 
@@ -15,10 +15,15 @@
15
15
  _applyErrorStyle = function($elem, conf) {
16
16
  $elem
17
17
  .addClass(conf.errorElementClass)
18
- .removeClass('valid')
19
- .parent()
20
- .addClass('has-error')
21
- .removeClass('has-success'); // twitter bs
18
+ .removeClass('valid');
19
+
20
+ var $parent = $elem.parent();
21
+ if($parent.hasClass("input-group"))
22
+ $parent = $parent.parent();
23
+
24
+ $parent
25
+ .addClass(conf.inputParentClassOnError)
26
+ .removeClass(conf.inputParentClassOnSuccess);
22
27
 
23
28
  if(conf.borderColorOnError !== '') {
24
29
  $elem.css('border-color', conf.borderColorOnError);
@@ -26,20 +31,29 @@
26
31
  },
27
32
  _removeErrorStyle = function($elem, conf) {
28
33
  $elem.each(function() {
29
- _setInlineErrorMessage($(this), '', conf, conf.errorMessagePosition);
30
- $(this)
34
+ var $this = $(this),
35
+ $parent = $this.parent();
36
+
37
+ if($parent.hasClass("input-group"))
38
+ $parent = $parent.parent();
39
+
40
+ _setInlineErrorMessage($this, '', conf, conf.errorMessagePosition);
41
+
42
+ $this
31
43
  .removeClass('valid')
32
44
  .removeClass(conf.errorElementClass)
33
- .css('border-color', '')
34
- .parent()
35
- .removeClass('has-error')
36
- .removeClass('has-success')
37
- .find('.'+conf.errorMessageClass) // remove inline error message
38
- .remove();
45
+ .css('border-color', '');
46
+
47
+ $parent
48
+ .removeClass(conf.inputParentClassOnError)
49
+ .removeClass(conf.inputParentClassOnSuccess)
50
+ .find('.'+conf.errorMessageClass) // remove inline span holding error message
51
+ .remove();
39
52
  });
40
53
  },
41
54
  _setInlineErrorMessage = function($input, mess, conf, $messageContainer) {
42
55
  var custom = _getInlineErrorElement($input);
56
+
43
57
  if( custom ) {
44
58
  custom.innerHTML = mess;
45
59
  }
@@ -64,10 +78,12 @@
64
78
  }
65
79
  }
66
80
  else {
67
- var $mess = $input.parent().find('.'+conf.errorMessageClass+'.help-block');
81
+ var $parent = $input.parent();
82
+ if($parent.hasClass("input-group")) $parent = $parent.parent();
83
+ var $mess = $parent.find('.'+conf.errorMessageClass+'.help-block');
68
84
  if( $mess.length == 0 ) {
69
85
  $mess = $('<span></span>').addClass('help-block').addClass(conf.errorMessageClass);
70
- $mess.appendTo($input.parent());
86
+ $mess.appendTo($parent);
71
87
  }
72
88
  $mess.html(mess);
73
89
  }
@@ -97,8 +113,15 @@
97
113
  $.fn.validateOnBlur = function(language, settings) {
98
114
  this.find('input[data-validation],textarea[data-validation],select[data-validation]')
99
115
  .bind('blur.validation', function() {
100
- $(this).validateInputOnBlur(language, settings);
116
+ $(this).validateInputOnBlur(language, settings, true, 'blur');
117
+ });
118
+ if(settings.validateCheckboxRadioOnClick) {
119
+ // bind click event to validate on click for radio & checkboxes for nice UX
120
+ this.find('input[type=checkbox][data-validation],input[type=radio][data-validation]')
121
+ .bind('click.validation', function() {
122
+ $(this).validateInputOnBlur(language, settings, true, 'click');
101
123
  });
124
+ }
102
125
 
103
126
  return this;
104
127
  };
@@ -113,10 +136,10 @@
113
136
  this.find('input[data-validation][data-validation-event],textarea[data-validation][data-validation-event],select[data-validation][data-validation-event]')
114
137
  .each(function(){
115
138
  var $el = $(this),
116
- etype = $el.attr("data-validation-event");
139
+ etype = $el.valAttr("event");
117
140
  if (etype){
118
141
  $el.bind(etype + ".validation", function(){
119
- $(this).validateInputOnBlur(language, settings, false, etype);
142
+ $(this).validateInputOnBlur(language, settings, true, etype);
120
143
  });
121
144
  }
122
145
  });
@@ -139,8 +162,6 @@
139
162
  // Remove previously added event listeners
140
163
  this.find('.has-help-txt')
141
164
  .valAttr('has-keyup-event', false)
142
- .valAttr('backend-valid', false)
143
- .valAttr('backend-invalid', false)
144
165
  .removeClass('has-help-txt');
145
166
 
146
167
  // Add help text listeners
@@ -188,23 +209,21 @@
188
209
  *
189
210
  * @param {Object} [language] Optional, will override $.formUtils.LANG
190
211
  * @param {Object} [conf] Optional, will override the default settings
191
- * @param {Boolean} [attachKeyupEvent] Optional
192
- * @param {String} [eventContext]
212
+ * @param {Boolean} attachKeyupEvent Optional
213
+ * @param {String} eventType
193
214
  * @return {jQuery}
194
215
  */
195
- $.fn.validateInputOnBlur = function(language, conf, attachKeyupEvent, eventContext) {
196
- if(attachKeyupEvent === undefined)
197
- attachKeyupEvent = true;
198
- if(!eventContext)
199
- eventContext = 'blur';
216
+ $.fn.validateInputOnBlur = function(language, conf, attachKeyupEvent, eventType) {
217
+
218
+ $.formUtils.eventType = eventType;
200
219
 
201
220
  if( (this.valAttr('suggestion-nr') || this.valAttr('postpone') || this.hasClass('hasDatepicker')) && !window.postponedValidation ) {
202
- // This validation has to be postponed
221
+ // This validation has to be postponed
203
222
  var _self = this,
204
223
  postponeTime = this.valAttr('postpone') || 200;
205
224
 
206
225
  window.postponedValidation = function() {
207
- _self.validateInputOnBlur(language, conf, attachKeyupEvent);
226
+ _self.validateInputOnBlur(language, conf, attachKeyupEvent, eventType);
208
227
  window.postponedValidation = false;
209
228
  };
210
229
  setTimeout(function() {
@@ -218,7 +237,6 @@
218
237
 
219
238
  language = $.extend({}, $.formUtils.LANG, language || {});
220
239
  _removeErrorStyle(this, conf);
221
-
222
240
  var $elem = this,
223
241
  $form = $elem.closest("form"),
224
242
  validationRule = $elem.attr(conf.validationRuleAttribute),
@@ -227,25 +245,26 @@
227
245
  language,
228
246
  $.extend({}, conf, {errorMessagePosition:'element'}),
229
247
  $form,
230
- eventContext
248
+ eventType
231
249
  );
232
-
233
- $elem.trigger('validation', [validation===null ? null : validation===true]);
234
-
250
+
235
251
  if(validation === true) {
236
252
  $elem
237
253
  .addClass('valid')
238
254
  .parent()
239
- .addClass('has-success'); // twitter bs
255
+ .addClass(conf.inputParentClassOnSuccess);
256
+
240
257
  } else if(validation !== null) {
241
258
 
242
259
  _applyErrorStyle($elem, conf);
243
260
  _setInlineErrorMessage($elem, validation, conf, conf.errorMessagePosition);
244
261
 
245
262
  if(attachKeyupEvent) {
246
- $elem.bind('keyup', function() {
247
- $(this).validateInputOnBlur(language, conf, false, 'keyup');
248
- });
263
+ $elem
264
+ .unbind('keyup.validation')
265
+ .bind('keyup.validation', function() {
266
+ $(this).validateInputOnBlur(language, conf, false, 'keyup');
267
+ });
249
268
  }
250
269
  }
251
270
 
@@ -273,7 +292,7 @@
273
292
  };
274
293
 
275
294
  /**
276
- * Function that validate all inputs in given element
295
+ * Function that validates all inputs in active form
277
296
  *
278
297
  * @param {Object} [language]
279
298
  * @param {Object} [conf]
@@ -293,6 +312,14 @@
293
312
  language = $.extend({}, $.formUtils.LANG, language || {});
294
313
  displayError = displayError !== false;
295
314
 
315
+ if($.formUtils.errorDisplayPreventedWhenHalted) {
316
+ // isValid() was called programmatically with argument displayError set
317
+ // to false when the validation was halted by any of the validators
318
+ delete $.formUtils.errorDisplayPreventedWhenHalted
319
+ displayError = false;
320
+ }
321
+
322
+
296
323
  $.formUtils.isValidatingEntireForm = true;
297
324
  $.formUtils.haltValidation = false;
298
325
 
@@ -303,18 +330,18 @@
303
330
  * @para {jQuery} $elem
304
331
  */
305
332
  var addErrorMessage = function(mess, $elem) {
306
- // validate server side will return null as error message before the server is requested
307
- if(mess !== null) {
308
- if ($.inArray(mess, errorMessages) < 0) {
309
- errorMessages.push(mess);
310
- }
311
- errorInputs.push($elem);
312
- $elem.attr('current-error', mess);
313
- if( displayError )
314
- _applyErrorStyle($elem, conf);
333
+ if ($.inArray(mess, errorMessages) < 0) {
334
+ errorMessages.push(mess);
315
335
  }
336
+ errorInputs.push($elem);
337
+ $elem.attr('current-error', mess);
338
+ if( displayError )
339
+ _applyErrorStyle($elem, conf);
316
340
  },
317
341
 
342
+ /** Holds inputs (of type checkox or radio) already validated, to prevent recheck of mulitple checkboxes & radios */
343
+ checkedInputs = [],
344
+
318
345
  /** Error messages for this validation */
319
346
  errorMessages = [],
320
347
 
@@ -346,9 +373,15 @@
346
373
 
347
374
  // Validate element values
348
375
  $form.find('input,textarea,select').filter(':not([type="submit"],[type="button"])').each(function() {
349
- var $elem = $(this);
350
- var elementType = $elem.attr('type');
351
- if (!ignoreInput($elem.attr('name'), elementType)) {
376
+ var $elem = $(this),
377
+ elementType = $elem.attr('type'),
378
+ isCheckboxOrRadioBtn = elementType == 'radio' || elementType == 'checkbox',
379
+ elementName = $elem.attr('name');
380
+
381
+ if (!ignoreInput(elementName, elementType) && (!isCheckboxOrRadioBtn || $.inArray(elementName, checkedInputs) < 0) ) {
382
+
383
+ if( isCheckboxOrRadioBtn )
384
+ checkedInputs.push(elementName);
352
385
 
353
386
  var validation = $.formUtils.validateInput(
354
387
  $elem,
@@ -358,24 +391,18 @@
358
391
  'submit'
359
392
  );
360
393
 
361
- $elem.trigger('validation', [validation===true]);
362
-
363
- // Run element validation callback
364
- if( typeof conf.onElementValidate == 'function' ) {
365
- conf.onElementValidate((validation === true), $elem, $form, validation);
366
- }
367
-
368
- if(validation !== true) {
369
- addErrorMessage(validation, $elem);
370
- } else {
371
- $elem
372
- .valAttr('current-error', false)
373
- .addClass('valid')
374
- .parent()
394
+ if(validation != null) {
395
+ if(validation !== true) {
396
+ addErrorMessage(validation, $elem);
397
+ } else {
398
+ $elem
399
+ .valAttr('current-error', false)
400
+ .addClass('valid')
401
+ .parent()
375
402
  .addClass('has-success');
403
+ }
376
404
  }
377
405
  }
378
-
379
406
  });
380
407
 
381
408
  // Run validation callback
@@ -423,6 +450,10 @@
423
450
  return false;
424
451
  }
425
452
 
453
+ if( !displayError && $.formUtils.haltValidation ) {
454
+ $.formUtils.errorDisplayPreventedWhenHalted = true;
455
+ }
456
+
426
457
  return !$.formUtils.haltValidation;
427
458
  };
428
459
 
@@ -469,32 +500,34 @@
469
500
 
470
501
  /**
471
502
  * A bit smarter split function
503
+ * delimiter can be space, comma, dash or pipe
472
504
  * @param {String} val
473
505
  * @param {Function|String} [func]
474
- * @param {String} [delim]
475
506
  * @returns {Array|void}
476
507
  */
477
- $.split = function(val, func, delim) {
508
+ $.split = function(val, func) {
478
509
  if( typeof func != 'function' ) {
479
- // return string
510
+ // return array
480
511
  if( !val )
481
512
  return [];
482
513
  var values = [];
483
- $.each(val.split(func ? func:','), function(i,str) {
484
- str = $.trim(str);
485
- if( str.length )
486
- values.push(str);
487
- });
514
+ $.each(val.split(func ? func: /[,|-\s]\s*/g ),
515
+ function(i,str) {
516
+ str = $.trim(str);
517
+ if( str.length )
518
+ values.push(str);
519
+ }
520
+ );
488
521
  return values;
489
522
  } else if( val ) {
490
- // use callback on each
491
- if( !delim )
492
- delim = ',';
493
- $.each(val.split(delim), function(i, str) {
494
- str = $.trim(str);
495
- if( str.length )
496
- return func(str, i);
497
- });
523
+ // exec callback func on each
524
+ $.each(val.split(/[,|-\s]\s*/g),
525
+ function(i, str) {
526
+ str = $.trim(str);
527
+ if( str.length )
528
+ return func(str, i);
529
+ }
530
+ );
498
531
  }
499
532
  };
500
533
 
@@ -511,6 +544,7 @@
511
544
  */
512
545
  validateOnEvent : true,
513
546
  validateOnBlur : true,
547
+ validateCheckboxRadioOnClick : true,
514
548
  showHelpOnFocus : true,
515
549
  addSuggestions : true,
516
550
  modules : '',
@@ -518,15 +552,15 @@
518
552
  language : false,
519
553
  onSuccess : false,
520
554
  onError : false,
521
- onElementValidate : false
555
+ onElementValidate : false,
522
556
  });
523
557
 
524
558
  conf = $.extend(defaultConf, conf || {});
525
559
 
526
560
  // Add validation to forms
527
- $.split(conf.form, function(formQuery) {
561
+ $(conf.form).each(function(i, form) {
528
562
 
529
- var $form = $(formQuery);
563
+ var $form = $(form);
530
564
  $window.trigger('formValidationSetup', [$form]);
531
565
 
532
566
  // Remove all event listeners previously added
@@ -544,22 +578,34 @@
544
578
  $form.bind('submit.validation', function() {
545
579
  var $form = $(this);
546
580
 
581
+ if( $.formUtils.haltValidation ) {
582
+ // pressing several times on submit button while validation is halted
583
+ return false;
584
+ }
585
+
547
586
  if($.formUtils.isLoadingModules) {
548
587
  setTimeout(function() {
549
588
  $form.trigger('submit.validation');
550
589
  }, 200);
551
590
  return false;
552
591
  }
592
+
553
593
  var valid = $form.isValid(conf.language, conf);
554
- if( valid && typeof conf.onSuccess == 'function') {
555
- var callbackResponse = conf.onSuccess($form);
556
- if( callbackResponse === false )
557
- return false;
558
- } else if ( !valid && typeof conf.onError == 'function' ) {
559
- conf.onError($form);
594
+
595
+ if( $.formUtils.haltValidation ) {
596
+ // Validation got halted by one of the validators
560
597
  return false;
561
598
  } else {
562
- return valid;
599
+ if( valid && typeof conf.onSuccess == 'function') {
600
+ var callbackResponse = conf.onSuccess($form);
601
+ if( callbackResponse === false )
602
+ return false;
603
+ } else if ( !valid && typeof conf.onError == 'function' ) {
604
+ conf.onError($form);
605
+ return false;
606
+ } else {
607
+ return valid;
608
+ }
563
609
  }
564
610
  })
565
611
  .bind('reset.validation', function() {
@@ -621,7 +667,9 @@
621
667
  scrollToTopOnError : true,
622
668
  dateFormat : 'yyyy-mm-dd',
623
669
  addValidClassOnAll : false, // whether or not to apply class="valid" even if the input wasn't validated
624
- decimalSeparator : '.'
670
+ decimalSeparator : '.',
671
+ inputParentClassOnError : 'has-error', // twitter-bootstrap default class name
672
+ inputParentClassOnSuccess : 'has-success' // twitter-bootstrap default class name
625
673
  }
626
674
  },
627
675
 
@@ -763,16 +811,11 @@
763
811
  } else {
764
812
  var findScriptPathAndLoadModules = function() {
765
813
  var foundPath = false;
766
- $('script').each(function() {
767
- if( this.src ) {
768
- var scriptName = this.src.substr(this.src.lastIndexOf('/')+1, this.src.length);
769
- if(scriptName.indexOf('jquery.form-validator.js') > -1 || scriptName.indexOf('jquery.form-validator.min.js') > -1) {
770
- foundPath = this.src.substr(0, this.src.lastIndexOf('/')) + '/';
771
- if( foundPath == '/' )
772
- foundPath = '';
773
- return false;
774
- }
775
- }
814
+ $('script[src*="form-validator"]').each(function() {
815
+ foundPath = this.src.substr(0, this.src.lastIndexOf('/')) + '/';
816
+ if( foundPath == '/' )
817
+ foundPath = '';
818
+ return false;
776
819
  });
777
820
 
778
821
  if( foundPath !== false) {
@@ -790,8 +833,8 @@
790
833
 
791
834
  /**
792
835
  * Validate the value of given element according to the validation rules
793
- * found in the attribute data-validation. Will return true if valid,
794
- * error message otherwise
836
+ * found in the attribute data-validation. Will return null if no validation
837
+ * should take place, returns true if valid or error message if not valid
795
838
  *
796
839
  * @param {jQuery} $elem
797
840
  * @param {Object} language ($.formUtils.LANG)
@@ -807,7 +850,7 @@
807
850
 
808
851
  $elem.trigger('beforeValidation');
809
852
 
810
- var value = $.trim( $elem.val() || ''),
853
+ var value = $elem.val() || '',
811
854
  optional = $elem.valAttr('optional'),
812
855
 
813
856
  // test if a checkbox forces this element to be validated
@@ -859,41 +902,58 @@
859
902
  var validator = $.formUtils.validators[rule];
860
903
 
861
904
  if( validator && typeof validator['validatorFunction'] == 'function' ) {
905
+
862
906
  // special change of element for checkbox_group rule
863
907
  if ( rule == 'validate_checkbox_group' ) {
864
- // set element to first in group, so error msg is set only once
908
+ // set element to first in group, so error msg attr doesn't need to be set on all elements in group
865
909
  $elem = $("[name='"+$elem.attr('name')+"']:eq(0)");
866
910
  }
867
-
868
- var isValid = true;
911
+
912
+ var isValid = null;
869
913
  if( eventContext != 'keyup' || validator.validateOnKeyUp ) {
870
914
  isValid = validator.validatorFunction(value, $elem, conf, language, $form);
871
915
  }
872
916
 
873
917
  if(!isValid) {
874
- validationErrorMsg = $elem.attr(conf.validationErrorMsgAttribute+'-'+rule.replace('validate_', ''));
875
- if( !validationErrorMsg ) {
876
- validationErrorMsg = $elem.attr(conf.validationErrorMsgAttribute);
918
+ validationErrorMsg = null;
919
+ if( isValid !== null ) {
920
+ validationErrorMsg = $elem.attr(conf.validationErrorMsgAttribute+'-'+rule.replace('validate_', ''));
877
921
  if( !validationErrorMsg ) {
878
- validationErrorMsg = language[validator.errorMessageKey];
879
- if( !validationErrorMsg )
880
- validationErrorMsg = validator.errorMessage;
922
+ validationErrorMsg = $elem.attr(conf.validationErrorMsgAttribute);
923
+ if( !validationErrorMsg ) {
924
+ validationErrorMsg = language[validator.errorMessageKey];
925
+ if( !validationErrorMsg )
926
+ validationErrorMsg = validator.errorMessage;
927
+ }
881
928
  }
882
929
  }
883
930
  return false; // breaks the iteration
884
931
  }
885
932
 
886
933
  } else {
887
- console.warn('Using undefined validator "'+rule+'"');
934
+ throw new Error('Using undefined validator "'+rule+'"');
888
935
  }
889
936
 
890
937
  }, ' ');
891
938
 
939
+ var result;
940
+
892
941
  if( typeof validationErrorMsg == 'string' ) {
893
- return validationErrorMsg;
942
+ $elem.trigger('validation', false);
943
+ result = validationErrorMsg;
944
+ } else if( validationErrorMsg === null && !conf.addValidClassOnAll ) {
945
+ result = null;
894
946
  } else {
895
- return true;
947
+ $elem.trigger('validation', true);
948
+ result = true;
949
+ }
950
+
951
+ // Run element validation callback
952
+ if( typeof conf.onElementValidate == 'function' && result !== null ) {
953
+ conf.onElementValidate((result === true), $elem, $form, validationErrorMsg);
896
954
  }
955
+
956
+ return result;
897
957
  },
898
958
 
899
959
  /**
@@ -907,7 +967,7 @@
907
967
  parseDate : function(val, dateFormat) {
908
968
  var divider = dateFormat.replace(/[a-zA-Z]/gi, '').substring(0,1),
909
969
  regexp = '^',
910
- formatParts = dateFormat.split(divider),
970
+ formatParts = dateFormat.split(divider || null),
911
971
  matches, day, month, year;
912
972
 
913
973
  $.each(formatParts, function(i, part) {
@@ -1018,7 +1078,7 @@
1018
1078
  numericRangeCheck : function(value, rangeAllowed)
1019
1079
  {
1020
1080
  // split by dash
1021
- var range = $.split(rangeAllowed, '-');
1081
+ var range = $.split(rangeAllowed);
1022
1082
  // min or max
1023
1083
  var minmax = parseInt(rangeAllowed.substr(3),10)
1024
1084
  // range ?
@@ -1028,7 +1088,8 @@
1028
1088
  { return ["min", minmax]; } // value is below min
1029
1089
  else if (rangeAllowed.indexOf('max') === 0 && (value > minmax ) ) // max
1030
1090
  { return ["max", minmax]; } // value is above max
1031
- else { return [ "ok" ] ; } // value is in allowed range
1091
+ // since no other returns executed, value is in allowed range
1092
+ return [ "ok" ] ;
1032
1093
  },
1033
1094
 
1034
1095
 
@@ -1269,24 +1330,24 @@
1269
1330
  badTelephone : 'You have not given a correct phone number',
1270
1331
  badSecurityAnswer : 'You have not given a correct answer to the security question',
1271
1332
  badDate : 'You have not given a correct date',
1272
- lengthBadStart : 'You must give an answer between ',
1333
+ lengthBadStart : 'The input value must be between ',
1273
1334
  lengthBadEnd : ' characters',
1274
- lengthTooLongStart : 'You have given an answer longer than ',
1275
- lengthTooShortStart : 'You have given an answer shorter than ',
1276
- notConfirmed : 'Values could not be confirmed',
1335
+ lengthTooLongStart : 'The input value is longer than ',
1336
+ lengthTooShortStart : 'The input value is shorter than ',
1337
+ notConfirmed : 'Input values could not be confirmed',
1277
1338
  badDomain : 'Incorrect domain value',
1278
- badUrl : 'The answer you gave was not a correct URL',
1279
- badCustomVal : 'You gave an incorrect answer',
1280
- badInt : 'The answer you gave was not a correct number',
1281
- badSecurityNumber : 'Your isVsocial security number was incorrect',
1339
+ badUrl : 'The input value is not a correct URL',
1340
+ badCustomVal : 'The input value is incorrect',
1341
+ badInt : 'The input value was not a correct number',
1342
+ badSecurityNumber : 'Your social security number was incorrect',
1282
1343
  badUKVatAnswer : 'Incorrect UK VAT Number',
1283
1344
  badStrength : 'The password isn\'t strong enough',
1284
1345
  badNumberOfSelectedOptionsStart : 'You have to choose at least ',
1285
1346
  badNumberOfSelectedOptionsEnd : ' answers',
1286
- badAlphaNumeric : 'The answer you gave must contain only alphanumeric characters ',
1347
+ badAlphaNumeric : 'The input value can only contain alphanumeric characters ',
1287
1348
  badAlphaNumericExtra: ' and ',
1288
- wrongFileSize : 'The file you are trying to upload is too large',
1289
- wrongFileType : 'The file you are trying to upload is of wrong type',
1349
+ wrongFileSize : 'The file you are trying to upload is too large (max %s)',
1350
+ wrongFileType : 'Only files of type %s is allowed',
1290
1351
  groupCheckedRangeStart : 'Please choose between ',
1291
1352
  groupCheckedTooFewStart : 'Please choose at least ',
1292
1353
  groupCheckedTooManyStart : 'Please choose a maximum of ',
@@ -1312,7 +1373,7 @@
1312
1373
  var emailParts = email.toLowerCase().split('@');
1313
1374
  if( emailParts.length == 2 ) {
1314
1375
  return $.formUtils.validators.validate_domain.validatorFunction(emailParts[1]) &&
1315
- !(/[^\w\+\.\-]/.test(emailParts[0]));
1376
+ !(/[^\w\+\.\-]/.test(emailParts[0])) && emailParts[0].length > 0;
1316
1377
  }
1317
1378
 
1318
1379
  return false;
@@ -1326,98 +1387,14 @@
1326
1387
  */
1327
1388
  $.formUtils.addValidator({
1328
1389
  name : 'domain',
1329
- validatorFunction : function(val, $input) {
1330
-
1331
- var topDomains = ['.ac', '.ad', '.ae', '.aero', '.af', '.ag', '.ai', '.al', '.am', '.an', '.ao',
1332
- '.aq', '.ar', '.arpa', '.as', '.asia', '.at', '.au', '.aw', '.ax', '.az', '.ba', '.bb',
1333
- '.bd', '.be', '.bf', '.bg', '.bh', '.bi', '.bike', '.biz', '.bj', '.bm', '.bn', '.bo',
1334
- '.br', '.bs', '.bt', '.bv', '.bw', '.by', '.bz', '.ca', '.camera', '.cat', '.cc', '.cd',
1335
- '.cf', '.cg', '.ch', '.ci', '.ck', '.cl', '.clothing', '.cm', '.cn', '.co', '.com',
1336
- '.construction', '.contractors', '.coop', '.cr', '.cu', '.cv', '.cw', '.cx', '.cy', '.cz',
1337
- '.de', '.diamonds', '.directory', '.dj', '.dk', '.dm', '.do', '.dz', '.ec', '.edu', '.ee',
1338
- '.eg', '.enterprises', '.equipment', '.er', '.es', '.estate', '.et', '.eu', '.fi', '.fj',
1339
- '.fk', '.fm', '.fo', '.fr', '.ga', '.gallery', '.gb', '.gd', '.ge', '.gf', '.gg', '.gh',
1340
- '.gi', '.gl', '.gm', '.gn', '.gov', '.gp', '.gq', '.gr', '.graphics', '.gs', '.gt', '.gu',
1341
- '.guru', '.gw', '.gy', '.hk', '.hm', '.hn', '.holdings', '.hr', '.ht', '.hu', '.id', '.ie',
1342
- '.il', '.im', '.in', '.info', '.int', '.io', '.iq', '.ir', '.is', '.it', '.je', '.jm', '.jo',
1343
- '.jobs', '.jp', '.ke', '.kg', '.kh', '.ki', '.kitchen', '.km', '.kn', '.kp', '.kr', '.kw',
1344
- '.ky', '.kz', '.la', '.land', '.lb', '.lc', '.li', '.lighting', '.lk', '.lr', '.ls', '.lt',
1345
- '.lu', '.lv', '.ly', '.ma', '.mc', '.md', '.me', '.menu', '.mg', '.mh', '.mil', '.mk', '.ml',
1346
- '.mm', '.mn', '.mo', '.mobi', '.mp', '.mq', '.mr', '.ms', '.mt', '.mu', '.museum', '.mv',
1347
- '.mw', '.mx', '.my', '.mz', '.na', '.name', '.nc', '.ne', '.net', '.nf', '.ng', '.ni',
1348
- '.nl', '.no', '.np', '.nr', '.nu', '.nz', '.om', '.org', '.pa', '.pe', '.pf', '.pg', '.ph',
1349
- '.photography', '.pk', '.pl', '.plumbing', '.pm', '.pn', '.post', '.pr', '.pro', '.ps', '.pt',
1350
- '.pw', '.py', '.qa', '.re', '.ro', '.rs', '.ru', '.rw', '.sa', '.sb', '.sc', '.sd', '.se',
1351
- '.sexy', '.sg', '.sh', '.si', '.singles', '.sj', '.sk', '.sl', '.sm', '.sn', '.so', '.sr',
1352
- '.st', '.su', '.sv', '.sx', '.sy', '.sz', '.tattoo', '.tc', '.td', '.technology', '.tel', '.tf',
1353
- '.tg', '.th', '.tips', '.tj', '.tk', '.tl', '.tm', '.tn', '.to', '.today', '.tp', '.tr', '.travel',
1354
- '.tt', '.tv', '.tw', '.tz', '.ua', '.ug', '.uk', '.uno', '.us', '.uy', '.uz', '.va', '.vc', '.ve',
1355
- '.ventures', '.vg', '.vi', '.vn', '.voyage', '.vu', '.wf', '.ws', '.xn--3e0b707e', '.xn--45brj9c',
1356
- '.xn--80ao21a', '.xn--80asehdb', '.xn--80aswg', '.xn--90a3ac', '.xn--clchc0ea0b2g2a9gcd', '.xn--fiqs8s',
1357
- '.xn--fiqz9s', '.xn--fpcrj9c3d', '.xn--fzc2c9e2c', '.xn--gecrj9c', '.xn--h2brj9c', '.xn--j1amh',
1358
- '.xn--j6w193g', '.xn--kprw13d', '.xn--kpry57d', '.xn--l1acc', '.xn--lgbbat1ad8j', '.xn--mgb9awbf',
1359
- '.xn--mgba3a4f16a', '.xn--mgbaam7a8h', '.xn--mgbayh7gpa', '.xn--mgbbh1a71e', '.xn--mgbc0a9azcg',
1360
- '.xn--mgberp4a5d4ar', '.xn--mgbx4cd0ab', '.xn--ngbc5azd', '.xn--o3cw4h', '.xn--ogbpf8fl', '.xn--p1ai',
1361
- '.xn--pgbs0dh', '.xn--q9jyb4c', '.xn--s9brj9c', '.xn--unup4y', '.xn--wgbh1c', '.xn--wgbl6a',
1362
- '.xn--xkc2al3hye2a', '.xn--xkc2dl3a5ee0h', '.xn--yfro4i67o', '.xn--ygbi2ammx', '.xxx', '.ye',
1363
- '.yt', '.za', '.zm', '.zw'],
1364
-
1365
- ukTopDomains = ['co', 'me', 'ac', 'gov', 'judiciary','ltd', 'mod', 'net', 'nhs', 'nic',
1366
- 'org', 'parliament', 'plc', 'police', 'sch', 'bl', 'british-library', 'jet','nls'],
1367
-
1368
- dot = val.lastIndexOf('.'),
1369
- domain = val.substring(0, dot),
1370
- ext = val.substring(dot, val.length),
1371
- hasTopDomain = false;
1372
-
1373
- for (var i = 0; i < topDomains.length; i++) {
1374
- if (topDomains[i] === ext) {
1375
- if(ext==='.uk') {
1376
- //Run Extra Checks for UK Domain Names
1377
- var domainParts = val.split('.');
1378
- var tld2 = domainParts[domainParts.length-2];
1379
- for(var j = 0; j < ukTopDomains.length; j++) {
1380
- if(ukTopDomains[j] === tld2) {
1381
- hasTopDomain = true;
1382
- break;
1383
- }
1384
- }
1385
-
1386
- if(hasTopDomain)
1387
- break;
1388
-
1389
- } else {
1390
- hasTopDomain = true;
1391
- break;
1392
- }
1393
- }
1394
- }
1395
-
1396
- if (!hasTopDomain) {
1397
- return false;
1398
- } else if (dot < 2 || dot > 57) {
1399
- return false;
1400
- } else {
1401
- var firstChar = domain.substring(0, 1),
1402
- lastChar = domain.substring(domain.length - 1, domain.length);
1403
-
1404
- if (firstChar === '-' || firstChar === '.' || lastChar === '-' || lastChar === '.') {
1405
- return false;
1406
- }
1407
- if (domain.split('.').length > 3 || domain.split('..').length > 1) {
1408
- return false;
1409
- }
1410
- if (domain.replace(/[-\da-z\.]/g, '') !== '') {
1411
- return false;
1412
- }
1413
- }
1414
-
1415
- // It's valid, lets update input with trimmed value perhaps??
1416
- if(typeof $input !== 'undefined') {
1417
- $input.val(val);
1418
- }
1419
-
1420
- return true;
1390
+ validatorFunction : function(val) {
1391
+ return val.length > 0 &&
1392
+ val.length <= 253 && // Including sub domains
1393
+ !(/[^a-zA-Z0-9]/.test(val.substr(-2))) &&
1394
+ !(/[^a-zA-Z]/.test(val.substr(0,1))) &&
1395
+ !(/[^a-zA-Z0-9\.\-]/.test(val)) &&
1396
+ val.split('..').length == 1 &&
1397
+ val.split('.').length > 1;
1421
1398
  },
1422
1399
  errorMessage : '',
1423
1400
  errorMessageKey: 'badDomain'
@@ -1452,8 +1429,7 @@
1452
1429
  type = $el.attr('type');
1453
1430
 
1454
1431
  if(lengthAllowed == undefined) {
1455
- var elementType = $el.get(0).nodeName;
1456
- alert('Please add attribute "data-validation-length" to '+elementType+' named '+$el.attr('name'));
1432
+ alert('Please add attribute "data-validation-length" to '+$el[0].nodeName+' named '+$el.attr('name'));
1457
1433
  return true;
1458
1434
  }
1459
1435
 
@@ -1500,8 +1476,9 @@
1500
1476
  // - General improvements made by Stéphane Moureau <https://github.com/TraderStf>
1501
1477
  var urlFilter = /^(https?|ftp):\/\/((((\w|-|\.|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])(\w|-|\.|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])(\w|-|\.|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/(((\w|-|\.|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/((\w|-|\.|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|\[|\]|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#(((\w|-|\.|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i;
1502
1478
  if( urlFilter.test(url) ) {
1503
- var domain = url.split('://')[1];
1504
- var domainSlashPos = domain.indexOf('/');
1479
+ var domain = url.split('://')[1],
1480
+ domainSlashPos = domain.indexOf('/');
1481
+
1505
1482
  if(domainSlashPos > -1)
1506
1483
  domain = domain.substr(0, domainSlashPos);
1507
1484
 
@@ -1523,7 +1500,9 @@
1523
1500
  var allowing = $el.valAttr('allowing') || '',
1524
1501
  decimalSeparator = $el.valAttr('decimal-separator') || conf.decimalSeparator,
1525
1502
  allowsRange = false,
1526
- begin, end;
1503
+ begin, end,
1504
+ steps = $el.valAttr('step') || '',
1505
+ allowsSteps = false;
1527
1506
 
1528
1507
  if(allowing.indexOf('number') == -1)
1529
1508
  allowing += ',number';
@@ -1538,6 +1517,9 @@
1538
1517
  end = parseFloat(allowing.substring(allowing.indexOf(";")+1,allowing.indexOf("]")));
1539
1518
  allowsRange = true;
1540
1519
  }
1520
+
1521
+ if(steps != "")
1522
+ allowsSteps = true;
1541
1523
 
1542
1524
  if( decimalSeparator == ',' ) {
1543
1525
  if( val.indexOf('.') > -1 ) {
@@ -1547,10 +1529,10 @@
1547
1529
  val = val.replace(',', '.');
1548
1530
  }
1549
1531
 
1550
- if(allowing.indexOf('number') > -1 && val.replace(/[0-9]/g, '') === '' && (!allowsRange || (val >= begin && val <= end)) ) {
1532
+ if(allowing.indexOf('number') > -1 && val.replace(/[0-9]/g, '') === '' && (!allowsRange || (val >= begin && val <= end)) && (!allowsSteps || (val%steps == 0)) ) {
1551
1533
  return true;
1552
1534
  }
1553
- if(allowing.indexOf('float') > -1 && val.match(new RegExp('^([0-9]+)\\.([0-9]+)$')) !== null && (!allowsRange || (val >= begin && val <= end)) ) {
1535
+ if(allowing.indexOf('float') > -1 && val.match(new RegExp('^([0-9]+)\\.([0-9]+)$')) !== null && (!allowsRange || (val >= begin && val <= end)) && (!allowsSteps || (val%steps == 0)) ) {
1554
1536
  return true;
1555
1537
  }
1556
1538
  }
@@ -1568,7 +1550,7 @@
1568
1550
  validatorFunction : function(val, $el, conf, language) {
1569
1551
  var patternStart = '^([a-zA-Z0-9',
1570
1552
  patternEnd = ']+)$',
1571
- additionalChars = $el.attr('data-validation-allowing'),
1553
+ additionalChars = $el.valAttr('allowing'),
1572
1554
  pattern = '';
1573
1555
 
1574
1556
  if( additionalChars ) {
@@ -1609,14 +1591,7 @@
1609
1591
  $.formUtils.addValidator({
1610
1592
  name : 'date',
1611
1593
  validatorFunction : function(date, $el, conf) {
1612
- var dateFormat = 'yyyy-mm-dd';
1613
- if($el.valAttr('format')) {
1614
- dateFormat = $el.valAttr('format');
1615
- }
1616
- else if( conf.dateFormat ) {
1617
- dateFormat = conf.dateFormat;
1618
- }
1619
-
1594
+ var dateFormat = $el.valAttr('format') || conf.dateFormat || 'yyyy-mm-dd';
1620
1595
  return $.formUtils.parseDate(date, dateFormat) !== false;
1621
1596
  },
1622
1597
  errorMessage : '',
@@ -1635,20 +1610,24 @@
1635
1610
  $.formUtils.addValidator({
1636
1611
  name : 'checkbox_group',
1637
1612
  validatorFunction : function(val, $el, conf, lang, $form)
1638
- { // preset return var
1639
- var checkResult = true;
1640
- // get name of element. since it is a checkbox group, all checkboxes will have same name
1641
- var elname = $el.attr('name');
1642
- // get count of checked checkboxes with this name
1643
- var checkedCount = $("input[type=checkbox][name^='"+elname+"']:checked", $form).length;
1644
- // get el attr that specs qty required / allowed
1645
- var qtyAllowed = $el.valAttr('qty');
1613
+ {
1614
+ // preset return var
1615
+ var checkResult = true,
1616
+ // get name of element. since it is a checkbox group, all checkboxes will have same name
1617
+ elname = $el.attr('name'),
1618
+ // get count of checked checkboxes with this name
1619
+ checkedCount = $("input[type=checkbox][name^='"+elname+"']:checked", $form).length,
1620
+ // get el attr that specs qty required / allowed
1621
+ qtyAllowed = $el.valAttr('qty');
1622
+
1646
1623
  if (qtyAllowed == undefined) {
1647
1624
  var elementType = $el.get(0).nodeName;
1648
1625
  alert('Attribute "data-validation-qty" is missing from '+elementType+' named '+$el.attr('name'));
1649
1626
  }
1627
+
1650
1628
  // call Utility function to check if count is above min, below max, within range etc.
1651
1629
  var qtyCheckResults = $.formUtils.numericRangeCheck(checkedCount, qtyAllowed) ;
1630
+
1652
1631
  // results will be array, [0]=result str, [1]=qty int
1653
1632
  switch(qtyCheckResults[0] ) {
1654
1633
  // outside allowed range
@@ -1671,8 +1650,7 @@
1671
1650
  checkResult = true;
1672
1651
  }
1673
1652
 
1674
- return checkResult;
1675
-
1653
+ return checkResult;
1676
1654
  }
1677
1655
  // errorMessage : '', // set above in switch statement
1678
1656
  // errorMessageKey: '' // not used