client_side_validations 2.4.2 → 2.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.markdown CHANGED
@@ -18,6 +18,9 @@ Currently the following validations are supported:
18
18
  * validates_length_of
19
19
  * validates_uniqueness_of
20
20
  * validates_confirmation_of
21
+ * validatse_acceptance_of
22
+ * validates_inclusion_of
23
+ * validates_exclusion_of
21
24
 
22
25
  The uniqueness validation works for both ActiveRecord and Mongoid.
23
26
 
@@ -32,6 +35,8 @@ Then run the generator:
32
35
 
33
36
  This will copy client_side_validations.js to "public/javascripts"
34
37
 
38
+ **This version of ClientSideValidations will also copy a patched version of jquery.validate.js to "public/javascript"**
39
+
35
40
  ### Rails 3
36
41
  Add "gem 'client_side_validations" to the Gemfile
37
42
 
@@ -40,7 +45,10 @@ Then run the generator:
40
45
 
41
46
  This will copy client_side_validations.js to "public/javascripts"
42
47
 
48
+ **This version of ClientSideValidations will also copy a patched version of jquery.validate.js to "public/javascript"**
49
+
43
50
  ## Configuration
51
+ #### *NOTE* This version of ClientSideValidations has a patched version of jquery.validate that will install automatically with the generator. *Do not* download the version listed below.
44
52
  Currently only [jquery.validate](http://bassistance.de/jquery-plugins/jquery-plugin-validation/) is supported so you will need to download [jQuery](http://docs.jquery.com/Downloading_jQuery) and the jQuery Validate plugin to "public/javascripts"
45
53
 
46
54
  ### Rack
@@ -10,6 +10,7 @@ class ClientSideValidationsGenerator < Rails::Generator::Base
10
10
  record do |c|
11
11
  c.directory('public/javascripts')
12
12
  c.file('client_side_validations.js', 'public/javascripts/client_side_validations.js')
13
+ c.file('jquery.validate.js', 'public/javascripts/jquery.validate.js')
13
14
  end
14
15
  end
15
16
 
@@ -3,6 +3,37 @@ if (typeof(jQuery) != "undefined") {
3
3
  var pattern = new RegExp(params, "i");
4
4
  return this.optional(element) || pattern.test(value);
5
5
  }, jQuery.validator.format("Invalid format."));
6
+
7
+ jQuery.validator.addMethod("acceptance", function(value, element, params) {
8
+ return element.checked;
9
+ }, jQuery.validator.format("Was not accepted."));
10
+
11
+ jQuery.validator.addMethod("inclusion", function(value, element, params) {
12
+ if (this.optional(element)) {
13
+ return true;
14
+ } else {
15
+
16
+ for (var i=0, len=params.length; i<len; ++i ) {
17
+ if (value == String(params[i])) {
18
+ return true;
19
+ }
20
+ }
21
+ }
22
+ return false;
23
+ }, jQuery.validator.format("Not included in list."));
24
+
25
+ jQuery.validator.addMethod("exclusion", function(value, element, params) {
26
+ if (this.optional(element)) {
27
+ return true;
28
+ } else {
29
+ for (var i=0, len=params.length; i<len; ++i ) {
30
+ if (value == String(params[i])) {
31
+ return false;
32
+ }
33
+ }
34
+ }
35
+ return true;
36
+ }, jQuery.validator.format("Is reserved."));
6
37
 
7
38
  $.extend($.fn, {
8
39
  clientSideValidations: function() {
@@ -21,11 +52,12 @@ if (typeof(jQuery) != "undefined") {
21
52
  } else {
22
53
  var options = { }
23
54
  }
24
- var client = new ClientSideValidations(object, adapter, object_id)
25
- var rules = eval(object + '_validation_rules');
26
- var validations = client.adaptValidations(rules);
27
- options['rules'] = validations.rules;
28
- options['messages'] = validations.messages;
55
+ var client = new ClientSideValidations(object, adapter, object_id)
56
+ var rules = eval(object + '_validation_rules');
57
+ var validations = client.adaptValidations(rules);
58
+ options.rules = validations.rules;
59
+ options.messages = validations.messages;
60
+ options.ignore = ':hidden';
29
61
  form.validate(options);
30
62
  }
31
63
  });
