1/* Simple JavaScript Inheritance 2* By John Resig http://ejohn.org/ 3* MIT Licensed. 4*/ 5 6(function(){var initializing=false;var fnTest=/var xyz/.test(function(){var xyz;})?/\b_super\b/:/.*/;this.Class=function(){};Class.extend = function(prop) {var _super = this.prototype;initializing = true;var prototype = new this();initializing = false;for (var name in prop) {if( typeof prop[name] == "function" && typeof _super[name] == "function" && fnTest.test(prop[name]) ){prototype[name] = (function(name,fn){return function() {var tmp=this._super;this._super=_super[name];var ret=fn.apply(this,arguments);this._super=tmp;return ret;};})(name,prop[name]);}else{prototype[name] = prop[name];}}function Class(){if(!initializing && this.init){this.init.apply(this,arguments);}}Class.prototype=prototype;Class.prototype.constructor=Class;Class.extend=arguments.callee;return Class;};})(); 7 8var FormValidator = Class.extend({ 9 10 init : function ( options ) { 11 if ( !options.hasOwnProperty('form') || !(options.form instanceof Element) ) { 12 throw new IllegalArgument('form expects HTML Element'); 13 } 14 15 this._onSubmitBind = this._onSubmit.bind(this); 16 this._onInputBind = this._onInput.bind(this); 17 18 this._delay = 0; 19 this._showValidFeedback = ( !options.hasOwnProperty('showValidFeedback') || (options.showValidFeedback != false && options.showValidFeedback != 'false') ); 20 21 this.inputs = {}; 22 this._validators = { 23 'native' : this._checkNative.bind(this) 24 } 25 26 if ( options.hasOwnProperty('custom') && typeof options.custom == 'object' ){ 27 for ( var key in options.custom ){ 28 if ( typeof options.custom[key] == 'function' ){ 29 this._validators[key] = options.custom[key]; 30 } 31 } 32 } 33 34 this.form = options.form; 35 this.submitButtons = this.form.querySelectorAll('button[type="submit"], input[type="submit"]'); 36 // make sure that validation will be triggered on disabled submit buttons 37 for ( var i = 0; i < this.submitButtons.length; i++ ){ 38 this.submitButtons[i].style.pointerEvents = 'auto'; 39 } 40 41 this.form.addEventListener('submit', this._onSubmitBind); 42 }, 43 destroy : function(){ 44 this.form.removeEventListener('submit', this._onSubmitBind); 45 for ( var id in this.inputs ){ 46 this.deRegisterInput(this.inputs[id].element); 47 } 48 this.inputs = null; 49 this._delay = null; 50 this._showValidFeedback = null; 51 this._validators = null; 52 this.submitButtons = null; 53 this.form = null; 54 }, 55 autoRegisterInputs : function(){ 56 for ( var id in this.inputs ){ 57 this._deRegisterInput(this.inputs[id].element); 58 } 59 for ( var i = 0; i < this.form.elements.length; i++ ){ 60 if ( this.form.elements[i].dataset.validate === 'false' ){ 61 continue; 62 } 63 if ( 64 this.form.elements[i].dataset.validate === 'true' || 65 ( this.form.elements[i].nodeName == 'INPUT' && ['hidden','button','submit'].indexOf(this.form.elements[i].type) < 0 ) || 66 this.form.elements[i].nodeName == 'SELECT' || this.form.elements[i].nodeName == 'TEXTAREA' 67 ){ 68 this._registerInput(this.form.elements[i]); 69 } 70 } 71 this._toggleSubmit(); 72 }, 73 registerInput : function( element ){ 74 if ( element instanceof Element ){ 75 this._registerInput( element ); 76 } else if ( element && element.length ){ 77 for ( var i = 0; i < element.length; i++ ){ 78 this._registerInput( element[i] ); 79 } 80 } 81 this._toggleSubmit(); 82 }, 83 deRegisterInput : function( element ){ 84 if ( element instanceof Element ){ 85 this._deRegisterInput( element ); 86 } else if ( element && element.length ){ 87 for ( var i = 0; i < element.length; i++ ){ 88 this._deRegisterInput( element[i] ); 89 } 90 } 91 this._toggleSubmit(); 92 }, 93 _registerInput : function( element ){ 94 if ( element.dataset.validator !== undefined ){ return; } 95 var uid = (''+Math.random()).replace(/\D/g,""); 96 element.dataset.validator = uid; 97 if ( element.nodeName == 'INPUT' && element.type != 'checkbox' ) 98 element.addEventListener('input',this._onInputBind); 99 element.addEventListener('change',this._onInputBind); 100 element.addEventListener('focusout',this._onInputBind); 101 element.addEventListener('validator.validate',this._onInputBind); 102 this.inputs[uid] = { 103 element : element, 104 error : '', 105 messageTimeout : null 106 }; 107 this._clearError( this.inputs[uid] );
108 this._validateInput( this.inputs[uid] ); 109 }, 110 _deRegisterInput : function( element ){ 111 var uid = (element instanceof Element) ? element.dataset.validator : element; 112 if ( !uid || !this.inputs.hasOwnProperty(uid) ){ return; } 113 this.inputs[uid].element.removeEventListener('input',this._onInputBind); 114 this.inputs[uid].element.removeEventListener('change',this._onInputBind); 115 this.inputs[uid].element.removeEventListener('focusout',this._onInputBind); 116 this.inputs[uid].element.removeEventListener('validator.validate',this._onInputBind); 117 this._clearError( this.inputs[uid] ); 118 delete this.inputs[uid]; 119 }, 120 121 // form validation 122 // ------------------------------------------------------------------------------ 123 _onSubmit : function(event){ 124 if ( !this.validate() ) { 125 event.preventDefault() 126 event.stopPropagation() 127 } 128 }, 129 reset : function(){ 130 var hasErrors; 131 for ( var key in this.inputs ){ 132 this._clearError( this.inputs[key] ) 133 this._validateInput( this.inputs[key] ); 134 if ( this.inputs[key].error ){ hasErrors = true; } 135 } 136 this._toggleSubmit(); 137 return !hasErrors; 138 }, 139 validate : function(){ 140 var hasErrors; 141 for( var key in this.inputs ){ 142 this._validateInput( this.inputs[key] ); 143 this._showError( this.inputs[key] ); 144 if ( this.inputs[key].error ){ hasErrors = true; } 145 } 146 this._toggleSubmit(); 147 return !hasErrors; 148 }, 149 isValid : function(){ 150 var isValid = true; 151 for( var key in this.inputs ){ 152 if ( this.inputs[key].error ){ 153 isValid = false; 154 break; 155 } 156 } 157 return isValid; 158 }, 159 _toggleSubmit : function(){ 160 if ( this.isValid() ){ 161 for ( var i = 0; i < this.submitButtons.length; i++ ){ 162 this.submitButtons[i].classList.remove('disabled'); 163 //this.submitButtons[i].removeAttribute('disabled'); 164 } 165 } else { 166 for ( var i = 0; i < this.submitButtons.length; i++ ){ 167 this.submitButtons[i].classList.add('disabled'); 168 //this.submitButtons[i].setAttribute('disabled',true); 169 } 170 } 171 }, 172 173 // input validation 174 // ------------------------------------------------------------------------------ 175 _onInput : function( event ){ 176 if ( event.target.dataset.validator == undefined || !this.inputs.hasOwnProperty(event.target.dataset.validator) ){ 177 return; 178 } 179 var input = this.inputs[event.target.dataset.validator]; 180 this._validateInput( input ); 181 if ( this._delay ){ 182 input.messageTimeout = setTimeout(function(){ 183 this.input.messageTimeout = null; 184 this.self._showError( this.input ); 185 }.bind({self: this, input: input}), this._delay) 186 } else { 187 this._showError( input ); 188 } 189 this._toggleSubmit(); 190 }, 191 validateInput : function( element ){ 192 if ( element.dataset.validator != undefined && this.inputs.hasOwnProperty(element.dataset.validator) ){ 193 return this._validateInput( this.inputs[element.dataset.validator] ); 194 this._toggleSubmit(); 195 } 196 return true; 197 }, 198 _validateInput : function( input ){ 199 if ( input.messageTimeout ){ 200 clearTimeout( input.messageTimeout ); 201 input.messageTimeout = null; 202 } 203 var error = ''; 204 for ( var key in this._validators ){ 205 if ( key == 'native' || input.element.dataset[key] != undefined ){ 206 error = this._validators[key](input.element); 207 if ( error ){ break; } 208 } 209 } 210 211 input.error = error; 212 213 return !error; 214 }, 215 _showError : function( input ){ 216 var group = input.element.closest('.form-group'); 217 var feedback = group? group.querySelector('.feedback') : input.element.parentNode.querySelector('.feedback'); 218 219 if ( input.error ){ 220 if ( this._showValidFeedback ){ 221 input.element.classList.remove( 'is-valid' ); 222 if ( group ){ group.classList.remove( 'is-valid' ); } 223 if ( feedback ){ feedback.classList.remove( 'valid-feedback' ); } 224 } 225 input.element.classList.add( 'is-invalid' ); 226 if ( group ){ group.classList.add( 'is-invalid' ); }
227 if ( feedback ){ feedback.classList.add( 'invalid-feedback' ); } 228 } else { 229 if ( this._showValidFeedback ){ 230 input.element.classList.add( 'is-valid' ); 231 if ( group ){ group.classList.add( 'is-valid' ); } 232 if ( feedback ){ feedback.classList.add( 'valid-feedback' ); } 233 } 234 input.element.classList.remove( 'is-invalid' ); 235 if ( group ){ group.classList.remove( 'is-invalid' ); } 236 if ( feedback ){ feedback.classList.remove( 'invalid-feedback' ); } 237 } 238 239 if ( feedback ){ 240 feedback.innerHTML = input.error; 241 } 242 }, 243 _clearError : function( input ){ 244 if ( input.messageTimeout ){ 245 clearTimeout( input.messageTimeout ); 246 input.messageTimeout = null; 247 } 248 input.error = ''; 249 var group = input.element.closest('.form-group'); 250 var feedback = group? group.querySelector('.feedback') : input.element.parentNode.querySelector('.feedback'); 251 input.element.classList.remove('is-invalid'); 252 input.element.classList.remove('is-valid'); 253 if ( group ){ 254 group.classList.remove('is-valid'); 255 group.classList.remove('is-invalid'); 256 } 257 if ( feedback ){ 258 feedback.classList.remove('invalid-feedback'); 259 feedback.innerHTML = ''; 260 } 261 }, 262 263 _checkNative : function( element ){ 264 if ( !element.checkValidity() && !element.validity.valid ){ 265 if ( element.validity.valueMissing ) { 266 return this.getErrorMessage(element,'requiredError'); 267 } else if ( element.validity.typeMismatch ){ 268 return this.getErrorMessage(element,'typeError'); 269 } else if ( element.validity.patternMismatch ) { 270 return this.getErrorMessage(element,'patternError'); 271 } else if ( element.validity.tooShort ){ 272 return this.getErrorMessage(element,'minlengthError'); 273 } else if ( element.validity.tooLong ){ 274 return this.getErrorMessage(element,'maxlengthError'); 275 } else if ( element.validity.stepMismatch ){ 276 return this.getErrorMessage(element,'stepError'); 277 } else if ( element.validity.rangeUnderflow ){ 278 return this.getErrorMessage(element,'minError'); 279 } else if ( element.validity.rangeOverflow ){ 280 return this.getErrorMessage(element,'maxError'); 281 } else { 282 return this.getErrorMessage(element,'error'); 283 } 284 } 285 var minlength = element.getAttribute('minlength'); 286 if ( minlength ){ 287 minlength = parseInt(minlength); 288 if ( minlength > element.value.length ){ 289 return this.getErrorMessage(element,'minlengthError'); 290 } 291 } 292 var maxlength = element.getAttribute('maxlength'); 293 if ( maxlength ){ 294 maxlength = parseInt(maxlength); 295 if ( maxlength < element.value.length ){ 296 return this.getErrorMessage(element,'maxlengthError'); 297 } 298 } 299 return ''; 300 }, 301 getErrorMessage : function( element, error ){ 302 if ( !error ){ 303 return ''; 304 } 305 if ( element.dataset[error] ){ 306 return element.dataset[error]; 307 } 308 if ( element.dataset['error'] ){ 309 return element.dataset['error']; 310 } 311 if (element.validationMessage) { 312 return element.validationMessage; 313 } 314 return 'error'; 315 }, 316});
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.