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