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