midas-g_live_validator 1.0.3

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,884 @@
1
+ // LiveValidation 1.3 (standalone version)
2
+ // Copyright (c) 2007-2008 Alec Hill (www.livevalidation.com)
3
+ // LiveValidation is licensed under the terms of the MIT License
4
+
5
+ /*********************************************** LiveValidation class ***********************************/
6
+
7
+ /**
8
+ * validates a form field in real-time based on validations you assign to it
9
+ *
10
+ * @var element {mixed} - either a dom element reference or the string id of the element to validate
11
+ * @var optionsObj {Object} - general options, see below for details
12
+ *
13
+ * optionsObj properties:
14
+ * validMessage {String} - the message to show when the field passes validation
15
+ * (DEFAULT: "Thankyou!")
16
+ * onValid {Function} - function to execute when field passes validation
17
+ * (DEFAULT: function(){ this.insertMessage(this.createMessageSpan()); this.addFieldClass(); } )
18
+ * onInvalid {Function} - function to execute when field fails validation
19
+ * (DEFAULT: function(){ this.insertMessage(this.createMessageSpan()); this.addFieldClass(); })
20
+ * insertAfterWhatNode {Int} - position to insert default message
21
+ * (DEFAULT: the field that is being validated)
22
+ * onlyOnBlur {Boolean} - whether you want it to validate as you type or only on blur
23
+ * (DEFAULT: false)
24
+ * wait {Integer} - the time you want it to pause from the last keystroke before it validates (ms)
25
+ * (DEFAULT: 0)
26
+ * onlyOnSubmit {Boolean} - whether should be validated only when the form it belongs to is submitted
27
+ * (DEFAULT: false)
28
+ */
29
+ var LiveValidation = function(element, optionsObj){
30
+ this.initialize(element, optionsObj);
31
+ }
32
+
33
+ LiveValidation.VERSION = '1.3 standalone';
34
+
35
+ /** element types constants ****/
36
+
37
+ LiveValidation.TEXTAREA = 1;
38
+ LiveValidation.TEXT = 2;
39
+ LiveValidation.PASSWORD = 3;
40
+ LiveValidation.CHECKBOX = 4;
41
+ LiveValidation.SELECT = 5;
42
+ LiveValidation.FILE = 6;
43
+
44
+ /****** Static methods *******/
45
+
46
+ /**
47
+ * pass an array of LiveValidation objects and it will validate all of them
48
+ *
49
+ * @var validations {Array} - an array of LiveValidation objects
50
+ * @return {Bool} - true if all passed validation, false if any fail
51
+ */
52
+ LiveValidation.massValidate = function(validations){
53
+ var returnValue = true;
54
+ for(var i = 0, len = validations.length; i < len; ++i ){
55
+ var valid = validations[i].validate();
56
+ if(returnValue) returnValue = valid;
57
+ }
58
+ return returnValue;
59
+ }
60
+
61
+ /****** prototype ******/
62
+
63
+ LiveValidation.prototype = {
64
+
65
+ validClass: 'LV_valid',
66
+ invalidClass: 'LV_invalid',
67
+ messageClass: 'LV_validation_message',
68
+ validFieldClass: 'LV_valid_field',
69
+ invalidFieldClass: 'LV_invalid_field',
70
+
71
+ /**
72
+ * initialises all of the properties and events
73
+ *
74
+ * @var - Same as constructor above
75
+ */
76
+ initialize: function(element, optionsObj){
77
+ var self = this;
78
+ if(!element) throw new Error("LiveValidation::initialize - No element reference or element id has been provided!");
79
+ this.element = element.nodeName ? element : document.getElementById(element);
80
+ if(!this.element) throw new Error("LiveValidation::initialize - No element with reference or id of '" + element + "' exists!");
81
+ // default properties that could not be initialised above
82
+ this.validations = [];
83
+ this.elementType = this.getElementType();
84
+ this.form = this.element.form;
85
+ // options
86
+ var options = optionsObj || {};
87
+ this.validMessage = options.validMessage || 'Thankyou!';
88
+ var node = options.insertAfterWhatNode || this.element;
89
+ this.insertAfterWhatNode = node.nodeType ? node : document.getElementById(node);
90
+ this.onValid = options.onValid || function(){ this.insertMessage(this.createMessageSpan()); this.addFieldClass(); };
91
+ this.onInvalid = options.onInvalid || function(){ this.insertMessage(this.createMessageSpan()); this.addFieldClass(); };
92
+ this.onlyOnBlur = options.onlyOnBlur || false;
93
+ this.wait = options.wait || 0;
94
+ this.onlyOnSubmit = options.onlyOnSubmit || false;
95
+ // add to form if it has been provided
96
+ if(this.form){
97
+ this.formObj = LiveValidationForm.getInstance(this.form);
98
+ this.formObj.addField(this);
99
+ }
100
+ // events
101
+ // collect old events
102
+ this.oldOnFocus = this.element.onfocus || function(){};
103
+ this.oldOnBlur = this.element.onblur || function(){};
104
+ this.oldOnClick = this.element.onclick || function(){};
105
+ this.oldOnChange = this.element.onchange || function(){};
106
+ this.oldOnKeyup = this.element.onkeyup || function(){};
107
+ this.element.onfocus = function(e){ self.doOnFocus(e); return self.oldOnFocus.call(this, e); }
108
+ if(!this.onlyOnSubmit){
109
+ switch(this.elementType){
110
+ case LiveValidation.CHECKBOX:
111
+ this.element.onclick = function(e){ self.validate(); return self.oldOnClick.call(this, e); }
112
+ // let it run into the next to add a change event too
113
+ case LiveValidation.SELECT:
114
+ case LiveValidation.FILE:
115
+ this.element.onchange = function(e){ self.validate(); return self.oldOnChange.call(this, e); }
116
+ break;
117
+ default:
118
+ if(!this.onlyOnBlur) this.element.onkeyup = function(e){ self.deferValidation(); return self.oldOnKeyup.call(this, e); }
119
+ this.element.onblur = function(e){ self.doOnBlur(e); return self.oldOnBlur.call(this, e); }
120
+ }
121
+ }
122
+ },
123
+
124
+ /**
125
+ * destroys the instance's events (restoring previous ones) and removes it from any LiveValidationForms
126
+ */
127
+ destroy: function(){
128
+ if(this.formObj){
129
+ // remove the field from the LiveValidationForm
130
+ this.formObj.removeField(this);
131
+ // destroy the LiveValidationForm if no LiveValidation fields left in it
132
+ this.formObj.destroy();
133
+ }
134
+ // remove events - set them back to the previous events
135
+ this.element.onfocus = this.oldOnFocus;
136
+ if(!this.onlyOnSubmit){
137
+ switch(this.elementType){
138
+ case LiveValidation.CHECKBOX:
139
+ this.element.onclick = this.oldOnClick;
140
+ // let it run into the next to add a change event too
141
+ case LiveValidation.SELECT:
142
+ case LiveValidation.FILE:
143
+ this.element.onchange = this.oldOnChange;
144
+ break;
145
+ default:
146
+ if(!this.onlyOnBlur) this.element.onkeyup = this.oldOnKeyup;
147
+ this.element.onblur = this.oldOnBlur;
148
+ }
149
+ }
150
+ this.validations = [];
151
+ this.removeMessageAndFieldClass();
152
+ },
153
+
154
+ /**
155
+ * adds a validation to perform to a LiveValidation object
156
+ *
157
+ * @var validationFunction {Function} - validation function to be used (ie Validate.Presence )
158
+ * @var validationParamsObj {Object} - parameters for doing the validation, if wanted or necessary
159
+ * @return {Object} - the LiveValidation object itself so that calls can be chained
160
+ */
161
+ add: function(validationFunction, validationParamsObj){
162
+ this.validations.push( {type: validationFunction, params: validationParamsObj || {} } );
163
+ return this;
164
+ },
165
+
166
+ /**
167
+ * removes a validation from a LiveValidation object - must have exactly the same arguments as used to add it
168
+ *
169
+ * @var validationFunction {Function} - validation function to be used (ie Validate.Presence )
170
+ * @var validationParamsObj {Object} - parameters for doing the validation, if wanted or necessary
171
+ * @return {Object} - the LiveValidation object itself so that calls can be chained
172
+ */
173
+ remove: function(validationFunction, validationParamsObj){
174
+ var found = false;
175
+ for( var i = 0, len = this.validations.length; i < len; i++ ){
176
+ if( this.validations[i].type == validationFunction ){
177
+ if (this.validations[i].params == validationParamsObj) {
178
+ found = true;
179
+ break;
180
+ }
181
+ }
182
+ }
183
+ if(found) this.validations.splice(i,1);
184
+ return this;
185
+ },
186
+
187
+
188
+ /**
189
+ * makes the validation wait the alotted time from the last keystroke
190
+ */
191
+ deferValidation: function(e){
192
+ if(this.wait >= 300) this.removeMessageAndFieldClass();
193
+ var self = this;
194
+ if(this.timeout) clearTimeout(self.timeout);
195
+ this.timeout = setTimeout( function(){ self.validate() }, self.wait);
196
+ },
197
+
198
+ /**
199
+ * sets the focused flag to false when field loses focus
200
+ */
201
+ doOnBlur: function(e){
202
+ this.focused = false;
203
+ this.validate(e);
204
+ },
205
+
206
+ /**
207
+ * sets the focused flag to true when field gains focus
208
+ */
209
+ doOnFocus: function(e){
210
+ this.focused = true;
211
+ this.removeMessageAndFieldClass();
212
+ },
213
+
214
+ /**
215
+ * gets the type of element, to check whether it is compatible
216
+ *
217
+ * @var validationFunction {Function} - validation function to be used (ie Validate.Presence )
218
+ * @var validationParamsObj {Object} - parameters for doing the validation, if wanted or necessary
219
+ */
220
+ getElementType: function(){
221
+ switch(true){
222
+ case (this.element.nodeName.toUpperCase() == 'TEXTAREA'):
223
+ return LiveValidation.TEXTAREA;
224
+ case (this.element.nodeName.toUpperCase() == 'INPUT' && this.element.type.toUpperCase() == 'TEXT'):
225
+ return LiveValidation.TEXT;
226
+ case (this.element.nodeName.toUpperCase() == 'INPUT' && this.element.type.toUpperCase() == 'PASSWORD'):
227
+ return LiveValidation.PASSWORD;
228
+ case (this.element.nodeName.toUpperCase() == 'INPUT' && this.element.type.toUpperCase() == 'CHECKBOX'):
229
+ return LiveValidation.CHECKBOX;
230
+ case (this.element.nodeName.toUpperCase() == 'INPUT' && this.element.type.toUpperCase() == 'FILE'):
231
+ return LiveValidation.FILE;
232
+ case (this.element.nodeName.toUpperCase() == 'SELECT'):
233
+ return LiveValidation.SELECT;
234
+ case (this.element.nodeName.toUpperCase() == 'INPUT'):
235
+ throw new Error('LiveValidation::getElementType - Cannot use LiveValidation on an ' + this.element.type + ' input!');
236
+ default:
237
+ throw new Error('LiveValidation::getElementType - Element must be an input, select, or textarea!');
238
+ }
239
+ },
240
+
241
+ /**
242
+ * loops through all the validations added to the LiveValidation object and checks them one by one
243
+ *
244
+ * @var validationFunction {Function} - validation function to be used (ie Validate.Presence )
245
+ * @var validationParamsObj {Object} - parameters for doing the validation, if wanted or necessary
246
+ * @return {Boolean} - whether the all the validations passed or if one failed
247
+ */
248
+ doValidations: function(){
249
+ this.validationFailed = false;
250
+ for(var i = 0, len = this.validations.length; i < len; ++i){
251
+ var validation = this.validations[i];
252
+ switch(validation.type){
253
+ case Validate.Presence:
254
+ case Validate.Confirmation:
255
+ case Validate.Acceptance:
256
+ this.displayMessageWhenEmpty = true;
257
+ this.validationFailed = !this.validateElement(validation.type, validation.params);
258
+ break;
259
+ default:
260
+ this.validationFailed = !this.validateElement(validation.type, validation.params);
261
+ break;
262
+ }
263
+ if(this.validationFailed) return false;
264
+ }
265
+ this.message = this.validMessage;
266
+ return true;
267
+ },
268
+
269
+ /**
270
+ * performs validation on the element and handles any error (validation or otherwise) it throws up
271
+ *
272
+ * @var validationFunction {Function} - validation function to be used (ie Validate.Presence )
273
+ * @var validationParamsObj {Object} - parameters for doing the validation, if wanted or necessary
274
+ * @return {Boolean} - whether the validation has passed or failed
275
+ */
276
+ validateElement: function(validationFunction, validationParamsObj){
277
+ var value = (this.elementType == LiveValidation.SELECT) ? this.element.options[this.element.selectedIndex].value : this.element.value;
278
+ if(validationFunction == Validate.Acceptance){
279
+ if(this.elementType != LiveValidation.CHECKBOX) throw new Error('LiveValidation::validateElement - Element to validate acceptance must be a checkbox!');
280
+ value = this.element.checked;
281
+ }
282
+ var isValid = true;
283
+ try{
284
+ validationFunction(value, validationParamsObj);
285
+ } catch(error) {
286
+ if(error instanceof Validate.Error){
287
+ if( value !== '' || (value === '' && this.displayMessageWhenEmpty) ){
288
+ this.validationFailed = true;
289
+ this.message = error.message;
290
+ isValid = false;
291
+ }
292
+ }else{
293
+ throw error;
294
+ }
295
+ }finally{
296
+ return isValid;
297
+ }
298
+ },
299
+
300
+ /**
301
+ * makes it do the all the validations and fires off the onValid or onInvalid callbacks
302
+ *
303
+ * @return {Boolean} - whether the all the validations passed or if one failed
304
+ */
305
+ validate: function(){
306
+ if(!this.element.disabled){
307
+ var isValid = this.doValidations();
308
+ if(isValid){
309
+ this.onValid();
310
+ return true;
311
+ }else {
312
+ this.onInvalid();
313
+ return false;
314
+ }
315
+ }else{
316
+ return true;
317
+ }
318
+ },
319
+
320
+ /**
321
+ * enables the field
322
+ *
323
+ * @return {LiveValidation} - the LiveValidation object for chaining
324
+ */
325
+ enable: function(){
326
+ this.element.disabled = false;
327
+ return this;
328
+ },
329
+
330
+ /**
331
+ * disables the field and removes any message and styles associated with the field
332
+ *
333
+ * @return {LiveValidation} - the LiveValidation object for chaining
334
+ */
335
+ disable: function(){
336
+ this.element.disabled = true;
337
+ this.removeMessageAndFieldClass();
338
+ return this;
339
+ },
340
+
341
+ /** Message insertion methods ****************************
342
+ *
343
+ * These are only used in the onValid and onInvalid callback functions and so if you overide the default callbacks,
344
+ * you must either impliment your own functions to do whatever you want, or call some of these from them if you
345
+ * want to keep some of the functionality
346
+ */
347
+
348
+ /**
349
+ * makes a span containg the passed or failed message
350
+ *
351
+ * @return {HTMLSpanObject} - a span element with the message in it
352
+ */
353
+ createMessageSpan: function(){
354
+ var span = document.createElement('span');
355
+ var textNode = document.createTextNode(this.message);
356
+ span.appendChild(textNode);
357
+ return span;
358
+ },
359
+
360
+ /**
361
+ * inserts the element containing the message in place of the element that already exists (if it does)
362
+ *
363
+ * @var elementToIsert {HTMLElementObject} - an element node to insert
364
+ */
365
+ insertMessage: function(elementToInsert){
366
+ this.removeMessage();
367
+ if( (this.displayMessageWhenEmpty && (this.elementType == LiveValidation.CHECKBOX || this.element.value == ''))
368
+ || this.element.value != '' ){
369
+ var className = this.validationFailed ? this.invalidClass : this.validClass;
370
+ elementToInsert.className += ' ' + this.messageClass + ' ' + className;
371
+ if(this.insertAfterWhatNode.nextSibling){
372
+ this.insertAfterWhatNode.parentNode.insertBefore(elementToInsert, this.insertAfterWhatNode.nextSibling);
373
+ }else{
374
+ this.insertAfterWhatNode.parentNode.appendChild(elementToInsert);
375
+ }
376
+ }
377
+ },
378
+
379
+
380
+ /**
381
+ * changes the class of the field based on whether it is valid or not
382
+ */
383
+ addFieldClass: function(){
384
+ this.removeFieldClass();
385
+ if(!this.validationFailed){
386
+ if(this.displayMessageWhenEmpty || this.element.value != ''){
387
+ if(this.element.className.indexOf(this.validFieldClass) == -1) this.element.className += ' ' + this.validFieldClass;
388
+ }
389
+ }else{
390
+ if(this.element.className.indexOf(this.invalidFieldClass) == -1) this.element.className += ' ' + this.invalidFieldClass;
391
+ }
392
+ },
393
+
394
+ /**
395
+ * removes the message element if it exists, so that the new message will replace it
396
+ */
397
+ removeMessage: function(){
398
+ var nextEl;
399
+ var el = this.insertAfterWhatNode;
400
+ while(el.nextSibling){
401
+ if(el.nextSibling.nodeType === 1){
402
+ nextEl = el.nextSibling;
403
+ break;
404
+ }
405
+ el = el.nextSibling;
406
+ }
407
+ if(nextEl && nextEl.className.indexOf(this.messageClass) != -1) this.insertAfterWhatNode.parentNode.removeChild(nextEl);
408
+ },
409
+
410
+ /**
411
+ * removes the class that has been applied to the field to indicte if valid or not
412
+ */
413
+ removeFieldClass: function(){
414
+ if(this.element.className.indexOf(this.invalidFieldClass) != -1) this.element.className = this.element.className.split(this.invalidFieldClass).join('');
415
+ if(this.element.className.indexOf(this.validFieldClass) != -1) this.element.className = this.element.className.split(this.validFieldClass).join(' ');
416
+ },
417
+
418
+ /**
419
+ * removes the message and the field class
420
+ */
421
+ removeMessageAndFieldClass: function(){
422
+ this.removeMessage();
423
+ this.removeFieldClass();
424
+ }
425
+
426
+ } // end of LiveValidation class
427
+
428
+ /*************************************** LiveValidationForm class ****************************************/
429
+ /**
430
+ * This class is used internally by LiveValidation class to associate a LiveValidation field with a form it is icontained in one
431
+ *
432
+ * It will therefore not really ever be needed to be used directly by the developer, unless they want to associate a LiveValidation
433
+ * field with a form that it is not a child of
434
+ */
435
+
436
+ /**
437
+ * handles validation of LiveValidation fields belonging to this form on its submittal
438
+ *
439
+ * @var element {HTMLFormElement} - a dom element reference to the form to turn into a LiveValidationForm
440
+ */
441
+ var LiveValidationForm = function(element){
442
+ this.initialize(element);
443
+ }
444
+
445
+ /**
446
+ * namespace to hold instances
447
+ */
448
+ LiveValidationForm.instances = {};
449
+
450
+ /**
451
+ * gets the instance of the LiveValidationForm if it has already been made or creates it if it doesnt exist
452
+ *
453
+ * @var element {HTMLFormElement} - a dom element reference to a form
454
+ */
455
+ LiveValidationForm.getInstance = function(element){
456
+ var rand = Math.random() * Math.random();
457
+ if(!element.id) element.id = 'formId_' + rand.toString().replace(/\./, '') + new Date().valueOf();
458
+ if(!LiveValidationForm.instances[element.id]) LiveValidationForm.instances[element.id] = new LiveValidationForm(element);
459
+ return LiveValidationForm.instances[element.id];
460
+ }
461
+
462
+ LiveValidationForm.prototype = {
463
+
464
+ /**
465
+ * constructor for LiveValidationForm - handles validation of LiveValidation fields belonging to this form on its submittal
466
+ *
467
+ * @var element {HTMLFormElement} - a dom element reference to the form to turn into a LiveValidationForm
468
+ */
469
+ initialize: function(element){
470
+ this.name = element.id;
471
+ this.element = element;
472
+ this.fields = [];
473
+ // preserve the old onsubmit event
474
+ this.oldOnSubmit = this.element.onsubmit || function(){};
475
+ var self = this;
476
+ this.element.onsubmit = function(e){
477
+ return (LiveValidation.massValidate(self.fields)) ? self.oldOnSubmit.call(this, e || window.event) !== false : false;
478
+ }
479
+ },
480
+
481
+ /**
482
+ * adds a LiveValidation field to the forms fields array
483
+ *
484
+ * @var element {LiveValidation} - a LiveValidation object
485
+ */
486
+ addField: function(newField){
487
+ this.fields.push(newField);
488
+ },
489
+
490
+ /**
491
+ * removes a LiveValidation field from the forms fields array
492
+ *
493
+ * @var victim {LiveValidation} - a LiveValidation object
494
+ */
495
+ removeField: function(victim){
496
+ var victimless = [];
497
+ for( var i = 0, len = this.fields.length; i < len; i++){
498
+ if(this.fields[i] !== victim) victimless.push(this.fields[i]);
499
+ }
500
+ this.fields = victimless;
501
+ },
502
+
503
+ /**
504
+ * destroy this instance and its events
505
+ *
506
+ * @var force {Boolean} - whether to force the detruction even if there are fields still associated
507
+ */
508
+ destroy: function(force){
509
+ // only destroy if has no fields and not being forced
510
+ if (this.fields.length != 0 && !force) return false;
511
+ // remove events - set back to previous events
512
+ this.element.onsubmit = this.oldOnSubmit;
513
+ // remove from the instances namespace
514
+ LiveValidationForm.instances[this.name] = null;
515
+ return true;
516
+ }
517
+
518
+ }// end of LiveValidationForm prototype
519
+
520
+ /*************************************** Validate class ****************************************/
521
+ /**
522
+ * This class contains all the methods needed for doing the actual validation itself
523
+ *
524
+ * All methods are static so that they can be used outside the context of a form field
525
+ * as they could be useful for validating stuff anywhere you want really
526
+ *
527
+ * All of them will return true if the validation is successful, but will raise a ValidationError if
528
+ * they fail, so that this can be caught and the message explaining the error can be accessed ( as just
529
+ * returning false would leave you a bit in the dark as to why it failed )
530
+ *
531
+ * Can use validation methods alone and wrap in a try..catch statement yourself if you want to access the failure
532
+ * message and handle the error, or use the Validate::now method if you just want true or false
533
+ */
534
+
535
+ var Validate = {
536
+
537
+ /**
538
+ * validates that the field has been filled in
539
+ *
540
+ * @var value {mixed} - value to be checked
541
+ * @var paramsObj {Object} - parameters for this particular validation, see below for details
542
+ *
543
+ * paramsObj properties:
544
+ * failureMessage {String} - the message to show when the field fails validation
545
+ * (DEFAULT: "Can't be empty!")
546
+ */
547
+ Presence: function(value, paramsObj){
548
+ var paramsObj = paramsObj || {};
549
+ var message = paramsObj.failureMessage || "Can't be empty!";
550
+ if(value === '' || value === null || value === undefined){
551
+ Validate.fail(message);
552
+ }
553
+ return true;
554
+ },
555
+
556
+ /**
557
+ * validates that the value is numeric, does not fall within a given range of numbers
558
+ *
559
+ * @var value {mixed} - value to be checked
560
+ * @var paramsObj {Object} - parameters for this particular validation, see below for details
561
+ *
562
+ * paramsObj properties:
563
+ * notANumberMessage {String} - the message to show when the validation fails when value is not a number
564
+ * (DEFAULT: "Must be a number!")
565
+ * notAnIntegerMessage {String} - the message to show when the validation fails when value is not an integer
566
+ * (DEFAULT: "Must be a number!")
567
+ * wrongNumberMessage {String} - the message to show when the validation fails when is param is used
568
+ * (DEFAULT: "Must be {is}!")
569
+ * tooLowMessage {String} - the message to show when the validation fails when minimum param is used
570
+ * (DEFAULT: "Must not be less than {minimum}!")
571
+ * tooHighMessage {String} - the message to show when the validation fails when maximum param is used
572
+ * (DEFAULT: "Must not be more than {maximum}!")
573
+ * is {Int} - the length must be this long
574
+ * minimum {Int} - the minimum length allowed
575
+ * maximum {Int} - the maximum length allowed
576
+ * onlyInteger {Boolean} - if true will only allow integers to be valid
577
+ * (DEFAULT: false)
578
+ *
579
+ * NB. can be checked if it is within a range by specifying both a minimum and a maximum
580
+ * NB. will evaluate numbers represented in scientific form (ie 2e10) correctly as numbers
581
+ */
582
+ Numericality: function(value, paramsObj){
583
+ var suppliedValue = value;
584
+ var value = Number(value);
585
+ var paramsObj = paramsObj || {};
586
+ var minimum = ((paramsObj.minimum) || (paramsObj.minimum == 0)) ? paramsObj.minimum : null;;
587
+ var maximum = ((paramsObj.maximum) || (paramsObj.maximum == 0)) ? paramsObj.maximum : null;
588
+ var is = ((paramsObj.is) || (paramsObj.is == 0)) ? paramsObj.is : null;
589
+ var notANumberMessage = paramsObj.notANumberMessage || "Must be a number!";
590
+ var notAnIntegerMessage = paramsObj.notAnIntegerMessage || "Must be an integer!";
591
+ var wrongNumberMessage = paramsObj.wrongNumberMessage || "Must be " + is + "!";
592
+ var tooLowMessage = paramsObj.tooLowMessage || "Must not be less than " + minimum + "!";
593
+ var tooHighMessage = paramsObj.tooHighMessage || "Must not be more than " + maximum + "!";
594
+ if (!isFinite(value)) Validate.fail(notANumberMessage);
595
+ if (paramsObj.onlyInteger && (/\.0+$|\.$/.test(String(suppliedValue)) || value != parseInt(value)) ) Validate.fail(notAnIntegerMessage);
596
+ switch(true){
597
+ case (is !== null):
598
+ if( value != Number(is) ) Validate.fail(wrongNumberMessage);
599
+ break;
600
+ case (minimum !== null && maximum !== null):
601
+ Validate.Numericality(value, {tooLowMessage: tooLowMessage, minimum: minimum});
602
+ Validate.Numericality(value, {tooHighMessage: tooHighMessage, maximum: maximum});
603
+ break;
604
+ case (minimum !== null):
605
+ if( value < Number(minimum) ) Validate.fail(tooLowMessage);
606
+ break;
607
+ case (maximum !== null):
608
+ if( value > Number(maximum) ) Validate.fail(tooHighMessage);
609
+ break;
610
+ }
611
+ return true;
612
+ },
613
+
614
+ /**
615
+ * validates against a RegExp pattern
616
+ *
617
+ * @var value {mixed} - value to be checked
618
+ * @var paramsObj {Object} - parameters for this particular validation, see below for details
619
+ *
620
+ * paramsObj properties:
621
+ * failureMessage {String} - the message to show when the field fails validation
622
+ * (DEFAULT: "Not valid!")
623
+ * pattern {RegExp} - the regular expression pattern
624
+ * (DEFAULT: /./)
625
+ * negate {Boolean} - if set to true, will validate true if the pattern is not matched
626
+ * (DEFAULT: false)
627
+ *
628
+ * NB. will return true for an empty string, to allow for non-required, empty fields to validate.
629
+ * If you do not want this to be the case then you must either add a LiveValidation.PRESENCE validation
630
+ * or build it into the regular expression pattern
631
+ */
632
+ Format: function(value, paramsObj){
633
+ var value = String(value);
634
+ var paramsObj = paramsObj || {};
635
+ var message = paramsObj.failureMessage || "Not valid!";
636
+ var pattern = paramsObj.pattern || /./;
637
+ var negate = paramsObj.negate || false;
638
+ if(!negate && !pattern.test(value)) Validate.fail(message); // normal
639
+ if(negate && pattern.test(value)) Validate.fail(message); // negated
640
+ return true;
641
+ },
642
+
643
+ /**
644
+ * validates that the field contains a valid email address
645
+ *
646
+ * @var value {mixed} - value to be checked
647
+ * @var paramsObj {Object} - parameters for this particular validation, see below for details
648
+ *
649
+ * paramsObj properties:
650
+ * failureMessage {String} - the message to show when the field fails validation
651
+ * (DEFAULT: "Must be a number!" or "Must be an integer!")
652
+ */
653
+ Email: function(value, paramsObj){
654
+ var paramsObj = paramsObj || {};
655
+ var message = paramsObj.failureMessage || "Must be a valid email address!";
656
+ Validate.Format(value, { failureMessage: message, pattern: /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i } );
657
+ return true;
658
+ },
659
+
660
+ /**
661
+ * validates the length of the value
662
+ *
663
+ * @var value {mixed} - value to be checked
664
+ * @var paramsObj {Object} - parameters for this particular validation, see below for details
665
+ *
666
+ * paramsObj properties:
667
+ * wrongLengthMessage {String} - the message to show when the fails when is param is used
668
+ * (DEFAULT: "Must be {is} characters long!")
669
+ * tooShortMessage {String} - the message to show when the fails when minimum param is used
670
+ * (DEFAULT: "Must not be less than {minimum} characters long!")
671
+ * tooLongMessage {String} - the message to show when the fails when maximum param is used
672
+ * (DEFAULT: "Must not be more than {maximum} characters long!")
673
+ * is {Int} - the length must be this long
674
+ * minimum {Int} - the minimum length allowed
675
+ * maximum {Int} - the maximum length allowed
676
+ *
677
+ * NB. can be checked if it is within a range by specifying both a minimum and a maximum
678
+ */
679
+ Length: function(value, paramsObj){
680
+ var value = String(value);
681
+ var paramsObj = paramsObj || {};
682
+ var minimum = ((paramsObj.minimum) || (paramsObj.minimum == 0)) ? paramsObj.minimum : null;
683
+ var maximum = ((paramsObj.maximum) || (paramsObj.maximum == 0)) ? paramsObj.maximum : null;
684
+ var is = ((paramsObj.is) || (paramsObj.is == 0)) ? paramsObj.is : null;
685
+ var wrongLengthMessage = paramsObj.wrongLengthMessage || "Must be " + is + " characters long!";
686
+ var tooShortMessage = paramsObj.tooShortMessage || "Must not be less than " + minimum + " characters long!";
687
+ var tooLongMessage = paramsObj.tooLongMessage || "Must not be more than " + maximum + " characters long!";
688
+ switch(true){
689
+ case (is !== null):
690
+ if( value.length != Number(is) ) Validate.fail(wrongLengthMessage);
691
+ break;
692
+ case (minimum !== null && maximum !== null):
693
+ Validate.Length(value, {tooShortMessage: tooShortMessage, minimum: minimum});
694
+ Validate.Length(value, {tooLongMessage: tooLongMessage, maximum: maximum});
695
+ break;
696
+ case (minimum !== null):
697
+ if( value.length < Number(minimum) ) Validate.fail(tooShortMessage);
698
+ break;
699
+ case (maximum !== null):
700
+ if( value.length > Number(maximum) ) Validate.fail(tooLongMessage);
701
+ break;
702
+ default:
703
+ throw new Error("Validate::Length - Length(s) to validate against must be provided!");
704
+ }
705
+ return true;
706
+ },
707
+
708
+ /**
709
+ * validates that the value falls within a given set of values
710
+ *
711
+ * @var value {mixed} - value to be checked
712
+ * @var paramsObj {Object} - parameters for this particular validation, see below for details
713
+ *
714
+ * paramsObj properties:
715
+ * failureMessage {String} - the message to show when the field fails validation
716
+ * (DEFAULT: "Must be included in the list!")
717
+ * within {Array} - an array of values that the value should fall in
718
+ * (DEFAULT: [])
719
+ * allowNull {Bool} - if true, and a null value is passed in, validates as true
720
+ * (DEFAULT: false)
721
+ * partialMatch {Bool} - if true, will not only validate against the whole value to check but also if it is a substring of the value
722
+ * (DEFAULT: false)
723
+ * caseSensitive {Bool} - if false will compare strings case insensitively
724
+ * (DEFAULT: true)
725
+ * negate {Bool} - if true, will validate that the value is not within the given set of values
726
+ * (DEFAULT: false)
727
+ */
728
+ Inclusion: function(value, paramsObj){
729
+ var paramsObj = paramsObj || {};
730
+ var message = paramsObj.failureMessage || "Must be included in the list!";
731
+ var caseSensitive = (paramsObj.caseSensitive === false) ? false : true;
732
+ if(paramsObj.allowNull && value == null) return true;
733
+ if(!paramsObj.allowNull && value == null) Validate.fail(message);
734
+ var within = paramsObj.within || [];
735
+ //if case insensitive, make all strings in the array lowercase, and the value too
736
+ if(!caseSensitive){
737
+ var lowerWithin = [];
738
+ for(var j = 0, length = within.length; j < length; ++j){
739
+ var item = within[j];
740
+ if(typeof item == 'string') item = item.toLowerCase();
741
+ lowerWithin.push(item);
742
+ }
743
+ within = lowerWithin;
744
+ if(typeof value == 'string') value = value.toLowerCase();
745
+ }
746
+ var found = false;
747
+ for(var i = 0, length = within.length; i < length; ++i){
748
+ if(within[i] == value) found = true;
749
+ if(paramsObj.partialMatch){
750
+ if(value.indexOf(within[i]) != -1) found = true;
751
+ }
752
+ }
753
+ if( (!paramsObj.negate && !found) || (paramsObj.negate && found) ) Validate.fail(message);
754
+ return true;
755
+ },
756
+
757
+ /**
758
+ * validates that the value does not fall within a given set of values
759
+ *
760
+ * @var value {mixed} - value to be checked
761
+ * @var paramsObj {Object} - parameters for this particular validation, see below for details
762
+ *
763
+ * paramsObj properties:
764
+ * failureMessage {String} - the message to show when the field fails validation
765
+ * (DEFAULT: "Must not be included in the list!")
766
+ * within {Array} - an array of values that the value should not fall in
767
+ * (DEFAULT: [])
768
+ * allowNull {Bool} - if true, and a null value is passed in, validates as true
769
+ * (DEFAULT: false)
770
+ * partialMatch {Bool} - if true, will not only validate against the whole value to check but also if it is a substring of the value
771
+ * (DEFAULT: false)
772
+ * caseSensitive {Bool} - if false will compare strings case insensitively
773
+ * (DEFAULT: true)
774
+ */
775
+ Exclusion: function(value, paramsObj){
776
+ var paramsObj = paramsObj || {};
777
+ paramsObj.failureMessage = paramsObj.failureMessage || "Must not be included in the list!";
778
+ paramsObj.negate = true;
779
+ Validate.Inclusion(value, paramsObj);
780
+ return true;
781
+ },
782
+
783
+ /**
784
+ * validates that the value matches that in another field
785
+ *
786
+ * @var value {mixed} - value to be checked
787
+ * @var paramsObj {Object} - parameters for this particular validation, see below for details
788
+ *
789
+ * paramsObj properties:
790
+ * failureMessage {String} - the message to show when the field fails validation
791
+ * (DEFAULT: "Does not match!")
792
+ * match {String} - id of the field that this one should match
793
+ */
794
+ Confirmation: function(value, paramsObj){
795
+ if(!paramsObj.match) throw new Error("Validate::Confirmation - Error validating confirmation: Id of element to match must be provided!");
796
+ var paramsObj = paramsObj || {};
797
+ var message = paramsObj.failureMessage || "Does not match!";
798
+ var match = paramsObj.match.nodeName ? paramsObj.match : document.getElementById(paramsObj.match);
799
+ if(!match) throw new Error("Validate::Confirmation - There is no reference with name of, or element with id of '" + paramsObj.match + "'!");
800
+ if(value != match.value){
801
+ Validate.fail(message);
802
+ }
803
+ return true;
804
+ },
805
+
806
+ /**
807
+ * validates that the value is true (for use primarily in detemining if a checkbox has been checked)
808
+ *
809
+ * @var value {mixed} - value to be checked if true or not (usually a boolean from the checked value of a checkbox)
810
+ * @var paramsObj {Object} - parameters for this particular validation, see below for details
811
+ *
812
+ * paramsObj properties:
813
+ * failureMessage {String} - the message to show when the field fails validation
814
+ * (DEFAULT: "Must be accepted!")
815
+ */
816
+ Acceptance: function(value, paramsObj){
817
+ var paramsObj = paramsObj || {};
818
+ var message = paramsObj.failureMessage || "Must be accepted!";
819
+ if(!value){
820
+ Validate.fail(message);
821
+ }
822
+ return true;
823
+ },
824
+
825
+ /**
826
+ * validates against a custom function that returns true or false (or throws a Validate.Error) when passed the value
827
+ *
828
+ * @var value {mixed} - value to be checked
829
+ * @var paramsObj {Object} - parameters for this particular validation, see below for details
830
+ *
831
+ * paramsObj properties:
832
+ * failureMessage {String} - the message to show when the field fails validation
833
+ * (DEFAULT: "Not valid!")
834
+ * against {Function} - a function that will take the value and object of arguments and return true or false
835
+ * (DEFAULT: function(){ return true; })
836
+ * args {Object} - an object of named arguments that will be passed to the custom function so are accessible through this object within it
837
+ * (DEFAULT: {})
838
+ */
839
+ Custom: function(value, paramsObj){
840
+ var paramsObj = paramsObj || {};
841
+ var against = paramsObj.against || function(){ return true; };
842
+ var args = paramsObj.args || {};
843
+ var message = paramsObj.failureMessage || "Not valid!";
844
+ if(!against(value, args)) Validate.fail(message);
845
+ return true;
846
+ },
847
+
848
+ /**
849
+ * validates whatever it is you pass in, and handles the validation error for you so it gives a nice true or false reply
850
+ *
851
+ * @var validationFunction {Function} - validation function to be used (ie Validation.validatePresence )
852
+ * @var value {mixed} - value to be checked if true or not (usually a boolean from the checked value of a checkbox)
853
+ * @var validationParamsObj {Object} - parameters for doing the validation, if wanted or necessary
854
+ */
855
+ now: function(validationFunction, value, validationParamsObj){
856
+ if(!validationFunction) throw new Error("Validate::now - Validation function must be provided!");
857
+ var isValid = true;
858
+ try{
859
+ validationFunction(value, validationParamsObj || {});
860
+ } catch(error) {
861
+ if(error instanceof Validate.Error){
862
+ isValid = false;
863
+ }else{
864
+ throw error;
865
+ }
866
+ }finally{
867
+ return isValid
868
+ }
869
+ },
870
+
871
+ /**
872
+ * shortcut for failing throwing a validation error
873
+ *
874
+ * @var errorMessage {String} - message to display
875
+ */
876
+ fail: function(errorMessage){
877
+ throw new Validate.Error(errorMessage);
878
+ },
879
+
880
+ Error: function(errorMessage){
881
+ this.message = errorMessage;
882
+ this.name = 'ValidationError';
883
+ }
884
+ }