1/* 2 * jquery.form-validation-and-hints.js 3 * 2009, icograma.com 4 * Licensed under GPL license (http://www.opensource.org/licenses/gpl-license.php). 5 * @version 0.201 6 * 7 * DEMO: http://www.icograma.com/form-validation-and-hints/ 8 * 9 */ 10 11 12/* --- TO SET --- */ 13// Prefix used to hook CSS classes to the script 14classprefix = 'verify'; // <input class="verifyInteger" type="text" name="mail" /> 15 16// Set your validation rules 17function isTypeValidExt( classprefix, type, value ) { 18 /* RULE EXAMPLE (Accept only integer values) 19 if( type == classprefix + 'Integer' ) { 20 return ( ( value.match(/^[\d|,|\.|\s]*$/) ) && ( value != '' ) ); 21 } 22 */ 23 return true; 24} 25 26 27 28 29 30 31var annoy=true; 32function debug(msg){if(annoy){annoy=confirm(msg);};} 33 34/* --- DOCUMEN READY --- */ 35$(document).ready(function(){ 36 mustCheck = true; 37 38 $("."+classprefix+"Cancel").click(function(event){ 39 mustCheck = false; 40 }); 41 42 // HINTS: Add *title hints to form elements 43 for( var i=0; i < document.forms.length; i++) { 44 var fe = document.forms[i].elements; 45 for ( var j=0; j < fe.length; j++ ) { 46 if( (fe[j]).title.indexOf("**")==0 ) { 47 if( (fe[j]).value == "" || (fe[j]).value == titleHint ) { 48 var titleHint = (fe[j]).title.substring(2); 49 (fe[j]).value = titleHint; 50 } 51 } else if( ( (fe[j]).type == "text" || (fe[j]).type == "password" || (fe[j]).tagName == 'TEXTAREA' ) && (fe[j]).title.indexOf("*")==0 ) { 52 addHint( (fe[j]) ); 53 $(fe[j]).blur(function(event){ addHint(this); }); 54 $(fe[j]).focus(function(event){ removeHint(this); }); 55 } 56 } 57 } 58 59 // VALIDATION: 60 $("FORM").submit(function(event){ 61 if(mustCheck) { 62 // Prevent submit if validation fails 63 if( !checkForm(this) ) { 64 var $alert = $('#alert'); 65 var alerttimer = window.setTimeout(function () { 66 $alert.trigger('click'); 67 }, 4000); 68 $alert.animate({height: $alert.css('line-height') || '50px'}, 300) 69 .click(function () { 70 window.clearTimeout(alerttimer); 71 $alert.animate({height: '0'}, 300); 72 }); 73 $('#showMsg').show(); 74 event.preventDefault(); 75 }; 76 } else { 77 mustCheck = !mustCheck; 78 } 79 }); 80}); // end jQuery $(document).ready 81 82 83 84/* --- FUNCTIONS --- */ 85function addHint(field) { 86 var titleHint = field.title.substring(1); 87 if( field.value == "" || field.value == titleHint ) { 88 //in "password" inputs, set to "text" to show hint, preserve type in class attribute 89 if( field.type == "password" ) { 90 $( field ).addClass("password"); 91 var newObject = changeInputType( field, "text" )//returns false for non-ie 92 if(document.all){ // if IE 93 field = newObject; 94 } 95 } //end type == "password" 96 $(field).addClass("hint"); 97 field.value = titleHint; 98 } //end value=="" 99} //end addHint 100 101 102function removeHint(field) { //only on INPUT.text items 103 /*if( field.type == "text" && field.title.indexOf("*")==0 ) {*/ 104 var titleHint = field.title.substring(1); 105 if( field.value == "" || field.value == titleHint ) { 106 $(field).removeClass('hint'); 107 field.value=""; 108 //re-set password type if appropiate 109 if($(field).hasClass("password")) { 110 var newObject = changeInputType( field, "password" ); //returns false for non-ie 111 if(newObject) { ///IE, element was replaced: reset focus 112 $(newObject).focus(); 113 $(newObject).select(); 114 } 115 }//end hasClass("password") 116 }//end value == titleHint 117 //}//end what.title 118}//end rmhint 119 120 121function changeInputType(oldObject, oType) { 122//based on http://arjansnaterse.nl/changing-type-attribute-in-ie 123//used to simulate change of INPUT type in IE 124 if(!document.all){ 125 oldObject.type = oType; 126 return false; 127 }else{ 128 //ie can't change INPUT's type, must create new element 129 /* 130 newObject = $(oldObject).clone(true); 131 //newObject.type = oType; 132 $(newObject).attr('type'); 133 $(newObject).insertBefore(oldObject); 134 debug(newObject); 135 return newObject; 136 */ 137 var newObject = document.createElement('input'); 138 newObject.type = oType; 139 if(oldObject.size) newObject.size = oldObject.size; 140 if(oldObject.title) newObject.title = oldObject.title; 141 if(oldObject.value) newObject.value = oldObject.value; 142 if(oldObject.name) newObject.name = oldObject.name; 143 if(oldObject.id) newObject.id = oldObject.id; 144 if(oldObject.className) newObject.className = oldObject.className; 145 oldObject.parentNode.replaceChild(newObject,oldObject); 146 //live() 147 //newObject.blur = oldObject.blur; 148 //newObject.focus = oldObject.focus; 149 //$(newObject).blur(function(event){ addHint(this); }); 150 //$(newObject).focus(function(event){ removeHint(this); }); 151 return newObject; 152 }//end document.all 153} 154 155function checkForm(form) { 156 var send = true; 157 var password = ''; 158 radioGroups = Array(); 159 160 $( form ).removeClass ( "haserrors" ); 161 162 //inputs = $(form).find('INPUT[class*="' + classprefix + '"]'); 163 inputs = $(form).find('INPUT[class*="' + classprefix + '"], .required INPUT, .required TEXTAREA, .required SELECT'); 164 165 $.each(inputs, function(i, val) { 166 input = $(val); 167 if( input.attr('offsetWidth') != 0 ) { 168 169 switch(input.attr('type')) { 170 171 case 'select-one': 172 if( input.get(0)[ input.attr('selectedIndex') ].value == '') { 173 if( send ) moveTo(input); 174 showErrorOn( input ); 175 send = false;
176 } 177 break; 178 179 case 'select-multiple': 180 if( input.get(0)[ input.attr('selectedIndex') ].value == '') { 181 if( send ) moveTo(input); 182 showErrorOn( input ); 183 send = false; 184 } 185 break; 186 187 case 'radio': 188 if( window.radioGroups[ input.attr('name') ] === undefined ) radioGroups[input.attr('name')] = new Array(); 189 radioGroups[input.attr('name')][ radioGroups[ input.attr('name') ].length ] = input; 190 break; 191 192 case 'checkbox': 193 if( !input.attr('checked') ) { 194 if( send ) moveTo(input); 195 showErrorOn( input ); 196 send = false; 197 } 198 break; 199 200 case 'file': 201 if( !isFilled(input) ) { 202 if( send ) moveTo(input); 203 showErrorOn( input ); 204 send = false; 205 } 206 break; 207 208 case 'password': 209 if( input.hasClass( classprefix + 'PasswordConfirm' ) ) { 210 if( input.val() != password ) { 211 if( send ) moveTo(input); 212 showErrorOn( input ); 213 send = false; 214 } 215 break; 216 } else { 217 password = input.val(); 218 } 219 220 case 'textarea': 221 case 'text': 222 if( ( isFilled(input) || isRequired(input) ) && ( !isValid(input) ) ) { 223 if( send ) moveTo(input); 224 showErrorOn( input ); 225 send = false; 226 } 227 break; 228 229 default: 230 break; 231 } 232 } 233 }); 234 for ( var i in radioGroups ) { 235 for ( var j in radioGroups[i] ) { 236 if( radioGroups[i][j].attr('checked') ) { 237 break; 238 } 239 } 240 if( !radioGroups[i][j].attr('checked') ) { 241 for ( var j in radioGroups[i] ) { 242 if( send ) moveTo( radioGroups[i][j] ); 243 showErrorOn( radioGroups[i][j] ); 244 } 245 send = false; 246 } 247 } 248 return send; 249} 250 251function isRequired(input) { 252 return input.parents( ".required" ).length != 0; 253} 254 255function isFilled(input) { 256 hintText = ''; 257 //clear HINTs before validation 258 if( input.attr('title').indexOf("**")==0) { 259 var hintText = input.attr('title').substring(2); 260 } else if( input.attr('title').indexOf("*")==0) { 261 var hintText = input.attr('title').substring(1); 262 }//end clear hints 263 return input.val() != hintText && input.val() != '' ; 264} 265 266function isValid( input ) { 267 if( !isFilled(input) ) return false; 268 string = input.attr('class'); 269 value = input.val(); 270 value = $.trim(value); 271 start = string.indexOf(classprefix); 272 type = ''; 273 result = true; 274 while(result) { 275 if( 276 start == -1 || 277 string.charAt( (start+classprefix.length) ) == ' ' || 278 string.charAt( (start+classprefix.length) ) != string.charAt( (start+classprefix.length) ).toUpperCase() 279 ) { 280 break; 281 } else { 282 for( i=start; i < string.length; i++ ) { 283 if(string.charAt(i) == ' ') { 284 break; 285 } 286 type += string.charAt(i); 287 } 288 if( !isTypeValid( type, value ) ) { 289 result = false;
290 break; 291 } 292 start = string.indexOf(classprefix,start+1); 293 } 294 } 295 return result; 296} 297 298function isTypeValid( type, value ) { 299 300 if( type == classprefix + 'Text' ) { 301 return true; 302 } 303 304 if( type == classprefix + 'Integer' ) { 305 return ( ( value.match(/^[\d|,|\.|\s]*$/) ) && ( value != '' ) ); 306 } 307 308 if( type == classprefix + 'Contact' ) { 309 return ( ( value.match(/^((\+)?(\d{5,12}){1})?((\+)?(\d{2,4}[-]))?(\d{5,12}){1}?$/) ) && ( value != '' ) ); 310 } 311 312 if( type == classprefix + 'Url' ) { 313 return ( value.match( /^(https?:\/\/)?(([0-9a-z_!~*'().&=+$%-]+: )?[0-9a-z_!~*'().&=+$%-]+@)?(([0-9]{1,3}\.){3}[0-9]{1,3}|([0-9a-z_!~*'()-]+\.)*([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\.[a-z]{2,6})(:[0-9]{1,4})?((\/?)|(\/[0-9a-z_!~*'().;?:@&=+$,%#-]+)+\/?)$/ ) ); 314 } 315 316 if( type == classprefix + 'MultipleWords' ) { 317 return value.match(/^.*[^^]\s[^$].*$/); 318 } 319 320 if( type == classprefix + 'Mail' ) { 321 if( value.indexOf("@example.com")>-1){return false;}; 322 //var emailFilter=/^.+@.+\..{2,}$/; 323 var emailFilter=/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/; 324 var illegalChars= /[\(\)\<\>\,\;\:\\\/\"\[\]]/ 325 if(!(emailFilter.test(value))||value.match(illegalChars)){return(false);}else{return (true);} 326 return false; 327 } 328 329 if(typeof isTypeValidExt == 'function') { 330 fr = isTypeValidExt( classprefix, type, value ); 331 if( isTypeValidExt( classprefix, type, value ) === null ) { 332 return false; 333 } else { 334 return true; 335 } 336 } 337 return true; 338} 339 340function moveTo( input ) { 341 var targetOffset = input.offset().top - 40; 342 $('html,body').animate({scrollTop: targetOffset}, 200 ); 343 input.get(0).focus(); 344} 345 346function showErrorOn( input ) { 347/* BUG FIXED FOR IE: when submited it auto focuses to the first required field, so the hint and red box aren't there. Might be confusing to a user! 348 349 input.bind('focus.rmErrorClass', function(){ 350 rmErrorClass( this ); 351 }); 352*/ 353 input.bind('mousedown.rmErrorClass', function(){ 354 rmErrorClass( this ); 355 }); 356 input.bind('keydown.rmErrorClass', function(){ 357 rmErrorClass( this ); 358 }); 359 input.addClass( "error" ); 360 input.parents( ".required, .field" ).addClass( "error" ); 361} 362 363function rmErrorClass( elm ) { 364 var etag=$(elm).parents(".error"); 365 var eform = $(elm).parents( 'FORM' ); 366 $(elm).removeClass("error"); 367 $(elm).unbind('.rmErrorClass'); //no further clicks will trigger rmErrorClass(); 368 if(etag){ $(etag).removeClass( "error" ); }; 369}
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.