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