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