vendor: 29,256 bytes, lines 1-795
1/*! 2 * jQuery Validation Plugin 3 * Copyright (c) 2015 Jörn Zaefferer 4 */ 5(function (factory) { 6 if (typeof define === "function" && define.amd) { 7 define(["jquery"], factory); 8 } else if (typeof module === "object" && module.exports) { 9 module.exports = factory(require("jquery")); 10 } else { 11 factory(jQuery); 12 } 13}(function ($) { 14 15 $.extend($.fn, { 16 validate: function (options) { 17 18 // If nothing is selected, return nothing; can't chain anyway 19 if (!this.length) { 20 if (options && options.debug && window.console) { 21 console.warn("Nothing selected, can't validate, returning nothing."); 22 } 23 return; 24 } 25 26 // Check if a validator for this form was already created 27 var validator = $.data(this[ 0 ], "validator"); 28 if (validator) { 29 return validator; 30 } 31 32 // Add novalidate tag if HTML5. 33 this.attr("novalidate", "novalidate"); 34 35 validator = new $.validator(options, this[ 0 ]); 36 $.data(this[ 0 ], "validator", validator); 37 38 if (validator.settings.onsubmit) { 39 40 this.on("click.validate", ":submit", function (event) { 41 if (validator.settings.submitHandler) { 42 validator.submitButton = event.target; 43 } 44 45 // Allow suppressing validation by adding a cancel class to the submit button 46 if ($(this).hasClass("cancel")) { 47 validator.cancelSubmit = true; 48 } 49 50 // Allow suppressing validation by adding the html5 formnovalidate attribute to the submit button 51 if ($(this).attr("formnovalidate") !== undefined) { 52 validator.cancelSubmit = true; 53 } 54 }); 55 56 // Validate the form on submit 57 this.on("submit.validate", function (event) { 58 if (validator.settings.debug) { 59 60 // Prevent form submit to be able to see console output 61 event.preventDefault(); 62 } 63 function handle() { 64 var hidden, result; 65 if (validator.settings.submitHandler) { 66 if (validator.submitButton) { 67 68 // Insert a hidden input as a replacement for the missing submit button 69 hidden = $("<input type='hidden'/>") 70 .attr("name", validator.submitButton.name) 71 .val($(validator.submitButton).val()) 72 .appendTo(validator.currentForm); 73 } 74 result = validator.settings.submitHandler.call(validator, validator.currentForm, event); 75 if (validator.submitButton) { 76 77 // And clean up afterwards; thanks to no-block-scope, hidden can be referenced 78 hidden.remove(); 79 } 80 if (result !== undefined) { 81 return result; 82 } 83 return false; 84 } 85 return true; 86 } 87 if (validator.cancelSubmit) { 88 validator.cancelSubmit = false; 89 return handle(); 90 } 91 if (validator.form()) { 92 if (validator.pendingRequest) { 93 validator.formSubmitted = true; 94 return false; 95 } 96 return handle(); 97 } else { 98 validator.focusInvalid(); 99 return false; 100 } 101 }); 102 } 103 104 return validator; 105 }, 106 valid: function () { 107 var valid, validator, errorList; 108 109 if ($(this[ 0 ]).is("form")) { 110 valid = this.validate().form(); 111 } else { 112 errorList = []; 113 valid = true; 114 validator = $(this[ 0 ].form).validate(); 115 this.each(function () { 116 valid = validator.element(this) && valid; 117 if (!valid) { 118 errorList = errorList.concat(validator.errorList); 119 } 120 }); 121 validator.errorList = errorList; 122 } 123 return valid; 124 }, 125 rules: function (command, argument) { 126 127 // If nothing is selected, return nothing; can't chain anyway 128 if (!this.length) { 129 return; 130 } 131 132 var element = this[ 0 ], 133 settings, staticRules, existingRules, data, param, filtered; 134 135 if (command) { 136 settings = $.data(element.form, "validator").settings; 137 staticRules = settings.rules; 138 existingRules = $.validator.staticRules(element); 139 switch (command) { 140 case "add": 141 $.extend(existingRules, $.validator.normalizeRule(argument)); 142 143 // Remove messages from rules, but allow them to be set separately 144 delete existingRules.messages; 145 staticRules[ element.name ] = existingRules; 146 if (argument.messages) { 147 settings.messages[ element.name ] = $.extend(settings.messages[ element.name ], argument.messages); 148 } 149 break; 150 case "remove": 151 if (!argument) { 152 delete staticRules[ element.name ]; 153 return existingRules; 154 } 155 filtered = {}; 156 $.each(argument.split(/\s/), function (index, method) { 157 filtered[ method ] = existingRules[ method ]; 158 delete existingRules[ method ]; 159 if (method === "required") { 160 $(element).removeAttr("aria-required"); 161 } 162 }); 163 return filtered; 164 } 165 } 166 167 data = $.validator.normalizeRules( 168 $.extend( 169 {}, 170 $.validator.classRules(element), 171 $.validator.attributeRules(element), 172 $.validator.dataRules(element), 173 $.validator.staticRules(element) 174 ), element); 175 176 // Make sure required is at front 177 if (data.required) { 178 param = data.required; 179 delete data.required; 180 data = $.extend({required: param}, data); 181 $(element).attr("aria-required", "true"); 182 } 183 184 // Make sure remote is at back 185 if (data.remote) { 186 param = data.remote; 187 delete data.remote; 188 data = $.extend(data, {remote: param}); 189 } 190 191 return data; 192 } 193 }); 194 195 // Custom selectors 196 $.extend($.expr[ ":" ], { 197 blank: function (a) { 198 return !$.trim("" + $(a).val()); 199 }, 200 filled: function (a) { 201 var val = $(a).val(); 202 return val !== null && !!$.trim("" + val); 203 }, 204 205 unchecked: function (a) { 206 return !$(a).prop("checked"); 207 } 208 }); 209 210 // Constructor for validator 211 $.validator = function (options, form) { 212 this.settings = $.extend(true, {}, $.validator.defaults, options); 213 this.currentForm = form; 214 this.init(); 215 }; 216 217 $.validator.format = function (source, params) { 218 if (arguments.length === 1) { 219 return function () { 220 var args = $.makeArray(arguments); 221 args.unshift(source); 222 return $.validator.format.apply(this, args); 223 }; 224 } 225 if (params === undefined) { 226 return source; 227 } 228 if (arguments.length > 2 && params.constructor !== Array) { 229 params = $.makeArray(arguments).slice(1); 230 } 231 if (params.constructor !== Array) { 232 params = [params]; 233 } 234 $.each(params, function (i, n) { 235 source = source.replace(new RegExp("\\{" + i + "\\}", "g"), function () { 236 return n; 237 }); 238 }); 239 return source; 240 }; 241 242 $.extend($.validator, { 243 244 defaults: { 245 messages: {}, 246 groups: {}, 247 rules: {}, 248 errorClass: "error", 249 pendingClass: "pending", 250 validClass: "valid", 251 errorElement: "label", 252 focusCleanup: false, 253 focusInvalid: true, 254 errorContainer: $([]), 255 errorLabelContainer: $([]), 256 onsubmit: true, 257 ignore: ":hidden", 258 ignoreTitle: false, 259 onfocusin: function (element) { 260 this.lastActive = element; 261 if (this.settings.focusCleanup) { 262 if (this.settings.unhighlight) { 263 this.settings.unhighlight.call(this, element, this.settings.errorClass, this.settings.validClass); 264 } 265 this.hideThese(this.errorsFor(element)); 266 } 267 }, 268 onfocusout: function (element) { 269 if (!this.checkable(element) && (element.name in this.submitted || !this.optional(element))) { 270 this.element(element); 271 } 272 }, 273 onkeyup: function (element, event) { 274 var excludedKeys = [ 275 16, 17, 18, 20, 35, 36, 37, 276 38, 39, 40, 45, 144, 225 277 ]; 278 279 if (event.which === 9 && this.elementValue(element) === "" || $.inArray(event.keyCode, excludedKeys) !== -1) { 280 return; 281 } else if (element.name in this.submitted || element.name in this.invalid) { 282 this.element(element); 283 } 284 }, 285 onclick: function (element) { 286 287 // Click on selects, radiobuttons and checkboxes 288 if (element.name in this.submitted) { 289 this.element(element); 290 291 // Or option elements, check parent select in that case 292 } else if (element.parentNode.name in this.submitted) { 293 this.element(element.parentNode); 294 } 295 }, 296 highlight: function (element, errorClass, validClass) { 297 if (element.type === "radio") { 298 this.findByName(element.name).addClass(errorClass).removeClass(validClass); 299 } else { 300 $(element).addClass(errorClass).removeClass(validClass); 301 } 302 }, 303 unhighlight: function (element, errorClass, validClass) { 304 if (element.type === "radio") { 305 this.findByName(element.name).removeClass(errorClass).addClass(validClass); 306 } else { 307 $(element).removeClass(errorClass).addClass(validClass); 308 } 309 } 310 }, 311 setDefaults: function (settings) { 312 $.extend($.validator.defaults, settings); 313 }, 314 315 messages: { 316 required: "This field is required.", 317 remote: "Please fix this field.", 318 email: "Please enter a valid email address.", 319 url: "Please enter a valid URL.", 320 date: "Please enter a valid date.", 321 dateISO: "Please enter a valid date ( ISO ).", 322 number: "Please enter a valid number.", 323 digits: "Please enter only digits.", 324 equalTo: "Please enter the same value again.", 325 maxlength: $.validator.format("Please enter no more than {0} characters."), 326 minlength: $.validator.format("Please enter at least {0} characters."), 327 rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."), 328 range: $.validator.format("Please enter a value between {0} and {1}."), 329 max: $.validator.format("Please enter a value less than or equal to {0}."), 330 min: $.validator.format("Please enter a value greater than or equal to {0}."), 331 step: $.validator.format("Please enter a multiple of {0}.") 332 }, 333 334 autoCreateRanges: false, 335 336 prototype: { 337 338 init: function () { 339 this.labelContainer = $(this.settings.errorLabelContainer); 340 this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm); 341 this.containers = $(this.settings.errorContainer).add(this.settings.errorLabelContainer); 342 this.submitted = {}; 343 this.valueCache = {}; 344 this.pendingRequest = 0; 345 this.pending = {}; 346 this.invalid = {}; 347 this.reset(); 348 349 var groups = (this.groups = {}), 350 rules; 351 $.each(this.settings.groups, function (key, value) { 352 if (typeof value === "string") { 353 value = value.split(/\s/); 354 } 355 $.each(value, function (index, name) { 356 groups[ name ] = key; 357 }); 358 }); 359 rules = this.settings.rules; 360 $.each(rules, function (key, value) { 361 rules[ key ] = $.validator.normalizeRule(value); 362 }); 363 364 function delegate(event) { 365 var validator = $.data(this.form, "validator"), 366 eventType = "on" + event.type.replace(/^validate/, ""), 367 settings = validator.settings; 368 if (settings[ eventType ] && !$(this).is(settings.ignore)) { 369 settings[ eventType ].call(validator, this, event); 370 } 371 } 372 373 $(this.currentForm) 374 .on("focusin.validate focusout.validate keyup.validate", 375 ":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], " + 376 "[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], " + 377 "[type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], " + 378 "[type='radio'], [type='checkbox'], [contenteditable]", delegate) 379 .on("click.validate", "select, option, [type='radio'], [type='checkbox']", delegate); 380 381 if (this.settings.invalidHandler) { 382 $(this.currentForm).on("invalid-form.validate", this.settings.invalidHandler); 383 } 384 385 // Add aria-required to any Static/Data/Class required fields before first validation 386 // Screen readers require this attribute to be present before the initial submission http://www.w3.org/TR/WCAG-TECHS/ARIA2.html 387 $(this.currentForm).find("[required], [data-rule-required], .required").attr("aria-required", "true"); 388 }, 389 390 form: function () { 391 this.checkForm(); 392 $.extend(this.submitted, this.errorMap); 393 this.invalid = $.extend({}, this.errorMap); 394 if (!this.valid()) { 395 $(this.currentForm).triggerHandler("invalid-form", [this]); 396 } 397 this.showErrors(); 398 return this.valid(); 399 }, 400 401 checkForm: function () { 402 this.prepareForm(); 403 for (var i = 0, elements = (this.currentElements = this.elements()); elements[ i ]; i++) { 404 this.check(elements[ i ]); 405 } 406 return this.valid(); 407 }, 408 element: function (element) { 409 var cleanElement = this.clean(element), 410 checkElement = this.validationTargetFor(cleanElement), 411 v = this, 412 result = true, 413 rs, group; 414 415 if (checkElement === undefined) { 416 delete this.invalid[ cleanElement.name ]; 417 } else { 418 this.prepareElement(checkElement); 419 this.currentElements = $(checkElement); 420 421 // If this element is grouped, then validate all group elements already 422 // containing a value 423 group = this.groups[ checkElement.name ]; 424 if (group) { 425 $.each(this.groups, function (name, testgroup) { 426 if (testgroup === group && name !== checkElement.name) { 427 cleanElement = v.validationTargetFor(v.clean(v.findByName(name))); 428 if (cleanElement && cleanElement.name in v.invalid) { 429 v.currentElements.push(cleanElement); 430 result = result && v.check(cleanElement); 431 } 432 } 433 }); 434 } 435 436 rs = this.check(checkElement) !== false; 437 result = result && rs; 438 if (rs) { 439 this.invalid[ checkElement.name ] = false; 440 } else { 441 this.invalid[ checkElement.name ] = true; 442 } 443 444 if (!this.numberOfInvalids()) { 445 446 // Hide error containers on last error 447 this.toHide = this.toHide.add(this.containers); 448 } 449 this.showErrors(); 450 451 // Add aria-invalid status for screen readers 452 $(element).attr("aria-invalid", !rs); 453 } 454 455 return result; 456 }, 457 showErrors: function (errors) { 458 if (errors) { 459 var validator = this; 460 461 // Add items to error list and map 462 $.extend(this.errorMap, errors); 463 this.errorList = $.map(this.errorMap, function (message, name) { 464 return { 465 message: message, 466 element: validator.findByName(name)[ 0 ] 467 }; 468 }); 469 470 // Remove items from success list 471 this.successList = $.grep(this.successList, function (element) { 472 return !(element.name in errors); 473 }); 474 } 475 if (this.settings.showErrors) { 476 this.settings.showErrors.call(this, this.errorMap, this.errorList); 477 } else { 478 this.defaultShowErrors(); 479 } 480 }, 481 resetForm: function () { 482 if ($.fn.resetForm) { 483 $(this.currentForm).resetForm(); 484 } 485 this.invalid = {}; 486 this.submitted = {}; 487 this.prepareForm(); 488 this.hideErrors(); 489 var elements = this.elements() 490 .removeData("previousValue") 491 .removeAttr("aria-invalid"); 492 493 this.resetElements(elements); 494 }, 495 496 resetElements: function (elements) { 497 var i; 498 499 if (this.settings.unhighlight) { 500 for (i = 0; elements[ i ]; i++) { 501 this.settings.unhighlight.call(this, elements[ i ], 502 this.settings.errorClass, ""); 503 this.findByName(elements[ i ].name).removeClass(this.settings.validClass); 504 } 505 } else { 506 elements 507 .removeClass(this.settings.errorClass) 508 .removeClass(this.settings.validClass); 509 } 510 }, 511 512 numberOfInvalids: function () { 513 return this.objectLength(this.invalid); 514 }, 515 516 objectLength: function (obj) { 517 /* jshint unused: false */ 518 var count = 0, 519 i; 520 for (i in obj) { 521 if (obj[ i ]) { 522 count++; 523 } 524 } 525 return count; 526 }, 527 528 hideErrors: function () { 529 this.hideThese(this.toHide); 530 }, 531 532 hideThese: function (errors) { 533 errors.not(this.containers).text(""); 534 this.addWrapper(errors).hide(); 535 }, 536 537 valid: function () { 538 return this.size() === 0; 539 }, 540 541 size: function () { 542 return this.errorList.length; 543 }, 544 545 focusInvalid: function () { 546 if (this.settings.focusInvalid) { 547 try { 548 $(this.findLastActive() || this.errorList.length && this.errorList[ 0 ].element || []) 549 .filter(":visible") 550 .focus() 551 552 // Manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find 553 .trigger("focusin"); 554 } catch (e) { 555 } 556 } 557 }, 558 559 findLastActive: function () { 560 var lastActive = this.lastActive; 561 return lastActive && $.grep(this.errorList, function (n) { 562 return n.element.name === lastActive.name; 563 }).length === 1 && lastActive; 564 }, 565 566 elements: function () { 567 var validator = this, 568 rulesCache = {}; 569 570 // Select all valid inputs inside the form (no submit or reset buttons) 571 return $(this.currentForm) 572 .find("input, select, textarea, [contenteditable]") 573 .not(":submit, :reset, :image, :disabled") 574 .not(this.settings.ignore) 575 .filter(function () { 576 var name = this.name || $(this).attr("name"); // For contenteditable 577 if (!name && validator.settings.debug && window.console) { 578 console.error("%o has no name assigned", this); 579 } 580 581 if (this.hasAttribute("contenteditable")) { 582 this.form = $(this).closest("form")[ 0 ]; 583 } 584 585 // Select only the first element for each name, and only those with rules specified 586 if (name in rulesCache || !validator.objectLength($(this).rules())) { 587 return false; 588 } 589 590 rulesCache[ name ] = true; 591 return true; 592 }); 593 }, 594 595 clean: function (selector) { 596 return $(selector)[ 0 ]; 597 }, 598 599 errors: function () { 600 var errorClass = this.settings.errorClass.split(" ").join("."); 601 return $(this.settings.errorElement + "." + errorClass, this.errorContext); 602 }, 603 604 resetInternals: function () { 605 this.successList = []; 606 this.errorList = []; 607 this.errorMap = {}; 608 this.toShow = $([]); 609 this.toHide = $([]); 610 }, 611 612 reset: function () { 613 this.resetInternals(); 614 this.currentElements = $([]); 615 }, 616 617 prepareForm: function () { 618 this.reset(); 619 this.toHide = this.errors().add(this.containers); 620 }, 621 622 prepareElement: function (element) { 623 this.reset(); 624 this.toHide = this.errorsFor(element); 625 }, 626 627 elementValue: function (element) { 628 var $element = $(element), 629 type = element.type, 630 val, idx; 631 632 if (type === "radio" || type === "checkbox") { 633 return this.findByName(element.name).filter(":checked").val(); 634 } else if (type === "number" && typeof element.validity !== "undefined") { 635 return element.validity.badInput ? "NaN" : $element.val(); 636 } 637 638 if (element.hasAttribute("contenteditable")) { 639 val = $element.text(); 640 } else { 641 val = $element.val(); 642 } 643 644 if (type === "file") { 645 646 // Modern browser (chrome & safari) 647 if (val.substr(0, 12) === "C:\\fakepath\\") { 648 return val.substr(12); 649 } 650 651 idx = val.lastIndexOf("/"); 652 if (idx >= 0) { 653 return val.substr(idx + 1); 654 } 655 656 // Windows-based path 657 idx = val.lastIndexOf("\\"); 658 if (idx >= 0) { 659 return val.substr(idx + 1); 660 } 661 662 // Just the file name 663 return val; 664 } 665 666 if (typeof val === "string") { 667 return val.replace(/\r/g, ""); 668 } 669 return val; 670 }, 671 672 check: function (element) { 673 element = this.validationTargetFor(this.clean(element)); 674 675 var rules = $(element).rules(), 676 rulesCount = $.map(rules, function (n, i) { 677 return i; 678 }).length, 679 dependencyMismatch = false, 680 val = this.elementValue(element), 681 result, method, rule; 682 if (typeof rules.normalizer === "function") { 683 val = rules.normalizer.call(element, val); 684 685 if (typeof val !== "string") { 686 throw new TypeError("The normalizer should return a string value."); 687 } 688 delete rules.normalizer; 689 } 690 691 for (method in rules) { 692 rule = {method: method, parameters: rules[ method ]}; 693 try { 694 result = $.validator.methods[ method ].call(this, val, element, rule.parameters); 695 if (result === "dependency-mismatch" && rulesCount === 1) { 696 dependencyMismatch = true; 697 continue; 698 } 699 dependencyMismatch = false; 700 701 if (result === "pending") { 702 this.toHide = this.toHide.not(this.errorsFor(element)); 703 return; 704 } 705 706 if (!result) { 707 this.formatAndAdd(element, rule); 708 return false; 709 } 710 } catch (e) { 711 if (this.settings.debug && window.console) { 712 console.log("Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.", e); 713 } 714 if (e instanceof TypeError) { 715 e.message += ". Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method."; 716 } 717 718 throw e; 719 } 720 } 721 if (dependencyMismatch) { 722 return; 723 } 724 if (this.objectLength(rules)) { 725 this.successList.push(element); 726 } 727 return true; 728 }, 729 730 customDataMessage: function (element, method) { 731 return $(element).data("msg" + method.charAt(0).toUpperCase() + 732 method.substring(1).toLowerCase()) || $(element).data("msg"); 733 }, 734 735 // Return the custom message for the given element name and validation method 736 customMessage: function (name, method) { 737 var m = this.settings.messages[ name ]; 738 return m && (m.constructor === String ? m : m[ method ]); 739 }, 740 741 // Return the first defined argument, allowing empty strings 742 findDefined: function () { 743 for (var i = 0; i < arguments.length; i++) { 744 if (arguments[ i ] !== undefined) { 745 return arguments[ i ]; 746 } 747 } 748 return undefined; 749 }, 750 751 defaultMessage: function (element, rule) { 752 var message = this.findDefined( 753 this.customMessage(element.name, rule.method), 754 this.customDataMessage(element, rule.method), 755 // 'title' is never undefined, so handle empty string as undefined 756 !this.settings.ignoreTitle && element.title || undefined, 757 $.validator.messages[ rule.method ], 758 "<strong>Warning: No message defined for " + element.name + "</strong>" 759 ), 760 theregex = /\$?\{(\d+)\}/g; 761 if (typeof message === "function") { 762 message = message.call(this, rule.parameters, element); 763 } else if (theregex.test(message)) { 764 message = $.validator.format(message.replace(theregex, "{$1}"), rule.parameters); 765 } 766 767 return message; 768 }, 769 770 formatAndAdd: function (element, rule) { 771 var message = this.defaultMessage(element, rule); 772 773 this.errorList.push({ 774 message: message, 775 element: element, 776 method: rule.method 777 }); 778 779 this.errorMap[ element.name ] = message; 780 this.submitted[ element.name ] = message; 781 }, 782 783 addWrapper: function (toToggle) { 784 if (this.settings.wrapper) { 785 toToggle = toToggle.add(toToggle.parent(this.settings.wrapper)); 786 } 787 return toToggle; 788 }, 789 790 defaultShowErrors: function () { 791 var i, elements, error; 792 for (i = 0; this.errorList[ i ]; i++) { 793 error = this.errorList[ i ]; 794 if (this.settings.highlight) { 795 this.settings.highlight.call(this, error.element, this.settings.errorClass, this.settings.val
795idClass); 796 } 797 this.showLabel(error.element, error.message); 798 } 799 if (this.errorList.length) { 800 this.toShow = this.toShow.add(this.containers); 801 } 802 if (this.settings.success) { 803 for (i = 0; this.successList[ i ]; i++) { 804 this.showLabel(this.successList[ i ]); 805 } 806 } 807 if (this.settings.unhighlight) { 808 for (i = 0, elements = this.validElements(); elements[ i ]; i++) { 809 this.settings.unhighlight.call(this, elements[ i ], this.settings.errorClass, this.settings.validClass); 810 } 811 } 812 this.toHide = this.toHide.not(this.toShow); 813 this.hideErrors(); 814 this.addWrapper(this.toShow).show(); 815 }, 816 817 validElements: function () { 818 return this.currentElements.not(this.invalidElements()); 819 }, 820 821 invalidElements: function () { 822 return $(this.errorList).map(function () { 823 return this.element; 824 }); 825 }, 826 827 showLabel: function (element, message) { 828 var place, group, errorID, v, 829 error = this.errorsFor(element), 830 elementID = this.idOrName(element), 831 describedBy = $(element).attr("aria-describedby"); 832 833 if (error.length) { 834 835 // Refresh error/success class 836 error.removeClass(this.settings.validClass).addClass(this.settings.errorClass); 837 838 // Replace message on existing label 839 error.html(message); 840 } else { 841 842 // Create error element 843 error = $("<" + this.settings.errorElement + ">") 844 .attr("id", elementID + "-error") 845 .addClass(this.settings.errorClass) 846 .html(message || ""); 847 848 // Maintain reference to the element to be placed into the DOM 849 place = error; 850 if (this.settings.wrapper) { 851 place = error.hide().show().wrap("<" + this.settings.wrapper + "/>").parent(); 852 } 853 if (this.labelContainer.length) { 854 this.labelContainer.append(place); 855 } else if (this.settings.errorPlacement) { 856 this.settings.errorPlacement(place, $(element)); 857 } else { 858 place.insertAfter(element); 859 } 860 861 if (error.is("label")) { 862 error.attr("for", elementID); 863 } else if (error.parents("label[for='" + this.escapeCssMeta(elementID) + "']").length === 0) { 864 errorID = error.attr("id"); 865 if (!describedBy) { 866 describedBy = errorID; 867 } else if (!describedBy.match(new RegExp("\\b" + this.escapeCssMeta(errorID) + "\\b"))) { 868 describedBy += " " + errorID; 869 } 870 $(element).attr("aria-describedby", describedBy); 871 group = this.groups[ element.name ]; 872 if (group) { 873 v = this; 874 $.each(v.groups, function (name, testgroup) { 875 if (testgroup === group) { 876 $("[name='" + v.escapeCssMeta(name) + "']", v.currentForm) 877 .attr("aria-describedby", error.attr("id")); 878 } 879 }); 880 } 881 } 882 } 883 if (!message && this.settings.success) { 884 error.text(""); 885 if (typeof this.settings.success === "string") { 886 error.addClass(this.settings.success); 887 } else { 888 this.settings.success(error, element); 889 } 890 } 891 this.toShow = this.toShow.add(error); 892 }, 893 894 errorsFor: function (element) { 895 var name = this.escapeCssMeta(this.idOrName(element)), 896 describer = $(element).attr("aria-describedby"), 897 selector = "label[for='" + name + "'], label[for='" + name + "'] *"; 898 if (describer) { 899 selector = selector + ", #" + this.escapeCssMeta(describer) 900 .replace(/\s+/g, ", #"); 901 } 902 903 return this 904 .errors() 905 .filter(selector); 906 }, 907 escapeCssMeta: function (string) { 908 return string.replace(/([\\!"#$%&'()*+,./:;<=>?@\[\]^`{|}~])/g, "\\$1"); 909 }, 910 911 idOrName: function (element) { 912 return this.groups[ element.name ] || (this.checkable(element) ? element.name : element.i
vendor: 14,231 bytes, lines 912-1269
912d || element.name); 913 }, 914 915 validationTargetFor: function (element) { 916 917 if (this.checkable(element)) { 918 element = this.findByName(element.name); 919 } 920 return $(element).not(this.settings.ignore)[ 0 ]; 921 }, 922 923 checkable: function (element) { 924 return (/radio|checkbox/i).test(element.type); 925 }, 926 927 findByName: function (name) { 928 return $(this.currentForm).find("[name='" + this.escapeCssMeta(name) + "']"); 929 }, 930 931 getLength: function (value, element) { 932 switch (element.nodeName.toLowerCase()) { 933 case "select": 934 return $("option:selected", element).length; 935 case "input": 936 if (this.checkable(element)) { 937 return this.findByName(element.name).filter(":checked").length; 938 } 939 } 940 return value.length; 941 }, 942 943 depend: function (param, element) { 944 return this.dependTypes[ typeof param ] ? this.dependTypes[ typeof param ](param, element) : true; 945 }, 946 947 dependTypes: { 948 "boolean": function (param) { 949 return param; 950 }, 951 "string": function (param, element) { 952 return !!$(param, element.form).length; 953 }, 954 "function": function (param, element) { 955 return param(element); 956 } 957 }, 958 959 optional: function (element) { 960 var val = this.elementValue(element); 961 return !$.validator.methods.required.call(this, val, element) && "dependency-mismatch"; 962 }, 963 964 startRequest: function (element) { 965 if (!this.pending[ element.name ]) { 966 this.pendingRequest++; 967 $(element).addClass(this.settings.pendingClass); 968 this.pending[ element.name ] = true; 969 } 970 }, 971 stopRequest: function (element, valid) { 972 this.pendingRequest--; 973 if (this.pendingRequest < 0) { 974 this.pendingRequest = 0; 975 } 976 delete this.pending[ element.name ]; 977 $(element).removeClass(this.settings.pendingClass); 978 if (valid && this.pendingRequest === 0 && this.formSubmitted && this.form()) { 979 $(this.currentForm).submit(); 980 this.formSubmitted = false; 981 } else if (!valid && this.pendingRequest === 0 && this.formSubmitted) { 982 $(this.currentForm).triggerHandler("invalid-form", [this]); 983 this.formSubmitted = false; 984 } 985 }, 986 previousValue: function (element, method) { 987 return $.data(element, "previousValue") || $.data(element, "previousValue", { 988 old: null, 989 valid: true, 990 message: this.defaultMessage(element, {method: method}) 991 }); 992 }, 993 destroy: function () { 994 this.resetForm(); 995 $(this.currentForm) 996 .off(".validate") 997 .removeData("validator") 998 .find(".validate-equalTo-blur") 999 .off(".validate-equalTo") 1000 .removeClass("validate-equalTo-blur"); 1001 } 1002 }, 1003 classRuleSettings: { 1004 required: {required: true}, 1005 email: {email: true}, 1006 url: {url: true}, 1007 date: {date: true}, 1008 dateISO: {dateISO: true}, 1009 number: {number: true}, 1010 digits: {digits: true}, 1011 creditcard: {creditcard: true} 1012 }, 1013 1014 addClassRules: function (className, rules) { 1015 if (className.constructor === String) { 1016 this.classRuleSettings[ className ] = rules; 1017 } else { 1018 $.extend(this.classRuleSettings, className); 1019 } 1020 }, 1021 1022 classRules: function (element) { 1023 var rules = {}, 1024 classes = $(element).attr("class"); 1025 1026 if (classes) { 1027 $.each(classes.split(" "), function () { 1028 if (this in $.validator.classRuleSettings) { 1029 $.extend(rules, $.validator.classRuleSettings[ this ]); 1030 } 1031 }); 1032 } 1033 return rules; 1034 }, 1035 1036 normalizeAttributeRule: function (rules, type, method, value) { 1037 if (/min|max|step/.test(method) && (type === null || /number|range|text/.test(type))) { 1038 value = Number(value); 1039 if (isNaN(value)) { 1040 value = undefined; 1041 } 1042 } 1043 1044 if (value || value === 0) { 1045 rules[ method ] = value; 1046 } else if (type === method && type !== "range") { 1047 rules[ method ] = true; 1048 } 1049 }, 1050 1051 attributeRules: function (element) { 1052 var rules = {}, 1053 $element = $(element), 1054 type = element.getAttribute("type"), 1055 method, value; 1056 1057 for (method in $.validator.methods) { 1058 if (method === "required") { 1059 value = element.getAttribute(method); 1060 if (value === "") { 1061 value = true; 1062 } 1063 value = !!value; 1064 } else { 1065 value = $element.attr(method); 1066 } 1067 this.normalizeAttributeRule(rules, type, method, value); 1068 } 1069 if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) { 1070 delete rules.maxlength; 1071 } 1072 1073 return rules; 1074 }, 1075 1076 dataRules: function (element) { 1077 var rules = {}, 1078 $element = $(element), 1079 type = element.getAttribute("type"), 1080 method, value; 1081 1082 for (method in $.validator.methods) { 1083 value = $element.data("rule" + method.charAt(0).toUpperCase() + method.substring(1).toLowerCase()); 1084 this.normalizeAttributeRule(rules, type, method, value); 1085 } 1086 return rules; 1087 }, 1088 1089 staticRules: function (element) { 1090 var rules = {}, 1091 validator = $.data(element.form, "validator"); 1092 1093 if (validator.settings.rules) { 1094 rules = $.validator.normalizeRule(validator.settings.rules[ element.name ]) || {}; 1095 } 1096 return rules; 1097 }, 1098 1099 normalizeRules: function (rules, element) { 1100 $.each(rules, function (prop, val) { 1101 if (val === false) { 1102 delete rules[ prop ]; 1103 return; 1104 } 1105 if (val.param || val.depends) { 1106 var keepRule = true; 1107 switch (typeof val.depends) { 1108 case "string": 1109 keepRule = !!$(val.depends, element.form).length; 1110 break; 1111 case "function": 1112 keepRule = val.depends.call(element, element); 1113 break; 1114 } 1115 if (keepRule) { 1116 rules[ prop ] = val.param !== undefined ? val.param : true; 1117 } else { 1118 $.data(element.form, "validator").resetElements($(element)); 1119 delete rules[ prop ]; 1120 } 1121 } 1122 }); 1123 $.each(rules, function (rule, parameter) { 1124 rules[ rule ] = $.isFunction(parameter) && rule !== "normalizer" ? parameter(element) : parameter; 1125 }); 1126 $.each(["minlength", "maxlength"], function () { 1127 if (rules[ this ]) { 1128 rules[ this ] = Number(rules[ this ]); 1129 } 1130 }); 1131 $.each(["rangelength", "range"], function () { 1132 var parts; 1133 if (rules[ this ]) { 1134 if ($.isArray(rules[ this ])) { 1135 rules[ this ] = [Number(rules[ this ][ 0 ]), Number(rules[ this ][ 1 ])]; 1136 } else if (typeof rules[ this ] === "string") { 1137 parts = rules[ this ].replace(/[\[\]]/g, "").split(/[\s,]+/); 1138 rules[ this ] = [Number(parts[ 0 ]), Number(parts[ 1 ])]; 1139 } 1140 } 1141 }); 1142 if ($.validator.autoCreateRanges) { 1143 if (rules.min != null && rules.max != null) { 1144 rules.range = [rules.min, rules.max]; 1145 delete rules.min; 1146 delete rules.max; 1147 } 1148 if (rules.minlength != null && rules.maxlength != null) { 1149 rules.rangelength = [rules.minlength, rules.maxlength]; 1150 delete rules.minlength; 1151 delete rules.maxlength; 1152 } 1153 } 1154 return rules; 1155 }, 1156 normalizeRule: function (data) { 1157 if (typeof data === "string") { 1158 var transformed = {}; 1159 $.each(data.split(/\s/), function () { 1160 transformed[ this ] = true; 1161 }); 1162 data = transformed; 1163 } 1164 return data; 1165 }, 1166 addMethod: function (name, method, message) { 1167 $.validator.methods[ name ] = method; 1168 $.validator.messages[ name ] = message !== undefined ? message : $.validator.messages[ name ]; 1169 if (method.length < 3) { 1170 $.validator.addClassRules(name, $.validator.normalizeRule(name)); 1171 } 1172 }, 1173 methods: { 1174 required: function (value, element, param) { 1175 if (!this.depend(param, element)) { 1176 return "dependency-mismatch"; 1177 } 1178 if (element.nodeName.toLowerCase() === "select") { 1179 var val = $(element).val(); 1180 return val && val.length > 0; 1181 } 1182 if (this.checkable(element)) { 1183 return this.getLength(value, element) > 0; 1184 } 1185 return value.length > 0; 1186 }, 1187 email: function (value, element) { 1188 return this.optional(element) || /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(value); 1189 }, 1190 url: function (value, element) { 1191 return this.optional(element) || /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(value); 1192 }, 1193 date: function (value, element) { 1194 return this.optional(element) || !/Invalid|NaN/.test(new Date(value).toString()); 1195 }, 1196 dateISO: function (value, element) { 1197 return this.optional(element) || /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(value); 1198 }, 1199 number: function (value, element) { 1200 return this.optional(element) || /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value); 1201 }, 1202 digits: function (value, element) { 1203 return this.optional(element) || /^\d+$/.test(value); 1204 }, 1205 minlength: function (value, element, param) { 1206 var length = $.isArray(value) ? value.length : this.getLength(value, element); 1207 return this.optional(element) || length >= param; 1208 }, 1209 maxlength: function (value, element, param) { 1210 var length = $.isArray(value) ? value.length : this.getLength(value, element); 1211 return this.optional(element) || length <= param; 1212 }, 1213 rangelength: function (value, element, param) { 1214 var length = $.isArray(value) ? value.length : this.getLength(value, element); 1215 return this.optional(element) || (length >= param[ 0 ] && length <= param[ 1 ]); 1216 }, 1217 min: function (value, element, param) { 1218 return this.optional(element) || value >= param; 1219 }, 1220 max: function (value, element, param) { 1221 return this.optional(element) || value <= param; 1222 }, 1223 range: function (value, element, param) { 1224 return this.optional(element) || (value >= param[ 0 ] && value <= param[ 1 ]); 1225 }, 1226 step: function (value, element, param) { 1227 var type = $(element).attr("type"), 1228 errorMessage = "Step attribute on input type " + type + " is not supported.", 1229 supportedTypes = ["text", "number", "range"], 1230 re = new RegExp("\\b" + type + "\\b"), 1231 notSupported = type && !re.test(supportedTypes.join()); 1232 if (notSupported) { 1233 throw new Error(errorMessage); 1234 } 1235 return this.optional(element) || (value % param === 0); 1236 }, 1237 equalTo: function (value, element, param) { 1238 var target = $(param); 1239 if (this.settings.onfocusout && target.not(".validate-equalTo-blur").length) { 1240 target.addClass("validate-equalTo-blur").on("blur.validate-equalTo", function () { 1241 $(element).valid(); 1242 }); 1243 } 1244 return value === target.val(); 1245 }, 1246 remote: function (value, element, param, method) { 1247 if (this.optional(element)) { 1248 return "dependency-mismatch"; 1249 } 1250 1251 method = typeof method === "string" && method || "remote"; 1252 1253 var previous = this.previousValue(element, method), 1254 validator, data, optionDataString; 1255 1256 if (!this.settings.messages[ element.name ]) { 1257 this.settings.messages[ element.name ] = {}; 1258 } 1259 previous.originalMessage = previous.originalMessage || this.settings.messages[ element.name ][ method ]; 1260 this.settings.messages[ element.name ][ method ] = previous.message; 1261 1262 param = typeof param === "string" && {url: param} || param; 1263 optionDataString = $.param($.extend({data: value}, param.data)); 1264 if (previous.old === optionDataString) { 1265 return previous.valid; 1266 } 1267 1268 previous.old = optionDataString; 1269 validator = this;
1270 this.startRequest(element); 1271 data = {}; 1272 data[ element.name ] = value; 1273 $.ajax($.extend(true, { 1274 mode: "abort", 1275 port: "validate" + element.name, 1276 dataType: "json", 1277 data: data, 1278 context: validator.currentForm, 1279 success: function (response) { 1280 var valid = response === true || response === "true", 1281 errors, message, submitted; 1282 1283 validator.settings.messages[ element.name ][ method ] = previous.originalMessage; 1284 if (valid) { 1285 submitted = validator.formSubmitted; 1286 validator.resetInternals(); 1287 validator.toHide = validator.errorsFor(element); 1288 validator.formSubmitted = submitted; 1289 validator.successList.push(element); 1290 validator.invalid[ element.name ] = false; 1291 validator.showErrors(); 1292 } else { 1293 errors = {}; 1294 message = response || validator.defaultMessage(element, {method: method, parameters: value}); 1295 errors[ element.name ] = previous.message = message; 1296 validator.invalid[ element.name ] = true; 1297 validator.showErrors(errors); 1298 } 1299 previous.valid = valid; 1300 validator.stopRequest(element, valid); 1301 } 1302 }, param)); 1303 return "pending"; 1304 } 1305 } 1306 }); 1307 var pendingRequests = {}, 1308 ajax; 1309 if ($.ajaxPrefilter) { 1310 $.ajaxPrefilter(function (settings, _, xhr) { 1311 var port = settings.port; 1312 if (settings.mode === "abort") { 1313 if (pendingRequests[ port ]) { 1314 pendingRequests[ port ].abort(); 1315 } 1316 pendingRequests[ port ] = xhr; 1317 } 1318 }); 1319 } else { 1320 ajax = $.ajax; 1321 $.ajax = function (settings) { 1322 var mode = ("mode" in settings ? settings : $.ajaxSettings).mode, 1323 port = ("port" in settings ? settings : $.ajaxSettings).port; 1324 if (mode === "abort") { 1325 if (pendingRequests[ port ]) { 1326 pendingRequests[ port ].abort(); 1327 } 1328 pendingRequests[ port ] = ajax.apply(this, arguments); 1329 return pendingRequests[ port ]; 1330 } 1331 return ajax.apply(this, arguments); 1332 }; 1333 } 1334}));
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.