@@ -63,10 +63,56 @@ class Pattern extends BasePattern {
6363 { capture : true }
6464 ) ;
6565
66- this . initialize_inputs ( ) ;
67- $ ( this . form ) . on ( "pat-update" , ( ) => {
68- this . initialize_inputs ( ) ;
69- } ) ;
66+ // Input debouncer map:
67+ // - key: input element
68+ // - value: debouncer function
69+ // 1) We want do debounce the validation checks to avoid validating
70+ // while typing.
71+ // 2) We want to debounce the input events individually, so that we can
72+ // do multiple checks in parallel and show multiple errors at once.
73+ const input_debouncer_map = new Map ( ) ;
74+ const debounce_filter = ( e ) => {
75+ const input = e . target ;
76+ if ( input ?. form !== this . form || ! this . inputs . includes ( input ) ) {
77+ // Ignore events from other forms or from elements which are
78+ // not inputs.
79+ return ;
80+ }
81+
82+ if ( ! input_debouncer_map . has ( input ) ) {
83+ // Create a new cancelable debouncer for this input.
84+ input_debouncer_map . set ( input , utils . debounce ( ( e ) => {
85+ logger . debug ( "Checking input for event" , input , e ) ;
86+ this . check_input ( { input : input , event : e } ) ;
87+ } , this . options . delay ) ) ;
88+ }
89+
90+ // Get the debouncer for this input.
91+ const debouncer = input_debouncer_map . get ( input ) ;
92+ // Debounce the validation check.
93+ debouncer ( input , e ) ;
94+ } ;
95+
96+ events . add_event_listener (
97+ document ,
98+ "input" ,
99+ `pat-validation--${ this . uuid } --input--validator` ,
100+ ( e ) => debounce_filter ( e )
101+ ) ;
102+
103+ events . add_event_listener (
104+ document ,
105+ "change" ,
106+ `pat-validation--${ this . uuid } --change--validator` ,
107+ ( e ) => debounce_filter ( e )
108+ ) ;
109+
110+ events . add_event_listener (
111+ document ,
112+ "focusout" ,
113+ `pat-validation--${ this . uuid } --focusout--validator` ,
114+ ( e ) => debounce_filter ( e )
115+ ) ;
70116
71117 // Set ``novalidate`` attribute to disable the browser's validation
72118 // bubbles but not disable the validation API.
@@ -94,35 +140,6 @@ class Pattern extends BasePattern {
94140 }
95141 }
96142
97- initialize_inputs ( ) {
98- for ( const [ cnt , input ] of this . inputs . entries ( ) ) {
99- // Cancelable debouncer.
100- const debouncer = utils . debounce ( ( e ) => {
101- logger . debug ( "Checking input for event" , input , e ) ;
102- this . check_input ( { input : input , event : e } ) ;
103- } , this . options . delay ) ;
104-
105- events . add_event_listener (
106- input ,
107- "input" ,
108- `pat-validation--input-${ input . name } --${ cnt } --validator` ,
109- ( e ) => debouncer ( e )
110- ) ;
111- events . add_event_listener (
112- input ,
113- "change" ,
114- `pat-validation--change-${ input . name } --${ cnt } --validator` ,
115- ( e ) => debouncer ( e )
116- ) ;
117- events . add_event_listener (
118- input ,
119- "blur" ,
120- `pat-validation--blur-${ input . name } --${ cnt } --validator` ,
121- ( e ) => debouncer ( e )
122- ) ;
123- }
124- }
125-
126143 check_input ( {
127144 input, // Input to check.
128145 event = null , // Optional event which triggered the check.
0 commit comments