Subversion Repositories wpShopGermany4

Rev

Rev 4943 | Details | Compare with Previous | Last modification | View Log | RSS feed

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