PageRenderTime 89ms CodeModel.GetById 21ms app.highlight 57ms RepoModel.GetById 1ms app.codeStats 0ms

/MvcMusicStore/Scripts/jquery.validate-vsdoc.js

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