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