@@ -62,7 +94,15 @@ ClientSideValidations = function(id, adapter, object_id) {
62
94
  value = true;
63
95
  break;
64
96
  case 'length':
65
- if('minimum' in this.validations[attr][validation]) {
97
+ if ('minimum' in this.validations[attr][validation] && 'maximum' in this.validations[attr][validation]) {
98
+ minrule = 'minlength';
99
+ rules[name][minrule] = this.validations[attr][validation]['minimum'];
100
+ messages[name][minrule] = this.validations[attr][validation]['message_min'];
101
+
102
+ rule = 'maxlength';
103
+ value = this.validations[attr][validation]['maximum'];
104
+ this.validations[attr][validation]['message'] = this.validations[attr][validation]['message_max']
105
+ } else if('minimum' in this.validations[attr][validation]) {
66
106
  rule = 'minlength';
67
107
  value = this.validations[attr][validation]['minimum'];
68
108
  } else if('maximum' in this.validations[attr][validation]) {
@@ -86,6 +126,18 @@ ClientSideValidations = function(id, adapter, object_id) {
86
126
  rule = 'equalTo';
87
127
  value = "[name='" + this.id + "[" + attr + "_confirmation]" + "']";
88
128
  break;
129
+ case 'acceptance':
130
+ rule = 'acceptance';
131
+ value = true;
132
+ break;
133
+ case 'inclusion':
134
+ rule = 'inclusion';
135
+ value = this.validations[attr][validation]['in']
136
+ break;
137
+ case 'exclusion':
138
+ rule = 'exclusion';
139
+ value = this.validations[attr][validation]['in']
140
+ break;
89
141
 
90
142
  default:
91
143
  }
@@ -0,0 +1,1146 @@
1
+ /*
2
+ * jQuery validation plug-in 1.7
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( true, {}, $.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
+ // click on selects, radiobuttons and checkboxes
237
+ if ( element.name in this.submitted )
238
+ this.element(element);
239
+ // or option elements, check parent select in that case
240
+ else if (element.parentNode.name in this.submitted)
241
+ this.element(element.parentNode);
242
+ },
243
+ highlight: function( element, errorClass, validClass ) {
244
+ $(element).addClass(errorClass).removeClass(validClass);
245
+ },
246
+ unhighlight: function( element, errorClass, validClass ) {
247
+ $(element).removeClass(errorClass).addClass(validClass);
248
+ }
249
+ },
250
+
251
+ // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
252
+ setDefaults: function(settings) {
253
+ $.extend( $.validator.defaults, settings );
254
+ },
255
+
256
+ messages: {
257
+ required: "This field is required.",
258
+ remote: "Please fix this field.",
259
+ email: "Please enter a valid email address.",
260
+ url: "Please enter a valid URL.",
261
+ date: "Please enter a valid date.",
262
+ dateISO: "Please enter a valid date (ISO).",
263
+ number: "Please enter a valid number.",
264
+ digits: "Please enter only digits.",
265
+ creditcard: "Please enter a valid credit card number.",
266
+ equalTo: "Please enter the same value again.",
267
+ accept: "Please enter a value with a valid extension.",
268
+ maxlength: $.validator.format("Please enter no more than {0} characters."),
269
+ minlength: $.validator.format("Please enter at least {0} characters."),
270
+ rangelength: $.validator.format("Please enter a value between {0} and {1} characters long."),
271
+ range: $.validator.format("Please enter a value between {0} and {1}."),
272
+ max: $.validator.format("Please enter a value less than or equal to {0}."),
273
+ min: $.validator.format("Please enter a value greater than or equal to {0}.")
274
+ },
275
+
276
+ autoCreateRanges: false,
277
+
278
+ prototype: {
279
+
280
+ init: function() {
281
+ this.labelContainer = $(this.settings.errorLabelContainer);
282
+ this.errorContext = this.labelContainer.length && this.labelContainer || $(this.currentForm);
283
+ this.containers = $(this.settings.errorContainer).add( this.settings.errorLabelContainer );
284
+ this.submitted = {};
285
+ this.valueCache = {};
286
+ this.pendingRequest = 0;
287
+ this.pending = {};
288
+ this.invalid = {};
289
+ this.reset();
290
+
291
+ var groups = (this.groups = {});
292
+ $.each(this.settings.groups, function(key, value) {
293
+ $.each(value.split(/\s/), function(index, name) {
294
+ groups[name] = key;
295
+ });
296
+ });
297
+ var rules = this.settings.rules;
298
+ $.each(rules, function(key, value) {
299
+ rules[key] = $.validator.normalizeRule(value);
300
+ });
301
+
302
+ function delegate(event) {
303
+ var validator = $.data(this[0].form, "validator"),
304
+ eventType = "on" + event.type.replace(/^validate/, "");
305
+ validator.settings[eventType] && validator.settings[eventType].call(validator, this[0] );
306
+ }
307
+ $(this.currentForm)
308
+ .validateDelegate(":text, :password, :file, select, textarea", "focusin focusout keyup", delegate)
309
+ .validateDelegate(":radio, :checkbox, select, option", "click", delegate);
310
+
311
+ if (this.settings.invalidHandler)
312
+ $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
313
+ },
314
+
315
+ // http://docs.jquery.com/Plugins/Validation/Validator/form
316
+ form: function() {
317
+ this.checkForm();
318
+ $.extend(this.submitted, this.errorMap);
319
+ this.invalid = $.extend({}, this.errorMap);
320
+ if (!this.valid())
321
+ $(this.currentForm).triggerHandler("invalid-form", [this]);
322
+ this.showErrors();
323
+ return this.valid();
324
+ },
325
+
326
+ checkForm: function() {
327
+ this.prepareForm();
328
+ for ( var i = 0, elements = (this.currentElements = this.elements()); elements[i]; i++ ) {
329
+ this.check( elements[i] );
330
+ }
331
+ return this.valid();
332
+ },
333
+
334
+ // http://docs.jquery.com/Plugins/Validation/Validator/element
335
+ element: function( element ) {
336
+ element = this.clean( element );
337
+ this.lastElement = element;
338
+ this.prepareElement( element );
339
+ this.currentElements = $(element);
340
+ var result = this.check( element );
341
+ if ( result ) {
342
+ delete this.invalid[element.name];
343
+ } else {
344
+ this.invalid[element.name] = true;
345
+ }
346
+ if ( !this.numberOfInvalids() ) {
347
+ // Hide error containers on last error
348
+ this.toHide = this.toHide.add( this.containers );
349
+ }
350
+ this.showErrors();
351
+ return result;
352
+ },
353
+
354
+ // http://docs.jquery.com/Plugins/Validation/Validator/showErrors
355
+ showErrors: function(errors) {
356
+ if(errors) {
357
+ // add items to error list and map
358
+ $.extend( this.errorMap, errors );
359
+ this.errorList = [];
360
+ for ( var name in errors ) {
361
+ this.errorList.push({
362
+ message: errors[name],
363
+ element: this.findByName(name)[0]
364
+ });
365
+ }
366
+ // remove items from success list
367
+ this.successList = $.grep( this.successList, function(element) {
368
+ return !(element.name in errors);
369
+ });
370
+ }
371
+ this.settings.showErrors
372
+ ? this.settings.showErrors.call( this, this.errorMap, this.errorList )
373
+ : this.defaultShowErrors();
374
+ },
375
+
376
+ // http://docs.jquery.com/Plugins/Validation/Validator/resetForm
377
+ resetForm: function() {
378
+ if ( $.fn.resetForm )
379
+ $( this.currentForm ).resetForm();
380
+ this.submitted = {};
381
+ this.prepareForm();
382
+ this.hideErrors();
383
+ this.elements().removeClass( this.settings.errorClass );
384
+ },
385
+
386
+ numberOfInvalids: function() {
387
+ return this.objectLength(this.invalid);
388
+ },
389
+
390
+ objectLength: function( obj ) {
391
+ var count = 0;
392
+ for ( var i in obj )
393
+ count++;
394
+ return count;
395
+ },
396
+
397
+ hideErrors: function() {
398
+ this.addWrapper( this.toHide ).hide();
399
+ },
400
+
401
+ valid: function() {
402
+ return this.size() == 0;
403
+ },
404
+
405
+ size: function() {
406
+ return this.errorList.length;
407
+ },
408
+
409
+ focusInvalid: function() {
410
+ if( this.settings.focusInvalid ) {
411
+ try {
412
+ $(this.findLastActive() || this.errorList.length && this.errorList[0].element || [])
413
+ .filter(":visible")
414
+ .focus()
415
+ // manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
416
+ .trigger("focusin");
417
+ } catch(e) {
418
+ // ignore IE throwing errors when focusing hidden elements
419
+ }
420
+ }
421
+ },
422
+
423
+ findLastActive: function() {
424
+ var lastActive = this.lastActive;
425
+ return lastActive && $.grep(this.errorList, function(n) {
426
+ return n.element.name == lastActive.name;
427
+ }).length == 1 && lastActive;
428
+ },
429
+
430
+ elements: function() {
431
+ var validator = this,
432
+ rulesCache = {};
433
+
434
+ // select all valid inputs inside the form (no submit or reset buttons)
435
+ // workaround $Query([]).add until http://dev.jquery.com/ticket/2114 is solved
436
+ return $([]).add(this.currentForm.elements)
437
+ .filter(":input")
438
+ .not(":submit, :reset, :image, [disabled]")
439
+ .not( this.settings.ignore )
440
+ .filter(function() {
441
+ !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);
442
+
443
+ // select only the first element for each name, and only those with rules specified
444
+ if ( this.name in rulesCache || !validator.objectLength($(this).rules()) )
445
+ return false;
446
+
447
+ rulesCache[this.name] = true;
448
+ return true;
449
+ });
450
+ },
451
+
452
+ clean: function( selector ) {
453
+ return $( selector )[0];
454
+ },
455
+
456
+ errors: function() {
457
+ return $( this.settings.errorElement + "." + this.settings.errorClass, this.errorContext );
458
+ },
459
+
460
+ reset: function() {
461
+ this.successList = [];
462
+ this.errorList = [];
463
+ this.errorMap = {};
464
+ this.toShow = $([]);
465
+ this.toHide = $([]);
466
+ this.currentElements = $([]);
467
+ },
468
+
469
+ prepareForm: function() {
470
+ this.reset();
471
+ this.toHide = this.errors().add( this.containers );
472
+ },
473
+
474
+ prepareElement: function( element ) {
475
+ this.reset();
476
+ this.toHide = this.errorsFor(element);
477
+ },
478
+
479
+ check: function( element ) {
480
+ element = this.clean( element );
481
+
482
+ // if radio/checkbox, validate first element in group instead
483
+ if (this.checkable(element)) {
484
+ element = this.findByName( element.name ).not(this.settings.ignore)[0];
485
+ }
486
+
487
+ var rules = $(element).rules();
488
+ var dependencyMismatch = false;
489
+ for( method in rules ) {
490
+ var rule = { method: method, parameters: rules[method] };
491
+ try {
492
+ var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters );
493
+
494
+ // if a method indicates that the field is optional and therefore valid,
495
+ // don't mark it as valid when there are no other rules
496
+ if ( result == "dependency-mismatch" ) {
497
+ dependencyMismatch = true;
498
+ continue;
499
+ }
500
+ dependencyMismatch = false;
501
+
502
+ if ( result == "pending" ) {
503
+ this.toHide = this.toHide.not( this.errorsFor(element) );
504
+ return;
505
+ }
506
+
507
+ if( !result ) {
508
+ this.formatAndAdd( element, rule );
509
+ return false;
510
+ }
511
+ } catch(e) {
512
+ this.settings.debug && window.console && console.log("exception occured when checking element " + element.id
513
+ + ", check the '" + rule.method + "' method", e);
514
+ throw e;
515
+ }
516
+ }
517
+ if (dependencyMismatch)
518
+ return;
519
+ if ( this.objectLength(rules) )
520
+ this.successList.push(element);
521
+ return true;
522
+ },
523
+
524
+ // return the custom message for the given element and validation method
525
+ // specified in the element's "messages" metadata
526
+ customMetaMessage: function(element, method) {
527
+ if (!$.metadata)
528
+ return;
529
+
530
+ var meta = this.settings.meta
531
+ ? $(element).metadata()[this.settings.meta]
532
+ : $(element).metadata();
533
+
534
+ return meta && meta.messages && meta.messages[method];
535
+ },
536
+
537
+ // return the custom message for the given element name and validation method
538
+ customMessage: function( name, method ) {
539
+ var m = this.settings.messages[name];
540
+ return m && (m.constructor == String
541
+ ? m
542
+ : m[method]);
543
+ },
544
+
545
+ // return the first defined argument, allowing empty strings
546
+ findDefined: function() {
547
+ for(var i = 0; i < arguments.length; i++) {
548
+ if (arguments[i] !== undefined)
549
+ return arguments[i];
550
+ }
551
+ return undefined;
552
+ },
553
+
554
+ defaultMessage: function( element, method) {
555
+ return this.findDefined(
556
+ this.customMessage( element.name, method ),
557
+ this.customMetaMessage( element, method ),
558
+ // title is never undefined, so handle empty string as undefined
559
+ !this.settings.ignoreTitle && element.title || undefined,
560
+ $.validator.messages[method],
561
+ "<strong>Warning: No message defined for " + element.name + "</strong>"
562
+ );
563
+ },
564
+
565
+ formatAndAdd: function( element, rule ) {
566
+ var message = this.defaultMessage( element, rule.method ),
567
+ theregex = /\$?\{(\d+)\}/g;
568
+ if ( typeof message == "function" ) {
569
+ message = message.call(this, rule.parameters, element);
570
+ } else if (theregex.test(message)) {
571
+ message = jQuery.format(message.replace(theregex, '{$1}'), rule.parameters);
572
+ }
573
+ this.errorList.push({
574
+ message: message,
575
+ element: element
576
+ });
577
+
578
+ this.errorMap[element.name] = message;
579
+ this.submitted[element.name] = message;
580
+ },
581
+
582
+ addWrapper: function(toToggle) {
583
+ if ( this.settings.wrapper )
584
+ toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
585
+ return toToggle;
586
+ },
587
+
588
+ defaultShowErrors: function() {
589
+ for ( var i = 0; this.errorList[i]; i++ ) {
590
+ var error = this.errorList[i];
591
+ this.settings.highlight && this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
592
+ this.showLabel( error.element, error.message );
593
+ }
594
+ if( this.errorList.length ) {
595
+ this.toShow = this.toShow.add( this.containers );
596
+ }
597
+ if (this.settings.success) {
598
+ for ( var i = 0; this.successList[i]; i++ ) {
599
+ this.showLabel( this.successList[i] );
600
+ }
601
+ }
602
+ if (this.settings.unhighlight) {
603
+ for ( var i = 0, elements = this.validElements(); elements[i]; i++ ) {
604
+ this.settings.unhighlight.call( this, elements[i], this.settings.errorClass, this.settings.validClass );
605
+ }
606
+ }
607
+ this.toHide = this.toHide.not( this.toShow );
608
+ this.hideErrors();
609
+ this.addWrapper( this.toShow ).show();
610
+ },
611
+
612
+ validElements: function() {
613
+ return this.currentElements.not(this.invalidElements());
614
+ },
615
+
616
+ invalidElements: function() {
617
+ return $(this.errorList).map(function() {
618
+ return this.element;
619
+ });
620
+ },
621
+
622
+ showLabel: function(element, message) {
623
+ var label = this.errorsFor( element );
624
+ if ( label.length ) {
625
+ // refresh error/success class
626
+ label.removeClass().addClass( this.settings.errorClass );
627
+
628
+ // check if we have a generated label, replace the message then
629
+ label.attr("generated") && label.html(message);
630
+ } else {
631
+ // create label
632
+ label = $("<" + this.settings.errorElement + "/>")
633
+ .attr({"for": this.idOrName(element), generated: true})
634
+ .addClass(this.settings.errorClass)
635
+ .html(message || "");
636
+ if ( this.settings.wrapper ) {
637
+ // make sure the element is visible, even in IE
638
+ // actually showing the wrapped element is handled elsewhere
639
+ label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();
640
+ }
641
+ if ( !this.labelContainer.append(label).length )
642
+ this.settings.errorPlacement
643
+ ? this.settings.errorPlacement(label, $(element) )
644
+ : label.insertAfter(element);
645
+ }
646
+ if ( !message && this.settings.success ) {
647
+ label.text("");
648
+ typeof this.settings.success == "string"
649
+ ? label.addClass( this.settings.success )
650
+ : this.settings.success( label );
651
+ }
652
+ this.toShow = this.toShow.add(label);
653
+ },
654
+
655
+ errorsFor: function(element) {
656
+ var name = this.idOrName(element);
657
+ return this.errors().filter(function() {
658
+ return $(this).attr('for') == name;
659
+ });
660
+ },
661
+
662
+ idOrName: function(element) {
663
+ return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
664
+ },
665
+
666
+ checkable: function( element ) {
667
+ return /radio|checkbox/i.test(element.type);
668
+ },
669
+
670
+ findByName: function( name ) {
671
+ // select by name and filter by form for performance over form.find("[name=...]")
672
+ var form = this.currentForm;
673
+ return $(document.getElementsByName(name)).map(function(index, element) {
674
+ return element.form == form && element.name == name && element || null;
675
+ });
676
+ },
677
+
678
+ getLength: function(value, element) {
679
+ switch( element.nodeName.toLowerCase() ) {
680
+ case 'select':
681
+ return $("option:selected", element).length;
682
+ case 'input':
683
+ if( this.checkable( element) )
684
+ return this.findByName(element.name).filter(':checked').length;
685
+ }
686
+ return value.length;
687
+ },
688
+
689
+ depend: function(param, element) {
690
+ return this.dependTypes[typeof param]
691
+ ? this.dependTypes[typeof param](param, element)
692
+ : true;
693
+ },
694
+
695
+ dependTypes: {
696
+ "boolean": function(param, element) {
697
+ return param;
698
+ },
699
+ "string": function(param, element) {
700
+ return !!$(param, element.form).length;
701
+ },
702
+ "function": function(param, element) {
703
+ return param(element);
704
+ }
705
+ },
706
+
707
+ optional: function(element) {
708
+ return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch";
709
+ },
710
+
711
+ startRequest: function(element) {
712
+ if (!this.pending[element.name]) {
713
+ this.pendingRequest++;
714
+ this.pending[element.name] = true;
715
+ }
716
+ },
717
+
718
+ stopRequest: function(element, valid) {
719
+ this.pendingRequest--;
720
+ // sometimes synchronization fails, make sure pendingRequest is never < 0
721
+ if (this.pendingRequest < 0)
722
+ this.pendingRequest = 0;
723
+ delete this.pending[element.name];
724
+ if ( valid && this.pendingRequest == 0 && this.formSubmitted && this.form() ) {
725
+ $(this.currentForm).submit();
726
+ this.formSubmitted = false;
727
+ } else if (!valid && this.pendingRequest == 0 && this.formSubmitted) {
728
+ $(this.currentForm).triggerHandler("invalid-form", [this]);
729
+ this.formSubmitted = false;
730
+ }
731
+ },
732
+
733
+ previousValue: function(element) {
734
+ return $.data(element, "previousValue") || $.data(element, "previousValue", {
735
+ old: null,
736
+ valid: true,
737
+ message: this.defaultMessage( element, "remote" )
738
+ });
739
+ }
740
+
741
+ },
742
+
743
+ classRuleSettings: {
744
+ required: {required: true},
745
+ email: {email: true},
746
+ url: {url: true},
747
+ date: {date: true},
748
+ dateISO: {dateISO: true},
749
+ dateDE: {dateDE: true},
750
+ number: {number: true},
751
+ numberDE: {numberDE: true},
752
+ digits: {digits: true},
753
+ creditcard: {creditcard: true}
754
+ },
755
+
756
+ addClassRules: function(className, rules) {
757
+ className.constructor == String ?
758
+ this.classRuleSettings[className] = rules :
759
+ $.extend(this.classRuleSettings, className);
760
+ },
761
+
762
+ classRules: function(element) {
763
+ var rules = {};
764
+ var classes = $(element).attr('class');
765
+ classes && $.each(classes.split(' '), function() {
766
+ if (this in $.validator.classRuleSettings) {
767
+ $.extend(rules, $.validator.classRuleSettings[this]);
768
+ }
769
+ });
770
+ return rules;
771
+ },
772
+
773
+ attributeRules: function(element) {
774
+ var rules = {};
775
+ var $element = $(element);
776
+
777
+ for (method in $.validator.methods) {
778
+ var value = $element.attr(method);
779
+ if (value) {
780
+ rules[method] = value;
781
+ }
782
+ }
783
+
784
+ // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari) for text inputs
785
+ if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {
786
+ delete rules.maxlength;
787
+ }
788
+
789
+ return rules;
790
+ },
791
+
792
+ metadataRules: function(element) {
793
+ if (!$.metadata) return {};
794
+
795
+ var meta = $.data(element.form, 'validator').settings.meta;
796
+ return meta ?
797
+ $(element).metadata()[meta] :
798
+ $(element).metadata();
799
+ },
800
+
801
+ staticRules: function(element) {
802
+ var rules = {};
803
+ var validator = $.data(element.form, 'validator');
804
+ if (validator.settings.rules) {
805
+ rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
806
+ }
807
+ return rules;
808
+ },
809
+
810
+ normalizeRules: function(rules, element) {
811
+ // handle dependency check
812
+ $.each(rules, function(prop, val) {
813
+ // ignore rule when param is explicitly false, eg. required:false
814
+ if (val === false) {
815
+ delete rules[prop];
816
+ return;
817
+ }
818
+ if (val.param || val.depends) {
819
+ var keepRule = true;
820
+ switch (typeof val.depends) {
821
+ case "string":
822
+ keepRule = !!$(val.depends, element.form).length;
823
+ break;
824
+ case "function":
825
+ keepRule = val.depends.call(element, element);
826
+ break;
827
+ }
828
+ if (keepRule) {
829
+ rules[prop] = val.param !== undefined ? val.param : true;
830
+ } else {
831
+ delete rules[prop];
832
+ }
833
+ }
834
+ });
835
+
836
+ // evaluate parameters
837
+ $.each(rules, function(rule, parameter) {
838
+ rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
839
+ });
840
+
841
+ // clean number parameters
842
+ $.each(['minlength', 'maxlength', 'min', 'max'], function() {
843
+ if (rules[this]) {
844
+ rules[this] = Number(rules[this]);
845
+ }
846
+ });
847
+ $.each(['rangelength', 'range'], function() {
848
+ if (rules[this]) {
849
+ rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
850
+ }
851
+ });
852
+
853
+ if ($.validator.autoCreateRanges) {
854
+ // auto-create ranges
855
+ if (rules.min && rules.max) {
856
+ rules.range = [rules.min, rules.max];
857
+ delete rules.min;
858
+ delete rules.max;
859
+ }
860
+ if (rules.minlength && rules.maxlength) {
861
+ rules.rangelength = [rules.minlength, rules.maxlength];
862
+ delete rules.minlength;
863
+ delete rules.maxlength;
864
+ }
865
+ }
866
+
867
+ // To support custom messages in metadata ignore rule methods titled "messages"
868
+ if (rules.messages) {
869
+ delete rules.messages;
870
+ }
871
+
872
+ return rules;
873
+ },
874
+
875
+ // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
876
+ normalizeRule: function(data) {
877
+ if( typeof data == "string" ) {
878
+ var transformed = {};
879
+ $.each(data.split(/\s/), function() {
880
+ transformed[this] = true;
881
+ });
882
+ data = transformed;
883
+ }
884
+ return data;
885
+ },
886
+
887
+ // http://docs.jquery.com/Plugins/Validation/Validator/addMethod
888
+ addMethod: function(name, method, message) {
889
+ $.validator.methods[name] = method;
890
+ $.validator.messages[name] = message != undefined ? message : $.validator.messages[name];
891
+ if (method.length < 3) {
892
+ $.validator.addClassRules(name, $.validator.normalizeRule(name));
893
+ }
894
+ },
895
+
896
+ methods: {
897
+
898
+ // http://docs.jquery.com/Plugins/Validation/Methods/required
899
+ required: function(value, element, param) {
900
+ // check if dependency is met
901
+ if ( !this.depend(param, element) )
902
+ return "dependency-mismatch";
903
+ switch( element.nodeName.toLowerCase() ) {
904
+ case 'select':
905
+ // could be an array for select-multiple or a string, both are fine this way
906
+ var val = $(element).val();
907
+ return val && val.length > 0;
908
+ case 'input':
909
+ if ( this.checkable(element) )
910
+ return this.getLength(value, element) > 0;
911
+ default:
912
+ return $.trim(value).length > 0;
913
+ }
914
+ },
915
+
916
+ // http://docs.jquery.com/Plugins/Validation/Methods/remote
917
+ remote: function(value, element, param) {
918
+ if ( this.optional(element) )
919
+ return "dependency-mismatch";
920
+
921
+ var previous = this.previousValue(element);
922
+ if (!this.settings.messages[element.name] )
923
+ this.settings.messages[element.name] = {};
924
+ previous.originalMessage = this.settings.messages[element.name].remote;
925
+ this.settings.messages[element.name].remote = previous.message;
926
+
927
+ param = typeof param == "string" && {url:param} || param;
928
+
929
+ if ( previous.old !== value ) {
930
+ previous.old = value;
931
+ var validator = this;
932
+ this.startRequest(element);
933
+ var data = {};
934
+ data[element.name] = value;
935
+ $.ajax($.extend(true, {
936
+ url: param,
937
+ mode: "abort",
938
+ port: "validate" + element.name,
939
+ dataType: "json",
940
+ data: data,
941
+ success: function(response) {
942
+ validator.settings.messages[element.name].remote = previous.originalMessage;
943
+ var valid = response === true;
944
+ if ( valid ) {
945
+ var submitted = validator.formSubmitted;
946
+ validator.prepareElement(element);
947
+ validator.formSubmitted = submitted;
948
+ validator.successList.push(element);
949
+ validator.showErrors();
950
+ } else {
951
+ var errors = {};
952
+ var message = (previous.message = response || validator.defaultMessage( element, "remote" ));
953
+ errors[element.name] = $.isFunction(message) ? message(value) : message;
954
+ validator.showErrors(errors);
955
+ }
956
+ previous.valid = valid;
957
+ validator.stopRequest(element, valid);
958
+ }
959
+ }, param));
960
+ return "pending";
961
+ } else if( this.pending[element.name] ) {
962
+ return "pending";
963
+ }
964
+ return previous.valid;
965
+ },
966
+
967
+ // http://docs.jquery.com/Plugins/Validation/Methods/minlength
968
+ minlength: function(value, element, param) {
969
+ return this.optional(element) || this.getLength($.trim(value), element) >= param;
970
+ },
971
+
972
+ // http://docs.jquery.com/Plugins/Validation/Methods/maxlength
973
+ maxlength: function(value, element, param) {
974
+ return this.optional(element) || this.getLength($.trim(value), element) <= param;
975
+ },
976
+
977
+ // http://docs.jquery.com/Plugins/Validation/Methods/rangelength
978
+ rangelength: function(value, element, param) {
979
+ var length = this.getLength($.trim(value), element);
980
+ return this.optional(element) || ( length >= param[0] && length <= param[1] );
981
+ },
982
+
983
+ // http://docs.jquery.com/Plugins/Validation/Methods/min
984
+ min: function( value, element, param ) {
985
+ return this.optional(element) || value >= param;
986
+ },
987
+
988
+ // http://docs.jquery.com/Plugins/Validation/Methods/max
989
+ max: function( value, element, param ) {
990
+ return this.optional(element) || value <= param;
991
+ },
992
+
993
+ // http://docs.jquery.com/Plugins/Validation/Methods/range
994
+ range: function( value, element, param ) {
995
+ return this.optional(element) || ( value >= param[0] && value <= param[1] );
996
+ },
997
+
998
+ // http://docs.jquery.com/Plugins/Validation/Methods/email
999
+ email: function(value, element) {
1000
+ // contributed by Scott Gonzalez: http://projects.scottsplayground.com/email_address_validation/
1001
+ 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);
1002
+ },
1003
+
1004
+ // http://docs.jquery.com/Plugins/Validation/Methods/url
1005
+ url: function(value, element) {
1006
+ // contributed by Scott Gonzalez: http://projects.scottsplayground.com/iri/
1007
+ 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);
1008
+ },
1009
+
1010
+ // http://docs.jquery.com/Plugins/Validation/Methods/date
1011
+ date: function(value, element) {
1012
+ return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
1013
+ },
1014
+
1015
+ // http://docs.jquery.com/Plugins/Validation/Methods/dateISO
1016
+ dateISO: function(value, element) {
1017
+ return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
1018
+ },
1019
+
1020
+ // http://docs.jquery.com/Plugins/Validation/Methods/number
1021
+ number: function(value, element) {
1022
+ return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
1023
+ },
1024
+
1025
+ // http://docs.jquery.com/Plugins/Validation/Methods/digits
1026
+ digits: function(value, element) {
1027
+ return this.optional(element) || /^\d+$/.test(value);
1028
+ },
1029
+
1030
+ // http://docs.jquery.com/Plugins/Validation/Methods/creditcard
1031
+ // based on http://en.wikipedia.org/wiki/Luhn
1032
+ creditcard: function(value, element) {
1033
+ if ( this.optional(element) )
1034
+ return "dependency-mismatch";
1035
+ // accept only digits and dashes
1036
+ if (/[^0-9-]+/.test(value))
1037
+ return false;
1038
+ var nCheck = 0,
1039
+ nDigit = 0,
1040
+ bEven = false;
1041
+
1042
+ value = value.replace(/\D/g, "");
1043
+
1044
+ for (var n = value.length - 1; n >= 0; n--) {
1045
+ var cDigit = value.charAt(n);
1046
+ var nDigit = parseInt(cDigit, 10);
1047
+ if (bEven) {
1048
+ if ((nDigit *= 2) > 9)
1049
+ nDigit -= 9;
1050
+ }
1051
+ nCheck += nDigit;
1052
+ bEven = !bEven;
1053
+ }
1054
+
1055
+ return (nCheck % 10) == 0;
1056
+ },
1057
+
1058
+ // http://docs.jquery.com/Plugins/Validation/Methods/accept
1059
+ accept: function(value, element, param) {
1060
+ param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif";
1061
+ return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i"));
1062
+ },
1063
+
1064
+ // http://docs.jquery.com/Plugins/Validation/Methods/equalTo
1065
+ equalTo: function(value, element, param) {
1066
+ // bind to the blur event of the target in order to revalidate whenever the target field is updated
1067
+ // TODO find a way to bind the event just once, avoiding the unbind-rebind overhead
1068
+ var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() {
1069
+ $(element).valid();
1070
+ });
1071
+ return value == target.val();
1072
+ }
1073
+
1074
+ }
1075
+
1076
+ });
1077
+
1078
+ // deprecated, use $.validator.format instead
1079
+ $.format = $.validator.format;
1080
+
1081
+ })(jQuery);
1082
+
1083
+ // ajax mode: abort
1084
+ // usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
1085
+ // if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
1086
+ ;(function($) {
1087
+ var ajax = $.ajax;
1088
+ var pendingRequests = {};
1089
+ $.ajax = function(settings) {
1090
+ // create settings for compatibility with ajaxSetup
1091
+ settings = $.extend(settings, $.extend({}, $.ajaxSettings, settings));
1092
+ var port = settings.port;
1093
+ if (settings.mode == "abort") {
1094
+ if ( pendingRequests[port] ) {
1095
+ pendingRequests[port].abort();
1096
+ }
1097
+ return (pendingRequests[port] = ajax.apply(this, arguments));
1098
+ }
1099
+ return ajax.apply(this, arguments);
1100
+ };
1101
+ })(jQuery);
1102
+
1103
+ // provides cross-browser focusin and focusout events
1104
+ // IE has native support, in other browsers, use event caputuring (neither bubbles)
1105
+
1106
+ // provides delegate(type: String, delegate: Selector, handler: Callback) plugin for easier event delegation
1107
+ // handler is only called when $(event.target).is(delegate), in the scope of the jquery-object for event.target
1108
+ ;(function($) {
1109
+ // only implement if not provided by jQuery core (since 1.4)
1110
+ // TODO verify if jQuery 1.4's implementation is compatible with older jQuery special-event APIs
1111
+ if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) {
1112
+ $.each({
1113
+ focus: 'focusin',
1114
+ blur: 'focusout'
1115
+ }, function( original, fix ){
1116
+ $.event.special[fix] = {
1117
+ setup:function() {
1118
+ this.addEventListener( original, handler, true );
1119
+ },
1120
+ teardown:function() {
1121
+ this.removeEventListener( original, handler, true );
1122
+ },
1123
+ handler: function(e) {
1124
+ arguments[0] = $.event.fix(e);
1125
+ arguments[0].type = fix;
1126
+ return $.event.handle.apply(this, arguments);
1127
+ }
1128
+ };
1129
+ function handler(e) {
1130
+ e = $.event.fix(e);
1131
+ e.type = fix;
1132
+ return $.event.handle.call(this, e);
1133
+ }
1134
+ });
1135
+ };
1136
+ $.extend($.fn, {
1137
+ validateDelegate: function(delegate, type, handler) {
1138
+ return this.bind(type, function(event) {
1139
+ var target = $(event.target);
1140
+ if (target.is(delegate)) {
1141
+ return handler.apply(target, arguments);
1142
+ }
1143
+ });
1144
+ }
1145
+ });
1146
+ })(jQuery);