1/* jqBootstrapValidation 2 * A plugin for automating validation on Twitter Bootstrap formatted forms. 3 * 4 * v1.3.6 5 * 6 * License: MIT <http://opensource.org/licenses/mit-license.php> - see LICENSE file 7 * 8 * http://ReactiveRaven.github.com/jqBootstrapValidation/ 9 */ 10 11(function( $ ){ 12 13 var createdElements = []; 14 15 var defaults = { 16 options: { 17 prependExistingHelpBlock: false, 18 sniffHtml: true, // sniff for 'required', 'maxlength', etc 19 preventSubmit: true, // stop the form submit event from firing if validation fails 20 submitError: false, // function called if there is an error when trying to submit 21 submitSuccess: false, // function called just before a successful submit event is sent to the server 22 semanticallyStrict: false, // set to true to tidy up generated HTML output 23 autoAdd: { 24 helpBlocks: true 25 }, 26 filter: function () { 27 // return $(this).is(":visible"); // only validate elements you can see 28 return true; // validate everything 29 } 30 }, 31 methods: { 32 init : function( options ) { 33 34 var settings = $.extend(true, {}, defaults); 35 36 settings.options = $.extend(true, settings.options, options); 37 38 var $siblingElements = this; 39 40 var uniqueForms = $.unique( 41 $siblingElements.map( function () { 42 return $(this).parents("form")[0]; 43 }).toArray() 44 ); 45 46 $(uniqueForms).bind("submit", function (e) { 47 var $form = $(this); 48 var warningsFound = 0; 49 var $inputs = $form.find("input,textarea,select").not("[type=submit],[type=image]").filter(settings.options.filter); 50 $inputs.trigger("submit.validation").trigger("validationLostFocus.validation"); 51 52 $inputs.each(function (i, el) { 53 var $this = $(el), 54 $controlGroup = $this.parents(".control-group").first(); 55 if ( 56 $controlGroup.hasClass("warning") 57 ) { 58 $controlGroup.removeClass("warning").addClass("error"); 59 warningsFound++; 60 } 61 }); 62 63 $inputs.trigger("validationLostFocus.validation"); 64 65 if (warningsFound) { 66 if (settings.options.preventSubmit) { 67 e.preventDefault(); 68 } 69 $form.addClass("error"); 70 if ($.isFunction(settings.options.submitError)) { 71 settings.options.submitError($form, e, $inputs.jqBootstrapValidation("collectErrors", true)); 72 } 73 } else { 74 $form.removeClass("error"); 75 if ($.isFunction(settings.options.submitSuccess)) { 76 settings.options.submitSuccess($form, e); 77 } 78 } 79 }); 80 81 return this.each(function(){ 82 83 // Get references to everything we're interested in 84 var $this = $(this), 85 $controlGroup = $this.parents(".control-group").first(), 86 $helpBlock = $controlGroup.find(".help-block").first(), 87 $inputBlock = $controlGroup.find(".form-control").first(), 88 $validationBlock = $controlGroup.find(".inline-validation"), 89 $validatedBlock = $controlGroup.find(".validation").first(), 90 $form = $this.parents("form").first(), 91 first = true, 92 validatorNames = []; 93 94 // create message container if not exists 95 if (!$helpBlock.length && settings.options.autoAdd && settings.options.autoAdd.helpBlocks) { 96 $helpBlock = $('<div class="help-block" />'); 97 $controlGroup.find('.controls').append($helpBlock); 98 createdElements.push($helpBlock[0]); 99 } 100 101 // ============================================================= 102 // SNIFF HTML FOR VALIDATORS 103 // ============================================================= 104 105 // *snort sniff snuffle* 106 107 if (settings.options.sniffHtml) { 108 var message = ""; 109 // --------------------------------------------------------- 110 // PATTERN 111 // --------------------------------------------------------- 112 // if ($this.attr("pattern") !== undefined) { 113 // message = "Not in the expected format<!-- data-validation-pattern-message to override -->"; 114 // if ($this.data("validationPatternMessage")) { 115 // message = $this.data("validationPatternMessage"); 116 // } 117 // $this.data("validationPatternMessage", message); 118 // $this.data("validationPatternRegex", $this.attr("pattern")); 119 // } 120 // --------------------------------------------------------- 121 // MAX 122 // --------------------------------------------------------- 123 if ($this.attr("max") !== undefined || $this.attr("aria-valuemax") !== undefined) { 124 var max = ($this.attr("max") !== undefined ? $this.attr("max") : $this.attr("aria-valuemax")); 125 message = "Too high: Maximum of '" + max + "'<!-- data-validation-max-message to override -->"; 126 if ($this.data("validationMaxMessage")) { 127 message = $this.data("validationMaxMessage"); 128 } 129 $this.data("validationMaxMessage", message); 130 $this.data("validationMaxMax", max); 131 } 132 // --------------------------------------------------------- 133 // MIN 134 // --------------------------------------------------------- 135 if ($this.attr("min") !== undefined || $this.attr("aria-valuemin") !== undefined) { 136 var min = ($this.attr("min") !== undefined ? $this.attr("min") : $this.attr("aria-valuemin")); 137 message = "Too low: Minimum of '" + min + "'<!-- data-validation-min-message to override -->"; 138 if ($this.data("validationMinMessage")) { 139 message = $this.data("validationMinMessage"); 140 } 141 $this.data("validationMinMessage", message); 142 $this.data("validationMinMin", min); 143 } 144 // --------------------------------------------------------- 145 // MAXLENGTH 146 // --------------------------------------------------------- 147 if ($this.attr("maxlength") !== undefined) { 148 message = "Too long: Maximum of '" + $this.attr("maxlength") + "' characters<!-- data-validation-maxlength-message to override -->"; 149 if ($this.data("validationMaxlengthMessage")) { 150 message = $this.data("validationMaxlengthMessage"); 151 } 152 $this.data("validationMaxlengthMessage", message); 153 $this.data("validationMaxlengthMaxlength", $this.attr("maxlength")); 154 } 155 // --------------------------------------------------------- 156 // MINLENGTH 157 // --------------------------------------------------------- 158 if ($this.attr("minlength") !== undefined) { 159 message = "Too short: Minimum of '" + $this.attr("minlength") + "' characters<!-- data-validation-minlength-message to override -->"; 160 if ($this.data("validationMinlengthMessage")) { 161 message = $this.data("validationMinlengthMessage"); 162 } 163 $this.data("validationMinlengthMessage", message); 164 $this.data("validationMinlengthMinlength", $this.attr("minlength")); 165 } 166 // --------------------------------------------------------- 167 // REQUIRED 168 // --------------------------------------------------------- 169 if ($this.attr("required") !== undefined || $this.attr("aria-required") !== undefined) { 170 message = settings.builtInValidators.required.message; 171 if ($this.data("validationRequiredMessage")) { 172 message = $this.data("validationRequiredMessage"); 173 } 174 $this.data("validationRequiredMessage", message); 175 } 176 // --------------------------------------------------------- 177 // NUMBER 178 // --------------------------------------------------------- 179 if ($this.attr("type") !== undefined && $this.attr("type").toLowerCase() === "number") { 180 message = settings.builtInValidators.number.message; 181 if ($this.data("validationNumberMessage")) { 182 message = $this.data("validationNumberMessage"); 183 } 184 $this.data("validationNumberMessage", message); 185 } 186 // --------------------------------------------------------- 187 // EMAIL 188 // --------------------------------------------------------- 189 if ($this.attr("type") !== undefined && $this.attr("type").toLowerCase() === "email") { 190 message = "Not a valid email address<!-- data-validator-validemail-message to override -->"; 191 if ($this.data("validationValidemailMessage")) { 192 message = $this.data("validationValidemailMessage"); 193 } else if ($this.data("validationEmailMessage")) { 194 message = $this.data("validationEmailMessage"); 195 } 196 $this.data("validationValidemailMessage", message); 197 } 198 // --------------------------------------------------------- 199 // PHONE 200 // --------------------------------------------------------- 201 if ($this.attr("type") !== undefined && $this.attr("type").toLowerCase() === "phone") { 202 message = "Not a valid phone number"; 203 if ($this.data("validationPhoneMessage")) { 204 message = $this.data("validationPhoneMessage"); 205 } 206 $this.data("validationPhoneMessage", message); 207 } 208 // --------------------------------------------------------- 209 // POSTAL 210 // --------------------------------------------------------- 211 // if ($this.attr("type") !== undefined && $this.attr("type").toLowerCase() === "postal") { 212 // message = "Not a valid postal code"; 213 // if ($this.data("validationPostalMessage")) { 214 // message = $this.data("validationPostalMessage"); 215 // } 216 // $this.data("validationPostalMessage", message); 217 // } 218 // --------------------------------------------------------- 219 // MINCHECKED 220 // --------------------------------------------------------- 221 if ($this.attr("minchecked") !== undefined) { 222 message = "Not enough options checked; Minimum of '" + $this.attr("minchecked") + "' required<!-- data-validation-minchecked-message to override -->"; 223 if ($this.data("validationMincheckedMessage")) { 224 message = $this.data("validationMincheckedMessage"); 225 } 226 $this.data("validationMincheckedMessage", message); 227 $this.data("validationMincheckedMinchecked", $this.attr("minchecked")); 228 } 229 // --------------------------------------------------------- 230 // MAXCHECKED 231 // --------------------------------------------------------- 232 if ($this.attr("maxchecked") !== undefined) { 233 message = "Too many options checked; Maximum of '" + $this.attr("maxchecked") + "' required<!-- data-validation-maxchecked-message to override -->";
234 if ($this.data("validationMaxcheckedMessage")) { 235 message = $this.data("validationMaxcheckedMessage"); 236 } 237 $this.data("validationMaxcheckedMessage", message); 238 $this.data("validationMaxcheckedMaxchecked", $this.attr("maxchecked")); 239 } 240 } 241 242 // ============================================================= 243 // COLLECT VALIDATOR NAMES 244 // ============================================================= 245 246 // Get named validators 247 if ($this.data("validation") !== undefined) { 248 validatorNames = $this.data("validation").split(","); 249 } 250 251 // Get extra ones defined on the element's data attributes 252 $.each($this.data(), function (i, el) { 253 var parts = i.replace(/([A-Z])/g, ",$1").split(","); 254 if (parts[0] === "validation" && parts[1]) { 255 validatorNames.push(parts[1]); 256 } 257 }); 258 259 // ============================================================= 260 // NORMALISE VALIDATOR NAMES 261 // ============================================================= 262 263 var validatorNamesToInspect = validatorNames; 264 var newValidatorNamesToInspect = []; 265 266 do // repeatedly expand 'shortcut' validators into their real validators 267 { 268 // Uppercase only the first letter of each name 269 $.each(validatorNames, function (i, el) { 270 validatorNames[i] = formatValidatorName(el); 271 }); 272 273 // Remove duplicate validator names 274 validatorNames = $.unique(validatorNames); 275 276 // Pull out the new validator names from each shortcut 277 newValidatorNamesToInspect = []; 278 $.each(validatorNamesToInspect, function(i, el) { 279 if ($this.data("validation" + el + "Shortcut") !== undefined) { 280 // Are these custom validators? 281 // Pull them out! 282 $.each($this.data("validation" + el + "Shortcut").split(","), function(i2, el2) { 283 newValidatorNamesToInspect.push(el2); 284 }); 285 } else if (settings.builtInValidators[el.toLowerCase()]) { 286 // Is this a recognised built-in? 287 // Pull it out! 288 var validator = settings.builtInValidators[el.toLowerCase()]; 289 if (validator.type.toLowerCase() === "shortcut") { 290 $.each(validator.shortcut.split(","), function (i, el) { 291 el = formatValidatorName(el); 292 newValidatorNamesToInspect.push(el); 293 validatorNames.push(el); 294 }); 295 } 296 } 297 }); 298 299 validatorNamesToInspect = newValidatorNamesToInspect; 300 301 } while (validatorNamesToInspect.length > 0) 302 303 // ============================================================= 304 // SET UP VALIDATOR ARRAYS 305 // ============================================================= 306 307 var validators = {}; 308 309 $.each(validatorNames, function (i, el) { 310 // Set up the 'override' message 311 var message = $this.data("validation" + el + "Message"); 312 var hasOverrideMessage = (message !== undefined); 313 var foundValidator = false; 314 message = 315 ( 316 message 317 ? message 318 : "'" + el + "' validation failed <!-- Add attribute 'data-validation-" + el.toLowerCase() + "-message' to input to change this message -->" 319 ) 320 ; 321 322 $.each( 323 settings.validatorTypes, 324 function (validatorType, validatorTemplate) { 325 if (validators[validatorType] === undefined) { 326 validators[validatorType] = []; 327 } 328 if (!foundValidator && $this.data("validation" + el + formatValidatorName(validatorTemplate.name)) !== undefined) { 329 validators[validatorType].push( 330 $.extend( 331 true, 332 { 333 name: formatValidatorName(validatorTemplate.name), 334 message: message 335 }, 336 validatorTemplate.init($this, el) 337 ) 338 ); 339 foundValidator = true; 340 } 341 } 342 ); 343 344 if (!foundValidator && settings.builtInValidators[el.toLowerCase()]) { 345
346 var validator = $.extend(true, {}, settings.builtInValidators[el.toLowerCase()]); 347 if (hasOverrideMessage) { 348 validator.message = message; 349 } 350 var validatorType = validator.type.toLowerCase(); 351 352 if (validatorType === "shortcut") { 353 foundValidator = true; 354 } else { 355 $.each( 356 settings.validatorTypes, 357 function (validatorTemplateType, validatorTemplate) { 358 if (validators[validatorTemplateType] === undefined) { 359 validators[validatorTemplateType] = []; 360 } 361 if (!foundValidator && validatorType === validatorTemplateType.toLowerCase()) { 362 $this.data("validation" + el + formatValidatorName(validatorTemplate.name), validator[validatorTemplate.name.toLowerCase()]); 363 validators[validatorType].push( 364 $.extend( 365 validator, 366 validatorTemplate.init($this, el) 367 ) 368 ); 369 foundValidator = true; 370 } 371 } 372 ); 373 } 374 } 375 376 if (! foundValidator) { 377 $.error("Cannot find validation info for '" + el + "'"); 378 } 379 }); 380 381 // ============================================================= 382 // STORE FALLBACK VALUES 383 // ============================================================= 384 385 $helpBlock.data( 386 "original-contents", 387 ( 388 $helpBlock.data("original-contents") 389 ? $helpBlock.data("original-contents") 390 : $helpBlock.html() 391 ) 392 ); 393 394 $helpBlock.data( 395 "original-role", 396 ( 397 $helpBlock.data("original-role") 398 ? $helpBlock.data("original-role") 399 : $helpBlock.attr("role") 400 ) 401 ); 402 403 $controlGroup.data( 404 "original-classes", 405 ( 406 $controlGroup.data("original-clases") 407 ? $controlGroup.data("original-classes") 408 : $controlGroup.attr("class") 409 ) 410 ); 411 412 $this.data( 413 "original-aria-invalid", 414 ( 415 $this.data("original-aria-invalid") 416 ? $this.data("original-aria-invalid") 417 : $this.attr("aria-invalid") 418 ) 419 ); 420 421 // ============================================================= 422 // VALIDATION 423 // ============================================================= 424 425 $this.bind( 426 "validation.validation", 427 function (event, params) { 428 429 var value = getValue($this); 430 431 // Get a list of the errors to apply 432 var errorsFound = []; 433 var a=true; 434 435 436 437 $.each(validators, function (validatorType, validatorTypeArray) { 438 439 if (value || value.length || (params && params.includeEmpty) || (!!settings.validatorTypes[validatorType].blockSubmit && params && !!params.submitting)) { 440 $.each(validatorTypeArray, function (i, validator) { 441 442 // if (validatorType == "match"){ 443 // setTimeout(function(){ 444 // if (settings.validatorTypes[validatorType].validate($this, value, validator)) { 445 // errorsFound.push(validator.message); 446 // console.log("a"+errorsFound); 447 // a=false; 448 // return false; 449 // } 450 // }, 1000); 451 // }else{ 452 if (settings.validatorTypes[validatorType].validate($this, value, validator)) { 453 errorsFound.push(validator.message); 454 } 455 // } 456 } 457 ); 458 // return a; 459 } 460 }); 461 462 // console.log("e"+errorsFound); 463 464 return errorsFound; 465 466 } 467 ); 468 469 $this.bind( 470 "getValidators.validation", 471 function () { 472 return validators; 473 } 474 ); 475 476 // ============================================================= 477 // WATCH FOR CHANGES 478 // ============================================================= 479 $this.bind( 480 "submit.validation", 481 function () { 482 first= false;
483 return $this.triggerHandler("change.validation", {submitting: true}); 484 } 485 ); 486 487 $this.bind( 488 [ 489 "keyup", 490 "focus", 491 "blur", 492 "click", 493 "keydown", 494 "keypress", 495 "change" 496 ].join(".validation ") + ".validation", 497 function (e, params) { 498 499 var value = getValue($this); 500 501 var errorsFound = []; 502 503 $controlGroup.find("input,textarea,select").each(function (i, el) { 504 505 var oldCount = errorsFound.length; 506 $.each($(el).triggerHandler("validation.validation", params), function (j, message) { 507 errorsFound.push(message); 508 }); 509 if (errorsFound.length > oldCount) { 510 $(el).attr("aria-invalid", "true"); 511 } else { 512 var original = $this.data("original-aria-invalid"); 513 $(el).attr("aria-invalid", (original !== undefined ? original : false)); 514 } 515 }); 516 517 $form.find("input,select,textarea").not($this).not("[name=\"" + $this.attr("name") + "\"]").trigger("validationLostFocus.validation"); 518 519 errorsFound = $.unique(errorsFound.sort()); 520 521 valid = true; 522 523 524 if (!first){ 525 526 // Were there any errors? 527 if (errorsFound.length) { 528 // Better flag it up as a warning. 529 $controlGroup.removeClass("success error").addClass("warning"); 530 531 // How many errors did we find? 532 if (settings.options.semanticallyStrict && errorsFound.length === 1) { 533 // Only one? Being strict? Just output it. 534 $helpBlock.html(errorsFound[0] + 535 ( settings.options.prependExistingHelpBlock ? $helpBlock.data("original-contents") : "" )); 536 537 addError($validationBlock); 538 valid = false; 539 540 } else { 541 // Multiple? Being sloppy? Glue them together into an UL. 542 $helpBlock.html("<ul role=\"alert\" style=\"list-style-type:none; padding:0;\"><li>" + errorsFound.join("</li><li>") + "</li></ul>" + 543 ( settings.options.prependExistingHelpBlock ? $helpBlock.data("original-contents") : "" )); 544 545 addError($validationBlock); 546 valid = false; 547 548 } 549 } else { 550 551 valid=true; 552 addSuccess($validationBlock); 553 if (!$inputBlock.val()){ 554 resetValidation($validationBlock); 555 valid=false; 556 } 557 558 $controlGroup.removeClass("warning error success"); 559 if (value.length > 0) { 560 $controlGroup.addClass("success"); 561 } 562 $helpBlock.html($helpBlock.data("original-contents")); 563 } 564 } else if(!$inputBlock.val() || errorsFound.length){ 565 566 valid=false; 567 568 } 569 570 if (e.type === "blur") { 571 first=false; 572 if (valid){ 573 addSuccess($validationBlock); 574 } else { 575 $i = $validatedBlock.val(); 576 $req = $validatedBlock.attr("required"); 577 if (errorsFound.length || $i == ""){ 578 if($i=="" && $req){ 579 $helpBlock.html("<ul role=\"alert\" style=\"list-style-type:none; padding:0;\"><li>This field is required</li> </ul>" + 580 ( settings.options.prependExistingHelpBlock ? $helpBlock.data("original-contents") : "" )); 581 addError($validationBlock); 582 } else if(errorsFound.length){ 583 $helpBlock.html("<ul role=\"alert\" style=\"list-style-type:none; padding:0;\"><li>" + errorsFound.join("</li><li>") + "</li></ul>" + 584 ( settings.options.prependExistingHelpBlock ? $helpBlock.data("original-contents") : "" )); 585 addError($validationBlock); 586 } 587 } 588 } 589 590 $controlGroup.removeClass("success"); 591 } 592 } 593 ); 594 $this.bind("validationLostFocus.validation", function () { 595 $controlGroup.removeClass("success"); 596 }); 597 }); 598 }, 599 destroy : function( ) { 600 601 return this.each( 602 function() { 603 604 var 605 $this = $(this), 606 $controlGroup = $this.parents(".control-group").first(), 607 $helpBlock = $controlGroup.find(".help-block").first(); 608 609 // remove our events 610 $this.unbind('.validation'); // events are namespaced. 611 // reset help text 612 $helpBlock.html($helpBlock.data("original-contents")); 613 // reset classes 614 $controlGroup.attr("class", $controlGroup.data("original-classes")); 615 // reset aria 616 $this.attr("aria-invalid", $this.data("original-aria-invalid")); 617 // reset role 618 $helpBlock.attr("role", $this.data("original-role")); 619 // remove all elements we created 620 if (createdElements.indexOf($helpBlock[0]) > -1) { 621 $helpBlock.remove(); 622 } 623 624 } 625 ); 626 627 }, 628 collectErrors : function(includeEmpty) { 629 630 var errorMessages = {}; 631 this.each(function (i, el) { 632 var $el = $(el); 633 var name = $el.attr("name"); 634 var errors = $el.triggerHandler("validation.validation", {includeEmpty: true}); 635 errorMessages[name] = $.extend(true, errors, errorMessages[name]); 636 }); 637 638 $.each(errorMessages, function (i, el) { 639 if (el.length === 0) { 640 delete errorMessages[i]; 641 } 642 }); 643 644 return errorMessages; 645 646 }, 647 hasErrors: function() { 648 649 var errorMessages = []; 650 651 this.each(function (i, el) { 652 errorMessages = errorMessages.concat( 653 $(el).triggerHandler("getValidators.validation") ? $(el).triggerHandler("validation.validation", {submitting: true}) : [] 654 ); 655 }); 656 657 return (errorMessages.length > 0); 658 }, 659 override : function (newDefaults) { 660 defaults = $.extend(true, defaults, newDefaults); 661 } 662 }, 663 validatorTypes: { 664 callback: { 665 name: "callback", 666 init: function ($this, name) { 667 return { 668 validatorName: name, 669 callback: $this.data("validation" + name + "Callback"),
670 lastValue: $this.val(), 671 lastValid: true, 672 lastFinished: true 673 }; 674 }, 675 validate: function ($this, value, validator) { 676 if (validator.lastValue === value && validator.lastFinished) { 677 return !validator.lastValid; 678 } 679 680 if (validator.lastFinished === true) 681 { 682 validator.lastValue = value; 683 validator.lastValid = true; 684 validator.lastFinished = false; 685 686 var rrjqbvValidator = validator; 687 var rrjqbvThis = $this; 688 executeFunctionByName( 689 validator.callback, 690 window, 691 $this, 692 value, 693 function (data) { 694 if (rrjqbvValidator.lastValue === data.value) { 695 rrjqbvValidator.lastValid = data.valid; 696 if (data.message) { 697 rrjqbvValidator.message = data.message; 698 } 699 rrjqbvValidator.lastFinished = true; 700 rrjqbvThis.data("validation" + rrjqbvValidator.validatorName + "Message", rrjqbvValidator.message); 701 // Timeout is set to avoid problems with the events being considered 'already fired' 702 setTimeout(function () { 703 rrjqbvThis.trigger("change.validation"); 704 }, 1); // doesn't need a long timeout, just long enough for the event bubble to burst 705 } 706 } 707 ); 708 } 709 710 return false; 711 712 } 713 }, 714 ajax: { 715 name: "ajax", 716 init: function ($this, name) { 717 return { 718 validatorName: name, 719 url: $this.data("validation" + name + "Ajax"), 720 lastValue: $this.val(), 721 lastValid: true, 722 lastFinished: true 723 }; 724 }, 725 validate: function ($this, value, validator) { 726 if (""+validator.lastValue === ""+value && validator.lastFinished === true) { 727 return validator.lastValid === false; 728 } 729 730 if (validator.lastFinished === true) 731 { 732 validator.lastValue = value; 733 validator.lastValid = true; 734 validator.lastFinished = false; 735 $.ajax({ 736 url: validator.url, 737 data: "value=" + value + "&field=" + $this.attr("name"), 738 dataType: "json", 739 success: function (data) { 740 if (""+validator.lastValue === ""+data.value) { 741 validator.lastValid = !!(data.valid); 742 if (data.message) { 743 validator.message = data.message; 744 } 745 validator.lastFinished = true; 746 $this.data("validation" + validator.validatorName + "Message", validator.message); 747 // Timeout is set to avoid problems with the events being considered 'already fired' 748 setTimeout(function () { 749 $this.trigger("change.validation"); 750 }, 1); // doesn't need a long timeout, just long enough for the event bubble to burst 751 } 752 }, 753 failure: function () { 754 validator.lastValid = true; 755 validator.message = "ajax call failed"; 756 validator.lastFinished = true; 757 $this.data("validation" + validator.validatorName + "Message", validator.message); 758 // Timeout is set to avoid problems with the events being considered 'already fired' 759 setTimeout(function () { 760 $this.trigger("change.validation"); 761 }, 1); // doesn't need a long timeout, just long enough for the event bubble to burst 762 } 763 }); 764 } 765 766 return false; 767 768 } 769 }, 770 regex: { 771 name: "regex", 772 init: function ($this, name) { 773 return {regex: regexFromString($this.data("validation" + name + "Regex"))}; 774 }, 775 validate: function ($this, value, validator) { 776 return (!validator.regex.test(value) && ! validator.negative) 777 || (validator.regex.test(value) && validator.negative); 778 } 779 }, 780 requires: { 781 name: "required", 782 init: function ($this, name) { 783 return {}; 784 }, 785 validate: function ($this, value, validator) { 786 787 return !!($this.val().length === 0 && ! validator.negative) 788 || !!($this.val().length > 0 && validator.negative) 789 ; 790 }, 791 blockSubmit: true 792 }, 793 match: { 794 name: "match", 795 init: function ($this, name) { 796 var element = $this.parents("form").first().find("[name=\"" + $this.data("validation" + name + "Match") + "\"]").first(); 797 element.bind("validation.validation", function () { 798 $this.trigger("change.validation", {submitting: true}); 799 }); 800 return {"element": element}; 801 }, 802 validate: function ($this, value, validator) { 803 return (value !== validator.element.val() && ! validator.negative) 804 || (value === validator.element.val() && validator.negative); 805 806 }, 807 blockSubmit: true 808 }, 809 max: { 810 name: "max", 811 init: function ($this, name) { 812 return {max: $this.data("validation" + name + "Max")}; 813 }, 814 validate: function ($this, value, validator) { 815 return (parseFloat(value, 10) > parseFloat(validator.max, 10) && ! validator.negative) 816 || (parseFloat(value, 10) <= parseFloat(validator.max, 10) && validator.negative); 817 } 818 }, 819 min: { 820 name: "min", 821 init: function ($this, name) { 822 return {min: $this.data("validation" + name + "Min")}; 823 }, 824 validate: function ($this, value, validator) { 825 return (parseFloat(value) < parseFloat(validator.min) && ! validator.negative) 826 || (parseFloat(value) >= parseFloat(validator.min) && validator.negative); 827 } 828 }, 829 maxlength: { 830 name: "maxlength", 831 init: function ($this, name) { 832 return {maxlength: $this.data("validation" + name + "Maxlength")}; 833 }, 834 validate: function ($this, value, validator) { 835 return ((value.length > validator.maxlength) && ! validator.negative) 836 || ((value.length <= validator.maxlength) && validator.negative); 837 } 838 }, 839 minlength: { 840 name: "minlength", 841 init: function ($this, name) { 842 return {minlength: $this.data("validation" + name + "Minlength")}; 843 }, 844 validate: function ($this, value, validator) { 845 return ((value.length < validator.minlength) && ! validator.negative) 846 || ((value.length >= validator.minlength) && validator.negative); 847 } 848 }, 849 maxchecked: { 850 name: "maxchecked", 851 init: function ($this, name) { 852 var elements = $this.parents("form").first().find("[name=\"" + $this.attr("name") + "\"]"); 853 elements.bind("click.validation", function () { 854 $this.trigger("change.validation", {includeEmpty: true}); 855 }); 856 return {maxchecked: $this.data("validation" + name + "Maxchecked"), elements: elements}; 857 }, 858 validate: function ($this, value, validator) { 859 return (validator.elements.filter(":checked").length > validator.maxchecked && ! validator.negative) 860 || (validator.elements.filter(":checked").length <= validator.maxchecked && validator.negative); 861 }, 862 blockSubmit: true 863 }, 864 minchecked: { 865 name: "minchecked", 866 init: function ($this, name) { 867 var elements = $this.parents("form").first().find("[name=\"" + $this.attr("name") + "\"]"); 868 elements.bind("click.validation", function () { 869 $this.trigger("change.validation", {includeEmpty: true}); 870 }); 871 return {minchecked: $this.data("validation" + name + "Minchecked"), elements: elements}; 872 }, 873 validate: function ($this, value, validator) { 874 return (validator.elements.filter(":checked").length < validator.minchecked && ! validator.negative) 875 || (validator.elements.filter(":checked").length >= validator.minchecked && validator.negative); 876 }, 877 blockSubmit: true 878 } 879 }, 880 builtInValidators: { 881 email: { 882 name: "Email", 883 type: "shortcut", 884 shortcut: "validemail" 885 }, 886 validemail: { 887 name: "Validemail", 888 type: "regex", 889 regex: "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\\.[A-Za-z]{2,4}", 890 message: "Not a valid email address<!-- data-validator-validemail-message to override -->" 891 }, 892 phone: { 893 name:"Phone", 894 type:"regex", 895 regex:"[6,8,9][0-9]{7}", 896 message: "Not a valid phone number" 897 }, 898 // postal: { 899 // name:"Postal", 900 // type:"regex", 901 // regex:"[0-9]{6}", 902 // message: "Not a valid postal code" 903 // }, 904 passwordagain: { 905 name: "Passwordagain", 906 type: "match", 907 match: "password", 908 message: "Does not match the given password<!-- data-validator-paswordagain-message to override -->" 909 }, 910 positive: { 911 name: "Positive", 912 type: "shortcut", 913 shortcut: "number,positivenumber" 914 }, 915 negative: { 916 name: "Negative", 917 type: "shortcut", 918 shortcut: "number,negativenumber" 919 }, 920 number: { 921 name: "Number", 922 type: "regex", 923 regex: "([+-]?\\\d+(\\\.\\\d*)?([eE][+-]?[0-9]+)?)?", 924 message: "Must be a number<!-- data-validator-number-message to override -->" 925 }, 926 integer: { 927 name: "Integer", 928 type: "regex", 929 regex: "[+-]?\\\d+", 930 message: "No decimal places allowed<!-- data-validator-integer-message to override -->" 931 }, 932 positivenumber: { 933 name: "Positivenumber", 934 type: "min", 935 min: 0, 936 message: "Must be a positive number<!-- data-validator-positivenumber-message to override -->" 937 }, 938 negativenumber: { 939 name: "Negativenumber", 940 type: "max", 941 max: 0, 942 message: "Must be a negative number<!-- data-validator-negativenumber-message to override -->" 943 }, 944 required: { 945 name: "Requird", 946 type: "requires", 947 message: "This is required<!-- data-validator-required-message to override -->" 948 }, 949 checkone: { 950 name: "Checkone", 951 type: "minchecked", 952 minchecked: 1, 953 message: "Check at least one option<!-- data-validation-checkone-message to override -->" 954 } 955 } 956 }; 957 958 var formatValidatorName = function (name) { 959 return name 960 .toLowerCase() 961 .replace( 962 /(^|\s)([a-z])/g , 963 function(m,p1,p2) { 964 return p1+p2.toUpperCase(); 965 } 966 ) 967 ; 968 }; 969 970 var getValue = function ($this) { 971 // Extract the value we're talking about 972 var value = $this.val(); 973 var type = $this.attr("type"); 974 if (type === "checkbox") { 975 value = ($this.is(":checked") ? value : ""); 976 } 977 if (type === "radio") { 978 value = ($('input[name="' + $this.attr("name") + '"]:checked').length > 0 ? value : ""); 979 } 980 return value; 981 }; 982 983 function regexFromString(inputstring) {
984 return new RegExp("^" + inputstring + "$"); 985 } 986 987 /** 988 * Thanks to Jason Bunting via StackOverflow.com 989 * 990 * http://stackoverflow.com/questions/359788/how-to-execute-a-javascript-function-when-i-have-its-name-as-a-string#answer-359910 991 * Short link: http://tinyurl.com/executeFunctionByName 992 **/ 993 function executeFunctionByName(functionName, context /*, args*/) { 994 var args = Array.prototype.slice.call(arguments).splice(2); 995 var namespaces = functionName.split("."); 996 var func = namespaces.pop(); 997 for(var i = 0; i < namespaces.length; i++) { 998 context = context[namespaces[i]]; 999 } 1000 return context[func].apply(this, args); 1001 } 1002 1003 $.fn.jqBootstrapValidation = function( method ) { 1004 1005 if ( defaults.methods[method] ) { 1006 return defaults.methods[method].apply( this, Array.prototype.slice.call( arguments, 1 )); 1007 } else if ( typeof method === 'object' || ! method ) { 1008 return defaults.methods.init.apply( this, arguments ); 1009 } else { 1010 $.error( 'Method ' + method + ' does not exist on jQuery.jqBootstrapValidation' ); 1011 return null; 1012 } 1013 1014 }; 1015 1016 $.jqBootstrapValidation = function (options) { 1017 $(":input").not("[type=image],[type=submit]").jqBootstrapValidation.apply(this,arguments); 1018 }; 1019 1020 addSuccess = function(validationBlock){ 1021 validationBlock.removeClass("inline-validation-error"); 1022 validationBlock.addClass("inline-validation-success"); 1023 validationBlock.html("✓"); 1024 } 1025 1026 addError = function(validationBlock){ 1027 validationBlock.removeClass("inline-validation-success"); 1028 validationBlock.addClass("inline-validation-error"); 1029 validationBlock.html("✗"); 1030 } 1031 1032 resetValidation = function(validationBlock){ 1033 validationBlock.removeClass("inline-validation-error"); 1034 validationBlock.removeClass("inline-validation-success"); 1035 validationBlock.html(""); 1036 } 1037 1038})( jQuery );
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.