[ Index ] |
PHP Cross Reference of phpwcms V1.4.7 _r403 (01.11.10) |
[Summary view] [Print] [Text view]
1 /* 2 --- 3 4 script: Form.Validator.js 5 6 name: Form.Validator 7 8 description: A css-class based form validation system. 9 10 license: MIT-style license 11 12 authors: 13 - Aaron Newton 14 15 requires: 16 - Core/Options 17 - Core/Events 18 - Core/Selectors 19 - Core/Element.Event 20 - Core/Element.Style 21 - Core/JSON 22 - /Lang 23 - /Class.Binds 24 - /Date 25 - /Element.Forms 26 - /Form.Validator.English 27 - /Element.Shortcuts 28 29 provides: [Form.Validator, InputValidator, FormValidator.BaseValidators] 30 31 ... 32 */ 33 if (!window.Form) window.Form = {}; 34 35 var InputValidator = new Class({ 36 37 Implements: [Options], 38 39 options: { 40 errorMsg: 'Validation failed.', 41 test: function(field){return true;} 42 }, 43 44 initialize: function(className, options){ 45 this.setOptions(options); 46 this.className = className; 47 }, 48 49 test: function(field, props){ 50 if (document.id(field)) return this.options.test(document.id(field), props||this.getProps(field)); 51 else return false; 52 }, 53 54 getError: function(field, props){ 55 var err = this.options.errorMsg; 56 if ($type(err) == 'function') err = err(document.id(field), props||this.getProps(field)); 57 return err; 58 }, 59 60 getProps: function(field){ 61 if (!document.id(field)) return {}; 62 return field.get('validatorProps'); 63 } 64 65 }); 66 67 Element.Properties.validatorProps = { 68 69 set: function(props){ 70 return this.eliminate('validatorProps').store('validatorProps', props); 71 }, 72 73 get: function(props){ 74 if (props) this.set(props); 75 if (this.retrieve('validatorProps')) return this.retrieve('validatorProps'); 76 if (this.getProperty('validatorProps')){ 77 try { 78 this.store('validatorProps', JSON.decode(this.getProperty('validatorProps'))); 79 }catch(e){ 80 return {}; 81 } 82 } else { 83 var vals = this.get('class').split(' ').filter(function(cls){ 84 return cls.test(':'); 85 }); 86 if (!vals.length){ 87 this.store('validatorProps', {}); 88 } else { 89 props = {}; 90 vals.each(function(cls){ 91 var split = cls.split(':'); 92 if (split[1]) { 93 try { 94 props[split[0]] = JSON.decode(split[1]); 95 } catch(e) {} 96 } 97 }); 98 this.store('validatorProps', props); 99 } 100 } 101 return this.retrieve('validatorProps'); 102 } 103 104 }; 105 106 Form.Validator = new Class({ 107 108 Implements:[Options, Events], 109 110 Binds: ['onSubmit'], 111 112 options: {/* 113 onFormValidate: $empty(isValid, form, event), 114 onElementValidate: $empty(isValid, field, className, warn), 115 onElementPass: $empty(field), 116 onElementFail: $empty(field, validatorsFailed) */ 117 fieldSelectors: 'input, select, textarea', 118 ignoreHidden: true, 119 ignoreDisabled: true, 120 useTitles: false, 121 evaluateOnSubmit: true, 122 evaluateFieldsOnBlur: true, 123 evaluateFieldsOnChange: true, 124 serial: true, 125 stopOnFailure: true, 126 warningPrefix: function(){ 127 return Form.Validator.getMsg('warningPrefix') || 'Warning: '; 128 }, 129 errorPrefix: function(){ 130 return Form.Validator.getMsg('errorPrefix') || 'Error: '; 131 } 132 }, 133 134 initialize: function(form, options){ 135 this.setOptions(options); 136 this.element = document.id(form); 137 this.element.store('validator', this); 138 this.warningPrefix = $lambda(this.options.warningPrefix)(); 139 this.errorPrefix = $lambda(this.options.errorPrefix)(); 140 if (this.options.evaluateOnSubmit) this.element.addEvent('submit', this.onSubmit); 141 if (this.options.evaluateFieldsOnBlur || this.options.evaluateFieldsOnChange) this.watchFields(this.getFields()); 142 }, 143 144 toElement: function(){ 145 return this.element; 146 }, 147 148 getFields: function(){ 149 return (this.fields = this.element.getElements(this.options.fieldSelectors)); 150 }, 151 152 watchFields: function(fields){ 153 fields.each(function(el){ 154 if (this.options.evaluateFieldsOnBlur) 155 el.addEvent('blur', this.validationMonitor.pass([el, false], this)); 156 if (this.options.evaluateFieldsOnChange) 157 el.addEvent('change', this.validationMonitor.pass([el, true], this)); 158 }, this); 159 }, 160 161 validationMonitor: function(){ 162 $clear(this.timer); 163 this.timer = this.validateField.delay(50, this, arguments); 164 }, 165 166 onSubmit: function(event){ 167 if (!this.validate(event) && event) event.preventDefault(); 168 else this.reset(); 169 }, 170 171 reset: function(){ 172 this.getFields().each(this.resetField, this); 173 return this; 174 }, 175 176 validate: function(event){ 177 var result = this.getFields().map(function(field){ 178 return this.validateField(field, true); 179 }, this).every(function(v){ return v;}); 180 this.fireEvent('formValidate', [result, this.element, event]); 181 if (this.options.stopOnFailure && !result && event) event.preventDefault(); 182 return result; 183 }, 184 185 validateField: function(field, force){ 186 if (this.paused) return true; 187 field = document.id(field); 188 var passed = !field.hasClass('validation-failed'); 189 var failed, warned; 190 if (this.options.serial && !force){ 191 failed = this.element.getElement('.validation-failed'); 192 warned = this.element.getElement('.warning'); 193 } 194 if (field && (!failed || force || field.hasClass('validation-failed') || (failed && !this.options.serial))){ 195 var validators = field.className.split(' ').some(function(cn){ 196 return this.getValidator(cn); 197 }, this); 198 var validatorsFailed = []; 199 field.className.split(' ').each(function(className){ 200 if (className && !this.test(className, field)) validatorsFailed.include(className); 201 }, this); 202 passed = validatorsFailed.length === 0; 203 if (validators && !field.hasClass('warnOnly')){ 204 if (passed){ 205 field.addClass('validation-passed').removeClass('validation-failed'); 206 this.fireEvent('elementPass', field); 207 } else { 208 field.addClass('validation-failed').removeClass('validation-passed'); 209 this.fireEvent('elementFail', [field, validatorsFailed]); 210 } 211 } 212 if (!warned){ 213 var warnings = field.className.split(' ').some(function(cn){ 214 if (cn.test('^warn-') || field.hasClass('warnOnly')) 215 return this.getValidator(cn.replace(/^warn-/,'')); 216 else return null; 217 }, this); 218 field.removeClass('warning'); 219 var warnResult = field.className.split(' ').map(function(cn){ 220 if (cn.test('^warn-') || field.hasClass('warnOnly')) 221 return this.test(cn.replace(/^warn-/,''), field, true); 222 else return null; 223 }, this); 224 } 225 } 226 return passed; 227 }, 228 229 test: function(className, field, warn){ 230 field = document.id(field); 231 if((this.options.ignoreHidden && !field.isVisible()) || (this.options.ignoreDisabled && field.get('disabled'))) return true; 232 var validator = this.getValidator(className); 233 warn = $pick(warn, false); 234 if (field.hasClass('warnOnly')) warn = true; 235 var isValid = field.hasClass('ignoreValidation') || (validator ? validator.test(field) : true); 236 if (validator && field.isVisible()) this.fireEvent('elementValidate', [isValid, field, className, warn]); 237 if (warn) return true; 238 return isValid; 239 }, 240 241 resetField: function(field){ 242 field = document.id(field); 243 if (field){ 244 field.className.split(' ').each(function(className){ 245 if (className.test('^warn-')) className = className.replace(/^warn-/, ''); 246 field.removeClass('validation-failed'); 247 field.removeClass('warning'); 248 field.removeClass('validation-passed'); 249 }, this); 250 } 251 return this; 252 }, 253 254 stop: function(){ 255 this.paused = true; 256 return this; 257 }, 258 259 start: function(){ 260 this.paused = false; 261 return this; 262 }, 263 264 ignoreField: function(field, warn){ 265 field = document.id(field); 266 if (field){ 267 this.enforceField(field); 268 if (warn) field.addClass('warnOnly'); 269 else field.addClass('ignoreValidation'); 270 } 271 return this; 272 }, 273 274 enforceField: function(field){ 275 field = document.id(field); 276 if (field) field.removeClass('warnOnly').removeClass('ignoreValidation'); 277 return this; 278 } 279 280 }); 281 282 Form.Validator.getMsg = function(key){ 283 return MooTools.lang.get('Form.Validator', key); 284 }; 285 286 Form.Validator.adders = { 287 288 validators:{}, 289 290 add : function(className, options){ 291 this.validators[className] = new InputValidator(className, options); 292 //if this is a class (this method is used by instances of Form.Validator and the Form.Validator namespace) 293 //extend these validators into it 294 //this allows validators to be global and/or per instance 295 if (!this.initialize){ 296 this.implement({ 297 validators: this.validators 298 }); 299 } 300 }, 301 302 addAllThese : function(validators){ 303 $A(validators).each(function(validator){ 304 this.add(validator[0], validator[1]); 305 }, this); 306 }, 307 308 getValidator: function(className){ 309 return this.validators[className.split(':')[0]]; 310 } 311 312 }; 313 314 $extend(Form.Validator, Form.Validator.adders); 315 316 Form.Validator.implement(Form.Validator.adders); 317 318 Form.Validator.add('IsEmpty', { 319 320 errorMsg: false, 321 test: function(element){ 322 if (element.type == 'select-one' || element.type == 'select') 323 return !(element.selectedIndex >= 0 && element.options[element.selectedIndex].value != ''); 324 else 325 return ((element.get('value') == null) || (element.get('value').length == 0)); 326 } 327 328 }); 329 330 Form.Validator.addAllThese([ 331 332 ['required', { 333 errorMsg: function(){ 334 return Form.Validator.getMsg('required'); 335 }, 336 test: function(element){ 337 return !Form.Validator.getValidator('IsEmpty').test(element); 338 } 339 }], 340 341 ['minLength', { 342 errorMsg: function(element, props){ 343 if ($type(props.minLength)) 344 return Form.Validator.getMsg('minLength').substitute({minLength:props.minLength,length:element.get('value').length }); 345 else return ''; 346 }, 347 test: function(element, props){ 348 if ($type(props.minLength)) return (element.get('value').length >= $pick(props.minLength, 0)); 349 else return true; 350 } 351 }], 352 353 ['maxLength', { 354 errorMsg: function(element, props){ 355 //props is {maxLength:10} 356 if ($type(props.maxLength)) 357 return Form.Validator.getMsg('maxLength').substitute({maxLength:props.maxLength,length:element.get('value').length }); 358 else return ''; 359 }, 360 test: function(element, props){ 361 //if the value is <= than the maxLength value, element passes test 362 return (element.get('value').length <= $pick(props.maxLength, 10000)); 363 } 364 }], 365 366 ['validate-integer', { 367 errorMsg: Form.Validator.getMsg.pass('integer'), 368 test: function(element){ 369 return Form.Validator.getValidator('IsEmpty').test(element) || (/^(-?[1-9]\d*|0)$/).test(element.get('value')); 370 } 371 }], 372 373 ['validate-numeric', { 374 errorMsg: Form.Validator.getMsg.pass('numeric'), 375 test: function(element){ 376 return Form.Validator.getValidator('IsEmpty').test(element) || 377 (/^-?(?:0$0(?=\d*\.)|[1-9]|0)\d*(\.\d+)?$/).test(element.get('value')); 378 } 379 }], 380 381 ['validate-digits', { 382 errorMsg: Form.Validator.getMsg.pass('digits'), 383 test: function(element){ 384 return Form.Validator.getValidator('IsEmpty').test(element) || (/^[\d() .:\-\+#]+$/.test(element.get('value'))); 385 } 386 }], 387 388 ['validate-alpha', { 389 errorMsg: Form.Validator.getMsg.pass('alpha'), 390 test: function(element){ 391 return Form.Validator.getValidator('IsEmpty').test(element) || (/^[a-zA-Z]+$/).test(element.get('value')); 392 } 393 }], 394 395 ['validate-alphanum', { 396 errorMsg: Form.Validator.getMsg.pass('alphanum'), 397 test: function(element){ 398 return Form.Validator.getValidator('IsEmpty').test(element) || !(/\W/).test(element.get('value')); 399 } 400 }], 401 402 ['validate-date', { 403 errorMsg: function(element, props){ 404 if (Date.parse){ 405 var format = props.dateFormat || '%x'; 406 return Form.Validator.getMsg('dateSuchAs').substitute({date: new Date().format(format)}); 407 } else { 408 return Form.Validator.getMsg('dateInFormatMDY'); 409 } 410 }, 411 test: function(element, props){ 412 if (Form.Validator.getValidator('IsEmpty').test(element)) return true; 413 var d; 414 if (Date.parse){ 415 var format = props.dateFormat || '%x'; 416 d = Date.parse(element.get('value')); 417 var formatted = d.format(format); 418 if (formatted != 'invalid date') element.set('value', formatted); 419 return !isNaN(d); 420 } else { 421 var regex = /^(\d{2})\/(\d{2})\/(\d{4})$/; 422 if (!regex.test(element.get('value'))) return false; 423 d = new Date(element.get('value').replace(regex, '$1/$2/$3')); 424 return (parseInt(RegExp.$1, 10) == (1 + d.getMonth())) && 425 (parseInt(RegExp.$2, 10) == d.getDate()) && 426 (parseInt(RegExp.$3, 10) == d.getFullYear()); 427 } 428 } 429 }], 430 431 ['validate-email', { 432 errorMsg: Form.Validator.getMsg.pass('email'), 433 test: function(element){ 434 return Form.Validator.getValidator('IsEmpty').test(element) || (/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i).test(element.get('value')); 435 } 436 }], 437 438 ['validate-url', { 439 errorMsg: Form.Validator.getMsg.pass('url'), 440 test: function(element){ 441 return Form.Validator.getValidator('IsEmpty').test(element) || (/^(https?|ftp|rmtp|mms):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i).test(element.get('value')); 442 } 443 }], 444 445 ['validate-currency-dollar', { 446 errorMsg: Form.Validator.getMsg.pass('currencyDollar'), 447 test: function(element){ 448 // [$]1[##][,###]+[.##] 449 // [$]1###+[.##] 450 // [$]0.## 451 // [$].## 452 return Form.Validator.getValidator('IsEmpty').test(element) || (/^\$?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/).test(element.get('value')); 453 } 454 }], 455 456 ['validate-one-required', { 457 errorMsg: Form.Validator.getMsg.pass('oneRequired'), 458 test: function(element, props){ 459 var p = document.id(props['validate-one-required']) || element.getParent(props['validate-one-required']); 460 return p.getElements('input').some(function(el){ 461 if (['checkbox', 'radio'].contains(el.get('type'))) return el.get('checked'); 462 return el.get('value'); 463 }); 464 } 465 }] 466 467 ]); 468 469 Element.Properties.validator = { 470 471 set: function(options){ 472 var validator = this.retrieve('validator'); 473 if (validator) validator.setOptions(options); 474 return this.store('validator:options', options); 475 }, 476 477 get: function(options){ 478 if (options || !this.retrieve('validator')){ 479 if (options || !this.retrieve('validator:options')) this.set('validator', options); 480 this.store('validator', new Form.Validator(this, this.retrieve('validator:options'))); 481 } 482 return this.retrieve('validator'); 483 } 484 485 }; 486 487 Element.implement({ 488 489 validate: function(options){ 490 if (options) this.set('validator', options); 491 return this.get('validator', options).validate(); 492 } 493 494 }); 495 //legacy 496 var FormValidator = Form.Validator;
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Nov 16 22:51:00 2010 | Cross-referenced by PHPXref 0.7 |