PageSourceSearch

https://edjoin.org/Scripts/plugins/validate/jquery.validate.js

js edjoin.org collected 2026-09-25 09:43:07 UTC 40,198 bytes, 1,231 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.