11/*!
2- * jQuery Validation Plugin v1.19.5
2+ * jQuery Validation Plugin v1.21.0
33 *
44 * https://jqueryvalidation.org/
55 *
6- * Copyright (c) 2022 Jörn Zaefferer
6+ * Copyright (c) 2024 Jörn Zaefferer
77 * Released under the MIT license
88 */
99( function ( factory ) {
@@ -293,6 +293,7 @@ $.extend( $.validator, {
293293 onsubmit : true ,
294294 ignore : ":hidden" ,
295295 ignoreTitle : false ,
296+ customElements : [ ] ,
296297 onfocusin : function ( element ) {
297298 this . lastActive = element ;
298299
@@ -440,17 +441,17 @@ $.extend( $.validator, {
440441 settings [ eventType ] . call ( validator , this , event ) ;
441442 }
442443 }
443-
444+ var focusListeners = [ ":text" , "[type='password']" , "[type='file']" , "select" , "textarea" , "[type='number']" , "[type='search']" ,
445+ "[type='tel']" , "[type='url']" , "[type='email']" , "[type='datetime']" , "[type='date']" , "[type='month']" ,
446+ "[type='week']" , "[type='time']" , "[type='datetime-local']" , "[type='range']" , "[type='color']" ,
447+ "[type='radio']" , "[type='checkbox']" , "[contenteditable]" , "[type='button']" ] ;
448+ var clickListeners = [ "select" , "option" , "[type='radio']" , "[type='checkbox']" ] ;
444449 $ ( this . currentForm )
445- . on ( "focusin.validate focusout.validate keyup.validate" ,
446- ":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], " +
447- "[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], " +
448- "[type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], " +
449- "[type='radio'], [type='checkbox'], [contenteditable], [type='button']" , delegate )
450+ . on ( "focusin.validate focusout.validate keyup.validate" , focusListeners . concat ( this . settings . customElements ) . join ( ", " ) , delegate )
450451
451452 // Support: Chrome, oldIE
452453 // "select" is provided as event.target when clicking a option
453- . on ( "click.validate" , "select, option, [type='radio'], [type='checkbox']" , delegate ) ;
454+ . on ( "click.validate" , clickListeners . concat ( this . settings . customElements ) . join ( ", " ) , delegate ) ;
454455
455456 if ( this . settings . invalidHandler ) {
456457 $ ( this . currentForm ) . on ( "invalid-form.validate" , this . settings . invalidHandler ) ;
@@ -647,11 +648,12 @@ $.extend( $.validator, {
647648
648649 elements : function ( ) {
649650 var validator = this ,
650- rulesCache = { } ;
651+ rulesCache = { } ,
652+ selectors = [ "input" , "select" , "textarea" , "[contenteditable]" ] ;
651653
652654 // Select all valid inputs inside the form (no submit or reset buttons)
653655 return $ ( this . currentForm )
654- . find ( "input, select, textarea, [contenteditable]" )
656+ . find ( selectors . concat ( this . settings . customElements ) . join ( ", " ) )
655657 . not ( ":submit, :reset, :image, :disabled" )
656658 . not ( this . settings . ignore )
657659 . filter ( function ( ) {
@@ -774,6 +776,9 @@ $.extend( $.validator, {
774776 val = this . elementValue ( element ) ,
775777 result , method , rule , normalizer ;
776778
779+ // Abort any pending Ajax request from a previous call to this method.
780+ this . abortRequest ( element ) ;
781+
777782 // Prioritize the local normalizer defined for this element over the global one
778783 // if the former exists, otherwise user the global one in case it exists.
779784 if ( typeof rules . normalizer === "function" ) {
@@ -960,14 +965,23 @@ $.extend( $.validator, {
960965 error . removeClass ( this . settings . validClass ) . addClass ( this . settings . errorClass ) ;
961966
962967 // Replace message on existing label
963- error . html ( message ) ;
968+ if ( this . settings && this . settings . escapeHtml ) {
969+ error . text ( message || "" ) ;
970+ } else {
971+ error . html ( message || "" ) ;
972+ }
964973 } else {
965974
966975 // Create error element
967976 error = $ ( "<" + this . settings . errorElement + ">" )
968977 . attr ( "id" , elementID + "-error" )
969- . addClass ( this . settings . errorClass )
970- . html ( message || "" ) ;
978+ . addClass ( this . settings . errorClass ) ;
979+
980+ if ( this . settings && this . settings . escapeHtml ) {
981+ error . text ( message || "" ) ;
982+ } else {
983+ error . html ( message || "" ) ;
984+ }
971985
972986 // Maintain reference to the element to be placed into the DOM
973987 place = error ;
@@ -1113,6 +1127,10 @@ $.extend( $.validator, {
11131127 return ! $ . validator . methods . required . call ( this , val , element ) && "dependency-mismatch" ;
11141128 } ,
11151129
1130+ elementAjaxPort : function ( element ) {
1131+ return "validate" + element . name ;
1132+ } ,
1133+
11161134 startRequest : function ( element ) {
11171135 if ( ! this . pending [ element . name ] ) {
11181136 this . pendingRequest ++ ;
@@ -1148,6 +1166,25 @@ $.extend( $.validator, {
11481166 }
11491167 } ,
11501168
1169+ abortRequest : function ( element ) {
1170+ var port ;
1171+
1172+ if ( this . pending [ element . name ] ) {
1173+ port = this . elementAjaxPort ( element ) ;
1174+ $ . ajaxAbort ( port ) ;
1175+
1176+ this . pendingRequest -- ;
1177+
1178+ // Sometimes synchronization fails, make sure pendingRequest is never < 0
1179+ if ( this . pendingRequest < 0 ) {
1180+ this . pendingRequest = 0 ;
1181+ }
1182+
1183+ delete this . pending [ element . name ] ;
1184+ $ ( element ) . removeClass ( this . settings . pendingClass ) ;
1185+ }
1186+ } ,
1187+
11511188 previousValue : function ( element , method ) {
11521189 method = typeof method === "string" && method || "remote" ;
11531190
@@ -1466,7 +1503,7 @@ $.extend( $.validator, {
14661503
14671504 // https://jqueryvalidation.org/number-method/
14681505 number : function ( value , element ) {
1469- return this . optional ( element ) || / ^ (?: - ? \d + | - ? \d { 1 , 3 } (?: , \d { 3 } ) + ) ? (?: \. \d + ) ? $ / . test ( value ) ;
1506+ return this . optional ( element ) || / ^ (?: - ? \d + | - ? \d { 1 , 3 } (?: , \d { 3 } ) + ) ? (?: - ? \. \d + ) ? $ / . test ( value ) ;
14701507 } ,
14711508
14721509 // https://jqueryvalidation.org/digits-method/
@@ -1577,18 +1614,19 @@ $.extend( $.validator, {
15771614
15781615 param = typeof param === "string" && { url : param } || param ;
15791616 optionDataString = $ . param ( $ . extend ( { data : value } , param . data ) ) ;
1580- if ( previous . old === optionDataString ) {
1617+ if ( previous . valid !== null && previous . old === optionDataString ) {
15811618 return previous . valid ;
15821619 }
15831620
15841621 previous . old = optionDataString ;
1622+ previous . valid = null ;
15851623 validator = this ;
15861624 this . startRequest ( element ) ;
15871625 data = { } ;
15881626 data [ element . name ] = value ;
15891627 $ . ajax ( $ . extend ( true , {
15901628 mode : "abort" ,
1591- port : "validate" + element . name ,
1629+ port : this . elementAjaxPort ( element ) ,
15921630 dataType : "json" ,
15931631 data : data ,
15941632 context : validator . currentForm ,
@@ -1599,7 +1637,6 @@ $.extend( $.validator, {
15991637 validator . settings . messages [ element . name ] [ method ] = previous . originalMessage ;
16001638 if ( valid ) {
16011639 submitted = validator . formSubmitted ;
1602- validator . resetInternals ( ) ;
16031640 validator . toHide = validator . errorsFor ( element ) ;
16041641 validator . formSubmitted = submitted ;
16051642 validator . successList . push ( element ) ;
@@ -1624,6 +1661,7 @@ $.extend( $.validator, {
16241661
16251662// Ajax mode: abort
16261663// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
1664+ // $.ajaxAbort( port );
16271665// if mode:"abort" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()
16281666
16291667var pendingRequests = { } ,
@@ -1634,9 +1672,7 @@ if ( $.ajaxPrefilter ) {
16341672 $ . ajaxPrefilter ( function ( settings , _ , xhr ) {
16351673 var port = settings . port ;
16361674 if ( settings . mode === "abort" ) {
1637- if ( pendingRequests [ port ] ) {
1638- pendingRequests [ port ] . abort ( ) ;
1639- }
1675+ $ . ajaxAbort ( port ) ;
16401676 pendingRequests [ port ] = xhr ;
16411677 }
16421678 } ) ;
@@ -1648,14 +1684,20 @@ if ( $.ajaxPrefilter ) {
16481684 var mode = ( "mode" in settings ? settings : $ . ajaxSettings ) . mode ,
16491685 port = ( "port" in settings ? settings : $ . ajaxSettings ) . port ;
16501686 if ( mode === "abort" ) {
1651- if ( pendingRequests [ port ] ) {
1652- pendingRequests [ port ] . abort ( ) ;
1653- }
1687+ $ . ajaxAbort ( port ) ;
16541688 pendingRequests [ port ] = ajax . apply ( this , arguments ) ;
16551689 return pendingRequests [ port ] ;
16561690 }
16571691 return ajax . apply ( this , arguments ) ;
16581692 } ;
16591693}
1694+
1695+ // Abort the previous request without sending a new one
1696+ $ . ajaxAbort = function ( port ) {
1697+ if ( pendingRequests [ port ] ) {
1698+ pendingRequests [ port ] . abort ( ) ;
1699+ delete pendingRequests [ port ] ;
1700+ }
1701+ } ;
16601702return $ ;
16611703} ) ) ;
0 commit comments