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