PageSourceSearch

https://crpf.gov.in/lib/jquery-validation/dist/jquery.validate.min.js

js crpf.gov.in collected 2026-10-03 17:34:57 UTC 52,730 bytes, 1,661 lines download raw bytes

vendor: 52,730 bytes, lines 1-1661
1/*!
2 * jQuery Validation Plugin v1.19.5
3 *
4 * https://jqueryvalidation.org/
5 *
6 * Copyright (c) 2022 Jörn Zaefferer
7 * Released under the MIT license
8 */
9(function (factory) {
10	if (typeof define === "function" && define.amd) {
11		define(["jquery"], factory);
12	} else if (typeof module === "object" && module.exports) {
13		module.exports = factory(require("jquery"));
14	} else {
15		factory(jQuery);
16	}
17}(function ($) {
18
19	$.extend($.fn, {
20
21		// https://jqueryvalidation.org/validate/
22		validate: function (options) {
23
24			// If nothing is selected, return nothing; can't chain anyway
25			if (!this.length) {
26				if (options && options.debug && window.console) {
27					console.warn("Nothing selected, can't validate, returning nothing.");
28				}
29				return;
30			}
31
32			// Check if a validator for this form was already created
33			var validator = $.data(this[0], "validator");
34			if (validator) {
35				return validator;
36			}
37
38			// Add novalidate tag if HTML5.
39			this.attr("novalidate", "novalidate");
40
41			validator = new $.validator(options, this[0]);
42			$.data(this[0], "validator", validator);
43
44			if (validator.settings.onsubmit) {
45
46				this.on("click.validate", ":submit", function (event) {
47
48					// Track the used submit button to properly handle scripted
49					// submits later.
50					validator.submitButton = event.currentTarget;
51
52					// Allow suppressing validation by adding a cancel class to the submit button
53					if ($(this).hasClass("cancel")) {
54						validator.cancelSubmit = true;
55					}
56
57					// Allow suppressing validation by adding the html5 formnovalidate attribute to the submit button
58					if ($(this).attr("formnovalidate") !== undefined) {
59						validator.cancelSubmit = true;
60					}
61				});
62
63				// Validate the form on submit
64				this.on("submit.validate", function (event) {
65					if (validator.settings.debug) {
66
67						// Prevent form submit to be able to see console output
68						event.preventDefault();
69					}
70
71					function handle() {
72						var hidden, result;
73
74						// Insert a hidden input as a replacement for the missing submit button
75						// The hidden input is inserted in two cases:
76						//   - A user defined a `submitHandler`
77						//   - There was a pending request due to `remote` method and `stopRequest()`
78						//     was called to submit the form in case it's valid
79						if (validator.submitButton && (validator.settings.submitHandler || validator.formSubmitted)) {
80							hidden = $("<input type='hidden'/>")
81								.attr("name", validator.submitButton.name)
82								.val($(validator.submitButton).val())
83								.appendTo(validator.currentForm);
84						}
85
86						if (validator.settings.submitHandler && !validator.settings.debug) {
87							result = validator.settings.submitHandler.call(validator, validator.currentForm, event);
88							if (hidden) {
89
90								// And clean up afterwards; thanks to no-block-scope, hidden can be referenced
91								hidden.remove();
92							}
93							if (result !== undefined) {
94								return result;
95							}
96							return false;
97						}
98						return true;
99					}
100
101					// Prevent submit for invalid forms or custom submit handlers
102					if (validator.cancelSubmit) {
103						validator.cancelSubmit = false;
104						return handle();
105					}
106					if (validator.form()) {
107						if (validator.pendingRequest) {
108							validator.formSubmitted = true;
109							return false;
110						}
111						return handle();
112					} else {
113						validator.focusInvalid();
114						return false;
115					}
116				});
117			}
118
119			return validator;
120		},
121
122		// https://jqueryvalidation.org/valid/
123		valid: function () {
124			var valid, validator, errorList;
125
126			if ($(this[0]).is("form")) {
127				valid = this.validate().form();
128			} else {
129				errorList = [];
130				valid = true;
131				validator = $(this[0].form).validate();
132				this.each(function () {
133					valid = validator.element(this) && valid;
134					if (!valid) {
135						errorList = errorList.concat(validator.errorList);
136					}
137				});
138				validator.errorList = errorList;
139			}
140			return valid;
141		},
142
143		// https://jqueryvalidation.org/rules/
144		rules: function (command, argument) {
145			var element = this[0],
146				isContentEditable = typeof this.attr("contenteditable") !== "undefined" && this.attr("contenteditable") !== "false",
147				settings, staticRules, existingRules, data, param, filtered;
148
149			// If nothing is selected, return empty object; can't chain anyway
150			if (element == null) {
151				return;
152			}
153
154			if (!element.form && isContentEditable) {
155				element.form = this.closest("form")[0];
156				element.name = this.attr("name");
157			}
158
159			if (element.form == null) {
160				return;
161			}
162
163			if (command) {
164				settings = $.data(element.form, "validator").settings;
165				staticRules = settings.rules;
166				existingRules = $.validator.staticRules(element);
167				switch (command) {
168					case "add":
169						$.extend(existingRules, $.validator.normalizeRule(argument));
170
171						// Remove messages from rules, but allow them to be set separately
172						delete existingRules.messages;
173						staticRules[element.name] = existingRules;
174						if (argument.messages) {
175							settings.messages[element.name] = $.extend(settings.messages[element.name], argument.messages);
176						}
177						break;
178					case "remove":
179						if (!argument) {
180							delete staticRules[element.name];
181							return existingRules;
182						}
183						filtered = {};
184						$.each(argument.split(/\s/), function (index, method) {
185							filtered[method] = existingRules[method];
186							delete existingRules[method];
187						});
188						return filtered;
189				}
190			}
191
192			data = $.validator.normalizeRules(
193				$.extend(
194					{},
195					$.validator.classRules(element),
196					$.validator.attributeRules(element),
197					$.validator.dataRules(element),
198					$.validator.staticRules(element)
199				), element);
200
201			// Make sure required is at front
202			if (data.required) {
203				param = data.required;
204				delete data.required;
205				data = $.extend({ required: param }, data);
206			}
207
208			// Make sure remote is at back
209			if (data.remote) {
210				param = data.remote;
211				delete data.remote;
212				data = $.extend(data, { remote: param });
213			}
214
215			return data;
216		}
217	});
218
219	// JQuery trim is deprecated, provide a trim method based on String.prototype.trim
220	var trim = function (str) {
221
222		// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trim#Polyfill
223		return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, "");
224	};
225
226	// Custom selectors
227	$.extend($.expr.pseudos || $.expr[":"], {		// '|| $.expr[ ":" ]' here enables backwards compatibility to jQuery 1.7. Can be removed when dropping jQ 1.7.x support
228
229		// https://jqueryvalidation.org/blank-selector/
230		blank: function (a) {
231			return !trim("" + $(a).val());
232		},
233
234		// https://jqueryvalidation.org/filled-selector/
235		filled: function (a) {
236			var val = $(a).val();
237			return val !== null && !!trim("" + val);
238		},
239
240		// https://jqueryvalidation.org/unchecked-selector/
241		unchecked: function (a) {
242			return !$(a).prop("checked");
243		}
244	});
245
246	// Constructor for validator
247	$.validator = function (options, form) {
248		this.settings = $.extend(true, {}, $.validator.defaults, options);
249		this.currentForm = form;
250		this.init();
251	};
252
253	// https://jqueryvalidation.org/jQuery.validator.format/
254	$.validator.format = function (source, params) {
255		if (arguments.length === 1) {
256			return function () {
257				var args = $.makeArray(arguments);
258				args.unshift(source);
259				return $.validator.format.apply(this, args);
260			};
261		}
262		if (params === undefined) {
263			return source;
264		}
265		if (arguments.length > 2 && params.constructor !== Array) {
266			params = $.makeArray(arguments).slice(1);
267		}
268		if (params.constructor !== Array) {
269			params = [params];
270		}
271		$.each(params, function (i, n) {
272			source = source.replace(new RegExp("\\{" + i + "\\}", "g"), function () {
273				return n;
274			});
275		});
276		return source;
277	};
278
279	$.extend($.validator, {
280
281		defaults: {
282			messages: {},
283			groups: {},
284			rules: {},
285			errorClass: "error",
286			pendingClass: "pending",
287			validClass: "valid",
288			errorElement: "label",
289			focusCleanup: false,
290			focusInvalid: true,
291			errorContainer: $([]),
292			errorLabelContainer: $([]),
293			onsubmit: true,
294			ignore: ":hidden",
295			ignoreTitle: false,
296			onfocusin: function (element) {
297				this.lastActive = element;
298
299				// Hide error label and remove error class on focus if enabled
300				if (this.settings.focusCleanup) {
301					if (this.settings.unhighlight) {
302						this.settings.unhighlight.call(this, element, this.settings.errorClass, this.settings.validClass);
303					}
304					this.hideThese(this.errorsFor(element));
305				}
306			},
307			onfocusout: function (element) {
308				if (!this.checkable(element) && (element.name in this.submitted || !this.optional(element))) {
309					this.element(element);
310				}
311			},
312			onkeyup: function (element, event) {
313
314				// Avoid revalidate the field when pressing one of the following keys
315				// Shift       => 16
316				// Ctrl        => 17
317				// Alt         => 18
318				// Caps lock   => 20
319				// End         => 35
320				// Home        => 36
321				// Left arrow  => 37
322				// Up arrow    => 38
323				// Right arrow => 39
324				// Down arrow  => 40
325				// Insert      => 45
326				// Num lock    => 144
327				// AltGr key   => 225
328				var excludedKeys = [
329					16, 17, 18, 20, 35, 36, 37,
330					38, 39, 40, 45, 144, 225
331				];
332
333				if (event.which === 9 && this.elementValue(element) === "" || $.inArray(event.keyCode, excludedKeys) !== -1) {
334					return;
335				} else if (element.name in this.submitted || element.name in this.invalid) {
336					this.element(element);
337				}
338			},
339			onclick: function (element) {
340
341				// Click on selects, radiobuttons and checkboxes
342				if (element.name in this.submitted) {
343					this.element(element);
344
345					// Or option elements, check parent select in that case
346				} else if (element.parentNode.name in this.submitted) {
347					this.element(element.parentNode);
348				}
349			},
350			highlight: function (element, errorClass, validClass) {
351				if (element.type === "radio") {
352					this.findByName(element.name).addClass(errorClass).removeClass(validClass);
353				} else {
354					$(element).addClass(errorClass).removeClass(validClass);
355				}
356			},
357			unhighlight: function (element, errorClass, validClass) {
358				if (element.type === "radio") {
359					this.findByName(element.name).removeClass(errorClass).addClass(validClass);
360				} else {
361					$(element).removeClass(errorClass).addClass(validClass);
362				}
363			}
364		},
365
366		// https://jqueryvalidation.org/jQuery.validator.setDefaults/
367		setDefaults: function (settings) {
368			$.extend($.validator.defaults, settings);
369		},
370
371		messages: {
372			required: "This field is required.",
373			remote: "Please fix this field.",
374			email: "Please enter a valid email address.",
375			url: "Please enter a valid URL.",
376			date: "Please enter a valid date.",
377			dateISO: "Please enter a valid date (ISO).",
378			number: "Please enter a valid number.",
379			digits: "Please enter only digits.",
380			equalTo: "Please enter the same value again.",
381			maxlength: $.validator.format("Please enter no more than {0} characters."),
382			minlength: $.validator.format("Please enter at least {0} characters."),
383			rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."),
384			range: $.validator.format("Please enter a value between {0} and {1}."),
385			max: $.validator.format("Please enter a value less than or equal to {0}."),
386			min: $.validator.format("Please enter a value greater than or equal to {0}."),
387			step: $.validator.format("Please enter a multiple of {0}.")
388		},
389
390		autoCreateRanges: false,
391
392		prototype: {
393
394			init: function () {
395				this.labelContainer = $(this.settings.errorLabelContainer);
396				this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
397				this.containers = $(this.settings.errorContainer).add(this.settings.errorLabelContainer);
398				this.submitted = {};
399				this.valueCache = {};
400				this.pendingRequest = 0;
401				this.pending = {};
402				this.invalid = {};
403				this.reset();
404
405				var currentForm = this.currentForm,
406					groups = (this.groups = {}),
407					rules;
408				$.each(this.settings.groups, function (key, value) {
409					if (typeof value === "string") {
410						value = value.split(/\s/);
411					}
412					$.each(value, function (index, name) {
413						groups[name] = key;
414					});
415				});
416				rules = this.settings.rules;
417				$.each(rules, function (key, value) {
418					rules[key] = $.validator.normalizeRule(value);
419				});
420
421				function delegate(event) {
422					var isContentEditable = typeof $(this).attr("contenteditable") !== "undefined" && $(this).attr("contenteditable") !== "false";
423
424					// Set form expando on contenteditable
425					if (!this.form && isContentEditable) {
426						this.form = $(this).closest("form")[0];
427						this.name = $(this).attr("name");
428					}
429
430					// Ignore the element if it belongs to another form. This will happen mainly
431					// when setting the `form` attribute of an input to the id of another form.
432					if (currentForm !== this.form) {
433						return;
434					}
435
436					var validator = $.data(this.form, "validator"),
437						eventType = "on" + event.type.replace(/^validate/, ""),
438						settings = validator.settings;
439					if (settings[eventType] && !$(this).is(settings.ignore)) {
440						settings[eventType].call(validator, this, event);
441					}
442				}
443
444				$(this.currentForm)
445					.on("focusin.validate focusout.validate keyup.validate",
446						":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], " +
447						"[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], " +
448						"[type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], " +
449						"[type='radio'], [type='checkbox'], [contenteditable], [type='button']", delegate)
450
451					// Support: Chrome, oldIE
452					// "select" is provided as event.target when clicking a option
453					.on("click.validate", "select, option, [type='radio'], [type='checkbox']", delegate);
454
455				if (this.settings.invalidHandler) {
456					$(this.currentForm).on("invalid-form.validate", this.settings.invalidHandler);
457				}
458			},
459
460			// https://jqueryvalidation.org/Validator.form/
461			form: function () {
462				this.checkForm();
463				$.extend(this.submitted, this.errorMap);
464				this.invalid = $.extend({}, this.errorMap);
465				if (!this.valid()) {
466					$(this.currentForm).triggerHandler("invalid-form", [this]);
467				}
468				this.showErrors();
469				return this.valid();
470			},
471
472			checkForm: function () {
473				this.prepareForm();
474				for (var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++) {
475					this.check(elements[i]);
476				}
477				return this.valid();
478			},
479
480			// https://jqueryvalidation.org/Validator.element/
481			element: function (element) {
482				var cleanElement = this.clean(element),
483					checkElement = this.validationTargetFor(cleanElement),
484					v = this,
485					result = true,
486					rs, group;
487
488				if (checkElement === undefined) {
489					delete this.invalid[cleanElement.name];
490				} else {
491					this.prepareElement(checkElement);
492					this.currentElements = $(checkElement);
493
494					// If this element is grouped, then validate all group elements already
495					// containing a value
496					group = this.groups[checkElement.name];
497					if (group) {
498						$.each(this.groups, function (name, testgroup) {
499							if (testgroup === group && name !== checkElement.name) {
500								cleanElement = v.validationTargetFor(v.clean(v.findByName(name)));
501								if (cleanElement && cleanElement.name in v.invalid) {
502									v.currentElements.push(cleanElement);
503									result = v.check(cleanElement) && result;
504								}
505							}
506						});
507					}
508
509					rs = this.check(checkElement) !== false;
510					result = result && rs;
511					if (rs) {
512						this.invalid[checkElement.name] = false;
513					} else {
514						this.invalid[checkElement.name] = true;
515					}
516
517					if (!this.numberOfInvalids()) {
518
519						// Hide error containers on last error
520						this.toHide = this.toHide.add(this.containers);
521					}
522					this.showErrors();
523
524					// Add aria-invalid status for screen readers
525					$(element).attr("aria-invalid", !rs);
526				}
527
528				return result;
529			},
530
531			// https://jqueryvalidation.org/Validator.showErrors/
532			showErrors: function (errors) {
533				if (errors) {
534					var validator = this;
535
536					// Add items to error list and map
537					$.extend(this.errorMap, errors);
538					this.errorList = $.map(this.errorMap, function (message, name) {
539						return {
540							message: message,
541							element: validator.findByName(name)[0]
542						};
543					});
544
545					// Remove items from success list
546					this.successList = $.grep(this.successList, function (element) {
547						return !(element.name in errors);
548					});
549				}
550				if (this.settings.showErrors) {
551					this.settings.showErrors.call(this, this.errorMap, this.errorList);
552				} else {
553					this.defaultShowErrors();
554				}
555			},
556
557			// https://jqueryvalidation.org/Validator.resetForm/
558			resetForm: function () {
559				if ($.fn.resetForm) {
560					$(this.currentForm).resetForm();
561				}
562				this.invalid = {};
563				this.submitted = {};
564				this.prepareForm();
565				this.hideErrors();
566				var elements = this.elements()
567					.removeData("previousValue")
568					.removeAttr("aria-invalid");
569
570				this.resetElements(elements);
571			},
572
573			resetElements: function (elements) {
574				var i;
575
576				if (this.settings.unhighlight) {
577					for (i = 0; elements[i]; i++) {
578						this.settings.unhighlight.call(this, elements[i],
579							this.settings.errorClass, "");
580						this.findByName(elements[i].name).removeClass(this.settings.validClass);
581					}
582				} else {
583					elements
584						.removeClass(this.settings.errorClass)
585						.removeClass(this.settings.validClass);
586				}
587			},
588
589			numberOfInvalids: function () {
590				return this.objectLength(this.invalid);
591			},
592
593			objectLength: function (obj) {
594				/* jshint unused: false */
595				var count = 0,
596					i;
597				for (i in obj) {
598
599					// This check allows counting elements with empty error
600					// message as invalid elements
601					if (obj[i] !== undefined && obj[i] !== null && obj[i] !== false) {
602						count++;
603					}
604				}
605				return count;
606			},
607
608			hideErrors: function () {
609				this.hideThese(this.toHide);
610			},
611
612			hideThese: function (errors) {
613				errors.not(this.containers).text("");
614				this.addWrapper(errors).hide();
615			},
616
617			valid: function () {
618				return this.size() === 0;
619			},
620
621			size: function () {
622				return this.errorList.length;
623			},
624
625			focusInvalid: function () {
626				if (this.settings.focusInvalid) {
627					try {
628						$(this.findLastActive() || this.errorList.length && this.errorList[0].element || [])
629							.filter(":visible")
630							.trigger("focus")
631
632							// Manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
633							.trigger("focusin");
634					} catch (e) {
635
636						// Ignore IE throwing errors when focusing hidden elements
637					}
638				}
639			},
640
641			findLastActive: function () {
642				var lastActive = this.lastActive;
643				return lastActive && $.grep(this.errorList, function (n) {
644					return n.element.name === lastActive.name;
645				}).length === 1 && lastActive;
646			},
647
648			elements: function () {
649				var validator = this,
650					rulesCache = {};
651
652				// Select all valid inputs inside the form (no submit or reset buttons)
653				return $(this.currentForm)
654					.find("input, select, textarea, [contenteditable]")
655					.not(":submit, :reset, :image, :disabled")
656					.not(this.settings.ignore)
657					.filter(function () {
658						var name = this.name || $(this).attr("name"); // For contenteditable
659						var isContentEditable = typeof $(this).attr("contenteditable") !== "undefined" && $(this).attr("contenteditable") !== "false";
660
661						if (!name && validator.settings.debug && window.console) {
662							console.error("%o has no name assigned", this);
663						}
664
665						// Set form expando on contenteditable
666						if (isContentEditable) {
667							this.form = $(this).closest("form")[0];
668							this.name = name;
669						}
670
671						// Ignore elements that belong to other/nested forms
672						if (this.form !== validator.currentForm) {
673							return false;
674						}
675
676						// Select only the first element for each name, and only those with rules specified
677						if (name in rulesCache || !validator.objectLength($(this).rules())) {
678							return false;
679						}
680
681						rulesCache[name] = true;
682						return true;
683					});
684			},
685
686			clean: function (selector) {
687				return $(selector)[0];
688			},
689
690			errors: function () {
691				var errorClass = this.settings.errorClass.split(" ").join(".");
692				return $(this.settings.errorElement + "." + errorClass, this.errorContext);
693			},
694
695			resetInternals: function () {
696				this.successList = [];
697				this.errorList = [];
698				this.errorMap = {};
699				this.toShow = $([]);
700				this.toHide = $([]);
701			},
702
703			reset: function () {
704				this.resetInternals();
705				this.currentElements = $([]);
706			},
707
708			prepareForm: function () {
709				this.reset();
710				this.toHide = this.errors().add(this.containers);
711			},
712
713			prepareElement: function (element) {
714				this.reset();
715				this.toHide = this.errorsFor(element);
716			},
717
718			elementValue: function (element) {
719				var $element = $(element),
720					type = element.type,
721					isContentEditable = typeof $element.attr("contenteditable") !== "undefined" && $element.attr("contenteditable") !== "false",
722					val, idx;
723
724				if (type === "radio" || type === "checkbox") {
725					return this.findByName(element.name).filter(":checked").val();
726				} else if (type === "number" && typeof element.validity !== "undefined") {
727					return element.validity.badInput ? "NaN" : $element.val();
728				}
729
730				if (isContentEditable) {
731					val = $element.text();
732				} else {
733					val = $element.val();
734				}
735
736				if (type === "file") {
737
738					// Modern browser (chrome & safari)
739					if (val.substr(0, 12) === "C:\\fakepath\\") {
740						return val.substr(12);
741					}
742
743					// Legacy browsers
744					// Unix-based path
745					idx = val.lastIndexOf("/");
746					if (idx >= 0) {
747						return val.substr(idx + 1);
748					}
749
750					// Windows-based path
751					idx = val.lastIndexOf("\\");
752					if (idx >= 0) {
753						return val.substr(idx + 1);
754					}
755
756					// Just the file name
757					return val;
758				}
759
760				if (typeof val === "string") {
761					return val.replace(/\r/g, "");
762				}
763				return val;
764			},
765
766			check: function (element) {
767				element = this.validationTargetFor(this.clean(element));
768
769				var rules = $(element).rules(),
770					rulesCount = $.map(rules, function (n, i) {
771						return i;
772					}).length,
773					dependencyMismatch = false,
774					val = this.elementValue(element),
775					result, method, rule, normalizer;
776
777				// Prioritize the local normalizer defined for this element over the global one
778				// if the former exists, otherwise user the global one in case it exists.
779				if (typeof rules.normalizer === "function") {
780					normalizer = rules.normalizer;
781				} else if (typeof this.settings.normalizer === "function") {
782					normalizer = this.settings.normalizer;
783				}
784
785				// If normalizer is defined, then call it to retreive the changed value instead
786				// of using the real one.
787				// Note that `this` in the normalizer is `element`.
788				if (normalizer) {
789					val = normalizer.call(element, val);
790
791					// Delete the normalizer from rules to avoid treating it as a pre-defined method.
792					delete rules.normalizer;
793				}
794
795				for (method in rules) {
796					rule = { method: method, parameters: rules[method] };
797					try {
798						result = $.validator.methods[method].call(this, val, element, rule.parameters);
799
800						// If a method indicates that the field is optional and therefore valid,
801						// don't mark it as valid when there are no other rules
802						if (result === "dependency-mismatch" && rulesCount === 1) {
803							dependencyMismatch = true;
804							continue;
805						}
806						dependencyMismatch = false;
807
808						if (result === "pending") {
809							this.toHide = this.toHide.not(this.errorsFor(element));
810							return;
811						}
812
813						if (!result) {
814							this.formatAndAdd(element, rule);
815							return false;
816						}
817					} catch (e) {
818						if (this.settings.debug && window.console) {
819							console.log("Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.", e);
820						}
821						if (e instanceof TypeError) {
822							e.message += ".  Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.";
823						}
824
825						throw e;
826					}
827				}
828				if (dependencyMismatch) {
829					return;
830				}
831				if (this.objectLength(rules)) {
832					this.successList.push(element);
833				}
834				return true;
835			},
836
837			// Return the custom message for the given element and validation method
838			// specified in the element's HTML5 data attribute
839			// return the generic message if present and no method specific message is present
840			customDataMessage: function (element, method) {
841				return $(element).data("msg" + method.charAt(0).toUpperCase() +
842					method.substring(1).toLowerCase()) || $(element).data("msg");
843			},
844
845			// Return the custom message for the given element name and validation method
846			customMessage: function (name, method) {
847				var m = this.settings.messages[name];
848				return m && (m.constructor === String ? m : m[method]);
849			},
850
851			// Return the first defined argument, allowing empty strings
852			findDefined: function () {
853				for (var i = 0; i < arguments.length; i++) {
854					if (arguments[i] !== undefined) {
855						return arguments[i];
856					}
857				}
858				return undefined;
859			},
860
861			// The second parameter 'rule' used to be a string, and extended to an object literal
862			// of the following form:
863			// rule = {
864			//     method: "method name",
865			//     parameters: "the given method parameters"
866			// }
867			//
868			// The old behavior still supported, kept to maintain backward compatibility with
869			// old code, and will be removed in the next major release.
870			defaultMessage: function (element, rule) {
871				if (typeof rule === "string") {
872					rule = { method: rule };
873				}
874
875				var message = this.findDefined(
876					this.customMessage(element.name, rule.method),
877					this.customDataMessage(element, rule.method),
878
879					// 'title' is never undefined, so handle empty string as undefined
880					!this.settings.ignoreTitle && element.title || undefined,
881					$.validator.messages[rule.method],
882					"<strong>Warning: No message defined for " + element.name + "</strong>"
883				),
884					theregex = /\$?\{(\d+)\}/g;
885				if (typeof message === "function") {
886					message = message.call(this, rule.parameters, element);
887				} else if (theregex.test(message)) {
888					message = $.validator.format(message.replace(theregex, "{$1}"), rule.parameters);
889				}
890
891				return message;
892			},
893
894			formatAndAdd: function (element, rule) {
895				var message = this.defaultMessage(element, rule);
896
897				this.errorList.push({
898					message: message,
899					element: element,
900					method: rule.method
901				});
902
903				this.errorMap[element.name] = message;
904				this.submitted[element.name] = message;
905			},
906
907			addWrapper: function (toToggle) {
908				if (this.settings.wrapper) {
909					toToggle = toToggle.add(toToggle.parent(this.settings.wrapper));
910				}
911				return toToggle;
912			},
913
914			defaultShowErrors: function () {
915				var i, elements, error;
916				for (i = 0; this.errorList[i]; i++) {
917					error = this.errorList[i];
918					if (this.settings.highlight) {
919						this.settings.highlight.call(this, error.element, this.settings.errorClass, this.settings.validClass);
920					}
921					this.showLabel(error.element, error.message);
922				}
923				if (this.errorList.length) {
924					this.toShow = this.toShow.add(this.containers);
925				}
926				if (this.settings.success) {
927					for (i = 0; this.successList[i]; i++) {
928						this.showLabel(this.successList[i]);
929					}
930				}
931				if (this.settings.unhighlight) {
932					for (i = 0, elements = this.validElements(); elements[i]; i++) {
933						this.settings.unhighlight.call(this, elements[i], this.settings.errorClass, this.settings.validClass);
934					}
935				}
936				this.toHide = this.toHide.not(this.toShow);
937				this.hideErrors();
938				this.addWrapper(this.toShow).show();
939			},
940
941			validElements: function () {
942				return this.currentElements.not(this.invalidElements());
943			},
944
945			invalidElements: function () {
946				return $(this.errorList).map(function () {
947					return this.element;
948				});
949			},
950
951			showLabel: function (element, message) {
952				var place, group, errorID, v,
953					error = this.errorsFor(element),
954					elementID = this.idOrName(element),
955					describedBy = $(element).attr("aria-describedby");
956
957				if (error.length) {
958
959					// Refresh error/success class
960					error.removeClass(this.settings.validClass).addClass(this.settings.errorClass);
961
962					// Replace message on existing label
963					error.html(message);
964				} else {
965
966					// Create error element
967					error = $("<" + this.settings.errorElement + ">")
968						.attr("id", elementID + "-error")
969						.addClass(this.settings.errorClass)
970						.html(message || "");
971
972					// Maintain reference to the element to be placed into the DOM
973					place = error;
974					if (this.settings.wrapper) {
975
976						// Make sure the element is visible, even in IE
977						// actually showing the wrapped element is handled elsewhere
978						place = error.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();
979					}
980					if (this.labelContainer.length) {
981						this.labelContainer.append(place);
982					} else if (this.settings.errorPlacement) {
983						this.settings.errorPlacement.call(this, place, $(element));
984					} else {
985						place.insertAfter(element);
986					}
987
988					// Link error back to the element
989					if (error.is("label")) {
990
991						// If the error is a label, then associate using 'for'
992						error.attr("for", elementID);
993
994						// If the element is not a child of an associated label, then it's necessary
995						// to explicitly apply aria-describedby
996					} else if (error.parents("label[for='" + this.escapeCssMeta(elementID) + "']").length === 0) {
997						errorID = error.attr("id");
998
999						// Respect existing non-error aria-describedby
1000						if (!describedBy) {
1001							describedBy = errorID;
1002						} else if (!describedBy.match(new RegExp("\\b" + this.escapeCssMeta(errorID) + "\\b"))) {
1003
1004							// Add to end of list if not already present
1005							describedBy += " " + errorID;
1006						}
1007						$(element).attr("aria-describedby", describedBy);
1008
1009						// If this element is grouped, then assign to all elements in the same group
1010						group = this.groups[element.name];
1011						if (group) {
1012							v = this;
1013							$.each(v.groups, function (name, testgroup) {
1014								if (testgroup === group) {
1015									$("[name='" + v.escapeCssMeta(name) + "']", v.currentForm)
1016										.attr("aria-describedby", error.attr("id"));
1017								}
1018							});
1019						}
1020					}
1021				}
1022				if (!message && this.settings.success) {
1023					error.text("");
1024					if (typeof this.settings.success === "string") {
1025						error.addClass(this.settings.success);
1026					} else {
1027						this.settings.success(error, element);
1028					}
1029				}
1030				this.toShow = this.toShow.add(error);
1031			},
1032
1033			errorsFor: function (element) {
1034				var name = this.escapeCssMeta(this.idOrName(element)),
1035					describer = $(element).attr("aria-describedby"),
1036					selector = "label[for='" + name + "'], label[for='" + name + "'] *";
1037
1038				// 'aria-describedby' should directly reference the error element
1039				if (describer) {
1040					selector = selector + ", #" + this.escapeCssMeta(describer)
1041						.replace(/\s+/g, ", #");
1042				}
1043
1044				return this
1045					.errors()
1046					.filter(selector);
1047			},
1048
1049			// See https://api.jquery.com/category/selectors/, for CSS
1050			// meta-characters that should be escaped in order to be used with JQuery
1051			// as a literal part of a name/id or any selector.
1052			escapeCssMeta: function (string) {
1053				if (string === undefined) {
1054					return "";
1055				}
1056
1057				return string.replace(/([\\!"#$%&'()*+,./:;<=>?@\[\]^`{|}~])/g, "\\$1");
1058			},
1059
1060			idOrName: function (element) {
1061				return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
1062			},
1063
1064			validationTargetFor: function (element) {
1065
1066				// If radio/checkbox, validate first element in group instead
1067				if (this.checkable(element)) {
1068					element = this.findByName(element.name);
1069				}
1070
1071				// Always apply ignore filter
1072				return $(element).not(this.settings.ignore)[0];
1073			},
1074
1075			checkable: function (element) {
1076				return (/radio|checkbox/i).test(element.type);
1077			},
1078
1079			findByName: function (name) {
1080				return $(this.currentForm).find("[name='" + this.escapeCssMeta(name) + "']");
1081			},
1082
1083			getLength: function (value, element) {
1084				switch (element.nodeName.toLowerCase()) {
1085					case "select":
1086						return $("option:selected", element).length;
1087					case "input":
1088						if (this.checkable(element)) {
1089							return this.findByName(element.name).filter(":checked").length;
1090						}
1091				}
1092				return value.length;
1093			},
1094
1095			depend: function (param, element) {
1096				return this.dependTypes[typeof param] ? this.dependTypes[typeof param](param, element) : true;
1097			},
1098
1099			dependTypes: {
1100				"boolean": function (param) {
1101					return param;
1102				},
1103				"string": function (param, element) {
1104					return !!$(param, element.form).length;
1105				},
1106				"function": function (param, element) {
1107					return param(element);
1108				}
1109			},
1110
1111			optional: function (element) {
1112				var val = this.elementValue(element);
1113				return !$.validator.methods.required.call(this, val, element) && "dependency-mismatch";
1114			},
1115
1116			startRequest: function (element) {
1117				if (!this.pending[element.name]) {
1118					this.pendingRequest++;
1119					$(element).addClass(this.settings.pendingClass);
1120					this.pending[element.name] = true;
1121				}
1122			},
1123
1124			stopRequest: function (element, valid) {
1125				this.pendingRequest--;
1126
1127				// Sometimes synchronization fails, make sure pendingRequest is never < 0
1128				if (this.pendingRequest < 0) {
1129					this.pendingRequest = 0;
1130				}
1131				delete this.pending[element.name];
1132				$(element).removeClass(this.settings.pendingClass);
1133				if (valid && this.pendingRequest === 0 && this.formSubmitted && this.form() && this.pendingRequest === 0) {
1134					$(this.currentForm).trigger("submit");
1135
1136					// Remove the hidden input that was used as a replacement for the
1137					// missing submit button. The hidden input is added by `handle()`
1138					// to ensure that the value of the used submit button is passed on
1139					// for scripted submits triggered by this method
1140					if (this.submitButton) {
1141						$("input:hidden[name='" + this.submitButton.name + "']", this.currentForm).remove();
1142					}
1143
1144					this.formSubmitted = false;
1145				} else if (!valid && this.pendingRequest === 0 && this.formSubmitted) {
1146					$(this.currentForm).triggerHandler("invalid-form", [this]);
1147					this.formSubmitted = false;
1148				}
1149			},
1150
1151			previousValue: function (element, method) {
1152				method = typeof method === "string" && method || "remote";
1153
1154				return $.data(element, "previousValue") || $.data(element, "previousValue", {
1155					old: null,
1156					valid: true,
1157					message: this.defaultMessage(element, { method: method })
1158				});
1159			},
1160
1161			// Cleans up all forms and elements, removes validator-specific events
1162			destroy: function () {
1163				this.resetForm();
1164
1165				$(this.currentForm)
1166					.off(".validate")
1167					.removeData("validator")
1168					.find(".validate-equalTo-blur")
1169					.off(".validate-equalTo")
1170					.removeClass("validate-equalTo-blur")
1171					.find(".validate-lessThan-blur")
1172					.off(".validate-lessThan")
1173					.removeClass("validate-lessThan-blur")
1174					.find(".validate-lessThanEqual-blur")
1175					.off(".validate-lessThanEqual")
1176					.removeClass("validate-lessThanEqual-blur")
1177					.find(".validate-greaterThanEqual-blur")
1178					.off(".validate-greaterThanEqual")
1179					.removeClass("validate-greaterThanEqual-blur")
1180					.find(".validate-greaterThan-blur")
1181					.off(".validate-greaterThan")
1182					.removeClass("validate-greaterThan-blur");
1183			}
1184
1185		},
1186
1187		classRuleSettings: {
1188			required: { required: true },
1189			email: { email: true },
1190			url: { url: true },
1191			date: { date: true },
1192			dateISO: { dateISO: true },
1193			number: { number: true },
1194			digits: { digits: true },
1195			creditcard: { creditcard: true }
1196		},
1197
1198		addClassRules: function (className, rules) {
1199			if (className.constructor === String) {
1200				this.classRuleSettings[className] = rules;
1201			} else {
1202				$.extend(this.classRuleSettings, className);
1203			}
1204		},
1205
1206		classRules: function (element) {
1207			var rules = {},
1208				classes = $(element).attr("class");
1209
1210			if (classes) {
1211				$.each(classes.split(" "), function () {
1212					if (this in $.validator.classRuleSettings) {
1213						$.extend(rules, $.validator.classRuleSettings[this]);
1214					}
1215				});
1216			}
1217			return rules;
1218		},
1219
1220		normalizeAttributeRule: function (rules, type, method, value) {
1221
1222			// Convert the value to a number for number inputs, and for text for backwards compability
1223			// allows type="date" and others to be compared as strings
1224			if (/min|max|step/.test(method) && (type === null || /number|range|text/.test(type))) {
1225				value = Number(value);
1226
1227				// Support Opera Mini, which returns NaN for undefined minlength
1228				if (isNaN(value)) {
1229					value = undefined;
1230				}
1231			}
1232
1233			if (value || value === 0) {
1234				rules[method] = value;
1235			} else if (type === method && type !== "range") {
1236
1237				// Exception: the jquery validate 'range' method
1238				// does not test for the html5 'range' type
1239				rules[type === "date" ? "dateISO" : method] = true;
1240			}
1241		},
1242
1243		attributeRules: function (element) {
1244			var rules = {},
1245				$element = $(element),
1246				type = element.getAttribute("type"),
1247				method, value;
1248
1249			for (method in $.validator.methods) {
1250
1251				// Support for <input required> in both html5 and older browsers
1252				if (method === "required") {
1253					value = element.getAttribute(method);
1254
1255					// Some browsers return an empty string for the required attribute
1256					// and non-HTML5 browsers might have required="" markup
1257					if (value === "") {
1258						value = true;
1259					}
1260
1261					// Force non-HTML5 browsers to return bool
1262					value = !!value;
1263				} else {
1264					value = $element.attr(method);
1265				}
1266
1267				this.normalizeAttributeRule(rules, type, method, value);
1268			}
1269
1270			// 'maxlength' may be returned as -1, 2147483647 ( IE ) and 524288 ( safari ) for text inputs
1271			if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {
1272				delete rules.maxlength;
1273			}
1274
1275			return rules;
1276		},
1277
1278		dataRules: function (element) {
1279			var rules = {},
1280				$element = $(element),
1281				type = element.getAttribute("type"),
1282				method, value;
1283
1284			for (method in $.validator.methods) {
1285				value = $element.data("rule" + method.charAt(0).toUpperCase() + method.substring(1).toLowerCase());
1286
1287				// Cast empty attributes like `data-rule-required` to `true`
1288				if (value === "") {
1289					value = true;
1290				}
1291
1292				this.normalizeAttributeRule(rules, type, method, value);
1293			}
1294			return rules;
1295		},
1296
1297		staticRules: function (element) {
1298			var rules = {},
1299				validator = $.data(element.form, "validator");
1300
1301			if (validator.settings.rules) {
1302				rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
1303			}
1304			return rules;
1305		},
1306
1307		normalizeRules: function (rules, element) {
1308
1309			// Handle dependency check
1310			$.each(rules, function (prop, val) {
1311
1312				// Ignore rule when param is explicitly false, eg. required:false
1313				if (val === false) {
1314					delete rules[prop];
1315					return;
1316				}
1317				if (val.param || val.depends) {
1318					var keepRule = true;
1319					switch (typeof val.depends) {
1320						case "string":
1321							keepRule = !!$(val.depends, element.form).length;
1322							break;
1323						case "function":
1324							keepRule = val.depends.call(element, element);
1325							break;
1326					}
1327					if (keepRule) {
1328						rules[prop] = val.param !== undefined ? val.param : true;
1329					} else {
1330						$.data(element.form, "validator").resetElements($(element));
1331						delete rules[prop];
1332					}
1333				}
1334			});
1335
1336			// Evaluate parameters
1337			$.each(rules, function (rule, parameter) {
1338				rules[rule] = typeof parameter === "function" && rule !== "normalizer" ? parameter(element) : parameter;
1339			});
1340
1341			// Clean number parameters
1342			$.each(["minlength", "maxlength"], function () {
1343				if (rules[this]) {
1344					rules[this] = Number(rules[this]);
1345				}
1346			});
1347			$.each(["rangelength", "range"], function () {
1348				var parts;
1349				if (rules[this]) {
1350					if (Array.isArray(rules[this])) {
1351						rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
1352					} else if (typeof rules[this] === "string") {
1353						parts = rules[this].replace(/[\[\]]/g, "").split(/[\s,]+/);
1354						rules[this] = [Number(parts[0]), Number(parts[1])];
1355					}
1356				}
1357			});
1358
1359			if ($.validator.autoCreateRanges) {
1360
1361				// Auto-create ranges
1362				if (rules.min != null && rules.max != null) {
1363					rules.range = [rules.min, rules.max];
1364					delete rules.min;
1365					delete rules.max;
1366				}
1367				if (rules.minlength != null && rules.maxlength != null) {
1368					rules.rangelength = [rules.minlength, rules.maxlength];
1369					delete rules.minlength;
1370					delete rules.maxlength;
1371				}
1372			}
1373
1374			return rules;
1375		},
1376
1377		// Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
1378		normalizeRule: function (data) {
1379			if (typeof data === "string") {
1380				var transformed = {};
1381				$.each(data.split(/\s/), function () {
1382					transformed[this] = true;
1383				});
1384				data = transformed;
1385			}
1386			return data;
1387		},
1388
1389		// https://jqueryvalidation.org/jQuery.validator.addMethod/
1390		addMethod: function (name, method, message) {
1391			$.validator.methods[name] = method;
1392			$.validator.messages[name] = message !== undefined ? message : $.validator.messages[name];
1393			if (method.length < 3) {
1394				$.validator.addClassRules(name, $.validator.normalizeRule(name));
1395			}
1396		},
1397
1398		// https://jqueryvalidation.org/jQuery.validator.methods/
1399		methods: {
1400
1401			// https://jqueryvalidation.org/required-method/
1402			required: function (value, element, param) {
1403
1404				// Check if dependency is met
1405				if (!this.depend(param, element)) {
1406					return "dependency-mismatch";
1407				}
1408				if (element.nodeName.toLowerCase() === "select") {
1409
1410					// Could be an array for select-multiple or a string, both are fine this way
1411					var val = $(element).val();
1412					return val && val.length > 0;
1413				}
1414				if (this.checkable(element)) {
1415					return this.getLength(value, element) > 0;
1416				}
1417				return value !== undefined && value !== null && value.length > 0;
1418			},
1419
1420			// https://jqueryvalidation.org/email-method/
1421			email: function (value, element) {
1422
1423				// From https://html.spec.whatwg.org/multipage/forms.html#valid-e-mail-address
1424				// Retrieved 2014-01-14
1425				// If you have a problem with this implementation, report a bug against the above spec
1426				// Or use custom methods to implement your own email validation
1427				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);
1428			},
1429
1430			// https://jqueryvalidation.org/url-method/
1431			url: function (value, element) {
1432
1433				// Copyright (c) 2010-2013 Diego Perini, MIT licensed
1434				// https://gist.github.com/dperini/729294
1435				// see also https://mathiasbynens.be/demo/url-regex
1436				// modified to allow protocol-relative URLs
1437				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);
1438			},
1439
1440			// https://jqueryvalidation.org/date-method/
1441			date: (function () {
1442				var called = false;
1443
1444				return function (value, element) {
1445					if (!called) {
1446						called = true;
1447						if (this.settings.debug && window.console) {
1448							console.warn(
1449								"The `date` method is deprecated and will be removed in version '2.0.0'.\n" +
1450								"Please don't use it, since it relies on the Date constructor, which\n" +
1451								"behaves very differently across browsers and locales. Use `dateISO`\n" +
1452								"instead or one of the locale specific methods in `localizations/`\n" +
1453								"and `additional-methods.js`."
1454							);
1455						}
1456					}
1457
1458					return this.optional(element) || !/Invalid|NaN/.test(new Date(value).toString());
1459				};
1460			}()),
1461
1462			// https://jqueryvalidation.org/dateISO-method/
1463			dateISO: function (value, element) {
1464				return this.optional(element) || /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(value);
1465			},
1466
1467			// https://jqueryvalidation.org/number-method/
1468			number: function (value, element) {
1469				return this.optional(element) || /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value);
1470			},
1471
1472			// https://jqueryvalidation.org/digits-method/
1473			digits: function (value, element) {
1474				return this.optional(element) || /^\d+$/.test(value);
1475			},
1476
1477			// https://jqueryvalidation.org/minlength-method/
1478			minlength: function (value, element, param) {
1479				var length = Array.isArray(value) ? value.length : this.getLength(value, element);
1480				return this.optional(element) || length >= param;
1481			},
1482
1483			// https://jqueryvalidation.org/maxlength-method/
1484			maxlength: function (value, element, param) {
1485				var length = Array.isArray(value) ? value.length : this.getLength(value, element);
1486				return this.optional(element) || length <= param;
1487			},
1488
1489			// https://jqueryvalidation.org/rangelength-method/
1490			rangelength: function (value, element, param) {
1491				var length = Array.isArray(value) ? value.length : this.getLength(value, element);
1492				return this.optional(element) || (length >= param[0] && length <= param[1]);
1493			},
1494
1495			// https://jqueryvalidation.org/min-method/
1496			min: function (value, element, param) {
1497				return this.optional(element) || value >= param;
1498			},
1499
1500			// https://jqueryvalidation.org/max-method/
1501			max: function (value, element, param) {
1502				return this.optional(element) || value <= param;
1503			},
1504
1505			// https://jqueryvalidation.org/range-method/
1506			range: function (value, element, param) {
1507				return this.optional(element) || (value >= param[0] && value <= param[1]);
1508			},
1509
1510			// https://jqueryvalidation.org/step-method/
1511			step: function (value, element, param) {
1512				var type = $(element).attr("type"),
1513					errorMessage = "Step attribute on input type " + type + " is not supported.",
1514					supportedTypes = ["text", "number", "range"],
1515					re = new RegExp("\\b" + type + "\\b"),
1516					notSupported = type && !re.test(supportedTypes.join()),
1517					decimalPlaces = function (num) {
1518						var match = ("" + num).match(/(?:\.(\d+))?$/);
1519						if (!match) {
1520							return 0;
1521						}
1522
1523						// Number of digits right of decimal point.
1524						return match[1] ? match[1].length : 0;
1525					},
1526					toInt = function (num) {
1527						return Math.round(num * Math.pow(10, decimals));
1528					},
1529					valid = true,
1530					decimals;
1531
1532				// Works only for text, number and range input types
1533				// TODO find a way to support input types date, datetime, datetime-local, month, time and week
1534				if (notSupported) {
1535					throw new Error(errorMessage);
1536				}
1537
1538				decimals = decimalPlaces(param);
1539
1540				// Value can't have too many decimals
1541				if (decimalPlaces(value) > decimals || toInt(value) % toInt(param) !== 0) {
1542					valid = false;
1543				}
1544
1545				return this.optional(element) || valid;
1546			},
1547
1548			// https://jqueryvalidation.org/equalTo-method/
1549			equalTo: function (value, element, param) {
1550
1551				// Bind to the blur event of the target in order to revalidate whenever the target field is updated
1552				var target = $(param);
1553				if (this.settings.onfocusout && target.not(".validate-equalTo-blur").length) {
1554					target.addClass("validate-equalTo-blur").on("blur.validate-equalTo", function () {
1555						$(element).valid();
1556					});
1557				}
1558				return value === target.val();
1559			},
1560
1561			// https://jqueryvalidation.org/remote-method/
1562			remote: function (value, element, param, method) {
1563				if (this.optional(element)) {
1564					return "dependency-mismatch";
1565				}
1566
1567				method = typeof method === "string" && method || "remote";
1568
1569				var previous = this.previousValue(element, method),
1570					validator, data, optionDataString;
1571
1572				if (!this.settings.messages[element.name]) {
1573					this.settings.messages[element.name] = {};
1574				}
1575				previous.originalMessage = previous.originalMessage || this.settings.messages[element.name][method];
1576				this.settings.messages[element.name][method] = previous.message;
1577
1578				param = typeof param === "string" && { url: param } || param;
1579				optionDataString = $.param($.extend({ data: value }, param.data));
1580				if (previous.old === optionDataString) {
1581					return previous.valid;
1582				}
1583
1584				previous.old = optionDataString;
1585				validator = this;
1586				this.startRequest(element);
1587				data = {};
1588				data[element.name] = value;
1589				$.ajax($.extend(true, {
1590					mode: "abort",
1591					port: "validate" + element.name,
1592					dataType: "json",
1593					data: data,
1594					context: validator.currentForm,
1595					success: function (response) {
1596						var valid = response === true || response === "true",
1597							errors, message, submitted;
1598
1599						validator.settings.messages[element.name][method] = previous.originalMessage;
1600						if (valid) {
1601							submitted = validator.formSubmitted;
1602							validator.resetInternals();
1603							validator.toHide = validator.errorsFor(element);
1604							validator.formSubmitted = submitted;
1605							validator.successList.push(element);
1606							validator.invalid[element.name] = false;
1607							validator.showErrors();
1608						} else {
1609							errors = {};
1610							message = response || validator.defaultMessage(element, { method: method, parameters: value });
1611							errors[element.name] = previous.message = message;
1612							validator.invalid[element.name] = true;
1613							validator.showErrors(errors);
1614						}
1615						previous.valid = valid;
1616						validator.stopRequest(element, valid);
1617					}
1618				}, param));
1619				return "pending";
1620			}
1621		}
1622
1623	});
1624
1625	// Ajax mode: abort
1626	// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
1627	// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
1628
1629	var pendingRequests = {},
1630		ajax;
1631
1632	// Use a prefilter if available (1.5+)
1633	if ($.ajaxPrefilter) {
1634		$.ajaxPrefilter(function (settings, _, xhr) {
1635			var port = settings.port;
1636			if (settings.mode === "abort") {
1637				if (pendingRequests[port]) {
1638					pendingRequests[port].abort();
1639				}
1640				pendingRequests[port] = xhr;
1641			}
1642		});
1643	} else {
1644
1645		// Proxy ajax
1646		ajax = $.ajax;
1647		$.ajax = function (settings) {
1648			var mode = ("mode" in settings ? settings : $.ajaxSettings).mode,
1649				port = ("port" in settings ? settings : $.ajaxSettings).port;
1650			if (mode === "abort") {
1651				if (pendingRequests[port]) {
1652					pendingRequests[port].abort();
1653				}
1654				pendingRequests[port] = ajax.apply(this, arguments);
1655				return pendingRequests[port];
1656			}
1657			return ajax.apply(this, arguments);
1658		};
1659	}
1660	return $;
1661}));

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.