PluginProbe ʕ •ᴥ•ʔ
Download Manager / 3.3.63
Download Manager v3.3.63
3.3.63 3.3.62 3.3.61 3.3.60 3.3.59 3.3.58 3.3.57 3.3.56 trunk 2.1.3 2.3.0 2.5.96 2.5.97 2.6.2 2.6.96 2.8.3 2.9.99 3.0.4 3.1.05 3.1.07 3.1.08 3.1.11 3.1.12 3.1.14 3.1.17 3.1.18 3.1.22 3.1.23 3.1.24 3.1.25 3.1.26 3.1.27 3.1.28 3.2.04 3.2.13 3.2.14 3.2.16 3.2.18 3.2.19 3.2.21 3.2.22 3.2.23 3.2.24 3.2.25 3.2.27 3.2.28 3.2.29 3.2.30 3.2.31 3.2.32 3.2.33 3.2.34 3.2.35 3.2.37 3.2.38 3.2.39 3.2.40 3.2.41 3.2.42 3.2.43 3.2.44 3.2.45 3.2.46 3.2.47 3.2.48 3.2.49 3.2.50 3.2.51 3.2.52 3.2.53 3.2.54 3.2.55 3.2.56 3.2.57 3.2.58 3.2.59 3.2.60 3.2.61 3.2.63 3.2.64 3.2.65 3.2.66 3.2.67 3.2.68 3.2.69 3.2.70 3.2.71 3.2.72 3.2.73 3.2.74 3.2.75 3.2.76 3.2.77 3.2.78 3.2.79 3.2.80 3.2.81 3.2.82 3.2.83 3.2.84 3.2.85 3.2.86 3.2.87 3.2.88 3.2.89 3.2.90 3.2.91 3.2.92 3.2.93 3.2.94 3.2.95 3.2.96 3.2.97 3.2.98 3.2.99 3.3.00 3.3.01 3.3.02 3.3.03 3.3.04 3.3.05 3.3.06 3.3.07 3.3.08 3.3.09 3.3.10 3.3.11 3.3.12 3.3.13 3.3.14 3.3.15 3.3.16 3.3.17 3.3.18 3.3.19 3.3.20 3.3.21 3.3.22 3.3.23 3.3.24 3.3.25 3.3.26 3.3.27 3.3.28 3.3.29 3.3.30 3.3.31 3.3.32 3.3.33 3.3.34 3.3.35 3.3.36 3.3.37 3.3.38 3.3.39 3.3.40 3.3.41 3.3.42 3.3.43 3.3.44 3.3.45 3.3.46 3.3.47 3.3.48 3.3.49 3.3.50 3.3.51 3.3.52 3.3.53 3.3.54 3.3.55
download-manager / assets / js / jquery.validate.js
download-manager / assets / js Last commit date
ads 8 months ago control 8 months ago img 10 years ago blocker.js 1 week ago blocker.min.js 1 week ago embed.js 5 years ago embed.min.js 7 months ago front.js 1 day ago front.min.js 1 day ago jquery-ui-timepicker-addon.js 10 years ago jquery-ui-timepicker-addon.min.js 7 months ago jquery.dataTables.min.js 1 year ago jquery.validate.js 7 months ago jquery.validate.min.js 1 week ago jqueryFileTree.js 5 years ago jqueryFileTree.min.js 7 months ago overwatch.js 7 months ago overwatch.min.js 7 months ago password-strength.js 2 years ago password-strength.min.js 7 months ago simple-scrollbar.js 7 months ago simple-scrollbar.min.js 7 months ago simplebar.js 6 years ago validator.min.js 9 years ago vue.js 9 months ago vue.min.js 9 months ago wpdm-admin.js 1 week ago wpdm-admin.min.js 1 week ago wpdm.js 6 months ago wpdm.min.js 6 months ago
jquery.validate.js
1661 lines
1 /*!
2 * jQuery Validation Plugin v1.19.5
3 *
4 * https://jqueryvalidation.org/
5 *
6 * Copyright (c) 2022 Jörn Zaefferer
7 * Released under the MIT license
8 */
9 (function( factory ) {
10 if ( typeof define === "function" && define.amd ) {
11 define( ["jquery"], factory );
12 } else if (typeof module === "object" && module.exports) {
13 module.exports = factory( require( "jquery" ) );
14 } else {
15 factory( jQuery );
16 }
17 }(function( $ ) {
18
19 $.extend( $.fn, {
20
21 // https://jqueryvalidation.org/validate/
22 validate: function( options ) {
23
24 // If nothing is selected, return nothing; can't chain anyway
25 if ( !this.length ) {
26 if ( options && options.debug && window.console ) {
27 console.warn( "Nothing selected, can't validate, returning nothing." );
28 }
29 return;
30 }
31
32 // Check if a validator for this form was already created
33 var validator = $.data( this[ 0 ], "validator" );
34 if ( validator ) {
35 return validator;
36 }
37
38 // Add novalidate tag if HTML5.
39 this.attr( "novalidate", "novalidate" );
40
41 validator = new $.validator( options, this[ 0 ] );
42 $.data( this[ 0 ], "validator", validator );
43
44 if ( validator.settings.onsubmit ) {
45
46 this.on( "click.validate", ":submit", function( event ) {
47
48 // Track the used submit button to properly handle scripted
49 // submits later.
50 validator.submitButton = event.currentTarget;
51
52 // Allow suppressing validation by adding a cancel class to the submit button
53 if ( $( this ).hasClass( "cancel" ) ) {
54 validator.cancelSubmit = true;
55 }
56
57 // Allow suppressing validation by adding the html5 formnovalidate attribute to the submit button
58 if ( $( this ).attr( "formnovalidate" ) !== undefined ) {
59 validator.cancelSubmit = true;
60 }
61 } );
62
63 // Validate the form on submit
64 this.on( "submit.validate", function( event ) {
65 if ( validator.settings.debug ) {
66
67 // Prevent form submit to be able to see console output
68 event.preventDefault();
69 }
70
71 function handle() {
72 var hidden, result;
73
74 // Insert a hidden input as a replacement for the missing submit button
75 // The hidden input is inserted in two cases:
76 // - A user defined a `submitHandler`
77 // - There was a pending request due to `remote` method and `stopRequest()`
78 // was called to submit the form in case it's valid
79 if ( validator.submitButton && ( validator.settings.submitHandler || validator.formSubmitted ) ) {
80 hidden = $( "<input type='hidden'/>" )
81 .attr( "name", validator.submitButton.name )
82 .val( $( validator.submitButton ).val() )
83 .appendTo( validator.currentForm );
84 }
85
86 if ( validator.settings.submitHandler && !validator.settings.debug ) {
87 result = validator.settings.submitHandler.call( validator, validator.currentForm, event );
88 if ( hidden ) {
89
90 // And clean up afterwards; thanks to no-block-scope, hidden can be referenced
91 hidden.remove();
92 }
93 if ( result !== undefined ) {
94 return result;
95 }
96 return false;
97 }
98 return true;
99 }
100
101 // Prevent submit for invalid forms or custom submit handlers
102 if ( validator.cancelSubmit ) {
103 validator.cancelSubmit = false;
104 return handle();
105 }
106 if ( validator.form() ) {
107 if ( validator.pendingRequest ) {
108 validator.formSubmitted = true;
109 return false;
110 }
111 return handle();
112 } else {
113 validator.focusInvalid();
114 return false;
115 }
116 } );
117 }
118
119 return validator;
120 },
121
122 // https://jqueryvalidation.org/valid/
123 valid: function() {
124 var valid, validator, errorList;
125
126 if ( $( this[ 0 ] ).is( "form" ) ) {
127 valid = this.validate().form();
128 } else {
129 errorList = [];
130 valid = true;
131 validator = $( this[ 0 ].form ).validate();
132 this.each( function() {
133 valid = validator.element( this ) && valid;
134 if ( !valid ) {
135 errorList = errorList.concat( validator.errorList );
136 }
137 } );
138 validator.errorList = errorList;
139 }
140 return valid;
141 },
142
143 // https://jqueryvalidation.org/rules/
144 rules: function( command, argument ) {
145 var element = this[ 0 ],
146 isContentEditable = typeof this.attr( "contenteditable" ) !== "undefined" && this.attr( "contenteditable" ) !== "false",
147 settings, staticRules, existingRules, data, param, filtered;
148
149 // If nothing is selected, return empty object; can't chain anyway
150 if ( element == null ) {
151 return;
152 }
153
154 if ( !element.form && isContentEditable ) {
155 element.form = this.closest( "form" )[ 0 ];
156 element.name = this.attr( "name" );
157 }
158
159 if ( element.form == null ) {
160 return;
161 }
162
163 if ( command ) {
164 settings = $.data( element.form, "validator" ).settings;
165 staticRules = settings.rules;
166 existingRules = $.validator.staticRules( element );
167 switch ( command ) {
168 case "add":
169 $.extend( existingRules, $.validator.normalizeRule( argument ) );
170
171 // Remove messages from rules, but allow them to be set separately
172 delete existingRules.messages;
173 staticRules[ element.name ] = existingRules;
174 if ( argument.messages ) {
175 settings.messages[ element.name ] = $.extend( settings.messages[ element.name ], argument.messages );
176 }
177 break;
178 case "remove":
179 if ( !argument ) {
180 delete staticRules[ element.name ];
181 return existingRules;
182 }
183 filtered = {};
184 $.each( argument.split( /\s/ ), function( index, method ) {
185 filtered[ method ] = existingRules[ method ];
186 delete existingRules[ method ];
187 } );
188 return filtered;
189 }
190 }
191
192 data = $.validator.normalizeRules(
193 $.extend(
194 {},
195 $.validator.classRules( element ),
196 $.validator.attributeRules( element ),
197 $.validator.dataRules( element ),
198 $.validator.staticRules( element )
199 ), element );
200
201 // Make sure required is at front
202 if ( data.required ) {
203 param = data.required;
204 delete data.required;
205 data = $.extend( { required: param }, data );
206 }
207
208 // Make sure remote is at back
209 if ( data.remote ) {
210 param = data.remote;
211 delete data.remote;
212 data = $.extend( data, { remote: param } );
213 }
214
215 return data;
216 }
217 } );
218
219 // JQuery trim is deprecated, provide a trim method based on String.prototype.trim
220 var trim = function( str ) {
221
222 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trim#Polyfill
223 return str.replace( /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, "" );
224 };
225
226 // Custom selectors
227 $.extend( $.expr.pseudos || $.expr[ ":" ], { // '|| $.expr[ ":" ]' here enables backwards compatibility to jQuery 1.7. Can be removed when dropping jQ 1.7.x support
228
229 // https://jqueryvalidation.org/blank-selector/
230 blank: function( a ) {
231 return !trim( "" + $( a ).val() );
232 },
233
234 // https://jqueryvalidation.org/filled-selector/
235 filled: function( a ) {
236 var val = $( a ).val();
237 return val !== null && !!trim( "" + val );
238 },
239
240 // https://jqueryvalidation.org/unchecked-selector/
241 unchecked: function( a ) {
242 return !$( a ).prop( "checked" );
243 }
244 } );
245
246 // Constructor for validator
247 $.validator = function( options, form ) {
248 this.settings = $.extend( true, {}, $.validator.defaults, options );
249 this.currentForm = form;
250 this.init();
251 };
252
253 // https://jqueryvalidation.org/jQuery.validator.format/
254 $.validator.format = function( source, params ) {
255 if ( arguments.length === 1 ) {
256 return function() {
257 var args = $.makeArray( arguments );
258 args.unshift( source );
259 return $.validator.format.apply( this, args );
260 };
261 }
262 if ( params === undefined ) {
263 return source;
264 }
265 if ( arguments.length > 2 && params.constructor !== Array ) {
266 params = $.makeArray( arguments ).slice( 1 );
267 }
268 if ( params.constructor !== Array ) {
269 params = [ params ];
270 }
271 $.each( params, function( i, n ) {
272 source = source.replace( new RegExp( "\\{" + i + "\\}", "g" ), function() {
273 return n;
274 } );
275 } );
276 return source;
277 };
278
279 $.extend( $.validator, {
280
281 defaults: {
282 messages: {},
283 groups: {},
284 rules: {},
285 errorClass: "error",
286 pendingClass: "pending",
287 validClass: "valid",
288 errorElement: "label",
289 focusCleanup: false,
290 focusInvalid: true,
291 errorContainer: $( [] ),
292 errorLabelContainer: $( [] ),
293 onsubmit: true,
294 ignore: ":hidden",
295 ignoreTitle: false,
296 onfocusin: function( element ) {
297 this.lastActive = element;
298
299 // Hide error label and remove error class on focus if enabled
300 if ( this.settings.focusCleanup ) {
301 if ( this.settings.unhighlight ) {
302 this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
303 }
304 this.hideThese( this.errorsFor( element ) );
305 }
306 },
307 onfocusout: function( element ) {
308 if ( !this.checkable( element ) && ( element.name in this.submitted || !this.optional( element ) ) ) {
309 this.element( element );
310 }
311 },
312 onkeyup: function( element, event ) {
313
314 // Avoid revalidate the field when pressing one of the following keys
315 // Shift => 16
316 // Ctrl => 17
317 // Alt => 18
318 // Caps lock => 20
319 // End => 35
320 // Home => 36
321 // Left arrow => 37
322 // Up arrow => 38
323 // Right arrow => 39
324 // Down arrow => 40
325 // Insert => 45
326 // Num lock => 144
327 // AltGr key => 225
328 var excludedKeys = [
329 16, 17, 18, 20, 35, 36, 37,
330 38, 39, 40, 45, 144, 225
331 ];
332
333 if ( event.which === 9 && this.elementValue( element ) === "" || $.inArray( event.keyCode, excludedKeys ) !== -1 ) {
334 return;
335 } else if ( element.name in this.submitted || element.name in this.invalid ) {
336 this.element( element );
337 }
338 },
339 onclick: function( element ) {
340
341 // Click on selects, radiobuttons and checkboxes
342 if ( element.name in this.submitted ) {
343 this.element( element );
344
345 // Or option elements, check parent select in that case
346 } else if ( element.parentNode.name in this.submitted ) {
347 this.element( element.parentNode );
348 }
349 },
350 highlight: function( element, errorClass, validClass ) {
351 if ( element.type === "radio" ) {
352 this.findByName( element.name ).addClass( errorClass ).removeClass( validClass );
353 } else {
354 $( element ).addClass( errorClass ).removeClass( validClass );
355 }
356 },
357 unhighlight: function( element, errorClass, validClass ) {
358 if ( element.type === "radio" ) {
359 this.findByName( element.name ).removeClass( errorClass ).addClass( validClass );
360 } else {
361 $( element ).removeClass( errorClass ).addClass( validClass );
362 }
363 }
364 },
365
366 // https://jqueryvalidation.org/jQuery.validator.setDefaults/
367 setDefaults: function( settings ) {
368 $.extend( $.validator.defaults, settings );
369 },
370
371 messages: {
372 required: "This field is required.",
373 remote: "Please fix this field.",
374 email: "Please enter a valid email address.",
375 url: "Please enter a valid URL.",
376 date: "Please enter a valid date.",
377 dateISO: "Please enter a valid date (ISO).",
378 number: "Please enter a valid number.",
379 digits: "Please enter only digits.",
380 equalTo: "Please enter the same value again.",
381 maxlength: $.validator.format( "Please enter no more than {0} characters." ),
382 minlength: $.validator.format( "Please enter at least {0} characters." ),
383 rangelength: $.validator.format( "Please enter a value between {0} and {1} characters long." ),
384 range: $.validator.format( "Please enter a value between {0} and {1}." ),
385 max: $.validator.format( "Please enter a value less than or equal to {0}." ),
386 min: $.validator.format( "Please enter a value greater than or equal to {0}." ),
387 step: $.validator.format( "Please enter a multiple of {0}." )
388 },
389
390 autoCreateRanges: false,
391
392 prototype: {
393
394 init: function() {
395 this.labelContainer = $( this.settings.errorLabelContainer );
396 this.errorContext = this.labelContainer.length && this.labelContainer || $( this.currentForm );
397 this.containers = $( this.settings.errorContainer ).add( this.settings.errorLabelContainer );
398 this.submitted = {};
399 this.valueCache = {};
400 this.pendingRequest = 0;
401 this.pending = {};
402 this.invalid = {};
403 this.reset();
404
405 var currentForm = this.currentForm,
406 groups = ( this.groups = {} ),
407 rules;
408 $.each( this.settings.groups, function( key, value ) {
409 if ( typeof value === "string" ) {
410 value = value.split( /\s/ );
411 }
412 $.each( value, function( index, name ) {
413 groups[ name ] = key;
414 } );
415 } );
416 rules = this.settings.rules;
417 $.each( rules, function( key, value ) {
418 rules[ key ] = $.validator.normalizeRule( value );
419 } );
420
421 function delegate( event ) {
422 var isContentEditable = typeof $( this ).attr( "contenteditable" ) !== "undefined" && $( this ).attr( "contenteditable" ) !== "false";
423
424 // Set form expando on contenteditable
425 if ( !this.form && isContentEditable ) {
426 this.form = $( this ).closest( "form" )[ 0 ];
427 this.name = $( this ).attr( "name" );
428 }
429
430 // Ignore the element if it belongs to another form. This will happen mainly
431 // when setting the `form` attribute of an input to the id of another form.
432 if ( currentForm !== this.form ) {
433 return;
434 }
435
436 var validator = $.data( this.form, "validator" ),
437 eventType = "on" + event.type.replace( /^validate/, "" ),
438 settings = validator.settings;
439 if ( settings[ eventType ] && !$( this ).is( settings.ignore ) ) {
440 settings[ eventType ].call( validator, this, event );
441 }
442 }
443
444 $( this.currentForm )
445 .on( "focusin.validate focusout.validate keyup.validate",
446 ":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], " +
447 "[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], " +
448 "[type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], " +
449 "[type='radio'], [type='checkbox'], [contenteditable], [type='button']", delegate )
450
451 // Support: Chrome, oldIE
452 // "select" is provided as event.target when clicking a option
453 .on( "click.validate", "select, option, [type='radio'], [type='checkbox']", delegate );
454
455 if ( this.settings.invalidHandler ) {
456 $( this.currentForm ).on( "invalid-form.validate", this.settings.invalidHandler );
457 }
458 },
459
460 // https://jqueryvalidation.org/Validator.form/
461 form: function() {
462 this.checkForm();
463 $.extend( this.submitted, this.errorMap );
464 this.invalid = $.extend( {}, this.errorMap );
465 if ( !this.valid() ) {
466 $( this.currentForm ).triggerHandler( "invalid-form", [ this ] );
467 }
468 this.showErrors();
469 return this.valid();
470 },
471
472 checkForm: function() {
473 this.prepareForm();
474 for ( var i = 0, elements = ( this.currentElements = this.elements() ); elements[ i ]; i++ ) {
475 this.check( elements[ i ] );
476 }
477 return this.valid();
478 },
479
480 // https://jqueryvalidation.org/Validator.element/
481 element: function( element ) {
482 var cleanElement = this.clean( element ),
483 checkElement = this.validationTargetFor( cleanElement ),
484 v = this,
485 result = true,
486 rs, group;
487
488 if ( checkElement === undefined ) {
489 delete this.invalid[ cleanElement.name ];
490 } else {
491 this.prepareElement( checkElement );
492 this.currentElements = $( checkElement );
493
494 // If this element is grouped, then validate all group elements already
495 // containing a value
496 group = this.groups[ checkElement.name ];
497 if ( group ) {
498 $.each( this.groups, function( name, testgroup ) {
499 if ( testgroup === group && name !== checkElement.name ) {
500 cleanElement = v.validationTargetFor( v.clean( v.findByName( name ) ) );
501 if ( cleanElement && cleanElement.name in v.invalid ) {
502 v.currentElements.push( cleanElement );
503 result = v.check( cleanElement ) && result;
504 }
505 }
506 } );
507 }
508
509 rs = this.check( checkElement ) !== false;
510 result = result && rs;
511 if ( rs ) {
512 this.invalid[ checkElement.name ] = false;
513 } else {
514 this.invalid[ checkElement.name ] = true;
515 }
516
517 if ( !this.numberOfInvalids() ) {
518
519 // Hide error containers on last error
520 this.toHide = this.toHide.add( this.containers );
521 }
522 this.showErrors();
523
524 // Add aria-invalid status for screen readers
525 $( element ).attr( "aria-invalid", !rs );
526 }
527
528 return result;
529 },
530
531 // https://jqueryvalidation.org/Validator.showErrors/
532 showErrors: function( errors ) {
533 if ( errors ) {
534 var validator = this;
535
536 // Add items to error list and map
537 $.extend( this.errorMap, errors );
538 this.errorList = $.map( this.errorMap, function( message, name ) {
539 return {
540 message: message,
541 element: validator.findByName( name )[ 0 ]
542 };
543 } );
544
545 // Remove items from success list
546 this.successList = $.grep( this.successList, function( element ) {
547 return !( element.name in errors );
548 } );
549 }
550 if ( this.settings.showErrors ) {
551 this.settings.showErrors.call( this, this.errorMap, this.errorList );
552 } else {
553 this.defaultShowErrors();
554 }
555 },
556
557 // https://jqueryvalidation.org/Validator.resetForm/
558 resetForm: function() {
559 if ( $.fn.resetForm ) {
560 $( this.currentForm ).resetForm();
561 }
562 this.invalid = {};
563 this.submitted = {};
564 this.prepareForm();
565 this.hideErrors();
566 var elements = this.elements()
567 .removeData( "previousValue" )
568 .removeAttr( "aria-invalid" );
569
570 this.resetElements( elements );
571 },
572
573 resetElements: function( elements ) {
574 var i;
575
576 if ( this.settings.unhighlight ) {
577 for ( i = 0; elements[ i ]; i++ ) {
578 this.settings.unhighlight.call( this, elements[ i ],
579 this.settings.errorClass, "" );
580 this.findByName( elements[ i ].name ).removeClass( this.settings.validClass );
581 }
582 } else {
583 elements
584 .removeClass( this.settings.errorClass )
585 .removeClass( this.settings.validClass );
586 }
587 },
588
589 numberOfInvalids: function() {
590 return this.objectLength( this.invalid );
591 },
592
593 objectLength: function( obj ) {
594 /* jshint unused: false */
595 var count = 0,
596 i;
597 for ( i in obj ) {
598
599 // This check allows counting elements with empty error
600 // message as invalid elements
601 if ( obj[ i ] !== undefined && obj[ i ] !== null && obj[ i ] !== false ) {
602 count++;
603 }
604 }
605 return count;
606 },
607
608 hideErrors: function() {
609 this.hideThese( this.toHide );
610 },
611
612 hideThese: function( errors ) {
613 errors.not( this.containers ).text( "" );
614 this.addWrapper( errors ).hide();
615 },
616
617 valid: function() {
618 return this.size() === 0;
619 },
620
621 size: function() {
622 return this.errorList.length;
623 },
624
625 focusInvalid: function() {
626 if ( this.settings.focusInvalid ) {
627 try {
628 $( this.findLastActive() || this.errorList.length && this.errorList[ 0 ].element || [] )
629 .filter( ":visible" )
630 .trigger( "focus" )
631
632 // Manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find
633 .trigger( "focusin" );
634 } catch ( e ) {
635
636 // Ignore IE throwing errors when focusing hidden elements
637 }
638 }
639 },
640
641 findLastActive: function() {
642 var lastActive = this.lastActive;
643 return lastActive && $.grep( this.errorList, function( n ) {
644 return n.element.name === lastActive.name;
645 } ).length === 1 && lastActive;
646 },
647
648 elements: function() {
649 var validator = this,
650 rulesCache = {};
651
652 // Select all valid inputs inside the form (no submit or reset buttons)
653 return $( this.currentForm )
654 .find( "input, select, textarea, [contenteditable]" )
655 .not( ":submit, :reset, :image, :disabled" )
656 .not( this.settings.ignore )
657 .filter( function() {
658 var name = this.name || $( this ).attr( "name" ); // For contenteditable
659 var isContentEditable = typeof $( this ).attr( "contenteditable" ) !== "undefined" && $( this ).attr( "contenteditable" ) !== "false";
660
661 if ( !name && validator.settings.debug && window.console ) {
662 console.error( "%o has no name assigned", this );
663 }
664
665 // Set form expando on contenteditable
666 if ( isContentEditable ) {
667 this.form = $( this ).closest( "form" )[ 0 ];
668 this.name = name;
669 }
670
671 // Ignore elements that belong to other/nested forms
672 if ( this.form !== validator.currentForm ) {
673 return false;
674 }
675
676 // Select only the first element for each name, and only those with rules specified
677 if ( name in rulesCache || !validator.objectLength( $( this ).rules() ) ) {
678 return false;
679 }
680
681 rulesCache[ name ] = true;
682 return true;
683 } );
684 },
685
686 clean: function( selector ) {
687 return $( selector )[ 0 ];
688 },
689
690 errors: function() {
691 var errorClass = this.settings.errorClass.split( " " ).join( "." );
692 return $( this.settings.errorElement + "." + errorClass, this.errorContext );
693 },
694
695 resetInternals: function() {
696 this.successList = [];
697 this.errorList = [];
698 this.errorMap = {};
699 this.toShow = $( [] );
700 this.toHide = $( [] );
701 },
702
703 reset: function() {
704 this.resetInternals();
705 this.currentElements = $( [] );
706 },
707
708 prepareForm: function() {
709 this.reset();
710 this.toHide = this.errors().add( this.containers );
711 },
712
713 prepareElement: function( element ) {
714 this.reset();
715 this.toHide = this.errorsFor( element );
716 },
717
718 elementValue: function( element ) {
719 var $element = $( element ),
720 type = element.type,
721 isContentEditable = typeof $element.attr( "contenteditable" ) !== "undefined" && $element.attr( "contenteditable" ) !== "false",
722 val, idx;
723
724 if ( type === "radio" || type === "checkbox" ) {
725 return this.findByName( element.name ).filter( ":checked" ).val();
726 } else if ( type === "number" && typeof element.validity !== "undefined" ) {
727 return element.validity.badInput ? "NaN" : $element.val();
728 }
729
730 if ( isContentEditable ) {
731 val = $element.text();
732 } else {
733 val = $element.val();
734 }
735
736 if ( type === "file" ) {
737
738 // Modern browser (chrome & safari)
739 if ( val.substr( 0, 12 ) === "C:\\fakepath\\" ) {
740 return val.substr( 12 );
741 }
742
743 // Legacy browsers
744 // Unix-based path
745 idx = val.lastIndexOf( "/" );
746 if ( idx >= 0 ) {
747 return val.substr( idx + 1 );
748 }
749
750 // Windows-based path
751 idx = val.lastIndexOf( "\\" );
752 if ( idx >= 0 ) {
753 return val.substr( idx + 1 );
754 }
755
756 // Just the file name
757 return val;
758 }
759
760 if ( typeof val === "string" ) {
761 return val.replace( /\r/g, "" );
762 }
763 return val;
764 },
765
766 check: function( element ) {
767 element = this.validationTargetFor( this.clean( element ) );
768
769 var rules = $( element ).rules(),
770 rulesCount = $.map( rules, function( n, i ) {
771 return i;
772 } ).length,
773 dependencyMismatch = false,
774 val = this.elementValue( element ),
775 result, method, rule, normalizer;
776
777 // Prioritize the local normalizer defined for this element over the global one
778 // if the former exists, otherwise user the global one in case it exists.
779 if ( typeof rules.normalizer === "function" ) {
780 normalizer = rules.normalizer;
781 } else if ( typeof this.settings.normalizer === "function" ) {
782 normalizer = this.settings.normalizer;
783 }
784
785 // If normalizer is defined, then call it to retreive the changed value instead
786 // of using the real one.
787 // Note that `this` in the normalizer is `element`.
788 if ( normalizer ) {
789 val = normalizer.call( element, val );
790
791 // Delete the normalizer from rules to avoid treating it as a pre-defined method.
792 delete rules.normalizer;
793 }
794
795 for ( method in rules ) {
796 rule = { method: method, parameters: rules[ method ] };
797 try {
798 result = $.validator.methods[ method ].call( this, val, element, rule.parameters );
799
800 // If a method indicates that the field is optional and therefore valid,
801 // don't mark it as valid when there are no other rules
802 if ( result === "dependency-mismatch" && rulesCount === 1 ) {
803 dependencyMismatch = true;
804 continue;
805 }
806 dependencyMismatch = false;
807
808 if ( result === "pending" ) {
809 this.toHide = this.toHide.not( this.errorsFor( element ) );
810 return;
811 }
812
813 if ( !result ) {
814 this.formatAndAdd( element, rule );
815 return false;
816 }
817 } catch ( e ) {
818 if ( this.settings.debug && window.console ) {
819 console.log( "Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.", e );
820 }
821 if ( e instanceof TypeError ) {
822 e.message += ". Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.";
823 }
824
825 throw e;
826 }
827 }
828 if ( dependencyMismatch ) {
829 return;
830 }
831 if ( this.objectLength( rules ) ) {
832 this.successList.push( element );
833 }
834 return true;
835 },
836
837 // Return the custom message for the given element and validation method
838 // specified in the element's HTML5 data attribute
839 // return the generic message if present and no method specific message is present
840 customDataMessage: function( element, method ) {
841 return $( element ).data( "msg" + method.charAt( 0 ).toUpperCase() +
842 method.substring( 1 ).toLowerCase() ) || $( element ).data( "msg" );
843 },
844
845 // Return the custom message for the given element name and validation method
846 customMessage: function( name, method ) {
847 var m = this.settings.messages[ name ];
848 return m && ( m.constructor === String ? m : m[ method ] );
849 },
850
851 // Return the first defined argument, allowing empty strings
852 findDefined: function() {
853 for ( var i = 0; i < arguments.length; i++ ) {
854 if ( arguments[ i ] !== undefined ) {
855 return arguments[ i ];
856 }
857 }
858 return undefined;
859 },
860
861 // The second parameter 'rule' used to be a string, and extended to an object literal
862 // of the following form:
863 // rule = {
864 // method: "method name",
865 // parameters: "the given method parameters"
866 // }
867 //
868 // The old behavior still supported, kept to maintain backward compatibility with
869 // old code, and will be removed in the next major release.
870 defaultMessage: function( element, rule ) {
871 if ( typeof rule === "string" ) {
872 rule = { method: rule };
873 }
874
875 var message = this.findDefined(
876 this.customMessage( element.name, rule.method ),
877 this.customDataMessage( element, rule.method ),
878
879 // 'title' is never undefined, so handle empty string as undefined
880 !this.settings.ignoreTitle && element.title || undefined,
881 $.validator.messages[ rule.method ],
882 "<strong>Warning: No message defined for " + element.name + "</strong>"
883 ),
884 theregex = /\$?\{(\d+)\}/g;
885 if ( typeof message === "function" ) {
886 message = message.call( this, rule.parameters, element );
887 } else if ( theregex.test( message ) ) {
888 message = $.validator.format( message.replace( theregex, "{$1}" ), rule.parameters );
889 }
890
891 return message;
892 },
893
894 formatAndAdd: function( element, rule ) {
895 var message = this.defaultMessage( element, rule );
896
897 this.errorList.push( {
898 message: message,
899 element: element,
900 method: rule.method
901 } );
902
903 this.errorMap[ element.name ] = message;
904 this.submitted[ element.name ] = message;
905 },
906
907 addWrapper: function( toToggle ) {
908 if ( this.settings.wrapper ) {
909 toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
910 }
911 return toToggle;
912 },
913
914 defaultShowErrors: function() {
915 var i, elements, error;
916 for ( i = 0; this.errorList[ i ]; i++ ) {
917 error = this.errorList[ i ];
918 if ( this.settings.highlight ) {
919 this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
920 }
921 this.showLabel( error.element, error.message );
922 }
923 if ( this.errorList.length ) {
924 this.toShow = this.toShow.add( this.containers );
925 }
926 if ( this.settings.success ) {
927 for ( i = 0; this.successList[ i ]; i++ ) {
928 this.showLabel( this.successList[ i ] );
929 }
930 }
931 if ( this.settings.unhighlight ) {
932 for ( i = 0, elements = this.validElements(); elements[ i ]; i++ ) {
933 this.settings.unhighlight.call( this, elements[ i ], this.settings.errorClass, this.settings.validClass );
934 }
935 }
936 this.toHide = this.toHide.not( this.toShow );
937 this.hideErrors();
938 this.addWrapper( this.toShow ).show();
939 },
940
941 validElements: function() {
942 return this.currentElements.not( this.invalidElements() );
943 },
944
945 invalidElements: function() {
946 return $( this.errorList ).map( function() {
947 return this.element;
948 } );
949 },
950
951 showLabel: function( element, message ) {
952 var place, group, errorID, v,
953 error = this.errorsFor( element ),
954 elementID = this.idOrName( element ),
955 describedBy = $( element ).attr( "aria-describedby" );
956
957 if ( error.length ) {
958
959 // Refresh error/success class
960 error.removeClass( this.settings.validClass ).addClass( this.settings.errorClass );
961
962 // Replace message on existing label
963 error.html( message );
964 } else {
965
966 // Create error element
967 error = $( "<" + this.settings.errorElement + ">" )
968 .attr( "id", elementID + "-error" )
969 .addClass( this.settings.errorClass )
970 .html( message || "" );
971
972 // Maintain reference to the element to be placed into the DOM
973 place = error;
974 if ( this.settings.wrapper ) {
975
976 // Make sure the element is visible, even in IE
977 // actually showing the wrapped element is handled elsewhere
978 place = error.hide().show().wrap( "<" + this.settings.wrapper + "/>" ).parent();
979 }
980 if ( this.labelContainer.length ) {
981 this.labelContainer.append( place );
982 } else if ( this.settings.errorPlacement ) {
983 this.settings.errorPlacement.call( this, place, $( element ) );
984 } else {
985 place.insertAfter( element );
986 }
987
988 // Link error back to the element
989 if ( error.is( "label" ) ) {
990
991 // If the error is a label, then associate using 'for'
992 error.attr( "for", elementID );
993
994 // If the element is not a child of an associated label, then it's necessary
995 // to explicitly apply aria-describedby
996 } else if ( error.parents( "label[for='" + this.escapeCssMeta( elementID ) + "']" ).length === 0 ) {
997 errorID = error.attr( "id" );
998
999 // Respect existing non-error aria-describedby
1000 if ( !describedBy ) {
1001 describedBy = errorID;
1002 } else if ( !describedBy.match( new RegExp( "\\b" + this.escapeCssMeta( errorID ) + "\\b" ) ) ) {
1003
1004 // Add to end of list if not already present
1005 describedBy += " " + errorID;
1006 }
1007 $( element ).attr( "aria-describedby", describedBy );
1008
1009 // If this element is grouped, then assign to all elements in the same group
1010 group = this.groups[ element.name ];
1011 if ( group ) {
1012 v = this;
1013 $.each( v.groups, function( name, testgroup ) {
1014 if ( testgroup === group ) {
1015 $( "[name='" + v.escapeCssMeta( name ) + "']", v.currentForm )
1016 .attr( "aria-describedby", error.attr( "id" ) );
1017 }
1018 } );
1019 }
1020 }
1021 }
1022 if ( !message && this.settings.success ) {
1023 error.text( "" );
1024 if ( typeof this.settings.success === "string" ) {
1025 error.addClass( this.settings.success );
1026 } else {
1027 this.settings.success( error, element );
1028 }
1029 }
1030 this.toShow = this.toShow.add( error );
1031 },
1032
1033 errorsFor: function( element ) {
1034 var name = this.escapeCssMeta( this.idOrName( element ) ),
1035 describer = $( element ).attr( "aria-describedby" ),
1036 selector = "label[for='" + name + "'], label[for='" + name + "'] *";
1037
1038 // 'aria-describedby' should directly reference the error element
1039 if ( describer ) {
1040 selector = selector + ", #" + this.escapeCssMeta( describer )
1041 .replace( /\s+/g, ", #" );
1042 }
1043
1044 return this
1045 .errors()
1046 .filter( selector );
1047 },
1048
1049 // See https://api.jquery.com/category/selectors/, for CSS
1050 // meta-characters that should be escaped in order to be used with JQuery
1051 // as a literal part of a name/id or any selector.
1052 escapeCssMeta: function( string ) {
1053 if ( string === undefined ) {
1054 return "";
1055 }
1056
1057 return string.replace( /([\\!"#$%&'()*+,./:;<=>?@\[\]^`{|}~])/g, "\\$1" );
1058 },
1059
1060 idOrName: function( element ) {
1061 return this.groups[ element.name ] || ( this.checkable( element ) ? element.name : element.id || element.name );
1062 },
1063
1064 validationTargetFor: function( element ) {
1065
1066 // If radio/checkbox, validate first element in group instead
1067 if ( this.checkable( element ) ) {
1068 element = this.findByName( element.name );
1069 }
1070
1071 // Always apply ignore filter
1072 return $( element ).not( this.settings.ignore )[ 0 ];
1073 },
1074
1075 checkable: function( element ) {
1076 return ( /radio|checkbox/i ).test( element.type );
1077 },
1078
1079 findByName: function( name ) {
1080 return $( this.currentForm ).find( "[name='" + this.escapeCssMeta( name ) + "']" );
1081 },
1082
1083 getLength: function( value, element ) {
1084 switch ( element.nodeName.toLowerCase() ) {
1085 case "select":
1086 return $( "option:selected", element ).length;
1087 case "input":
1088 if ( this.checkable( element ) ) {
1089 return this.findByName( element.name ).filter( ":checked" ).length;
1090 }
1091 }
1092 return value.length;
1093 },
1094
1095 depend: function( param, element ) {
1096 return this.dependTypes[ typeof param ] ? this.dependTypes[ typeof param ]( param, element ) : true;
1097 },
1098
1099 dependTypes: {
1100 "boolean": function( param ) {
1101 return param;
1102 },
1103 "string": function( param, element ) {
1104 return !!$( param, element.form ).length;
1105 },
1106 "function": function( param, element ) {
1107 return param( element );
1108 }
1109 },
1110
1111 optional: function( element ) {
1112 var val = this.elementValue( element );
1113 return !$.validator.methods.required.call( this, val, element ) && "dependency-mismatch";
1114 },
1115
1116 startRequest: function( element ) {
1117 if ( !this.pending[ element.name ] ) {
1118 this.pendingRequest++;
1119 $( element ).addClass( this.settings.pendingClass );
1120 this.pending[ element.name ] = true;
1121 }
1122 },
1123
1124 stopRequest: function( element, valid ) {
1125 this.pendingRequest--;
1126
1127 // Sometimes synchronization fails, make sure pendingRequest is never < 0
1128 if ( this.pendingRequest < 0 ) {
1129 this.pendingRequest = 0;
1130 }
1131 delete this.pending[ element.name ];
1132 $( element ).removeClass( this.settings.pendingClass );
1133 if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() && this.pendingRequest === 0 ) {
1134 $( this.currentForm ).trigger( "submit" );
1135
1136 // Remove the hidden input that was used as a replacement for the
1137 // missing submit button. The hidden input is added by `handle()`
1138 // to ensure that the value of the used submit button is passed on
1139 // for scripted submits triggered by this method
1140 if ( this.submitButton ) {
1141 $( "input:hidden[name='" + this.submitButton.name + "']", this.currentForm ).remove();
1142 }
1143
1144 this.formSubmitted = false;
1145 } else if ( !valid && this.pendingRequest === 0 && this.formSubmitted ) {
1146 $( this.currentForm ).triggerHandler( "invalid-form", [ this ] );
1147 this.formSubmitted = false;
1148 }
1149 },
1150
1151 previousValue: function( element, method ) {
1152 method = typeof method === "string" && method || "remote";
1153
1154 return $.data( element, "previousValue" ) || $.data( element, "previousValue", {
1155 old: null,
1156 valid: true,
1157 message: this.defaultMessage( element, { method: method } )
1158 } );
1159 },
1160
1161 // Cleans up all forms and elements, removes validator-specific events
1162 destroy: function() {
1163 this.resetForm();
1164
1165 $( this.currentForm )
1166 .off( ".validate" )
1167 .removeData( "validator" )
1168 .find( ".validate-equalTo-blur" )
1169 .off( ".validate-equalTo" )
1170 .removeClass( "validate-equalTo-blur" )
1171 .find( ".validate-lessThan-blur" )
1172 .off( ".validate-lessThan" )
1173 .removeClass( "validate-lessThan-blur" )
1174 .find( ".validate-lessThanEqual-blur" )
1175 .off( ".validate-lessThanEqual" )
1176 .removeClass( "validate-lessThanEqual-blur" )
1177 .find( ".validate-greaterThanEqual-blur" )
1178 .off( ".validate-greaterThanEqual" )
1179 .removeClass( "validate-greaterThanEqual-blur" )
1180 .find( ".validate-greaterThan-blur" )
1181 .off( ".validate-greaterThan" )
1182 .removeClass( "validate-greaterThan-blur" );
1183 }
1184
1185 },
1186
1187 classRuleSettings: {
1188 required: { required: true },
1189 email: { email: true },
1190 url: { url: true },
1191 date: { date: true },
1192 dateISO: { dateISO: true },
1193 number: { number: true },
1194 digits: { digits: true },
1195 creditcard: { creditcard: true }
1196 },
1197
1198 addClassRules: function( className, rules ) {
1199 if ( className.constructor === String ) {
1200 this.classRuleSettings[ className ] = rules;
1201 } else {
1202 $.extend( this.classRuleSettings, className );
1203 }
1204 },
1205
1206 classRules: function( element ) {
1207 var rules = {},
1208 classes = $( element ).attr( "class" );
1209
1210 if ( classes ) {
1211 $.each( classes.split( " " ), function() {
1212 if ( this in $.validator.classRuleSettings ) {
1213 $.extend( rules, $.validator.classRuleSettings[ this ] );
1214 }
1215 } );
1216 }
1217 return rules;
1218 },
1219
1220 normalizeAttributeRule: function( rules, type, method, value ) {
1221
1222 // Convert the value to a number for number inputs, and for text for backwards compability
1223 // allows type="date" and others to be compared as strings
1224 if ( /min|max|step/.test( method ) && ( type === null || /number|range|text/.test( type ) ) ) {
1225 value = Number( value );
1226
1227 // Support Opera Mini, which returns NaN for undefined minlength
1228 if ( isNaN( value ) ) {
1229 value = undefined;
1230 }
1231 }
1232
1233 if ( value || value === 0 ) {
1234 rules[ method ] = value;
1235 } else if ( type === method && type !== "range" ) {
1236
1237 // Exception: the jquery validate 'range' method
1238 // does not test for the html5 'range' type
1239 rules[ type === "date" ? "dateISO" : method ] = true;
1240 }
1241 },
1242
1243 attributeRules: function( element ) {
1244 var rules = {},
1245 $element = $( element ),
1246 type = element.getAttribute( "type" ),
1247 method, value;
1248
1249 for ( method in $.validator.methods ) {
1250
1251 // Support for <input required> in both html5 and older browsers
1252 if ( method === "required" ) {
1253 value = element.getAttribute( method );
1254
1255 // Some browsers return an empty string for the required attribute
1256 // and non-HTML5 browsers might have required="" markup
1257 if ( value === "" ) {
1258 value = true;
1259 }
1260
1261 // Force non-HTML5 browsers to return bool
1262 value = !!value;
1263 } else {
1264 value = $element.attr( method );
1265 }
1266
1267 this.normalizeAttributeRule( rules, type, method, value );
1268 }
1269
1270 // 'maxlength' may be returned as -1, 2147483647 ( IE ) and 524288 ( safari ) for text inputs
1271 if ( rules.maxlength && /-1|2147483647|524288/.test( rules.maxlength ) ) {
1272 delete rules.maxlength;
1273 }
1274
1275 return rules;
1276 },
1277
1278 dataRules: function( element ) {
1279 var rules = {},
1280 $element = $( element ),
1281 type = element.getAttribute( "type" ),
1282 method, value;
1283
1284 for ( method in $.validator.methods ) {
1285 value = $element.data( "rule" + method.charAt( 0 ).toUpperCase() + method.substring( 1 ).toLowerCase() );
1286
1287 // Cast empty attributes like `data-rule-required` to `true`
1288 if ( value === "" ) {
1289 value = true;
1290 }
1291
1292 this.normalizeAttributeRule( rules, type, method, value );
1293 }
1294 return rules;
1295 },
1296
1297 staticRules: function( element ) {
1298 var rules = {},
1299 validator = $.data( element.form, "validator" );
1300
1301 if ( validator.settings.rules ) {
1302 rules = $.validator.normalizeRule( validator.settings.rules[ element.name ] ) || {};
1303 }
1304 return rules;
1305 },
1306
1307 normalizeRules: function( rules, element ) {
1308
1309 // Handle dependency check
1310 $.each( rules, function( prop, val ) {
1311
1312 // Ignore rule when param is explicitly false, eg. required:false
1313 if ( val === false ) {
1314 delete rules[ prop ];
1315 return;
1316 }
1317 if ( val.param || val.depends ) {
1318 var keepRule = true;
1319 switch ( typeof val.depends ) {
1320 case "string":
1321 keepRule = !!$( val.depends, element.form ).length;
1322 break;
1323 case "function":
1324 keepRule = val.depends.call( element, element );
1325 break;
1326 }
1327 if ( keepRule ) {
1328 rules[ prop ] = val.param !== undefined ? val.param : true;
1329 } else {
1330 $.data( element.form, "validator" ).resetElements( $( element ) );
1331 delete rules[ prop ];
1332 }
1333 }
1334 } );
1335
1336 // Evaluate parameters
1337 $.each( rules, function( rule, parameter ) {
1338 rules[ rule ] = typeof parameter === "function" && rule !== "normalizer" ? parameter( element ) : parameter;
1339 } );
1340
1341 // Clean number parameters
1342 $.each( [ "minlength", "maxlength" ], function() {
1343 if ( rules[ this ] ) {
1344 rules[ this ] = Number( rules[ this ] );
1345 }
1346 } );
1347 $.each( [ "rangelength", "range" ], function() {
1348 var parts;
1349 if ( rules[ this ] ) {
1350 if ( Array.isArray( rules[ this ] ) ) {
1351 rules[ this ] = [ Number( rules[ this ][ 0 ] ), Number( rules[ this ][ 1 ] ) ];
1352 } else if ( typeof rules[ this ] === "string" ) {
1353 parts = rules[ this ].replace( /[\[\]]/g, "" ).split( /[\s,]+/ );
1354 rules[ this ] = [ Number( parts[ 0 ] ), Number( parts[ 1 ] ) ];
1355 }
1356 }
1357 } );
1358
1359 if ( $.validator.autoCreateRanges ) {
1360
1361 // Auto-create ranges
1362 if ( rules.min != null && rules.max != null ) {
1363 rules.range = [ rules.min, rules.max ];
1364 delete rules.min;
1365 delete rules.max;
1366 }
1367 if ( rules.minlength != null && rules.maxlength != null ) {
1368 rules.rangelength = [ rules.minlength, rules.maxlength ];
1369 delete rules.minlength;
1370 delete rules.maxlength;
1371 }
1372 }
1373
1374 return rules;
1375 },
1376
1377 // Converts a simple string to a {string: true} rule, e.g., "required" to {required:true}
1378 normalizeRule: function( data ) {
1379 if ( typeof data === "string" ) {
1380 var transformed = {};
1381 $.each( data.split( /\s/ ), function() {
1382 transformed[ this ] = true;
1383 } );
1384 data = transformed;
1385 }
1386 return data;
1387 },
1388
1389 // https://jqueryvalidation.org/jQuery.validator.addMethod/
1390 addMethod: function( name, method, message ) {
1391 $.validator.methods[ name ] = method;
1392 $.validator.messages[ name ] = message !== undefined ? message : $.validator.messages[ name ];
1393 if ( method.length < 3 ) {
1394 $.validator.addClassRules( name, $.validator.normalizeRule( name ) );
1395 }
1396 },
1397
1398 // https://jqueryvalidation.org/jQuery.validator.methods/
1399 methods: {
1400
1401 // https://jqueryvalidation.org/required-method/
1402 required: function( value, element, param ) {
1403
1404 // Check if dependency is met
1405 if ( !this.depend( param, element ) ) {
1406 return "dependency-mismatch";
1407 }
1408 if ( element.nodeName.toLowerCase() === "select" ) {
1409
1410 // Could be an array for select-multiple or a string, both are fine this way
1411 var val = $( element ).val();
1412 return val && val.length > 0;
1413 }
1414 if ( this.checkable( element ) ) {
1415 return this.getLength( value, element ) > 0;
1416 }
1417 return value !== undefined && value !== null && value.length > 0;
1418 },
1419
1420 // https://jqueryvalidation.org/email-method/
1421 email: function( value, element ) {
1422
1423 // From https://html.spec.whatwg.org/multipage/forms.html#valid-e-mail-address
1424 // Retrieved 2014-01-14
1425 // If you have a problem with this implementation, report a bug against the above spec
1426 // Or use custom methods to implement your own email validation
1427 return this.optional( element ) || /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test( value );
1428 },
1429
1430 // https://jqueryvalidation.org/url-method/
1431 url: function( value, element ) {
1432
1433 // Copyright (c) 2010-2013 Diego Perini, MIT licensed
1434 // https://gist.github.com/dperini/729294
1435 // see also https://mathiasbynens.be/demo/url-regex
1436 // modified to allow protocol-relative URLs
1437 return this.optional( element ) || /^(?:(?:(?:https?|ftp):)?\/\/)(?:(?:[^\]\[?\/<~#`!@$^&*()+=}|:";',>{ ]|%[0-9A-Fa-f]{2})+(?::(?:[^\]\[?\/<~#`!@$^&*()+=}|:";',>{ ]|%[0-9A-Fa-f]{2})*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62})?[a-z0-9\u00a1-\uffff]\.)+(?:[a-z\u00a1-\uffff]{2,}\.?))(?::\d{2,5})?(?:[/?#]\S*)?$/i.test( value );
1438 },
1439
1440 // https://jqueryvalidation.org/date-method/
1441 date: ( function() {
1442 var called = false;
1443
1444 return function( value, element ) {
1445 if ( !called ) {
1446 called = true;
1447 if ( this.settings.debug && window.console ) {
1448 console.warn(
1449 "The `date` method is deprecated and will be removed in version '2.0.0'.\n" +
1450 "Please don't use it, since it relies on the Date constructor, which\n" +
1451 "behaves very differently across browsers and locales. Use `dateISO`\n" +
1452 "instead or one of the locale specific methods in `localizations/`\n" +
1453 "and `additional-methods.js`."
1454 );
1455 }
1456 }
1457
1458 return this.optional( element ) || !/Invalid|NaN/.test( new Date( value ).toString() );
1459 };
1460 }() ),
1461
1462 // https://jqueryvalidation.org/dateISO-method/
1463 dateISO: function( value, element ) {
1464 return this.optional( element ) || /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test( value );
1465 },
1466
1467 // https://jqueryvalidation.org/number-method/
1468 number: function( value, element ) {
1469 return this.optional( element ) || /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test( value );
1470 },
1471
1472 // https://jqueryvalidation.org/digits-method/
1473 digits: function( value, element ) {
1474 return this.optional( element ) || /^\d+$/.test( value );
1475 },
1476
1477 // https://jqueryvalidation.org/minlength-method/
1478 minlength: function( value, element, param ) {
1479 var length = Array.isArray( value ) ? value.length : this.getLength( value, element );
1480 return this.optional( element ) || length >= param;
1481 },
1482
1483 // https://jqueryvalidation.org/maxlength-method/
1484 maxlength: function( value, element, param ) {
1485 var length = Array.isArray( value ) ? value.length : this.getLength( value, element );
1486 return this.optional( element ) || length <= param;
1487 },
1488
1489 // https://jqueryvalidation.org/rangelength-method/
1490 rangelength: function( value, element, param ) {
1491 var length = Array.isArray( value ) ? value.length : this.getLength( value, element );
1492 return this.optional( element ) || ( length >= param[ 0 ] && length <= param[ 1 ] );
1493 },
1494
1495 // https://jqueryvalidation.org/min-method/
1496 min: function( value, element, param ) {
1497 return this.optional( element ) || value >= param;
1498 },
1499
1500 // https://jqueryvalidation.org/max-method/
1501 max: function( value, element, param ) {
1502 return this.optional( element ) || value <= param;
1503 },
1504
1505 // https://jqueryvalidation.org/range-method/
1506 range: function( value, element, param ) {
1507 return this.optional( element ) || ( value >= param[ 0 ] && value <= param[ 1 ] );
1508 },
1509
1510 // https://jqueryvalidation.org/step-method/
1511 step: function( value, element, param ) {
1512 var type = $( element ).attr( "type" ),
1513 errorMessage = "Step attribute on input type " + type + " is not supported.",
1514 supportedTypes = [ "text", "number", "range" ],
1515 re = new RegExp( "\\b" + type + "\\b" ),
1516 notSupported = type && !re.test( supportedTypes.join() ),
1517 decimalPlaces = function( num ) {
1518 var match = ( "" + num ).match( /(?:\.(\d+))?$/ );
1519 if ( !match ) {
1520 return 0;
1521 }
1522
1523 // Number of digits right of decimal point.
1524 return match[ 1 ] ? match[ 1 ].length : 0;
1525 },
1526 toInt = function( num ) {
1527 return Math.round( num * Math.pow( 10, decimals ) );
1528 },
1529 valid = true,
1530 decimals;
1531
1532 // Works only for text, number and range input types
1533 // TODO find a way to support input types date, datetime, datetime-local, month, time and week
1534 if ( notSupported ) {
1535 throw new Error( errorMessage );
1536 }
1537
1538 decimals = decimalPlaces( param );
1539
1540 // Value can't have too many decimals
1541 if ( decimalPlaces( value ) > decimals || toInt( value ) % toInt( param ) !== 0 ) {
1542 valid = false;
1543 }
1544
1545 return this.optional( element ) || valid;
1546 },
1547
1548 // https://jqueryvalidation.org/equalTo-method/
1549 equalTo: function( value, element, param ) {
1550
1551 // Bind to the blur event of the target in order to revalidate whenever the target field is updated
1552 var target = $( param );
1553 if ( this.settings.onfocusout && target.not( ".validate-equalTo-blur" ).length ) {
1554 target.addClass( "validate-equalTo-blur" ).on( "blur.validate-equalTo", function() {
1555 $( element ).valid();
1556 } );
1557 }
1558 return value === target.val();
1559 },
1560
1561 // https://jqueryvalidation.org/remote-method/
1562 remote: function( value, element, param, method ) {
1563 if ( this.optional( element ) ) {
1564 return "dependency-mismatch";
1565 }
1566
1567 method = typeof method === "string" && method || "remote";
1568
1569 var previous = this.previousValue( element, method ),
1570 validator, data, optionDataString;
1571
1572 if ( !this.settings.messages[ element.name ] ) {
1573 this.settings.messages[ element.name ] = {};
1574 }
1575 previous.originalMessage = previous.originalMessage || this.settings.messages[ element.name ][ method ];
1576 this.settings.messages[ element.name ][ method ] = previous.message;
1577
1578 param = typeof param === "string" && { url: param } || param;
1579 optionDataString = $.param( $.extend( { data: value }, param.data ) );
1580 if ( previous.old === optionDataString ) {
1581 return previous.valid;
1582 }
1583
1584 previous.old = optionDataString;
1585 validator = this;
1586 this.startRequest( element );
1587 data = {};
1588 data[ element.name ] = value;
1589 $.ajax( $.extend( true, {
1590 mode: "abort",
1591 port: "validate" + element.name,
1592 dataType: "json",
1593 data: data,
1594 context: validator.currentForm,
1595 success: function( response ) {
1596 var valid = response === true || response === "true",
1597 errors, message, submitted;
1598
1599 validator.settings.messages[ element.name ][ method ] = previous.originalMessage;
1600 if ( valid ) {
1601 submitted = validator.formSubmitted;
1602 validator.resetInternals();
1603 validator.toHide = validator.errorsFor( element );
1604 validator.formSubmitted = submitted;
1605 validator.successList.push( element );
1606 validator.invalid[ element.name ] = false;
1607 validator.showErrors();
1608 } else {
1609 errors = {};
1610 message = response || validator.defaultMessage( element, { method: method, parameters: value } );
1611 errors[ element.name ] = previous.message = message;
1612 validator.invalid[ element.name ] = true;
1613 validator.showErrors( errors );
1614 }
1615 previous.valid = valid;
1616 validator.stopRequest( element, valid );
1617 }
1618 }, param ) );
1619 return "pending";
1620 }
1621 }
1622
1623 } );
1624
1625 // Ajax mode: abort
1626 // usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
1627 // if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
1628
1629 var pendingRequests = {},
1630 ajax;
1631
1632 // Use a prefilter if available (1.5+)
1633 if ( $.ajaxPrefilter ) {
1634 $.ajaxPrefilter( function( settings, _, xhr ) {
1635 var port = settings.port;
1636 if ( settings.mode === "abort" ) {
1637 if ( pendingRequests[ port ] ) {
1638 pendingRequests[ port ].abort();
1639 }
1640 pendingRequests[ port ] = xhr;
1641 }
1642 } );
1643 } else {
1644
1645 // Proxy ajax
1646 ajax = $.ajax;
1647 $.ajax = function( settings ) {
1648 var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
1649 port = ( "port" in settings ? settings : $.ajaxSettings ).port;
1650 if ( mode === "abort" ) {
1651 if ( pendingRequests[ port ] ) {
1652 pendingRequests[ port ].abort();
1653 }
1654 pendingRequests[ port ] = ajax.apply( this, arguments );
1655 return pendingRequests[ port ];
1656 }
1657 return ajax.apply( this, arguments );
1658 };
1659 }
1660 return $;
1661 }));