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