1/* 2* This file has been commented to support Visual Studio Intellisense. 3* You should not use this file at runtime inside the browser--it is only 4* intended to be used only for design-time IntelliSense. Please use the 5* standard jQuery library for all production use. 6 7* Comment version: 1.19.5 8*/ 9 10/* 11* Note: While Microsoft is not the author of this file, Microsoft is 12* offering you a license subject to the terms of the Microsoft Software 13* License Terms for Microsoft ASP.NET Model View Controller 3. 14* Microsoft reserves all other rights. The notices below are provided 15* for informational purposes only and are not the license terms under 16* which Microsoft distributed this file. 17* 18* jQuery Validation Plugin - v1.19.5 - 12/5/2016 19* https://github.com/jzaefferer/jquery-validation 20* Copyright (c) 2013 J�rn Zaefferer; Licensed MIT 21* 22*/ 23 24(function ($) { 25 26 $.extend($.fn, { 27 // http://docs.jquery.com/Plugins/Validation/validate 28 validate: function (options) { 29 /// <summary> 30 /// Validates the selected form. This method sets up event handlers for submit, focus, 31 /// keyup, blur and click to trigger validation of the entire form or individual 32 /// elements. Each one can be disabled, see the onxxx options (onsubmit, onfocusout, 33 /// onkeyup, onclick). focusInvalid focuses elements when submitting a invalid form. 34 /// </summary> 35 /// <param name="options" type="Object"> 36 /// A set of key/value pairs that configure the validate. All options are optional. 37 /// </param> 38 39 // if nothing is selected, return nothing; can't chain anyway 40 if (!this.length) { 41 options && options.debug && window.console && console.warn("nothing selected, can't validate, returning nothing"); 42 return; 43 } 44 45 // check if a validator for this form was already created 46 var validator = $.data(this[0], 'validator'); 47 if (validator) { 48 return validator; 49 } 50 51 validator = new $.validator(options, this[0]); 52 $.data(this[0], 'validator', validator); 53 54 if (validator.settings.onsubmit) { 55 56 // allow suppresing validation by adding a cancel class to the submit button 57 this.find("input, button").filter(".cancel").click(function () { 58 validator.cancelSubmit = true; 59 }); 60 61 // when a submitHandler is used, capture the submitting button 62 if (validator.settings.submitHandler) { 63 this.find("input, button").filter(":submit").click(function () { 64 validator.submitButton = this; 65 }); 66 } 67 68 // validate the form on submit 69 this.submit(function (event) { 70 if (validator.settings.debug) 71 // prevent form submit to be able to see console output 72 event.preventDefault(); 73 74 function handle() { 75 if (validator.settings.submitHandler) { 76 if (validator.submitButton) { 77 // insert a hidden input as a replacement for the missing submit button 78 var hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm); 79 } 80 validator.settings.submitHandler.call(validator, validator.currentForm); 81 if (validator.submitButton) { 82 // and clean up afterwards; thanks to no-block-scope, hidden can be referenced 83 hidden.remove(); 84 } 85 return false; 86 } 87 return true; 88 } 89 90 // prevent submit for invalid forms or custom submit handlers 91 if (validator.cancelSubmit) { 92 validator.cancelSubmit = false; 93 return handle(); 94 } 95 if (validator.form()) { 96 if (validator.pendingRequest) { 97 validator.formSubmitted = true; 98 return false; 99 } 100 return handle(); 101 } else { 102 validator.focusInvalid(); 103 return false; 104 } 105 }); 106 } 107 108 return validator; 109 }, 110 // http://docs.jquery.com/Plugins/Validation/valid 111 valid: function () { 112 /// <summary> 113 /// Checks if the selected form is valid or if all selected elements are valid. 114 /// validate() needs to be called on the form before checking it using this method. 115 /// </summary> 116 /// <returns type="Boolean" /> 117 118 if ($(this[0]).is('form')) { 119 return this.validate().form(); 120 } else {
121 var valid = true; 122 var validator = $(this[0].form).validate(); 123 this.each(function () { 124 valid &= validator.element(this); 125 }); 126 return valid; 127 } 128 }, 129 // attributes: space seperated list of attributes to retrieve and remove 130 removeAttrs: function (attributes) { 131 /// <summary> 132 /// Remove the specified attributes from the first matched element and return them. 133 /// </summary> 134 /// <param name="attributes" type="String"> 135 /// A space-seperated list of attribute names to remove. 136 /// </param> 137 138 var result = {}, 139 $element = this; 140 $.each(attributes.split(/\s/), function (index, value) { 141 result[value] = $element.attr(value); 142 $element.removeAttr(value); 143 }); 144 return result; 145 }, 146 // http://docs.jquery.com/Plugins/Validation/rules 147 rules: function (command, argument) { 148 /// <summary> 149 /// Return the validations rules for the first selected element. 150 /// </summary> 151 /// <param name="command" type="String"> 152 /// Can be either "add" or "remove". 153 /// </param> 154 /// <param name="argument" type=""> 155 /// A list of rules to add or remove. 156 /// </param> 157 158 var element = this[0]; 159 160 if (command) { 161 var settings = $.data(element.form, 'validator').settings; 162 var staticRules = settings.rules; 163 var existingRules = $.validator.staticRules(element); 164 switch (command) { 165 case "add": 166 $.extend(existingRules, $.validator.normalizeRule(argument)); 167 staticRules[element.name] = existingRules; 168 if (argument.messages) 169 settings.messages[element.name] = $.extend(settings.messages[element.name], argument.messages); 170 break; 171 case "remove": 172 if (!argument) { 173 delete staticRules[element.name]; 174 return existingRules; 175 } 176 var filtered = {}; 177 $.each(argument.split(/\s/), function (index, method) { 178 filtered[method] = existingRules[method]; 179 delete existingRules[method]; 180 }); 181 return filtered; 182 } 183 } 184 185 var data = $.validator.normalizeRules( 186 $.extend( 187 {}, 188 $.validator.metadataRules(element), 189 $.validator.classRules(element), 190 $.validator.attributeRules(element), 191 $.validator.staticRules(element) 192 ), element); 193 194 // make sure required is at front 195 if (data.required) { 196 var param = data.required; 197 delete data.required; 198 data = $.extend({ required: param }, data); 199 } 200 201 return data; 202 } 203 }); 204 205 // Custom selectors 206 $.extend($.expr[":"], { 207 // http://docs.jquery.com/Plugins/Validation/blank 208 blank: function (a) { return !$.trim("" + a.value); }, 209 // http://docs.jquery.com/Plugins/Validation/filled 210 filled: function (a) { return !!$.trim("" + a.value); }, 211 // http://docs.jquery.com/Plugins/Validation/unchecked 212 unchecked: function (a) { return !a.checked; } 213 }); 214 215 // constructor for validator 216 $.validator = function (options, form) { 217 this.settings = $.extend(true, {}, $.validator.defaults, options); 218 this.currentForm = form; 219 this.init(); 220 }; 221 222 $.validator.format = function (source, params) { 223 /// <summary> 224 /// Replaces {n} placeholders with arguments. 225 /// One or more arguments can be passed, in addition to the string template itself, to insert 226 /// into the string. 227 /// </summary> 228 /// <param name="source" type="String"> 229 /// The string to format. 230 /// </param> 231 /// <param name="params" type="String"> 232 /// The first argument to insert, or an array of Strings to insert 233 /// </param> 234 /// <returns type="String" /> 235 236 if (arguments.length == 1) 237 return function () { 238 var args = $.makeArray(arguments); 239 args.unshift(source); 240 return $.validator.format.apply(this, args); 241 }; 242 if (arguments.length > 2 && params.constructor != Array) { 243 params = $.makeArray(arguments).slice(1); 244 } 245 if (params.constructor != Array) { 246 params = [params]; 247 } 248 $.each(params, function (i, n) { 249 source = source.replace(new RegExp("\\{" + i + "\\}", "g"), n); 250 }); 251 return source; 252 }; 253 254 $.extend($.validator, { 255 256 defaults: { 257 messages: {}, 258 groups: {}, 259 rules: {}, 260 errorClass: "error", 261 validClass: "valid", 262 errorElement: "label", 263 focusInvalid: true, 264 errorContainer: $([]), 265 errorLabelContainer: $([]), 266 onsubmit: true, 267 ignore: [], 268 ignoreTitle: false, 269 onfocusin: function (element) { 270 this.lastActive = element; 271 272 // hide error label and remove error class on focus if enabled 273 if (this.settings.focusCleanup && !this.blockFocusCleanup) { 274 this.settings.unhighlight && this.settings.unhighlight.call(this, element, this.settings.errorClass, this.settings.val
274idClass); 275 this.addWrapper(this.errorsFor(element)).hide(); 276 } 277 }, 278 onfocusout: function (element) { 279 if (!this.checkable(element) && (element.name in this.submitted || !this.optional(element))) { 280 this.element(element); 281 } 282 }, 283 onkeyup: function (element) { 284 if (element.name in this.submitted || element == this.lastElement) { 285 this.element(element); 286 } 287 }, 288 onclick: function (element) { 289 // click on selects, radiobuttons and checkboxes 290 if (element.name in this.submitted) 291 this.element(element); 292 // or option elements, check parent select in that case 293 else if (element.parentNode.name in this.submitted) 294 this.element(element.parentNode); 295 }, 296 highlight: function (element, errorClass, validClass) { 297 $(element).addClass(errorClass).removeClass(validClass); 298 }, 299 unhighlight: function (element, errorClass, validClass) { 300 $(element).removeClass(errorClass).addClass(validClass); 301 } 302 }, 303 304 // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults 305 setDefaults: function (settings) { 306 /// <summary> 307 /// Modify default settings for validation. 308 /// Accepts everything that Plugins/Validation/validate accepts. 309 /// </summary> 310 /// <param name="settings" type="Options"> 311 /// Options to set as default. 312 /// </param> 313 314 $.extend($.validator.defaults, settings); 315 }, 316 317 messages: { 318 required: "This field is required.", 319 remote: "Please fix this field.", 320 email: "Please enter a valid email address.", 321 url: "Please enter a valid URL.", 322 date: "Please enter a valid date.", 323 dateISO: "Please enter a valid date (ISO).", 324 number: "Please enter a valid number.", 325 digits: "Please enter only digits.", 326 creditcard: "Please enter a valid credit card number.", 327 equalTo: "Please enter the same value again.", 328 accept: "Please enter a value with a valid extension.", 329 maxlength: $.validator.format("Please enter no more than {0} characters."), 330 minlength: $.validator.format("Please enter at least {0} characters."), 331 rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."), 332 range: $.validator.format("Please enter a value between {0} and {1}."), 333 max: $.validator.format("Please enter a value less than or equal to {0}."), 334 min: $.validator.format("Please enter a value greater than or equal to {0}.") 335 }, 336 337 autoCreateRanges: false, 338 339 prototype: { 340 341 init: function () { 342 this.labelContainer = $(this.settings.errorLabelContainer); 343 this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm); 344 this.containers = $(this.settings.errorContainer).add(this.settings.errorLabelContainer); 345 this.submitted = {}; 346 this.valueCache = {}; 347 this.pendingRequest = 0; 348 this.pending = {}; 349 this.invalid = {}; 350 this.reset(); 351 352 var groups = (this.groups = {}); 353 $.each(this.settings.groups, function (key, value) { 354 $.each(value.split(/\s/), function (index, name) { 355 groups[name] = key; 356 }); 357 }); 358 var rules = this.settings.rules; 359 $.each(rules, function (key, value) { 360 rules[key] = $.validator.normalizeRule(value); 361 }); 362 363 function delegate(event) { 364 var validator = $.data(this[0].form, "validator"), 365 eventType = "on" + event.type.replace(/^validate/, ""); 366 validator.settings[eventType] && validator.settings[eventType].call(validator, this[0]); 367 } 368 $(this.currentForm) 369 .validateDelegate(":text, :password, :file, select, textarea", "focusin focusout keyup", delegate) 370 .validateDelegate(":radio, :checkbox, select, option", "click", delegate); 371 372 if (this.settings.invalidHandler) 373 $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler); 374 }, 375 376 // http://docs.jquery.com/Plugins/Validation/Validator/form 377 form: function () { 378 /// <summary> 379 /// Validates the form, returns true if it is valid, false otherwise. 380 /// This behaves as a normal submit event, but returns the result. 381 /// </summary> 382 /// <returns type="Boolean" /> 383 384 this.checkForm(); 385 $.extend(this.submitted, this.errorMap); 386 this.invalid = $.extend({}, this.errorMap); 387 if (!this.valid()) 388 $(this.currentForm).triggerHandler("invalid-form", [this]); 389 this.showErrors(); 390 return this.valid(); 391 }, 392 393 checkForm: function () { 394 this.prepareForm(); 395 for (var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++) { 396 this.check(elements[i]); 397 } 398 return this.valid(); 399 }, 400 401 // http://docs.jquery.com/Plugins/Validation/Validator/element 402 element: function (element) { 403 /// <summary> 404 /// Validates a single element, returns true if it is valid, false otherwise. 405 /// This behaves as validation on blur or keyup, but returns the result. 406 /// </summary> 407 /// <param name="element" type="Selector"> 408 /// An element to validate, must be inside the validated form. 409 /// </param> 410 /// <returns type="Boolean" /> 411 412 element = this.clean(element); 413 this.lastElement = element; 414 this.prepareElement(element); 415 this.currentElements = $(element); 416 var result = this.check(element); 417 if (result) { 418 delete this.invalid[element.name]; 419 } else { 420 this.invalid[element.name] = true; 421 } 422 if (!this.numberOfInvalids()) { 423 // Hide error containers on last error
424 this.toHide = this.toHide.add(this.containers); 425 } 426 this.showErrors(); 427 return result; 428 }, 429 430 // http://docs.jquery.com/Plugins/Validation/Validator/showErrors 431 showErrors: function (errors) { 432 /// <summary> 433 /// Show the specified messages. 434 /// Keys have to refer to the names of elements, values are displayed for those elements, using the configured error placement. 435 /// </summary> 436 /// <param name="errors" type="Object"> 437 /// One or more key/value pairs of input names and messages. 438 /// </param> 439 440 if (errors) { 441 // add items to error list and map 442 $.extend(this.errorMap, errors); 443 this.errorList = []; 444 for (var name in errors) { 445 this.errorList.push({ 446 message: errors[name], 447 element: this.findByName(name)[0] 448 }); 449 } 450 // remove items from success list 451 this.successList = $.grep(this.successList, function (element) { 452 return !(element.name in errors); 453 }); 454 } 455 this.settings.showErrors 456 ? this.settings.showErrors.call(this, this.errorMap, this.errorList) 457 : this.defaultShowErrors(); 458 }, 459 460 // http://docs.jquery.com/Plugins/Validation/Validator/resetForm 461 resetForm: function () { 462 /// <summary> 463 /// Resets the controlled form. 464 /// Resets input fields to their original value (requires form plugin), removes classes 465 /// indicating invalid elements and hides error messages. 466 /// </summary> 467 468 if ($.fn.resetForm) 469 $(this.currentForm).resetForm(); 470 this.submitted = {}; 471 this.prepareForm(); 472 this.hideErrors(); 473 this.elements().removeClass(this.settings.errorClass); 474 }, 475 476 numberOfInvalids: function () { 477 /// <summary> 478 /// Returns the number of invalid fields. 479 /// This depends on the internal validator state. It covers all fields only after 480 /// validating the complete form (on submit or via $("form").valid()). After validating 481 /// a single element, only that element is counted. Most useful in combination with the 482 /// invalidHandler-option. 483 /// </summary> 484 /// <returns type="Number" /> 485 486 return this.objectLength(this.invalid); 487 }, 488 489 objectLength: function (obj) { 490 var count = 0; 491 for (var i in obj) 492 count++; 493 return count; 494 }, 495 496 hideErrors: function () { 497 this.addWrapper(this.toHide).hide(); 498 }, 499 500 valid: function () { 501 return this.size() == 0; 502 }, 503 504 size: function () { 505 return this.errorList.length; 506 }, 507 508 focusInvalid: function () { 509 if (this.settings.focusInvalid) { 510 try { 511 $(this.findLastActive() || this.errorList.length && this.errorList[0].element || []) 512 .filter(":visible") 513 .focus() 514 // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find 515 .trigger("focusin"); 516 } catch (e) { 517 // ignore IE throwing errors when focusing hidden elements 518 } 519 } 520 }, 521 522 findLastActive: function () { 523 var lastActive = this.lastActive; 524 return lastActive && $.grep(this.errorList, function (n) { 525 return n.element.name == lastActive.name; 526 }).length == 1 && lastActive; 527 }, 528 529 elements: function () { 530 var validator = this, 531 rulesCache = {}; 532 533 // select all valid inputs inside the form (no submit or reset buttons) 534 // workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved 535 return $([]).add(this.currentForm.elements) 536 .filter(":input") 537 .not(":submit, :reset, :image, [disabled]") 538 .not(this.settings.ignore) 539 .filter(function () { 540 !this.name && validator.settings.debug && window.console && console.error("%o has no name assigned", this); 541 542 // select only the first element for each name, and only those with rules specified 543 if (this.name in rulesCache || !validator.objectLength($(this).rules())) 544 return false; 545 546 rulesCache[this.name] = true; 547 return true; 548 }); 549 }, 550 551 clean: function (selector) { 552 return $(selector)[0]; 553 }, 554 555 errors: function () { 556 return $(this.settings.errorElement + "." + this.settings.errorClass, this.errorContext); 557 }, 558 559 reset: function () { 560 this.successList = []; 561 this.errorList = []; 562 this.errorMap = {}; 563 this.toShow = $([]); 564 this.toHide = $([]); 565 this.currentElements = $([]); 566 }, 567 568 prepareForm: function () { 569 this.reset();
570 this.toHide = this.errors().add(this.containers); 571 }, 572 573 prepareElement: function (element) { 574 this.reset(); 575 this.toHide = this.errorsFor(element); 576 }, 577 578 check: function (element) { 579 element = this.clean(element); 580 581 // if radio/checkbox, validate first element in group instead 582 if (this.checkable(element)) { 583 element = this.findByName(element.name).not(this.settings.ignore)[0]; 584 } 585 586 var rules = $(element).rules(); 587 var dependencyMismatch = false; 588 for (var method in rules) { 589 var rule = { method: method, parameters: rules[method] }; 590 try { 591 var result = $.validator.methods[method].call(this, element.value.replace(/\r/g, ""), element, rule.parameters); 592 593 // if a method indicates that the field is optional and therefore valid, 594 // don't mark it as valid when there are no other rules 595 if (result == "dependency-mismatch") { 596 dependencyMismatch = true; 597 continue; 598 } 599 dependencyMismatch = false; 600 601 if (result == "pending") { 602 this.toHide = this.toHide.not(this.errorsFor(element)); 603 return; 604 } 605 606 if (!result) { 607 this.formatAndAdd(element, rule); 608 return false; 609 } 610 } catch (e) { 611 this.settings.debug && window.console && console.log("exception occured when checking element " + element.id 612 + ", check the '" + rule.method + "' method", e); 613 throw e; 614 } 615 } 616 if (dependencyMismatch) 617 return; 618 if (this.objectLength(rules)) 619 this.successList.push(element); 620 return true; 621 }, 622 623 // return the custom message for the given element and validation method 624 // specified in the element's "messages" metadata 625 customMetaMessage: function (element, method) { 626 if (!$.metadata) 627 return; 628 629 var meta = this.settings.meta 630 ? $(element).metadata()[this.settings.meta] 631 : $(element).metadata(); 632 633 return meta && meta.messages && meta.messages[method]; 634 }, 635 636 // return the custom message for the given element name and validation method 637 customMessage: function (name, method) { 638 var m = this.settings.messages[name]; 639 return m && (m.constructor == String 640 ? m 641 : m[method]); 642 }, 643 644 // return the first defined argument, allowing empty strings 645 findDefined: function () { 646 for (var i = 0; i < arguments.length; i++) { 647 if (arguments[i] !== undefined) 648 return arguments[i]; 649 } 650 return undefined; 651 }, 652 653 defaultMessage: function (element, method) { 654 return this.findDefined( 655 this.customMessage(element.name, method), 656 this.customMetaMessage(element, method), 657 // title is never undefined, so handle empty string as undefined 658 !this.settings.ignoreTitle && element.title || undefined, 659 $.validator.messages[method], 660 "<strong>Warning: No message defined for " + element.name + "</strong>" 661 ); 662 }, 663 664 formatAndAdd: function (element, rule) { 665 var message = this.defaultMessage(element, rule.method), 666 theregex = /\$?\{(\d+)\}/g; 667 if (typeof message == "function") { 668 message = message.call(this, rule.parameters, element); 669 } else if (theregex.test(message)) { 670 message = jQuery.format(message.replace(theregex, '{$1}'), rule.parameters); 671 } 672 this.errorList.push({ 673 message: message, 674 element: element 675 }); 676 677 this.errorMap[element.name] = message; 678 this.submitted[element.name] = message; 679 }, 680 681 addWrapper: function (toToggle) { 682 if (this.settings.wrapper) 683 toToggle = toToggle.add(toToggle.parent(this.settings.wrapper)); 684 return toToggle; 685 }, 686 687 defaultShowErrors: function () { 688 for (var i = 0; this.errorList[i]; i++) { 689 var error = this.errorList[i]; 690 this.settings.highlight && this.settings.highlight.call(this, error.element, this.settings.errorClass, this.settings.validClass); 691 this.showLabel(error.element, error.message); 692 } 693 if (this.errorList.length) {
694 this.toShow = this.toShow.add(this.containers); 695 } 696 if (this.settings.success) { 697 for (var i = 0; this.successList[i]; i++) { 698 this.showLabel(this.successList[i]); 699 } 700 } 701 if (this.settings.unhighlight) { 702 for (var i = 0, elements = this.validElements(); elements[i]; i++) { 703 this.settings.unhighlight.call(this, elements[i], this.settings.errorClass, this.settings.validClass); 704 } 705 } 706 this.toHide = this.toHide.not(this.toShow); 707 this.hideErrors(); 708 this.addWrapper(this.toShow).show(); 709 }, 710 711 validElements: function () { 712 return this.currentElements.not(this.invalidElements()); 713 }, 714 715 invalidElements: function () { 716 return $(this.errorList).map(function () { 717 return this.element; 718 }); 719 }, 720 721 showLabel: function (element, message) { 722 var label = this.errorsFor(element); 723 if (label.length) { 724 // refresh error/success class 725 label.removeClass().addClass(this.settings.errorClass); 726 727 // check if we have a generated label, replace the message then 728 label.attr("generated") && label.html(message); 729 } else { 730 // create label 731 label = $("<" + this.settings.errorElement + "/>") 732 .attr({ "for": this.idOrName(element), generated: true }) 733 .addClass(this.settings.errorClass) 734 .html(message || ""); 735 if (this.settings.wrapper) { 736 // make sure the element is visible, even in IE 737 // actually showing the wrapped element is handled elsewhere 738 label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent(); 739 } 740 if (!this.labelContainer.append(label).length) 741 this.settings.errorPlacement 742 ? this.settings.errorPlacement(label, $(element)) 743 : label.insertAfter(element); 744 } 745 if (!message && this.settings.success) { 746 label.text(""); 747 typeof this.settings.success == "string" 748 ? label.addClass(this.settings.success) 749 : this.settings.success(label); 750 } 751 this.toShow = this.toShow.add(label); 752 }, 753 754 errorsFor: function (element) { 755 var name = this.idOrName(element); 756 return this.errors().filter(function () { 757 return $(this).attr('for') == name; 758 }); 759 }, 760 761 idOrName: function (element) { 762 return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name); 763 }, 764 765 checkable: function (element) { 766 return /radio|checkbox/i.test(element.type); 767 }, 768 769 findByName: function (name) { 770 // select by name and filter by form for performance over form.find("[name=...]") 771 var form = this.currentForm; 772 return $(document.getElementsByName(name)).map(function (index, element) { 773 return element.form == form && element.name == name && element || null; 774 }); 775 }, 776 777 getLength: function (value, element) { 778 switch (element.nodeName.toLowerCase()) { 779 case 'select': 780 return $("option:selected", element).length; 781 case 'input': 782 if (this.checkable(element)) 783 return this.findByName(element.name).filter(':checked').length; 784 } 785 return value.length; 786 }, 787 788 depend: function (param, element) { 789 return this.dependTypes[typeof param] 790 ? this.dependTypes[typeof param](param, element) 791 : true; 792 }, 793 794 dependTypes: { 795 "boolean": function (param, element) { 796 return param; 797 }, 798 "string": function (param, element) { 799 return !!$(param, element.form).length; 800 }, 801 "function": function (param, element) { 802 return param(element); 803 } 804 }, 805 806 optional: function (element) { 807 return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch"; 808 }, 809 810 startRequest: function (element) { 811 if (!this.pending[element.name]) { 812 this.pendingRequest++; 813 this.pending[element.name] = true; 814 } 815 }, 816 817 stopRequest: function (element, valid) { 818 this.pendingRequest--; 819 // sometimes synchronization fails, make sure pendingRequest is never < 0 820 if (this.pendingRequest < 0) 821 this.pendingRequest = 0; 822 delete this.pending[element.name]; 823 if (valid && this.pendingRequest == 0 && this.formSubmitted && this.form()) { 824 $(this.currentForm).submit(); 825 this.formSubmitted = false; 826 } else if (!valid && this.pendingRequest == 0 && this.formSubmitted) { 827 $(this.currentForm).triggerHandler("invalid-form", [this]); 828 this.formSubmitted = false; 829 } 830 }, 831 832 previousValue: function (element) { 833 return $.data(element, "previousValue") || $.data(element, "previousValue", {
834 old: null, 835 valid: true, 836 message: this.defaultMessage(element, "remote") 837 }); 838 } 839 840 }, 841 842 classRuleSettings: { 843 required: { required: true }, 844 email: { email: true }, 845 url: { url: true }, 846 date: { date: true }, 847 dateISO: { dateISO: true }, 848 dateDE: { dateDE: true }, 849 number: { number: true }, 850 numberDE: { numberDE: true }, 851 digits: { digits: true }, 852 creditcard: { creditcard: true } 853 }, 854 855 addClassRules: function (className, rules) { 856 /// <summary> 857 /// Add a compound class method - useful to refactor common combinations of rules into a single 858 /// class. 859 /// </summary> 860 /// <param name="name" type="String"> 861 /// The name of the class rule to add 862 /// </param> 863 /// <param name="rules" type="Options"> 864 /// The compound rules 865 /// </param> 866 867 className.constructor == String ? 868 this.classRuleSettings[className] = rules : 869 $.extend(this.classRuleSettings, className); 870 }, 871 872 classRules: function (element) { 873 var rules = {}; 874 var classes = $(element).attr('class'); 875 classes && $.each(classes.split(' '), function () { 876 if (this in $.validator.classRuleSettings) { 877 $.extend(rules, $.validator.classRuleSettings[this]); 878 } 879 }); 880 return rules; 881 }, 882 883 attributeRules: function (element) { 884 var rules = {}; 885 var $element = $(element); 886 887 for (var method in $.validator.methods) { 888 var value = $element.attr(method); 889 if (value) { 890 rules[method] = value; 891 } 892 } 893 894 // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs 895 if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) { 896 delete rules.maxlength; 897 } 898 899 return rules; 900 }, 901 902 metadataRules: function (element) { 903 if (!$.metadata) return {}; 904 905 var meta = $.data(element.form, 'validator').settings.meta; 906 return meta ? 907 $(element).metadata()[meta] : 908 $(element).metadata(); 909 }, 910 911 staticRules: function (element) { 912 var rules = {}; 913 var validator = $.data(element.form, 'validator'); 914 if (validator.settings.rules) { 915 rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {}; 916 } 917 return rules; 918 }, 919 920 normalizeRules: function (rules, element) { 921 // handle dependency check 922 $.each(rules, function (prop, val) { 923 // ignore rule when param is explicitly false, eg. required:false 924 if (val === false) { 925 delete rules[prop]; 926 return; 927 } 928 if (val.param || val.depends) { 929 var keepRule = true; 930 switch (typeof val.depends) { 931 case "string": 932 keepRule = !!$(val.depends, element.form).length; 933 break; 934 case "function": 935 keepRule = val.depends.call(element, element); 936 break; 937 } 938 if (keepRule) { 939 rules[prop] = val.param !== undefined ? val.param : true; 940 } else { 941 delete rules[prop]; 942 } 943 } 944 }); 945 946 // evaluate parameters 947 $.each(rules, function (rule, parameter) { 948 rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter; 949 }); 950 951 // clean number parameters 952 $.each(['minlength', 'maxlength', 'min', 'max'], function () { 953 if (rules[this]) { 954 rules[this] = Number(rules[this]); 955 } 956 }); 957 $.each(['rangelength', 'range'], function () { 958 if (rules[this]) { 959 rules[this] = [Number(rules[this][0]), Number(rules[this][1])]; 960 } 961 }); 962 963 if ($.validator.autoCreateRanges) { 964 // auto-create ranges 965 if (rules.min && rules.max) { 966 rules.range = [rules.min, rules.max]; 967 delete rules.min; 968 delete rules.max; 969 } 970 if (rules.minlength && rules.maxlength) { 971 rules.rangelength = [rules.minlength, rules.maxlength]; 972 delete rules.minlength; 973 delete rules.maxlength; 974 } 975 } 976 977 // To support custom messages in metadata ignore rule methods titled "messages" 978 if (rules.messages) { 979 delete rules.messages; 980 } 981 982 return rules; 983 }, 984 985 // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true} 986 normalizeRule: function (data) { 987 if (typeof data == "string") { 988 var transformed = {}; 989 $.each(data.split(/\s/), function () { 990 transformed[this] = true; 991 }); 992 data = transformed; 993 } 994 return data; 995 }, 996 997 // http://docs.jquery.com/Plugins/Validation/Validator/addMethod 998 addMethod: function (name, method, message) { 999 /// <summary> 1000 /// Add a custom validation method. It must consist of a name (must be a legal javascript 1001 /// identifier), a javascript based function and a default string message. 1002 /// </summary> 1003 /// <param name="name" type="String"> 1004 /// The name of the method, used to identify and referencing it, must be a valid javascript 1005 /// identifier 1006 /// </param> 1007 /// <param name="method" type="Function"> 1008 /// The actual method implementation, returning true if an element is valid 1009 /// </param> 1010 /// <param name="message" type="String" optional="true"> 1011 /// (Optional) The default message to display for this method. Can be a function created by 1012 /// jQuery.validator.format(value). When undefined, an already existing message is used 1013 /// (handy for localization), otherwise the field-specific messages have to be defined. 1014 /// </param> 1015 1016 $.validator.methods[name] = method; 1017 $.validator.messages[name] = message != undefined ? message : $.validator.messages[name]; 1018 if (method.length < 3) { 1019 $.validator.addClassRules(name, $.validator.normalizeRule(name)); 1020 } 1021 }, 1022 1023 methods: { 1024 1025 // http://docs.jquery.com/Plugins/Validation/Methods/required 1026 required: function (value, element, param) { 1027 // check if dependency is met 1028 if (!this.depend(param, element)) 1029 return "dependency-mismatch"; 1030 switch (element.nodeName.toLowerCase()) { 1031 case 'select': 1032 // could be an array for select-multiple or a string, both are fine this way 1033 var val = $(element).val(); 1034 return val && val.length > 0;
1035 case 'input': 1036 if (this.checkable(element)) 1037 return this.getLength(value, element) > 0; 1038 default: 1039 return $.trim(value).length > 0; 1040 } 1041 }, 1042 1043 // http://docs.jquery.com/Plugins/Validation/Methods/remote 1044 remote: function (value, element, param) { 1045 if (this.optional(element)) 1046 return "dependency-mismatch"; 1047 1048 var previous = this.previousValue(element); 1049 if (!this.settings.messages[element.name]) 1050 this.settings.messages[element.name] = {}; 1051 previous.originalMessage = this.settings.messages[element.name].remote; 1052 this.settings.messages[element.name].remote = previous.message; 1053 1054 param = typeof param == "string" && { url: param } || param; 1055 1056 if (this.pending[element.name]) { 1057 return "pending"; 1058 } 1059 if (previous.old === value) { 1060 return previous.valid; 1061 } 1062 1063 previous.old = value; 1064 var validator = this; 1065 this.startRequest(element); 1066 var data = {}; 1067 data[element.name] = value; 1068 $.ajax($.extend(true, { 1069 url: param, 1070 mode: "abort", 1071 port: "validate" + element.name, 1072 dataType: "json", 1073 data: data, 1074 success: function (response) { 1075 validator.settings.messages[element.name].remote = previous.originalMessage; 1076 var valid = response === true; 1077 if (valid) { 1078 var submitted = validator.formSubmitted; 1079 validator.prepareElement(element); 1080 validator.formSubmitted = submitted; 1081 validator.successList.push(element); 1082 validator.showErrors(); 1083 } else { 1084 var errors = {}; 1085 var message = response || validator.defaultMessage(element, "remote"); 1086 errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message; 1087 validator.showErrors(errors); 1088 } 1089 previous.valid = valid; 1090 validator.stopRequest(element, valid); 1091 } 1092 }, param)); 1093 return "pending"; 1094 }, 1095 1096 // http://docs.jquery.com/Plugins/Validation/Methods/minlength 1097 minlength: function (value, element, param) { 1098 return this.optional(element) || this.getLength($.trim(value), element) >= param; 1099 }, 1100 1101 // http://docs.jquery.com/Plugins/Validation/Methods/maxlength 1102 maxlength: function (value, element, param) { 1103 return this.optional(element) || this.getLength($.trim(value), element) <= param; 1104 }, 1105 1106 // http://docs.jquery.com/Plugins/Validation/Methods/rangelength 1107 rangelength: function (value, element, param) { 1108 var length = this.getLength($.trim(value), element); 1109 return this.optional(element) || (length >= param[0] && length <= param[1]); 1110 }, 1111 1112 // http://docs.jquery.com/Plugins/Validation/Methods/min 1113 min: function (value, element, param) { 1114 return this.optional(element) || value >= param; 1115 }, 1116 1117 // http://docs.jquery.com/Plugins/Validation/Methods/max 1118 max: function (value, element, param) { 1119 return this.optional(element) || value <= param; 1120 }, 1121 1122 // http://docs.jquery.com/Plugins/Validation/Methods/range 1123 range: function (value, element, param) { 1124 return this.optional(element) || (value >= param[0] && value <= param[1]); 1125 }, 1126 1127 // http://docs.jquery.com/Plugins/Validation/Methods/email 1128 email: function (value, element) { 1129 // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/ 1130 return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value); 1131 }, 1132 1133 // http://docs.jquery.com/Plugins/Validation/Methods/url 1134 url: function (value, element) { 1135 // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/ 1136 return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value); 1137 }, 1138 1139 // http://docs.jquery.com/Plugins/Validation/Methods/date 1140 date: function (value, element) { 1141 return this.optional(element) || !/Invalid|NaN/.test(new Date(value)); 1142 }, 1143 1144 // http://docs.jquery.com/Plugins/Validation/Methods/dateISO 1145 dateISO: function (value, element) { 1146 return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value); 1147 }, 1148 1149 // http://docs.jquery.com/Plugins/Validation/Methods/number 1150 number: function (value, element) { 1151 return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value); 1152 }, 1153 1154 // http://docs.jquery.com/Plugins/Validation/Methods/digits 1155 digits: function (value, element) { 1156 return this.optional(element) || /^\d+$/.test(value); 1157 }, 1158 1159 // http://docs.jquery.com/Plugins/Validation/Methods/creditcard 1160 // based on http://en.wikipedia.org/wiki/Luhn 1161 creditcard: function (value, element) { 1162 if (this.optional(element)) 1163 return "dependency-mismatch"; 1164 // accept only digits and dashes 1165 if (/[^0-9-]+/.test(value)) 1166 return false; 1167 var nCheck = 0, 1168 nDigit = 0, 1169 bEven = false; 1170 1171 value = value.replace(/\D/g, ""); 1172 1173 for (var n = value.length - 1; n >= 0; n--) { 1174 var cDigit = value.charAt(n); 1175 var nDigit = parseInt(cDigit, 10); 1176 if (bEven) { 1177 if ((nDigit *= 2) > 9) 1178 nDigit -= 9; 1179 } 1180 nCheck += nDigit; 1181 bEven = !bEven; 1182 } 1183 1184 return (nCheck % 10) == 0;
1185 }, 1186 1187 // http://docs.jquery.com/Plugins/Validation/Methods/accept 1188 accept: function (value, element, param) { 1189 param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif"; 1190 return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i")); 1191 }, 1192 1193 // http://docs.jquery.com/Plugins/Validation/Methods/equalTo 1194 equalTo: function (value, element, param) { 1195 // bind to the blur event of the target in order to revalidate whenever the target field is updated 1196 // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead 1197 var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function () { 1198 $(element).valid(); 1199 }); 1200 return value == target.val(); 1201 } 1202 1203 } 1204 1205 }); 1206 1207 // deprecated, use $.validator.format instead 1208 $.format = $.validator.format; 1209 1210})(jQuery); 1211 1212// ajax mode: abort 1213// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]}); 1214// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() 1215; (function ($) { 1216 var pendingRequests = {}; 1217 // Use a prefilter if available (1.5+) 1218 if ($.ajaxPrefilter) { 1219 $.ajaxPrefilter(function (settings, _, xhr) { 1220 var port = settings.port; 1221 if (settings.mode == "abort") { 1222 if (pendingRequests[port]) { 1223 pendingRequests[port].abort(); 1224 } pendingRequests[port] = xhr; 1225 } 1226 }); 1227 } else { 1228 // Proxy ajax 1229 var ajax = $.ajax; 1230 $.ajax = function (settings) { 1231 var mode = ("mode" in settings ? settings : $.ajaxSettings).mode, 1232 port = ("port" in settings ? settings : $.ajaxSettings).port; 1233 if (mode == "abort") { 1234 if (pendingRequests[port]) { 1235 pendingRequests[port].abort(); 1236 } 1237 1238 return (pendingRequests[port] = ajax.apply(this, arguments)); 1239 } 1240 return ajax.apply(this, arguments); 1241 }; 1242 } 1243})(jQuery); 1244 1245// provides cross-browser focusin and focusout events 1246// IE has native support, in other browsers, use event caputuring (neither bubbles) 1247 1248// provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation 1249// handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target 1250; (function ($) { 1251 // only implement if not provided by jQuery core (since 1.4) 1252 // TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs 1253 if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) { 1254 $.each({ 1255 focus: 'focusin', 1256 blur: 'focusout' 1257 }, function (original, fix) { 1258 $.event.special[fix] = { 1259 setup: function () { 1260 this.addEventListener(original, handler, true); 1261 }, 1262 teardown: function () { 1263 this.removeEventListener(original, handler, true); 1264 }, 1265 handler: function (e) { 1266 arguments[0] = $.event.fix(e); 1267 arguments[0].type = fix; 1268 return $.event.handle.apply(this, arguments); 1269 } 1270 }; 1271 function handler(e) { 1272 e = $.event.fix(e); 1273 e.type = fix; 1274 return $.event.handle.call(this, e); 1275 } 1276 }); 1277 }; 1278 $.extend($.fn, { 1279 validateDelegate: function (delegate, type, handler) { 1280 return this.bind(type, function (event) { 1281 var target = $(event.target); 1282 if (target.is(delegate)) { 1283 return handler.apply(target, arguments); 1284 } 1285 }); 1286 } 1287 }); 1288})(jQuery); 1289 1290/*! 1291 * jQuery Validation Plugin v1.19.5 1292 * 1293 * https://jqueryvalidation.org/ 1294 * 1295 * Copyright (c) 2022 Jörn Zaefferer 1296 * Released under the MIT license 1297 */ 1298(function( factory ) { 1299 if ( typeof define === "function" && define.amd ) { 1300 define( ["jquery"], factory ); 1301 } else if (typeof module === "object" && module.exports) { 1302 module.exports = factory( require( "jquery" ) ); 1303 } else { 1304 factory( jQuery ); 1305 } 1306}(function( $ ) { 1307 1308$.extend( $.fn, { 1309 1310 // https://jqueryvalidation.org/validate/ 1311 validate: function( options ) { 1312 1313 // If nothing is selected, return nothing; can't chain anyway 1314 if ( !this.length ) { 1315 if ( options && options.debug && window.console ) { 1316 console.warn( "Nothing selected, can't validate, returning nothing." ); 1317 } 1318 return; 1319 } 1320 1321 // Check if a validator for this form was already created
vendor: 49,688 bytes, lines 1322-2874
1322 var validator = $.data( this[ 0 ], "validator" ); 1323 if ( validator ) { 1324 return validator; 1325 } 1326 1327 // Add novalidate tag if HTML5. 1328 this.attr( "novalidate", "novalidate" ); 1329 1330 validator = new $.validator( options, this[ 0 ] ); 1331 $.data( this[ 0 ], "validator", validator ); 1332 1333 if ( validator.settings.onsubmit ) { 1334 1335 this.on( "click.validate", ":submit", function( event ) { 1336 1337 // Track the used submit button to properly handle scripted 1338 // submits later. 1339 validator.submitButton = event.currentTarget; 1340 1341 // Allow suppressing validation by adding a cancel class to the submit button 1342 if ( $( this ).hasClass( "cancel" ) ) { 1343 validator.cancelSubmit = true; 1344 } 1345 1346 // Allow suppressing validation by adding the html5 formnovalidate attribute to the submit button 1347 if ( $( this ).attr( "formnovalidate" ) !== undefined ) { 1348 validator.cancelSubmit = true; 1349 } 1350 } ); 1351 1352 // Validate the form on submit 1353 this.on( "submit.validate", function( event ) { 1354 if ( validator.settings.debug ) { 1355 1356 // Prevent form submit to be able to see console output 1357 event.preventDefault(); 1358 } 1359 1360 function handle() { 1361 var hidden, result; 1362 1363 // Insert a hidden input as a replacement for the missing submit button 1364 // The hidden input is inserted in two cases: 1365 // - A user defined a `submitHandler` 1366 // - There was a pending request due to `remote` method and `stopRequest()` 1367 // was called to submit the form in case it's valid 1368 if ( validator.submitButton && ( validator.settings.submitHandler || validator.formSubmitted ) ) { 1369 hidden = $( "<input type='hidden'/>" ) 1370 .attr( "name", validator.submitButton.name ) 1371 .val( $( validator.submitButton ).val() ) 1372 .appendTo( validator.currentForm ); 1373 } 1374 1375 if ( validator.settings.submitHandler && !validator.settings.debug ) { 1376 result = validator.settings.submitHandler.call( validator, validator.currentForm, event ); 1377 if ( hidden ) { 1378 1379 // And clean up afterwards; thanks to no-block-scope, hidden can be referenced 1380 hidden.remove(); 1381 } 1382 if ( result !== undefined ) { 1383 return result; 1384 } 1385 return false; 1386 } 1387 return true; 1388 } 1389 1390 // Prevent submit for invalid forms or custom submit handlers 1391 if ( validator.cancelSubmit ) { 1392 validator.cancelSubmit = false; 1393 return handle(); 1394 } 1395 if ( validator.form() ) { 1396 if ( validator.pendingRequest ) { 1397 validator.formSubmitted = true; 1398 return false; 1399 } 1400 return handle(); 1401 } else { 1402 validator.focusInvalid(); 1403 return false; 1404 } 1405 } ); 1406 } 1407 1408 return validator; 1409 }, 1410 1411 // https://jqueryvalidation.org/valid/ 1412 valid: function() { 1413 var valid, validator, errorList; 1414 1415 if ( $( this[ 0 ] ).is( "form" ) ) { 1416 valid = this.validate().form(); 1417 } else { 1418 errorList = []; 1419 valid = true; 1420 validator = $( this[ 0 ].form ).validate(); 1421 this.each( function() { 1422 valid = validator.element( this ) && valid; 1423 if ( !valid ) { 1424 errorList = errorList.concat( validator.errorList ); 1425 } 1426 } ); 1427 validator.errorList = errorList; 1428 } 1429 return valid; 1430 }, 1431 1432 // https://jqueryvalidation.org/rules/ 1433 rules: function( command, argument ) { 1434 var element = this[ 0 ], 1435 isContentEditable = typeof this.attr( "contenteditable" ) !== "undefined" && this.attr( "contenteditable" ) !== "false", 1436 settings, staticRules, existingRules, data, param, filtered; 1437 1438 // If nothing is selected, return empty object; can't chain anyway 1439 if ( element == null ) { 1440 return; 1441 } 1442 1443 if ( !element.form && isContentEditable ) { 1444 element.form = this.closest( "form" )[ 0 ]; 1445 element.name = this.attr( "name" ); 1446 } 1447 1448 if ( element.form == null ) { 1449 return; 1450 } 1451 1452 if ( command ) { 1453 settings = $.data( element.form, "validator" ).settings; 1454 staticRules = settings.rules; 1455 existingRules = $.validator.staticRules( element ); 1456 switch ( command ) { 1457 case "add": 1458 $.extend( existingRules, $.validator.normalizeRule( argument ) ); 1459 1460 // Remove messages from rules, but allow them to be set separately 1461 delete existingRules.messages; 1462 staticRules[ element.name ] = existingRules; 1463 if ( argument.messages ) { 1464 settings.messages[ element.name ] = $.extend( settings.messages[ element.name ], argument.messages ); 1465 } 1466 break; 1467 case "remove": 1468 if ( !argument ) { 1469 delete staticRules[ element.name ]; 1470 return existingRules; 1471 } 1472 filtered = {}; 1473 $.each( argument.split( /\s/ ), function( index, method ) { 1474 filtered[ method ] = existingRules[ method ]; 1475 delete existingRules[ method ]; 1476 } ); 1477 return filtered; 1478 } 1479 } 1480 1481 data = $.validator.normalizeRules( 1482 $.extend( 1483 {}, 1484 $.validator.classRules( element ), 1485 $.validator.attributeRules( element ), 1486 $.validator.dataRules( element ), 1487 $.validator.staticRules( element ) 1488 ), element ); 1489 1490 // Make sure required is at front 1491 if ( data.required ) { 1492 param = data.required; 1493 delete data.required; 1494 data = $.extend( { required: param }, data ); 1495 } 1496 1497 // Make sure remote is at back 1498 if ( data.remote ) { 1499 param = data.remote; 1500 delete data.remote; 1501 data = $.extend( data, { remote: param } ); 1502 } 1503 1504 return data; 1505 } 1506} ); 1507 1508// JQuery trim is deprecated, provide a trim method based on String.prototype.trim 1509var trim = function( str ) { 1510 1511 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trim#Polyfill 1512 return str.replace( /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, "" ); 1513}; 1514 1515// Custom selectors 1516$.extend( $.expr.pseudos || $.expr[ ":" ], { // '|| $.expr[ ":" ]' here enables backwards compatibility to jQuery 1.7. Can be removed when dropping jQ 1.7.x support 1517 1518 // https://jqueryvalidation.org/blank-selector/ 1519 blank: function( a ) { 1520 return !trim( "" + $( a ).val() ); 1521 }, 1522 1523 // https://jqueryvalidation.org/filled-selector/ 1524 filled: function( a ) { 1525 var val = $( a ).val(); 1526 return val !== null && !!trim( "" + val ); 1527 }, 1528 1529 // https://jqueryvalidation.org/unchecked-selector/ 1530 unchecked: function( a ) { 1531 return !$( a ).prop( "checked" ); 1532 } 1533} ); 1534 1535// Constructor for validator 1536$.validator = function( options, form ) { 1537 this.settings = $.extend( true, {}, $.validator.defaults, options ); 1538 this.currentForm = form; 1539 this.init(); 1540}; 1541 1542// https://jqueryvalidation.org/jQuery.validator.format/ 1543$.validator.format = function( source, params ) { 1544 if ( arguments.length === 1 ) { 1545 return function() { 1546 var args = $.makeArray( arguments ); 1547 args.unshift( source ); 1548 return $.validator.format.apply( this, args ); 1549 }; 1550 } 1551 if ( params === undefined ) { 1552 return source; 1553 } 1554 if ( arguments.length > 2 && params.constructor !== Array ) { 1555 params = $.makeArray( arguments ).slice( 1 ); 1556 } 1557 if ( params.constructor !== Array ) { 1558 params = [ params ]; 1559 } 1560 $.each( params, function( i, n ) { 1561 source = source.replace( new RegExp( "\\{" + i + "\\}", "g" ), function() { 1562 return n; 1563 } ); 1564 } ); 1565 return source; 1566}; 1567 1568$.extend( $.validator, { 1569 1570 defaults: { 1571 messages: {}, 1572 groups: {}, 1573 rules: {}, 1574 errorClass: "error", 1575 pendingClass: "pending", 1576 validClass: "valid", 1577 errorElement: "label", 1578 focusCleanup: false, 1579 focusInvalid: true, 1580 errorContainer: $( [] ), 1581 errorLabelContainer: $( [] ), 1582 onsubmit: true, 1583 ignore: ":hidden", 1584 ignoreTitle: false, 1585 onfocusin: function( element ) { 1586 this.lastActive = element; 1587 1588 // Hide error label and remove error class on focus if enabled 1589 if ( this.settings.focusCleanup ) { 1590 if ( this.settings.unhighlight ) { 1591 this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass ); 1592 } 1593 this.hideThese( this.errorsFor( element ) ); 1594 } 1595 }, 1596 onfocusout: function( element ) { 1597 if ( !this.checkable( element ) && ( element.name in this.submitted || !this.optional( element ) ) ) { 1598 this.element( element ); 1599 } 1600 }, 1601 onkeyup: function( element, event ) { 1602 1603 // Avoid revalidate the field when pressing one of the following keys 1604 // Shift => 16 1605 // Ctrl => 17 1606 // Alt => 18 1607 // Caps lock => 20 1608 // End => 35 1609 // Home => 36 1610 // Left arrow => 37 1611 // Up arrow => 38 1612 // Right arrow => 39 1613 // Down arrow => 40 1614 // Insert => 45 1615 // Num lock => 144 1616 // AltGr key => 225 1617 var excludedKeys = [ 1618 16, 17, 18, 20, 35, 36, 37, 1619 38, 39, 40, 45, 144, 225 1620 ]; 1621 1622 if ( event.which === 9 && this.elementValue( element ) === "" || $.inArray( event.keyCode, excludedKeys ) !== -1 ) { 1623 return; 1624 } else if ( element.name in this.submitted || element.name in this.invalid ) { 1625 this.element( element ); 1626 } 1627 }, 1628 onclick: function( element ) { 1629 1630 // Click on selects, radiobuttons and checkboxes 1631 if ( element.name in this.submitted ) { 1632 this.element( element ); 1633 1634 // Or option elements, check parent select in that case 1635 } else if ( element.parentNode.name in this.submitted ) { 1636 this.element( element.parentNode ); 1637 } 1638 }, 1639 highlight: function( element, errorClass, validClass ) { 1640 if ( element.type === "radio" ) { 1641 this.findByName( element.name ).addClass( errorClass ).removeClass( validClass ); 1642 } else { 1643 $( element ).addClass( errorClass ).removeClass( validClass ); 1644 } 1645 }, 1646 unhighlight: function( element, errorClass, validClass ) { 1647 if ( element.type === "radio" ) { 1648 this.findByName( element.name ).removeClass( errorClass ).addClass( validClass ); 1649 } else { 1650 $( element ).removeClass( errorClass ).addClass( validClass ); 1651 } 1652 } 1653 }, 1654 1655 // https://jqueryvalidation.org/jQuery.validator.setDefaults/ 1656 setDefaults: function( settings ) { 1657 $.extend( $.validator.defaults, settings ); 1658 }, 1659 1660 messages: { 1661 required: "This field is required.", 1662 remote: "Please fix this field.", 1663 email: "Please enter a valid email address.", 1664 url: "Please enter a valid URL.", 1665 date: "Please enter a valid date.", 1666 dateISO: "Please enter a valid date (ISO).", 1667 number: "Please enter a valid number.", 1668 digits: "Please enter only digits.", 1669 equalTo: "Please enter the same value again.", 1670 maxlength: $.validator.format( "Please enter no more than {0} characters." ), 1671 minlength: $.validator.format( "Please enter at least {0} characters." ), 1672 rangelength: $.validator.format( "Please enter a value between {0} and {1} characters long." ), 1673 range: $.validator.format( "Please enter a value between {0} and {1}." ), 1674 max: $.validator.format( "Please enter a value less than or equal to {0}." ), 1675 min: $.validator.format( "Please enter a value greater than or equal to {0}." ), 1676 step: $.validator.format( "Please enter a multiple of {0}." ) 1677 }, 1678 1679 autoCreateRanges: false, 1680 1681 prototype: { 1682 1683 init: function() { 1684 this.labelContainer = $( this.settings.errorLabelContainer ); 1685 this.errorContext = this.labelContainer.length && this.labelContainer || $( this.currentForm ); 1686 this.containers = $( this.settings.errorContainer ).add( this.settings.errorLabelContainer ); 1687 this.submitted = {}; 1688 this.valueCache = {}; 1689 this.pendingRequest = 0; 1690 this.pending = {}; 1691 this.invalid = {}; 1692 this.reset(); 1693 1694 var currentForm = this.currentForm, 1695 groups = ( this.groups = {} ), 1696 rules; 1697 $.each( this.settings.groups, function( key, value ) { 1698 if ( typeof value === "string" ) { 1699 value = value.split( /\s/ ); 1700 } 1701 $.each( value, function( index, name ) { 1702 groups[ name ] = key; 1703 } ); 1704 } ); 1705 rules = this.settings.rules; 1706 $.each( rules, function( key, value ) { 1707 rules[ key ] = $.validator.normalizeRule( value ); 1708 } ); 1709 1710 function delegate( event ) { 1711 var isContentEditable = typeof $( this ).attr( "contenteditable" ) !== "undefined" && $( this ).attr( "contenteditable" ) !== "false"; 1712 1713 // Set form expando on contenteditable 1714 if ( !this.form && isContentEditable ) { 1715 this.form = $( this ).closest( "form" )[ 0 ]; 1716 this.name = $( this ).attr( "name" ); 1717 } 1718 1719 // Ignore the element if it belongs to another form. This will happen mainly 1720 // when setting the `form` attribute of an input to the id of another form. 1721 if ( currentForm !== this.form ) { 1722 return; 1723 } 1724 1725 var validator = $.data( this.form, "validator" ), 1726 eventType = "on" + event.type.replace( /^validate/, "" ), 1727 settings = validator.settings; 1728 if ( settings[ eventType ] && !$( this ).is( settings.ignore ) ) { 1729 settings[ eventType ].call( validator, this, event ); 1730 } 1731 } 1732 1733 $( this.currentForm ) 1734 .on( "focusin.validate focusout.validate keyup.validate", 1735 ":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], " + 1736 "[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], " + 1737 "[type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], " + 1738 "[type='radio'], [type='checkbox'], [contenteditable], [type='button']", delegate ) 1739 1740 // Support: Chrome, oldIE 1741 // "select" is provided as event.target when clicking a option 1742 .on( "click.validate", "select, option, [type='radio'], [type='checkbox']", delegate ); 1743 1744 if ( this.settings.invalidHandler ) { 1745 $( this.currentForm ).on( "invalid-form.validate", this.settings.invalidHandler ); 1746 } 1747 }, 1748 1749 // https://jqueryvalidation.org/Validator.form/ 1750 form: function() { 1751 this.checkForm(); 1752 $.extend( this.submitted, this.errorMap ); 1753 this.invalid = $.extend( {}, this.errorMap ); 1754 if ( !this.valid() ) { 1755 $( this.currentForm ).triggerHandler( "invalid-form", [ this ] ); 1756 } 1757 this.showErrors(); 1758 return this.valid(); 1759 }, 1760 1761 checkForm: function() { 1762 this.prepareForm(); 1763 for ( var i = 0, elements = ( this.currentElements = this.elements() ); elements[ i ]; i++ ) { 1764 this.check( elements[ i ] ); 1765 } 1766 return this.valid(); 1767 }, 1768 1769 // https://jqueryvalidation.org/Validator.element/ 1770 element: function( element ) { 1771 var cleanElement = this.clean( element ), 1772 checkElement = this.validationTargetFor( cleanElement ), 1773 v = this, 1774 result = true, 1775 rs, group; 1776 1777 if ( checkElement === undefined ) { 1778 delete this.invalid[ cleanElement.name ]; 1779 } else { 1780 this.prepareElement( checkElement ); 1781 this.currentElements = $( checkElement ); 1782 1783 // If this element is grouped, then validate all group elements already 1784 // containing a value 1785 group = this.groups[ checkElement.name ]; 1786 if ( group ) { 1787 $.each( this.groups, function( name, testgroup ) { 1788 if ( testgroup === group && name !== checkElement.name ) { 1789 cleanElement = v.validationTargetFor( v.clean( v.findByName( name ) ) ); 1790 if ( cleanElement && cleanElement.name in v.invalid ) { 1791 v.currentElements.push( cleanElement ); 1792 result = v.check( cleanElement ) && result; 1793 } 1794 } 1795 } ); 1796 } 1797 1798 rs = this.check( checkElement ) !== false; 1799 result = result && rs; 1800 if ( rs ) { 1801 this.invalid[ checkElement.name ] = false; 1802 } else { 1803 this.invalid[ checkElement.name ] = true; 1804 } 1805 1806 if ( !this.numberOfInvalids() ) { 1807 1808 // Hide error containers on last error 1809 this.toHide = this.toHide.add( this.containers ); 1810 } 1811 this.showErrors(); 1812 1813 // Add aria-invalid status for screen readers 1814 $( element ).attr( "aria-invalid", !rs ); 1815 } 1816 1817 return result; 1818 }, 1819 1820 // https://jqueryvalidation.org/Validator.showErrors/ 1821 showErrors: function( errors ) { 1822 if ( errors ) { 1823 var validator = this; 1824 1825 // Add items to error list and map 1826 $.extend( this.errorMap, errors ); 1827 this.errorList = $.map( this.errorMap, function( message, name ) { 1828 return { 1829 message: message, 1830 element: validator.findByName( name )[ 0 ] 1831 }; 1832 } ); 1833 1834 // Remove items from success list 1835 this.successList = $.grep( this.successList, function( element ) { 1836 return !( element.name in errors ); 1837 } ); 1838 } 1839 if ( this.settings.showErrors ) { 1840 this.settings.showErrors.call( this, this.errorMap, this.errorList ); 1841 } else { 1842 this.defaultShowErrors(); 1843 } 1844 }, 1845 1846 // https://jqueryvalidation.org/Validator.resetForm/ 1847 resetForm: function() { 1848 if ( $.fn.resetForm ) { 1849 $( this.currentForm ).resetForm(); 1850 } 1851 this.invalid = {}; 1852 this.submitted = {}; 1853 this.prepareForm(); 1854 this.hideErrors(); 1855 var elements = this.elements() 1856 .removeData( "previousValue" ) 1857 .removeAttr( "aria-invalid" ); 1858 1859 this.resetElements( elements ); 1860 }, 1861 1862 resetElements: function( elements ) { 1863 var i; 1864 1865 if ( this.settings.unhighlight ) { 1866 for ( i = 0; elements[ i ]; i++ ) { 1867 this.settings.unhighlight.call( this, elements[ i ], 1868 this.settings.errorClass, "" ); 1869 this.findByName( elements[ i ].name ).removeClass( this.settings.validClass ); 1870 } 1871 } else { 1872 elements 1873 .removeClass( this.settings.errorClass ) 1874 .removeClass( this.settings.validClass ); 1875 } 1876 }, 1877 1878 numberOfInvalids: function() { 1879 return this.objectLength( this.invalid ); 1880 }, 1881 1882 objectLength: function( obj ) { 1883 /* jshint unused: false */ 1884 var count = 0, 1885 i; 1886 for ( i in obj ) { 1887 1888 // This check allows counting elements with empty error 1889 // message as invalid elements 1890 if ( obj[ i ] !== undefined && obj[ i ] !== null && obj[ i ] !== false ) { 1891 count++; 1892 } 1893 } 1894 return count; 1895 }, 1896 1897 hideErrors: function() { 1898 this.hideThese( this.toHide ); 1899 }, 1900 1901 hideThese: function( errors ) { 1902 errors.not( this.containers ).text( "" ); 1903 this.addWrapper( errors ).hide(); 1904 }, 1905 1906 valid: function() { 1907 return this.size() === 0; 1908 }, 1909 1910 size: function() { 1911 return this.errorList.length; 1912 }, 1913 1914 focusInvalid: function() { 1915 if ( this.settings.focusInvalid ) { 1916 try { 1917 $( this.findLastActive() || this.errorList.length && this.errorList[ 0 ].element || [] ) 1918 .filter( ":visible" ) 1919 .trigger( "focus" ) 1920 1921 // Manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find 1922 .trigger( "focusin" ); 1923 } catch ( e ) { 1924 1925 // Ignore IE throwing errors when focusing hidden elements 1926 } 1927 } 1928 }, 1929 1930 findLastActive: function() { 1931 var lastActive = this.lastActive; 1932 return lastActive && $.grep( this.errorList, function( n ) { 1933 return n.element.name === lastActive.name; 1934 } ).length === 1 && lastActive; 1935 }, 1936 1937 elements: function() { 1938 var validator = this, 1939 rulesCache = {}; 1940 1941 // Select all valid inputs inside the form (no submit or reset buttons) 1942 return $( this.currentForm ) 1943 .find( "input, select, textarea, [contenteditable]" ) 1944 .not( ":submit, :reset, :image, :disabled" ) 1945 .not( this.settings.ignore ) 1946 .filter( function() { 1947 var name = this.name || $( this ).attr( "name" ); // For contenteditable 1948 var isContentEditable = typeof $( this ).attr( "contenteditable" ) !== "undefined" && $( this ).attr( "contenteditable" ) !== "false"; 1949 1950 if ( !name && validator.settings.debug && window.console ) { 1951 console.error( "%o has no name assigned", this ); 1952 } 1953 1954 // Set form expando on contenteditable 1955 if ( isContentEditable ) { 1956 this.form = $( this ).closest( "form" )[ 0 ]; 1957 this.name = name; 1958 } 1959 1960 // Ignore elements that belong to other/nested forms 1961 if ( this.form !== validator.currentForm ) { 1962 return false; 1963 } 1964 1965 // Select only the first element for each name, and only those with rules specified 1966 if ( name in rulesCache || !validator.objectLength( $( this ).rules() ) ) { 1967 return false; 1968 } 1969 1970 rulesCache[ name ] = true; 1971 return true; 1972 } ); 1973 }, 1974 1975 clean: function( selector ) { 1976 return $( selector )[ 0 ]; 1977 }, 1978 1979 errors: function() { 1980 var errorClass = this.settings.errorClass.split( " " ).join( "." ); 1981 return $( this.settings.errorElement + "." + errorClass, this.errorContext ); 1982 }, 1983 1984 resetInternals: function() { 1985 this.successList = []; 1986 this.errorList = []; 1987 this.errorMap = {}; 1988 this.toShow = $( [] ); 1989 this.toHide = $( [] ); 1990 }, 1991 1992 reset: function() { 1993 this.resetInternals(); 1994 this.currentElements = $( [] ); 1995 }, 1996 1997 prepareForm: function() { 1998 this.reset(); 1999 this.toHide = this.errors().add( this.containers ); 2000 }, 2001 2002 prepareElement: function( element ) { 2003 this.reset(); 2004 this.toHide = this.errorsFor( element ); 2005 }, 2006 2007 elementValue: function( element ) { 2008 var $element = $( element ), 2009 type = element.type, 2010 isContentEditable = typeof $element.attr( "contenteditable" ) !== "undefined" && $element.attr( "contenteditable" ) !== "false", 2011 val, idx; 2012 2013 if ( type === "radio" || type === "checkbox" ) { 2014 return this.findByName( element.name ).filter( ":checked" ).val(); 2015 } else if ( type === "number" && typeof element.validity !== "undefined" ) { 2016 return element.validity.badInput ? "NaN" : $element.val(); 2017 } 2018 2019 if ( isContentEditable ) { 2020 val = $element.text(); 2021 } else { 2022 val = $element.val(); 2023 } 2024 2025 if ( type === "file" ) { 2026 2027 // Modern browser (chrome & safari) 2028 if ( val.substr( 0, 12 ) === "C:\\fakepath\\" ) { 2029 return val.substr( 12 ); 2030 } 2031 2032 // Legacy browsers 2033 // Unix-based path 2034 idx = val.lastIndexOf( "/" ); 2035 if ( idx >= 0 ) { 2036 return val.substr( idx + 1 ); 2037 } 2038 2039 // Windows-based path 2040 idx = val.lastIndexOf( "\\" ); 2041 if ( idx >= 0 ) { 2042 return val.substr( idx + 1 ); 2043 } 2044 2045 // Just the file name 2046 return val; 2047 } 2048 2049 if ( typeof val === "string" ) { 2050 return val.replace( /\r/g, "" ); 2051 } 2052 return val; 2053 }, 2054 2055 check: function( element ) { 2056 element = this.validationTargetFor( this.clean( element ) ); 2057 2058 var rules = $( element ).rules(), 2059 rulesCount = $.map( rules, function( n, i ) { 2060 return i; 2061 } ).length, 2062 dependencyMismatch = false, 2063 val = this.elementValue( element ), 2064 result, method, rule, normalizer; 2065 2066 // Prioritize the local normalizer defined for this element over the global one 2067 // if the former exists, otherwise user the global one in case it exists. 2068 if ( typeof rules.normalizer === "function" ) { 2069 normalizer = rules.normalizer; 2070 } else if ( typeof this.settings.normalizer === "function" ) { 2071 normalizer = this.settings.normalizer; 2072 } 2073 2074 // If normalizer is defined, then call it to retreive the changed value instead 2075 // of using the real one. 2076 // Note that `this` in the normalizer is `element`. 2077 if ( normalizer ) { 2078 val = normalizer.call( element, val ); 2079 2080 // Delete the normalizer from rules to avoid treating it as a pre-defined method. 2081 delete rules.normalizer; 2082 } 2083 2084 for ( method in rules ) { 2085 rule = { method: method, parameters: rules[ method ] }; 2086 try { 2087 result = $.validator.methods[ method ].call( this, val, element, rule.parameters ); 2088 2089 // If a method indicates that the field is optional and therefore valid, 2090 // don't mark it as valid when there are no other rules 2091 if ( result === "dependency-mismatch" && rulesCount === 1 ) { 2092 dependencyMismatch = true; 2093 continue; 2094 } 2095 dependencyMismatch = false; 2096 2097 if ( result === "pending" ) { 2098 this.toHide = this.toHide.not( this.errorsFor( element ) ); 2099 return; 2100 } 2101 2102 if ( !result ) { 2103 this.formatAndAdd( element, rule ); 2104 return false; 2105 } 2106 } catch ( e ) { 2107 if ( this.settings.debug && window.console ) { 2108 console.log( "Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.", e ); 2109 } 2110 if ( e instanceof TypeError ) { 2111 e.message += ". Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method."; 2112 } 2113 2114 throw e; 2115 } 2116 } 2117 if ( dependencyMismatch ) { 2118 return; 2119 } 2120 if ( this.objectLength( rules ) ) { 2121 this.successList.push( element ); 2122 } 2123 return true; 2124 }, 2125 2126 // Return the custom message for the given element and validation method 2127 // specified in the element's HTML5 data attribute 2128 // return the generic message if present and no method specific message is present 2129 customDataMessage: function( element, method ) { 2130 return $( element ).data( "msg" + method.charAt( 0 ).toUpperCase() + 2131 method.substring( 1 ).toLowerCase() ) || $( element ).data( "msg" ); 2132 }, 2133 2134 // Return the custom message for the given element name and validation method 2135 customMessage: function( name, method ) { 2136 var m = this.settings.messages[ name ]; 2137 return m && ( m.constructor === String ? m : m[ method ] ); 2138 }, 2139 2140 // Return the first defined argument, allowing empty strings 2141 findDefined: function() { 2142 for ( var i = 0; i < arguments.length; i++ ) { 2143 if ( arguments[ i ] !== undefined ) { 2144 return arguments[ i ]; 2145 } 2146 } 2147 return undefined; 2148 }, 2149 2150 // The second parameter 'rule' used to be a string, and extended to an object literal 2151 // of the following form: 2152 // rule = { 2153 // method: "method name", 2154 // parameters: "the given method parameters" 2155 // } 2156 // 2157 // The old behavior still supported, kept to maintain backward compatibility with 2158 // old code, and will be removed in the next major release. 2159 defaultMessage: function( element, rule ) { 2160 if ( typeof rule === "string" ) { 2161 rule = { method: rule }; 2162 } 2163 2164 var message = this.findDefined( 2165 this.customMessage( element.name, rule.method ), 2166 this.customDataMessage( element, rule.method ), 2167 2168 // 'title' is never undefined, so handle empty string as undefined 2169 !this.settings.ignoreTitle && element.title || undefined, 2170 $.validator.messages[ rule.method ], 2171 "<strong>Warning: No message defined for " + element.name + "</strong>" 2172 ), 2173 theregex = /\$?\{(\d+)\}/g; 2174 if ( typeof message === "function" ) { 2175 message = message.call( this, rule.parameters, element ); 2176 } else if ( theregex.test( message ) ) { 2177 message = $.validator.format( message.replace( theregex, "{$1}" ), rule.parameters ); 2178 } 2179 2180 return message; 2181 }, 2182 2183 formatAndAdd: function( element, rule ) { 2184 var message = this.defaultMessage( element, rule ); 2185 2186 this.errorList.push( { 2187 message: message, 2188 element: element, 2189 method: rule.method 2190 } ); 2191 2192 this.errorMap[ element.name ] = message; 2193 this.submitted[ element.name ] = message; 2194 }, 2195 2196 addWrapper: function( toToggle ) { 2197 if ( this.settings.wrapper ) { 2198 toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) ); 2199 } 2200 return toToggle; 2201 }, 2202 2203 defaultShowErrors: function() { 2204 var i, elements, error; 2205 for ( i = 0; this.errorList[ i ]; i++ ) { 2206 error = this.errorList[ i ]; 2207 if ( this.settings.highlight ) { 2208 this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass ); 2209 } 2210 this.showLabel( error.element, error.message ); 2211 } 2212 if ( this.errorList.length ) { 2213 this.toShow = this.toShow.add( this.containers ); 2214 } 2215 if ( this.settings.success ) { 2216 for ( i = 0; this.successList[ i ]; i++ ) { 2217 this.showLabel( this.successList[ i ] ); 2218 } 2219 } 2220 if ( this.settings.unhighlight ) { 2221 for ( i = 0, elements = this.validElements(); elements[ i ]; i++ ) { 2222 this.settings.unhighlight.call( this, elements[ i ], this.settings.errorClass, this.settings.validClass ); 2223 } 2224 } 2225 this.toHide = this.toHide.not( this.toShow ); 2226 this.hideErrors(); 2227 this.addWrapper( this.toShow ).show(); 2228 }, 2229 2230 validElements: function() { 2231 return this.currentElements.not( this.invalidElements() ); 2232 }, 2233 2234 invalidElements: function() { 2235 return $( this.errorList ).map( function() { 2236 return this.element; 2237 } ); 2238 }, 2239 2240 showLabel: function( element, message ) { 2241 var place, group, errorID, v, 2242 error = this.errorsFor( element ), 2243 elementID = this.idOrName( element ), 2244 describedBy = $( element ).attr( "aria-describedby" ); 2245 2246 if ( error.length ) { 2247 2248 // Refresh error/success class 2249 error.removeClass( this.settings.validClass ).addClass( this.settings.errorClass ); 2250 2251 // Replace message on existing label 2252 error.html( message ); 2253 } else { 2254 2255 // Create error element 2256 error = $( "<" + this.settings.errorElement + ">" ) 2257 .attr( "id", elementID + "-error" ) 2258 .addClass( this.settings.errorClass ) 2259 .html( message || "" ); 2260 2261 // Maintain reference to the element to be placed into the DOM 2262 place = error; 2263 if ( this.settings.wrapper ) { 2264 2265 // Make sure the element is visible, even in IE 2266 // actually showing the wrapped element is handled elsewhere 2267 place = error.hide().show().wrap( "<" + this.settings.wrapper + "/>" ).parent(); 2268 } 2269 if ( this.labelContainer.length ) { 2270 this.labelContainer.append( place ); 2271 } else if ( this.settings.errorPlacement ) { 2272 this.settings.errorPlacement.call( this, place, $( element ) ); 2273 } else { 2274 place.insertAfter( element ); 2275 } 2276 2277 // Link error back to the element 2278 if ( error.is( "label" ) ) { 2279 2280 // If the error is a label, then associate using 'for' 2281 error.attr( "for", elementID ); 2282 2283 // If the element is not a child of an associated label, then it's necessary 2284 // to explicitly apply aria-describedby 2285 } else if ( error.parents( "label[for='" + this.escapeCssMeta( elementID ) + "']" ).length === 0 ) { 2286 errorID = error.attr( "id" ); 2287 2288 // Respect existing non-error aria-describedby 2289 if ( !describedBy ) { 2290 describedBy = errorID; 2291 } else if ( !describedBy.match( new RegExp( "\\b" + this.escapeCssMeta( errorID ) + "\\b" ) ) ) { 2292 2293 // Add to end of list if not already present 2294 describedBy += " " + errorID; 2295 } 2296 $( element ).attr( "aria-describedby", describedBy ); 2297 2298 // If this element is grouped, then assign to all elements in the same group 2299 group = this.groups[ element.name ]; 2300 if ( group ) { 2301 v = this; 2302 $.each( v.groups, function( name, testgroup ) { 2303 if ( testgroup === group ) { 2304 $( "[name='" + v.escapeCssMeta( name ) + "']", v.currentForm ) 2305 .attr( "aria-describedby", error.attr( "id" ) ); 2306 } 2307 } ); 2308 } 2309 } 2310 } 2311 if ( !message && this.settings.success ) { 2312 error.text( "" ); 2313 if ( typeof this.settings.success === "string" ) { 2314 error.addClass( this.settings.success ); 2315 } else { 2316 this.settings.success( error, element ); 2317 } 2318 } 2319 this.toShow = this.toShow.add( error ); 2320 }, 2321 2322 errorsFor: function( element ) { 2323 var name = this.escapeCssMeta( this.idOrName( element ) ), 2324 describer = $( element ).attr( "aria-describedby" ), 2325 selector = "label[for='" + name + "'], label[for='" + name + "'] *"; 2326 2327 // 'aria-describedby' should directly reference the error element 2328 if ( describer ) { 2329 selector = selector + ", #" + this.escapeCssMeta( describer ) 2330 .replace( /\s+/g, ", #" ); 2331 } 2332 2333 return this 2334 .errors() 2335 .filter( selector ); 2336 }, 2337 2338 // See https://api.jquery.com/category/selectors/, for CSS 2339 // meta-characters that should be escaped in order to be used with JQuery 2340 // as a literal part of a name/id or any selector. 2341 escapeCssMeta: function( string ) { 2342 if ( string === undefined ) { 2343 return ""; 2344 } 2345 2346 return string.replace( /([\\!"#$%&'()*+,./:;<=>?@\[\]^`{|}~])/g, "\\$1" ); 2347 }, 2348 2349 idOrName: function( element ) { 2350 return this.groups[ element.name ] || ( this.checkable( element ) ? element.name : element.id || element.name ); 2351 }, 2352 2353 validationTargetFor: function( element ) { 2354 2355 // If radio/checkbox, validate first element in group instead 2356 if ( this.checkable( element ) ) { 2357 element = this.findByName( element.name ); 2358 } 2359 2360 // Always apply ignore filter 2361 return $( element ).not( this.settings.ignore )[ 0 ]; 2362 }, 2363 2364 checkable: function( element ) { 2365 return ( /radio|checkbox/i ).test( element.type ); 2366 }, 2367 2368 findByName: function( name ) { 2369 return $( this.currentForm ).find( "[name='" + this.escapeCssMeta( name ) + "']" ); 2370 }, 2371 2372 getLength: function( value, element ) { 2373 switch ( element.nodeName.toLowerCase() ) { 2374 case "select": 2375 return $( "option:selected", element ).length; 2376 case "input": 2377 if ( this.checkable( element ) ) { 2378 return this.findByName( element.name ).filter( ":checked" ).length; 2379 } 2380 } 2381 return value.length; 2382 }, 2383 2384 depend: function( param, element ) { 2385 return this.dependTypes[ typeof param ] ? this.dependTypes[ typeof param ]( param, element ) : true; 2386 }, 2387 2388 dependTypes: { 2389 "boolean": function( param ) { 2390 return param; 2391 }, 2392 "string": function( param, element ) { 2393 return !!$( param, element.form ).length; 2394 }, 2395 "function": function( param, element ) { 2396 return param( element ); 2397 } 2398 }, 2399 2400 optional: function( element ) { 2401 var val = this.elementValue( element ); 2402 return !$.validator.methods.required.call( this, val, element ) && "dependency-mismatch"; 2403 }, 2404 2405 startRequest: function( element ) { 2406 if ( !this.pending[ element.name ] ) { 2407 this.pendingRequest++; 2408 $( element ).addClass( this.settings.pendingClass ); 2409 this.pending[ element.name ] = true; 2410 } 2411 }, 2412 2413 stopRequest: function( element, valid ) { 2414 this.pendingRequest--; 2415 2416 // Sometimes synchronization fails, make sure pendingRequest is never < 0 2417 if ( this.pendingRequest < 0 ) { 2418 this.pendingRequest = 0; 2419 } 2420 delete this.pending[ element.name ]; 2421 $( element ).removeClass( this.settings.pendingClass ); 2422 if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() && this.pendingRequest === 0 ) { 2423 $( this.currentForm ).trigger( "submit" ); 2424 2425 // Remove the hidden input that was used as a replacement for the 2426 // missing submit button. The hidden input is added by `handle()` 2427 // to ensure that the value of the used submit button is passed on 2428 // for scripted submits triggered by this method 2429 if ( this.submitButton ) { 2430 $( "input:hidden[name='" + this.submitButton.name + "']", this.currentForm ).remove(); 2431 } 2432 2433 this.formSubmitted = false; 2434 } else if ( !valid && this.pendingRequest === 0 && this.formSubmitted ) { 2435 $( this.currentForm ).triggerHandler( "invalid-form", [ this ] ); 2436 this.formSubmitted = false; 2437 } 2438 }, 2439 2440 previousValue: function( element, method ) { 2441 method = typeof method === "string" && method || "remote"; 2442 2443 return $.data( element, "previousValue" ) || $.data( element, "previousValue", { 2444 old: null, 2445 valid: true, 2446 message: this.defaultMessage( element, { method: method } ) 2447 } ); 2448 }, 2449 2450 // Cleans up all forms and elements, removes validator-specific events 2451 destroy: function() { 2452 this.resetForm(); 2453 2454 $( this.currentForm ) 2455 .off( ".validate" ) 2456 .removeData( "validator" ) 2457 .find( ".validate-equalTo-blur" ) 2458 .off( ".validate-equalTo" ) 2459 .removeClass( "validate-equalTo-blur" ) 2460 .find( ".validate-lessThan-blur" ) 2461 .off( ".validate-lessThan" ) 2462 .removeClass( "validate-lessThan-blur" ) 2463 .find( ".validate-lessThanEqual-blur" ) 2464 .off( ".validate-lessThanEqual" ) 2465 .removeClass( "validate-lessThanEqual-blur" ) 2466 .find( ".validate-greaterThanEqual-blur" ) 2467 .off( ".validate-greaterThanEqual" ) 2468 .removeClass( "validate-greaterThanEqual-blur" ) 2469 .find( ".validate-greaterThan-blur" ) 2470 .off( ".validate-greaterThan" ) 2471 .removeClass( "validate-greaterThan-blur" ); 2472 } 2473 2474 }, 2475 2476 classRuleSettings: { 2477 required: { required: true }, 2478 email: { email: true }, 2479 url: { url: true }, 2480 date: { date: true }, 2481 dateISO: { dateISO: true }, 2482 number: { number: true }, 2483 digits: { digits: true }, 2484 creditcard: { creditcard: true } 2485 }, 2486 2487 addClassRules: function( className, rules ) { 2488 if ( className.constructor === String ) { 2489 this.classRuleSettings[ className ] = rules; 2490 } else { 2491 $.extend( this.classRuleSettings, className ); 2492 } 2493 }, 2494 2495 classRules: function( element ) { 2496 var rules = {}, 2497 classes = $( element ).attr( "class" ); 2498 2499 if ( classes ) { 2500 $.each( classes.split( " " ), function() { 2501 if ( this in $.validator.classRuleSettings ) { 2502 $.extend( rules, $.validator.classRuleSettings[ this ] ); 2503 } 2504 } ); 2505 } 2506 return rules; 2507 }, 2508 2509 normalizeAttributeRule: function( rules, type, method, value ) { 2510 2511 // Convert the value to a number for number inputs, and for text for backwards compability 2512 // allows type="date" and others to be compared as strings 2513 if ( /min|max|step/.test( method ) && ( type === null || /number|range|text/.test( type ) ) ) { 2514 value = Number( value ); 2515 2516 // Support Opera Mini, which returns NaN for undefined minlength 2517 if ( isNaN( value ) ) { 2518 value = undefined; 2519 } 2520 } 2521 2522 if ( value || value === 0 ) { 2523 rules[ method ] = value; 2524 } else if ( type === method && type !== "range" ) { 2525 2526 // Exception: the jquery validate 'range' method 2527 // does not test for the html5 'range' type 2528 rules[ type === "date" ? "dateISO" : method ] = true; 2529 } 2530 }, 2531 2532 attributeRules: function( element ) { 2533 var rules = {}, 2534 $element = $( element ), 2535 type = element.getAttribute( "type" ), 2536 method, value; 2537 2538 for ( method in $.validator.methods ) { 2539 2540 // Support for <input required> in both html5 and older browsers 2541 if ( method === "required" ) { 2542 value = element.getAttribute( method ); 2543 2544 // Some browsers return an empty string for the required attribute 2545 // and non-HTML5 browsers might have required="" markup 2546 if ( value === "" ) { 2547 value = true; 2548 } 2549 2550 // Force non-HTML5 browsers to return bool 2551 value = !!value; 2552 } else { 2553 value = $element.attr( method ); 2554 } 2555 2556 this.normalizeAttributeRule( rules, type, method, value ); 2557 } 2558 2559 // 'maxlength' may be returned as -1, 2147483647 ( IE ) and 524288 ( safari ) for text inputs 2560 if ( rules.maxlength && /-1|2147483647|524288/.test( rules.maxlength ) ) { 2561 delete rules.maxlength; 2562 } 2563 2564 return rules; 2565 }, 2566 2567 dataRules: function( element ) { 2568 var rules = {}, 2569 $element = $( element ), 2570 type = element.getAttribute( "type" ), 2571 method, value; 2572 2573 for ( method in $.validator.methods ) { 2574 value = $element.data( "rule" + method.charAt( 0 ).toUpperCase() + method.substring( 1 ).toLowerCase() ); 2575 2576 // Cast empty attributes like `data-rule-required` to `true` 2577 if ( value === "" ) { 2578 value = true; 2579 } 2580 2581 this.normalizeAttributeRule( rules, type, method, value ); 2582 } 2583 return rules; 2584 }, 2585 2586 staticRules: function( element ) { 2587 var rules = {}, 2588 validator = $.data( element.form, "validator" ); 2589 2590 if ( validator.settings.rules ) { 2591 rules = $.validator.normalizeRule( validator.settings.rules[ element.name ] ) || {}; 2592 } 2593 return rules; 2594 }, 2595 2596 normalizeRules: function( rules, element ) { 2597 2598 // Handle dependency check 2599 $.each( rules, function( prop, val ) { 2600 2601 // Ignore rule when param is explicitly false, eg. required:false 2602 if ( val === false ) { 2603 delete rules[ prop ]; 2604 return; 2605 } 2606 if ( val.param || val.depends ) { 2607 var keepRule = true; 2608 switch ( typeof val.depends ) { 2609 case "string": 2610 keepRule = !!$( val.depends, element.form ).length; 2611 break; 2612 case "function": 2613 keepRule = val.depends.call( element, element ); 2614 break; 2615 } 2616 if ( keepRule ) { 2617 rules[ prop ] = val.param !== undefined ? val.param : true; 2618 } else { 2619 $.data( element.form, "validator" ).resetElements( $( element ) ); 2620 delete rules[ prop ]; 2621 } 2622 } 2623 } ); 2624 2625 // Evaluate parameters 2626 $.each( rules, function( rule, parameter ) { 2627 rules[ rule ] = typeof parameter === "function" && rule !== "normalizer" ? parameter( element ) : parameter; 2628 } ); 2629 2630 // Clean number parameters 2631 $.each( [ "minlength", "maxlength" ], function() { 2632 if ( rules[ this ] ) { 2633 rules[ this ] = Number( rules[ this ] ); 2634 } 2635 } ); 2636 $.each( [ "rangelength", "range" ], function() { 2637 var parts; 2638 if ( rules[ this ] ) { 2639 if ( Array.isArray( rules[ this ] ) ) { 2640 rules[ this ] = [ Number( rules[ this ][ 0 ] ), Number( rules[ this ][ 1 ] ) ]; 2641 } else if ( typeof rules[ this ] === "string" ) { 2642 parts = rules[ this ].replace( /[\[\]]/g, "" ).split( /[\s,]+/ ); 2643 rules[ this ] = [ Number( parts[ 0 ] ), Number( parts[ 1 ] ) ]; 2644 } 2645 } 2646 } ); 2647 2648 if ( $.validator.autoCreateRanges ) { 2649 2650 // Auto-create ranges 2651 if ( rules.min != null && rules.max != null ) { 2652 rules.range = [ rules.min, rules.max ]; 2653 delete rules.min; 2654 delete rules.max; 2655 } 2656 if ( rules.minlength != null && rules.maxlength != null ) { 2657 rules.rangelength = [ rules.minlength, rules.maxlength ]; 2658 delete rules.minlength; 2659 delete rules.maxlength; 2660 } 2661 } 2662 2663 return rules; 2664 }, 2665 2666 // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true} 2667 normalizeRule: function( data ) { 2668 if ( typeof data === "string" ) { 2669 var transformed = {}; 2670 $.each( data.split( /\s/ ), function() { 2671 transformed[ this ] = true; 2672 } ); 2673 data = transformed; 2674 } 2675 return data; 2676 }, 2677 2678 // https://jqueryvalidation.org/jQuery.validator.addMethod/ 2679 addMethod: function( name, method, message ) { 2680 $.validator.methods[ name ] = method; 2681 $.validator.messages[ name ] = message !== undefined ? message : $.validator.messages[ name ]; 2682 if ( method.length < 3 ) { 2683 $.validator.addClassRules( name, $.validator.normalizeRule( name ) ); 2684 } 2685 }, 2686 2687 // https://jqueryvalidation.org/jQuery.validator.methods/ 2688 methods: { 2689 2690 // https://jqueryvalidation.org/required-method/ 2691 required: function( value, element, param ) { 2692 2693 // Check if dependency is met 2694 if ( !this.depend( param, element ) ) { 2695 return "dependency-mismatch"; 2696 } 2697 if ( element.nodeName.toLowerCase() === "select" ) { 2698 2699 // Could be an array for select-multiple or a string, both are fine this way 2700 var val = $( element ).val(); 2701 return val && val.length > 0; 2702 } 2703 if ( this.checkable( element ) ) { 2704 return this.getLength( value, element ) > 0; 2705 } 2706 return value !== undefined && value !== null && value.length > 0; 2707 }, 2708 2709 // https://jqueryvalidation.org/email-method/ 2710 email: function( value, element ) { 2711 2712 // From https://html.spec.whatwg.org/multipage/forms.html#valid-e-mail-address 2713 // Retrieved 2014-01-14 2714 // If you have a problem with this implementation, report a bug against the above spec 2715 // Or use custom methods to implement your own email validation 2716 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 ); 2717 }, 2718 2719 // https://jqueryvalidation.org/url-method/ 2720 url: function( value, element ) { 2721 2722 // Copyright (c) 2010-2013 Diego Perini, MIT licensed 2723 // https://gist.github.com/dperini/729294 2724 // see also https://mathiasbynens.be/demo/url-regex 2725 // modified to allow protocol-relative URLs 2726 return this.optional( element ) || /^(?:(?:(?:https?|ftp):)?\/\/)(?:(?:[^\]\[?\/<~#`!@$^&*()+=}|:";',>{ ]|%[0-9A-Fa-f]{2})+(?::(?:[^\]\[?\/<~#`!@$^&*()+=}|:";',>{ ]|%[0-9A-Fa-f]{2})*)?@)?(?:(?!(?: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-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62})?[a-z0-9\u00a1-\uffff]\.)+(?:[a-z\u00a1-\uffff]{2,}\.?))(?::\d{2,5})?(?:[/?#]\S*)?$/i.test( value ); 2727 }, 2728 2729 // https://jqueryvalidation.org/date-method/ 2730 date: ( function() { 2731 var called = false; 2732 2733 return function( value, element ) { 2734 if ( !called ) { 2735 called = true; 2736 if ( this.settings.debug && window.console ) { 2737 console.warn( 2738 "The `date` method is deprecated and will be removed in version '2.0.0'.\n" + 2739 "Please don't use it, since it relies on the Date constructor, which\n" + 2740 "behaves very differently across browsers and locales. Use `dateISO`\n" + 2741 "instead or one of the locale specific methods in `localizations/`\n" + 2742 "and `additional-methods.js`." 2743 ); 2744 } 2745 } 2746 2747 return this.optional( element ) || !/Invalid|NaN/.test( new Date( value ).toString() ); 2748 }; 2749 }() ), 2750 2751 // https://jqueryvalidation.org/dateISO-method/ 2752 dateISO: function( value, element ) { 2753 return this.optional( element ) || /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test( value ); 2754 }, 2755 2756 // https://jqueryvalidation.org/number-method/ 2757 number: function( value, element ) { 2758 return this.optional( element ) || /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test( value ); 2759 }, 2760 2761 // https://jqueryvalidation.org/digits-method/ 2762 digits: function( value, element ) { 2763 return this.optional( element ) || /^\d+$/.test( value ); 2764 }, 2765 2766 // https://jqueryvalidation.org/minlength-method/ 2767 minlength: function( value, element, param ) { 2768 var length = Array.isArray( value ) ? value.length : this.getLength( value, element ); 2769 return this.optional( element ) || length >= param; 2770 }, 2771 2772 // https://jqueryvalidation.org/maxlength-method/ 2773 maxlength: function( value, element, param ) { 2774 var length = Array.isArray( value ) ? value.length : this.getLength( value, element ); 2775 return this.optional( element ) || length <= param; 2776 }, 2777 2778 // https://jqueryvalidation.org/rangelength-method/ 2779 rangelength: function( value, element, param ) { 2780 var length = Array.isArray( value ) ? value.length : this.getLength( value, element ); 2781 return this.optional( element ) || ( length >= param[ 0 ] && length <= param[ 1 ] ); 2782 }, 2783 2784 // https://jqueryvalidation.org/min-method/ 2785 min: function( value, element, param ) { 2786 return this.optional( element ) || value >= param; 2787 }, 2788 2789 // https://jqueryvalidation.org/max-method/ 2790 max: function( value, element, param ) { 2791 return this.optional( element ) || value <= param; 2792 }, 2793 2794 // https://jqueryvalidation.org/range-method/ 2795 range: function( value, element, param ) { 2796 return this.optional( element ) || ( value >= param[ 0 ] && value <= param[ 1 ] ); 2797 }, 2798 2799 // https://jqueryvalidation.org/step-method/ 2800 step: function( value, element, param ) { 2801 var type = $( element ).attr( "type" ), 2802 errorMessage = "Step attribute on input type " + type + " is not supported.", 2803 supportedTypes = [ "text", "number", "range" ], 2804 re = new RegExp( "\\b" + type + "\\b" ), 2805 notSupported = type && !re.test( supportedTypes.join() ), 2806 decimalPlaces = function( num ) { 2807 var match = ( "" + num ).match( /(?:\.(\d+))?$/ ); 2808 if ( !match ) { 2809 return 0; 2810 } 2811 2812 // Number of digits right of decimal point. 2813 return match[ 1 ] ? match[ 1 ].length : 0; 2814 }, 2815 toInt = function( num ) { 2816 return Math.round( num * Math.pow( 10, decimals ) ); 2817 }, 2818 valid = true, 2819 decimals; 2820 2821 // Works only for text, number and range input types 2822 // TODO find a way to support input types date, datetime, datetime-local, month, time and week 2823 if ( notSupported ) { 2824 throw new Error( errorMessage ); 2825 } 2826 2827 decimals = decimalPlaces( param ); 2828 2829 // Value can't have too many decimals 2830 if ( decimalPlaces( value ) > decimals || toInt( value ) % toInt( param ) !== 0 ) { 2831 valid = false; 2832 } 2833 2834 return this.optional( element ) || valid; 2835 }, 2836 2837 // https://jqueryvalidation.org/equalTo-method/ 2838 equalTo: function( value, element, param ) { 2839 2840 // Bind to the blur event of the target in order to revalidate whenever the target field is updated 2841 var target = $( param ); 2842 if ( this.settings.onfocusout && target.not( ".validate-equalTo-blur" ).length ) { 2843 target.addClass( "validate-equalTo-blur" ).on( "blur.validate-equalTo", function() { 2844 $( element ).valid(); 2845 } ); 2846 } 2847 return value === target.val(); 2848 }, 2849 2850 // https://jqueryvalidation.org/remote-method/ 2851 remote: function( value, element, param, method ) { 2852 if ( this.optional( element ) ) { 2853 return "dependency-mismatch"; 2854 } 2855 2856 method = typeof method === "string" && method || "remote"; 2857 2858 var previous = this.previousValue( element, method ), 2859 validator, data, optionDataString; 2860 2861 if ( !this.settings.messages[ element.name ] ) { 2862 this.settings.messages[ element.name ] = {}; 2863 } 2864 previous.originalMessage = previous.originalMessage || this.settings.messages[ element.name ][ method ]; 2865 this.settings.messages[ element.name ][ method ] = previous.message; 2866 2867 param = typeof param === "string" && { url: param } || param; 2868 optionDataString = $.param( $.extend( { data: value }, param.data ) ); 2869 if ( previous.old === optionDataString ) { 2870 return previous.valid; 2871 } 2872 2873 previous.old = optionDataString; 2874 validator = this;
vendor: 29,940 bytes, lines 2875-2955
2875 this.startRequest( element ); 2876 data = {}; 2877 data[ element.name ] = value; 2878 $.ajax( $.extend( true, { 2879 mode: "abort", 2880 port: "validate" + element.name, 2881 dataType: "json", 2882 data: data, 2883 context: validator.currentForm, 2884 success: function( response ) { 2885 var valid = response === true || response === "true", 2886 errors, message, submitted; 2887 2888 validator.settings.messages[ element.name ][ method ] = previous.originalMessage; 2889 if ( valid ) { 2890 submitted = validator.formSubmitted; 2891 validator.resetInternals(); 2892 validator.toHide = validator.errorsFor( element ); 2893 validator.formSubmitted = submitted; 2894 validator.successList.push( element ); 2895 validator.invalid[ element.name ] = false; 2896 validator.showErrors(); 2897 } else { 2898 errors = {}; 2899 message = response || validator.defaultMessage( element, { method: method, parameters: value } ); 2900 errors[ element.name ] = previous.message = message; 2901 validator.invalid[ element.name ] = true; 2902 validator.showErrors( errors ); 2903 } 2904 previous.valid = valid; 2905 validator.stopRequest( element, valid ); 2906 } 2907 }, param ) ); 2908 return "pending"; 2909 } 2910 } 2911 2912} ); 2913 2914// Ajax mode: abort 2915// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]}); 2916// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort() 2917 2918var pendingRequests = {}, 2919 ajax; 2920 2921// Use a prefilter if available (1.5+) 2922if ( $.ajaxPrefilter ) { 2923 $.ajaxPrefilter( function( settings, _, xhr ) { 2924 var port = settings.port; 2925 if ( settings.mode === "abort" ) { 2926 if ( pendingRequests[ port ] ) { 2927 pendingRequests[ port ].abort(); 2928 } 2929 pendingRequests[ port ] = xhr; 2930 } 2931 } ); 2932} else { 2933 2934 // Proxy ajax 2935 ajax = $.ajax; 2936 $.ajax = function( settings ) { 2937 var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode, 2938 port = ( "port" in settings ? settings : $.ajaxSettings ).port; 2939 if ( mode === "abort" ) { 2940 if ( pendingRequests[ port ] ) { 2941 pendingRequests[ port ].abort(); 2942 } 2943 pendingRequests[ port ] = ajax.apply( this, arguments ); 2944 return pendingRequests[ port ]; 2945 } 2946 return ajax.apply( this, arguments ); 2947 }; 2948} 2949return $; 2950})); 2951 2952/*! jQuery Validation Plugin - v1.19.5 - 7/1/2022 2953 * https://jqueryvalidation.org/ 2954 * Copyright (c) 2022 J�rn Zaefferer; Licensed MIT */ 2955!function (a) { "function" == typeof define && define.amd ? define(["jquery"], a) : "object" == typeof module && module.exports ? module.exports = a(require("jquery")) : a(jQuery) }(function (a) { a.extend(a.fn, { validate: function (b) { if (!this.length) return void (b && b.debug && window.console && console.warn("Nothing selected, can't validate, returning nothing.")); var c = a.data(this[0], "validator"); return c ? c : (this.attr("novalidate", "novalidate"), c = new a.validator(b, this[0]), a.data(this[0], "validator", c), c.settings.onsubmit && (this.on("click.validate", ":submit", function (b) { c.submitButton = b.currentTarget, a(this).hasClass("cancel") && (c.cancelSubmit = !0), void 0 !== a(this).attr("formnovalidate") && (c.cancelSubmit = !0) }), this.on("submit.validate", function (b) { function d() { var d, e; return c.submitButton && (c.settings.submitHandler || c.formSubmitted) && (d = a("<input type='hidden'/>").attr("name", c.submitButton.name).val(a(c.submitButton).val()).appendTo(c.currentForm)), !(c.settings.submitHandler && !c.settings.debug) || (e = c.settings.submitHandler.call(c, c.currentForm, b), d && d.remove(), void 0 !== e && e) } return c.settings.debug && b.preventDefault(), c.cancelSubmit ? (c.cancelSubmit = !1, d()) : c.form() ? c.pendingRequest ? (c.formSubmitted = !0, !1) : d() : (c.focusInvalid(), !1) })), c) }, valid: function () { var b, c, d; return a(this[0]).is("form") ? b = this.validate().form() : (d = [], b = !0, c = a(this[0].form).validate(), this.each(function () { b = c.element(this) && b, b || (d = d.concat(c.errorList)) }), c.errorList = d), b }, rules: function (b, c) { var d, e, f, g, h, i, j = this[0], k = "undefined" != typeof this.attr("contenteditable") && "false" !== this.attr("contenteditable"); if (null != j && (!j.form && k && (j.form = this.closest("form")[0], j.name = this.attr("name")), null != j.form)) { if (b) switch (d = a.data(j.form, "validator").settings, e = d.rules, f = a.validator.staticRules(j), b) { case "add": a.extend(f, a.validator.normalizeRule(c)), delete f.messages, e[j.name] = f, c.messages && (d.messages[j.name] = a.extend(d.messages[j.name], c.messages)); break; case "remove": return c ? (i = {}, a.each(c.split(/\s/), function (a, b) { i[b] = f[b], delete f[b] }), i) : (delete e[j.name], f) }return g = a.validator.normalizeRules(a.extend({}, a.validator.classRules(j), a.validator.attributeRules(j), a.validator.dataRules(j), a.validator.staticRules(j)), j), g.required && (h = g.required, delete g.required, g = a.extend({ required: h }, g)), g.remote && (h = g.remote, delete g.remote, g = a.extend(g, { remote: h })), g } } }); var b = function (a) { return a.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, "") }; a.extend(a.expr.pseudos || a.expr[":"], { blank: function (c) { return !b("" + a(c).val()) }, filled: function (c) { var d = a(c).val(); return null !== d && !!b("" + d) }, unchecked: function (b) { return !a(b).prop("checked") } }), a.validator = function (b, c) { this.settings = a.extend(!0, {}, a.validator.defaults, b), this.currentForm = c, this.init() }, a.validator.format = function (b, c) { return 1 === arguments.length ? function () { var c = a.makeArray(arguments); return c.unshift(b), a.validator.format.apply(this, c) } : void 0 === c ? b : (arguments.length > 2 && c.constructor !== Array && (c = a.makeArray(arguments).slice(1)), c.constructor !== Array && (c = [c]), a.each(c, function (a, c) { b = b.replace(new RegExp("\\{" + a + "\\}", "g"), function () { return c }) }), b) }, a.extend(a.validator, { defaults: { messages: {}, groups: {}, rules: {}, errorClass: "error", pendingClass: "pending", validClass: "valid", errorElement: "label", focusCleanup: !1, focusInvalid: !0, errorContainer: a([]), errorLabelContainer: a([]), onsubmit: !0, ignore: ":hidden", ignoreTitle: !1, onfocusin: function (a) { this.lastActive = a, this.settings.focusCleanup && (this.settings.unhighlight && this.settings.unhighlight.call(this, a, this.settings.errorClass, this.settings.validClass), this.hideThese(this.errorsFor(a))) }, onfocusout: function (a) { this.checkable(a) || !(a.name in this.submitted) && this.optional(a) || this.element(a) }, onkeyup: function (b, c) { var d = [16, 17, 18, 20, 35, 36, 37, 38, 39, 40, 45, 144, 225]; 9 === c.which && "" === this.elementValue(b) || a.inArray(c.keyCode, d) !== -1 || (b.name in this.submitted || b.name in this.invalid) && this.element(b) }, onclick: function (a) { a.name in this.submitted ? this.element(a) : a.parentNode.name in this.submitted && this.element(a.parentNode) }, highlight: function (b, c, d) { "radio" === b.type ? this.findByName(b.name).addClass(c).removeClass(d) : a(b).addClass(c).removeClass(d) }, unhighlight: function (b, c, d) { "radio" === b.type ? this.findByName(b.name).removeClass(c).addClass(d) : a(b).removeClass(c).addClass(d) } }, setDefaults: function (b) { a.extend(a.validator.defaults, b) }, messages: { required: "This field is required.", remote: "Please fix this field.", email: "Please enter a valid email address.", url: "Please enter a valid URL.", date: "Please enter a valid date.", dateISO: "Please enter a valid date (ISO).", number: "Please enter a valid number.", digits: "Please enter only digits.", equalTo: "Please enter the same value again.", maxlength: a.validator.format("Please enter no more than {0} characters."), minlength: a.validator.format("Please enter at least {0} characters."), rangelength: a.validator.format("Please enter a value between {0} and {1} characters long."), range: a.validator.format("Please enter a value between {0} and {1}."), max: a.validator.format("Please enter a value less than or equal to {0}."), min: a.validator.format("Please enter a value greater than or equal to {0}."), step: a.validator.format("Please enter a multiple of {0}.") }, autoCreateRanges: !1, prototype: { init: function () { function b(b) { var c = "undefined" != typeof a(this).attr("contenteditable") && "false" !== a(this).attr("contenteditable"); if (!this.form && c && (this.form = a(this).closest("form")[0], this.name = a(this).attr("name")), d === this.form) { var e = a.data(this.form, "validator"), f = "on" + b.type.replace(/^validate/, ""), g = e.settings; g[f] && !a(this).is(g.ignore) && g[f].call(e, this, b) } } this.labelContainer = a(this.settings.errorLabelContainer), this.errorContext = this.labelContainer.length && this.labelContainer || a(this.currentForm), this.containers = a(this.settings.errorContainer).add(this.settings.errorLabelContainer), this.submitted = {}, this.valueCache = {}, this.pendingRequest = 0, this.pending = {}, this.invalid = {}, this.reset(); var c, d = this.currentForm, e = this.groups = {}; a.each(this.settings.groups, function (b, c) { "string" == typeof c && (c = c.split(/\s/)), a.each(c, function (a, c) { e[c] = b }) }), c = this.settings.rules, a.each(c, function (b, d) { c[b] = a.validator.normalizeRule(d) }), a(this.currentForm).on("focusin.validate focusout.validate keyup.validate", ":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], [type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], [type='radio'], [type='checkbox'], [contenteditable], [type='button']", b).on("click.validate", "select, option, [type='radio'], [type='checkbox']", b), this.settings.invalidHandler && a(this.currentForm).on("invalid-form.validate", this.settings.invalidHandler) }, form: function () { return this.checkForm(), a.extend(this.submitted, this.errorMap), this.invalid = a.extend({}, this.errorMap), this.valid() || a(this.currentForm).triggerHandler("invalid-form", [this]), this.showErrors(), this.valid() }, checkForm: function () { this.prepareForm(); for (var a = 0, b = this.currentElements = this.elements(); b[a]; a++)this.check(b[a]); return this.valid() }, element: function (b) { var c, d, e = this.clean(b), f = this.validationTargetFor(e), g = this, h = !0; return void 0 === f ? delete this.invalid[e.name] : (this.prepareElement(f), this.currentElements = a(f), d = this.groups[f.name], d && a.each(this.groups, function (a, b) { b === d && a !== f.name && (e = g.validationTargetFor(g.clean(g.findByName(a))), e && e.name in g.invalid && (g.currentElements.push(e), h = g.check(e) && h)) }), c = this.check(f) !== !1, h = h && c, c ? this.invalid[f.name] = !1 : this.invalid[f.name] = !0, this.numberOfInvalids() || (this.toHide = this.toHide.add(this.containers)), this.showErrors(), a(b).attr("aria-invalid", !c)), h }, showErrors: function (b) { if (b) { var c = this; a.extend(this.errorMap, b), this.errorList = a.map(this.errorMap, function (a, b) { return { message: a, element: c.findByName(b)[0] } }), this.successList = a.grep(this.successList, function (a) { return !(a.name in b) }) } this.settings.showErrors ? this.settings.showErrors.call(this, this.errorMap, this.errorList) : this.defaultShowErrors() }, resetForm: function () { a.fn.resetForm && a(this.currentForm).resetForm(), this.invalid = {}, this.submitted = {}, this.prepareForm(), this.hideErrors(); var b = this.elements().removeData("previousValue").removeAttr("aria-invalid"); this.resetElements(b) }, resetElements: function (a) { var b; if (this.settings.unhighlight) for (b = 0; a[b]; b++)this.settings.unhighlight.call(this, a[b], this.settings.errorClass, ""), this.findByName(a[b].name).removeClass(this.settings.validClass); else a.removeClass(this.settings.errorClass).removeClass(this.settings.validClass) }, numberOfInvalids: function () { return this.objectLength(this.invalid) }, objectLength: function (a) { var b, c = 0; for (b in a) void 0 !== a[b] && null !== a[b] && a[b] !== !1 && c++; return c }, hideErrors: function () { this.hideThese(this.toHide) }, hideThese: function (a) { a.not(this.containers).text(""), this.addWrapper(a).hide() }, valid: function () { return 0 === this.size() }, size: function () { return this.errorList.length }, focusInvalid: function () { if (this.settings.focusInvalid) try { a(this.findLastActive() || this.errorList.length && this.errorList[0].element || []).filter(":visible").trigger("focus").trigger("focusin") } catch (b) { } }, findLastActive: function () { var b = this.lastActive; return b && 1 === a.grep(this.errorList, function (a) { return a.element.name === b.name }).length && b }, elements: function () { var b = this, c = {}; return a(this.currentForm).find("input, select, textarea, [contenteditable]").not(":submit, :reset, :image, :disabled").not(this.settings.ignore).filter(function () { var d = this.name || a(this).attr("name"), e = "undefined" != typeof a(this).attr("contenteditable") && "false" !== a(this).attr("contenteditable"); return !d && b.settings.debug && window.console && console.error("%o has no name assigned", this), e && (this.form = a(this).closest("form")[0], this.name = d), this.form === b.currentForm && (!(d in c || !b.objectLength(a(this).rules())) && (c[d] = !0, !0)) }) }, clean: function (b) { return a(b)[0] }, errors: function () { var b = this.settings.errorClass.split(" ").join("."); return a(this.settings.errorElement + "." + b, this.errorContext) }, resetInternals: function () { this.successList = [], this.errorList = [], this.errorMap = {}, this.toShow = a([]), this.toHide = a([]) }, reset: function () { this.resetInternals(), this.currentElements = a([]) }, prepareForm: function () { this.reset(), this.toHide = this.errors().add(this.containers) }, prepareElement: function (a) { this.reset(), this.toHide = this.errorsFor(a) }, elementValue: function (b) { var c, d, e = a(b), f = b.type, g = "undefined" != typeof e.attr("contenteditable") && "false" !== e.attr("contenteditable"); return "radio" === f || "checkbox" === f ? this.findByName(b.name).filter(":checked").val() : "number" === f && "undefined" != typeof b.validity ? b.validity.badInput ? "NaN" : e.val() : (c = g ? e.text() : e.val(), "file" === f ? "C:\\fakepath\\" === c.substr(0, 12) ? c.substr(12) : (d = c.lastIndexOf("/"), d >= 0 ? c.substr(d + 1) : (d = c.lastIndexOf("\\"), d >= 0 ? c.substr(d + 1) : c)) : "string" == typeof c ? c.replace(/\r/g, "") : c) }, check: function (b) { b = this.validationTargetFor(this.clean(b)); var c, d, e, f, g = a(b).rules(), h = a.map(g, function (a, b) { return b }).length, i = !1, j = this.elementValue(b); "function" == typeof g.normalizer ? f = g.normalizer : "function" == typeof this.settings.normalizer && (f = this.settings.normalizer), f && (j = f.call(b, j), delete g.normalizer); for (d in g) { e = { method: d, parameters: g[d] }; try { if (c = a.validator.methods[d].call(this, j, b, e.parameters), "dependency-mismatch" === c && 1 === h) { i = !0; continue } if (i = !1, "pending" === c) return void (this.toHide = this.toHide.not(this.errorsFor(b))); if (!c) return this.formatAndAdd(b, e), !1 } catch (k) { throw this.settings.debug && window.console && console.log("Exception occurred when checking element " + b.id + ", check the '" + e.method + "' method.", k), k instanceof TypeError && (k.message += ". Exception occurred when checking element " + b.id + ", check the '" + e.method + "' method."), k } } if (!i) return this.objectLength(g) && this.successList.push(b), !0 }, customDataMessage: function (b, c) { return a(b).data("msg" + c.charAt(0).toUpperCase() + c.substring(1).toLowerCase()) || a(b).data("msg") }, customMessage: function (a, b) { var c = this.settings.messages[a]; return c && (c.constructor === String ? c : c[b]) }, findDefined: function () { for (var a = 0; a < arguments.length; a++)if (void 0 !== arguments[a]) return arguments[a] }, defaultMessage: function (b, c) { "string" == typeof c && (c = { method: c }); var d = this.findDefined(this.customMessage(b.name, c.method), this.customDataMessage(b, c.method), !this.settings.ignoreTitle && b.title || void 0, a.validator.messages[c.method], "<strong>Warning: No message defined for " + b.name + "</strong>"), e = /\$?\{(\d+)\}/g; return "function" == typeof d ? d = d.call(this, c.parameters, b) : e.test(d) && (d = a.validator.format(d.replace(e, "{$1}"), c.parameters)), d }, formatAndAdd: function (a, b) { var c = this.defaultMessage(a, b); this.errorList.push({ message: c, element: a, method: b.method }), this.errorMap[a.name] = c, this.submitted[a.name] = c }, addWrapper: function (a) { return this.settings.wrapper && (a = a.add(a.parent(this.settings.wrapper))), a }, defaultShowErrors: function () { var a, b, c; for (a = 0; this.errorList[a]; a++)c = this.errorList[a], this.settings.highlight && this.settings.highlight.call(this, c.element, this.settings.errorClass, this.settings.validClass), this.showLabel(c.element, c.message); if (this.errorList.length && (this.toShow = this.toShow.add(this.containers)), this.settings.success) for (a = 0; this.successList[a]; a++)this.showLabel(this.successList[a]); if (this.settings.unhighlight) for (a = 0, b = this.validElements(); b[a]; a++)this.settings.unhighlight.call(this, b[a], this.settings.errorClass, this.settings.validClass); this.toHide = this.toHide.not(this.toShow), this.hideErrors(), this.addWrapper(this.toShow).show() }, validElements: function () { return this.currentElements.not(this.invalidElements()) }, invalidElements: function () { return a(this.errorList).map(function () { return this.element }) }, showLabel: function (b, c) { var d, e, f, g, h = this.errorsFor(b), i = this.idOrName(b), j = a(b).attr("aria-describedby"); h.length ? (h.removeClass(this.settings.validClass).addClass(this.settings.errorClass), h.html(c)) : (h = a("<" + this.settings.errorElement + ">").attr("id", i + "-error").addClass(this.settings.errorClass).html(c || ""), d = h, this.settings.wrapper && (d = h.hide().show().wrap("<" + this.settings.wrapper + "/>").parent()), this.labelContainer.length ? this.labelContainer.append(d) : this.settings.errorPlacement ? this.settings.errorPlacement.call(this, d, a(b)) : d.insertAfter(b), h.is("label") ? h.attr("for", i) : 0 === h.parents("label[for='" + this.escapeCssMeta(i) + "']").length && (f = h.attr("id"), j ? j.match(new RegExp("\\b" + this.escapeCssMeta(f) + "\\b")) || (j += " " + f) : j = f, a(b).attr("aria-describedby", j), e = this.groups[b.name], e && (g = this, a.each(g.groups, function (b, c) { c === e && a("[name='" + g.escapeCssMeta(b) + "']", g.currentForm).attr("aria-describedby", h.attr("id")) })))), !c && this.settings.success && (h.text(""), "string" == typeof this.settings.success ? h.addClass(this.settings.success) : this.settings.success(h, b)), this.toShow = this.toShow.add(h) }, errorsFor: function (b) { var c = this.escapeCssMeta(this.idOrName(b)), d = a(b).attr("aria-describedby"), e = "label[for='" + c + "'], label[for='" + c + "'] *"; return d && (e = e + ", #" + this.escapeCssMeta(d).replace(/\s+/g, ", #")), this.errors().filter(e) }, escapeCssMeta: function (a) { return void 0 === a ? "" : a.replace(/([\\!"#$%&'()*+,./:;<=>?@\[\]^`{|}~])/g, "\\$1") }, idOrName: function (a) { return this.groups[a.name] || (this.checkable(a) ? a.name : a.id || a.name) }, validationTargetFor: function (b) { return this.checkable(b) && (b = this.findByName(b.name)), a(b).not(this.settings.ignore)[0] }, checkable: function (a) { return /radio|checkbox/i.test(a.type) }, findByName: function (b) { return a(this.currentForm).find("[name='" + this.escapeCssMeta(b) + "']") }, getLength: function (b, c) { switch (c.nodeName.toLowerCase()) { case "select": return a("option:selected", c).length; case "input": if (this.checkable(c)) return this.findByName(c.name).filter(":checked").length }return b.length }, depend: function (a, b) { return !this.dependTypes[typeof a] || this.dependTypes[typeof a](a, b) }, dependTypes: { "boolean": function (a) { return a }, string: function (b, c) { return !!a(b, c.form).length }, "function": function (a, b) { return a(b) } }, optional: function (b) { var c = this.elementValue(b); return !a.validator.methods.required.call(this, c, b) && "dependency-mismatch" }, startRequest: function (b) { this.pending[b.name] || (this.pendingRequest++, a(b).addClass(this.settings.pendingClass), this.pending[b.name] = !0) }, stopRequest: function (b, c) { this.pendingRequest--, this.pendingRequest < 0 && (this.pendingRequest = 0), delete this.pending[b.name], a(b).removeClass(this.settings.pendingClass), c && 0 === this.pendingRequest && this.formSubmitted && this.form() && 0 === this.pendingRequest ? (a(this.currentForm).trigger("submit"), this.submitButton && a("input:hidden[name='" + this.submitButton.name + "']", this.currentForm).remove(), this.formSubmitted = !1) : !c && 0 === this.pendingRequest && this.formSubmitted && (a(this.currentForm).triggerHandler("invalid-form", [this]), this.formSubmitted = !1) }, previousValue: function (b, c) { return c = "string" == typeof c && c || "remote", a.data(b, "previousValue") || a.data(b, "previousValue", { old: null, valid: !0, message: this.defaultMessage(b, { method: c }) }) }, destroy: function () { this.resetForm(), a(this.currentForm).off(".validate").removeData("validator").find(".validate-equalTo-blur").off(".validate-equalTo").removeClass("validate-equalTo-blur").find(".validate-lessThan-blur").off(".validate-lessThan").removeClass("validate-lessThan-blur").find(".validate-lessThanEqual-blur").off(".validate-lessThanEqual").removeClass("validate-lessThanEqual-blur").find(".validate-greaterThanEqual-blur").off(".validate-greaterThanEqual").removeClass("validate-greaterThanEqual-blur").find(".validate-greaterThan-blur").off(".validate-greaterThan").removeClass("validate-greaterThan-blur") } }, classRuleSettings: { required: { required: !0 }, email: { email: !0 }, url: { url: !0 }, date: { date: !0 }, dateISO: { dateISO: !0 }, number: { number: !0 }, digits: { digits: !0 }, creditcard: { creditcard: !0 } }, addClassRules: function (b, c) { b.constructor === String ? this.classRuleSettings[b] = c : a.extend(this.classRuleSettings, b) }, classRules: function (b) { var c = {}, d = a(b).attr("class"); return d && a.each(d.split(" "), function () { this in a.validator.classRuleSettings && a.extend(c, a.validator.classRuleSettings[this]) }), c }, normalizeAttributeRule: function (a, b, c, d) { /min|max|step/.test(c) && (null === b || /number|range|text/.test(b)) && (d = Number(d), isNaN(d) && (d = void 0)), d || 0 === d ? a[c] = d : b === c && "range" !== b && (a["date" === b ? "dateISO" : c] = !0) }, attributeRules: function (b) { var c, d, e = {}, f = a(b), g = b.getAttribute("type"); for (c in a.validator.methods) "required" === c ? (d = b.getAttribute(c), "" === d && (d = !0), d = !!d) : d = f.attr(c), this.normalizeAttributeRule(e, g, c, d); return e.maxlength && /-1|2147483647|524288/.test(e.maxlength) && delete e.maxlength, e }, dataRules: function (b) { var c, d, e = {}, f = a(b), g = b.getAttribute("type"); for (c in a.validator.methods) d = f.data("rule" + c.charAt(0).toUpperCase() + c.substring(1).toLowerCase()), "" === d && (d = !0), this.normalizeAttributeRule(e, g, c, d); return e }, staticRules: function (b) { var c = {}, d = a.data(b.form, "validator"); return d.settings.rules && (c = a.validator.normalizeRule(d.settings.rules[b.name]) || {}), c }, normalizeRules: function (b, c) { return a.each(b, function (d, e) { if (e === !1) return void delete b[d]; if (e.param || e.depends) { var f = !0; switch (typeof e.depends) { case "string": f = !!a(e.depends, c.form).length; break; case "function": f = e.depends.call(c, c) }f ? b[d] = void 0 === e.param || e.param : (a.data(c.form, "validator").resetElements(a(c)), delete b[d]) } }), a.each(b, function (a, d) { b[a] = "function" == typeof d && "normalizer" !== a ? d(c) : d }), a.each(["minlength", "maxlength"], function () { b[this] && (b[this] = Number(b[this])) }), a.each(["rangelength", "range"], function () { var a; b[this] && (Array.isArray(b[this]) ? b[this] = [Number(b[this][0]), Number(b[this][1])] : "string" == typeof b[this] && (a = b[this].replace(/[\[\]]/g, "").split(/[\s,]+/), b[this] = [Number(a[0]), Number(a[1])])) }), a.validator.autoCreateRanges && (null != b.min && null != b.max && (b.range = [b.min, b.max], delete b.min, delete b.max), null != b.minlength && null != b.maxlength && (b.rangelength = [b.minlength, b.maxlength], delete b.minlength, delete b.maxlength)), b }, normalizeRule: function (b) { if ("string" == typeof b) { var c = {}; a.each(b.split(/\s/), function () { c[this] = !0 }), b = c } return b }, addMethod: function (b, c, d) { a.validator.methods[b] = c, a.validator.messages[b] = void 0 !== d ? d : a.validator.messages[b], c.length < 3 && a.validator.addClassRules(b, a.validator.normalizeRule(b)) }, methods: { required: function (b, c, d) { if (!this.depend(d, c)) return "dependency-mismatch"; if ("select" === c.nodeName.toLowerCase()) { var e = a(c).val(); return e && e.length > 0 } return this.checkable(c) ? this.getLength(b, c) > 0 : void 0 !== b && null !== b && b.length > 0 }, email: function (a, b) { return this.optional(b) || /^[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(a) }, url: function (a, b) { return this.optional(b) || /^(?:(?:(?:https?|ftp):)?\/\/)(?:(?:[^\]\[?\/<~#`!@$^&*()+=}|:";',>{ ]|%[0-9A-Fa-f]{2})+(?::(?:[^\]\[?\/<~#`!@$^&*()+=}|:";',>{ ]|%[0-9A-Fa-f]{2})*)?@)?(?:(?!(?: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-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62})?[a-z0-9\u00a1-\uffff]\.)+(?:[a-z\u00a1-\uffff]{2,}\.?))(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(a) }, date: function () { var a = !1; return function (b, c) { return a || (a = !0, this.settings.debug && window.console && console.warn("The `date` method is deprecated and will be removed in version '2.0.0'.\nPlease don't use it, since it relies on the Date constructor, which\nbehaves very differently across browsers and locales. Use `dateISO`\ninstead or one of the locale specific methods in `localizations/`\nand `additional-methods.js`.")), this.optional(c) || !/Invalid|NaN/.test(new Date(b).toString()) } }(), dateISO: function (a, b) { return this.optional(b) || /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(a) }, number: function (a, b) { return this.optional(b) || /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(a) }, digits: function (a, b) { return this.optional(b) || /^\d+$/.test(a) }, minlength: function (a, b, c) { var d = Array.isArray(a) ? a.length : this.getLength(a, b); return this.optional(b) || d >= c }, maxlength: function (a, b, c) { var d = Array.isArray(a) ? a.length : this.getLength(a, b); return this.optional(b) || d <= c }, rangelength: function (a, b, c) { var d = Array.isArray(a) ? a.length : this.getLength(a, b); return this.optional(b) || d >= c[0] && d <= c[1] }, min: function (a, b, c) { return this.optional(b) || a >= c }, max: function (a, b, c) { return this.optional(b) || a <= c }, range: function (a, b, c) { return this.optional(b) || a >= c[0] && a <= c[1] }, step: function (b, c, d) { var e, f = a(c).attr("type"), g = "Step attribute on input type " + f + " is not supported.", h = ["text", "number", "range"], i = new RegExp("\\b" + f + "\\b"), j = f && !i.test(h.join()), k = function (a) { var b = ("" + a).match(/(?:\.(\d+))?$/); return b && b[1] ? b[1].length : 0 }, l = function (a) { return Math.round(a * Math.pow(10, e)) }, m = !0; if (j) throw new Error(g); return e = k(d), (k(b) > e || l(b) % l(d) !== 0) && (m = !1), this.optional(c) || m }, equalTo: function (b, c, d) { var e = a(d); return this.settings.onfocusout && e.not(".validate-equalTo-blur").length && e.addClass("validate-equalTo-blur").on("blur.validate-equalTo", function () { a(c).valid() }), b === e.val() }, remote: function (b, c, d, e) { if (this.optional(c)) return "dependency-mismatch"; e = "string" == typeof e && e || "remote"; var f, g, h, i = this.previousValue(c, e); return this.settings.messages[c.name] || (this.settings.messages[c.name] = {}), i.originalMessage = i.originalMessage || this.settings.messages[c.name][e], this.settings.messages[c.name][e] = i.message, d = "string" == typeof d && { url: d } || d, h = a.param(a.extend({ data: b }, d.data)), i.old === h ? i.valid : (i.old = h, f = this, this.startRequest(c), g = {}, g[c.name] = b, a.ajax(a.extend(!0, { mode: "abort", port: "validate" + c.name, dataType: "json", data: g, context: f.currentForm, success: function (a) { var d, g, h, j = a === !0 || "true" === a; f.settings.messages[c.name][e] = i.originalMessage, j ? (h = f.formSubmitted, f.resetInternals(), f.toHide = f.errorsFor(c), f.formSubmitted = h, f.successList.push(c), f.invalid[c.name] = !1, f.showErrors()) : (d = {}, g = a || f.defaultMessage(c, { method: e, parameters: b }), d[c.name] = i.message = g, f.invalid[c.name] = !0, f.showErrors(d)), i.valid = j, f.stopRequest(c, j) } }, d)), "pending") } } }); var c, d = {}; return a.ajaxPrefilter ? a.ajaxPrefilter(function (a, b, c) { var e = a.port; "abort" === a.mode && (d[e] && d[e].abort(), d[e] = c) }) : (c = a.ajax, a.ajax = function (b) { var e = ("mode" in b ? b : a.ajaxSettings).mode, f = ("port" in b ? b : a.ajaxSettings).port; return "abort" === e ? (d[f] && d[f].abort(), d[f] = c.apply(this, arguments), d[f]) : c.apply(this, arguments) }), a });
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.