From a86e404ddec85def51b091cf9f9b2f789040800a Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Tue, 23 Apr 2024 18:12:01 +0200 Subject: [PATCH 1/5] Allow multiple handlers --- .../directive-on-document/render.php | 4 ++++ .../directive-on-document/view.js | 8 +++++++ packages/interactivity/src/directives.js | 19 +++++++++++------ .../directive-on-document.spec.ts | 21 +++++++++++++++++++ 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-on-document/render.php b/packages/e2e-tests/plugins/interactive-blocks/directive-on-document/render.php index 685e6dfc475826..a491a52161dfb7 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/directive-on-document/render.php +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-on-document/render.php @@ -24,4 +24,8 @@

0

+
+

no

+

no

+
diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-on-document/view.js b/packages/e2e-tests/plugins/interactive-blocks/directive-on-document/view.js index c2a41832737ab5..eb32d6e6e15f08 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/directive-on-document/view.js +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-on-document/view.js @@ -25,6 +25,8 @@ const { state } = store( 'directive-on-document', { counter: 0, isVisible: true, isEventAttached: 'no', + keydownHandler: 'no', + keydownSecondHandler: 'no', }, callbacks: { keydownHandler() { @@ -39,5 +41,11 @@ const { state } = store( 'directive-on-document', { state.isEventAttached = 'no'; state.isVisible = ! state.isVisible; }, + keydownHandler: () => { + state.keydownHandler = 'yes'; + }, + keydownSecondHandler: () => { + state.keydownSecondHandler = 'yes'; + } } } ); diff --git a/packages/interactivity/src/directives.js b/packages/interactivity/src/directives.js index 7afcbbbd60e228..d16eeb4dd66e4e 100644 --- a/packages/interactivity/src/directives.js +++ b/packages/interactivity/src/directives.js @@ -205,21 +205,28 @@ const cssStringToObject = ( val ) => { * @param {string} type 'window' or 'document' * @return {void} */ -const getGlobalEventDirective = - ( type ) => - ( { directives, evaluate } ) => { +const getGlobalEventDirective = ( type ) => { + return ( { directives, evaluate } ) => { + const events = new Map(); directives[ `on-${ type }` ] .filter( ( { suffix } ) => suffix !== 'default' ) .forEach( ( entry ) => { + const event = entry.suffix.split( '--' )[ 0 ]; + if ( ! events.has( event ) ) events.set( event, new Set() ); + events.get( event ).add( entry ); + } ); + events.forEach( ( entries, eventType ) => { + entries.forEach( ( entry ) => { useInit( () => { const cb = ( event ) => evaluate( entry, event ); const globalVar = type === 'window' ? window : document; - globalVar.addEventListener( entry.suffix, cb ); - return () => - globalVar.removeEventListener( entry.suffix, cb ); + globalVar.addEventListener( eventType, cb ); + return () => globalVar.removeEventListener( eventType, cb ); }, [] ); } ); + } ); }; +}; export default () => { // data-wp-context diff --git a/test/e2e/specs/interactivity/directive-on-document.spec.ts b/test/e2e/specs/interactivity/directive-on-document.spec.ts index 2b4f36f51efcc7..62d122ee2359e8 100644 --- a/test/e2e/specs/interactivity/directive-on-document.spec.ts +++ b/test/e2e/specs/interactivity/directive-on-document.spec.ts @@ -65,4 +65,25 @@ test.describe( 'data-wp-on-document', () => { await page.keyboard.press( 'ArrowDown' ); await expect( counter ).toHaveText( '2' ); } ); + test( 'should work with multiple event handlers on the same event type', async ( { + page, + } ) => { + const keydownHandler = page.getByTestId( 'keydownHandler' ); + const keydownSecondHandler = page.getByTestId( 'keydownSecondHandler' ); + + // Initial value. + await expect( keydownHandler ).toHaveText( 'no' ); + await expect( keydownSecondHandler ).toHaveText( 'no' ); + + // Make sure the event listener is attached. + await page + .getByTestId( 'isEventAttached' ) + .filter( { hasText: 'yes' } ) + .waitFor(); + + // This keyboard press should increase the counter. + await page.keyboard.press( 'ArrowDown' ); + await expect( keydownHandler ).toHaveText( 'yes' ); + await expect( keydownSecondHandler ).toHaveText( 'yes' ); + } ); } ); From e88a8d885326f0092c4b134e1adc697c8f8f5d88 Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Tue, 23 Apr 2024 18:16:19 +0200 Subject: [PATCH 2/5] Add test in window events --- .../directive-on-window/render.php | 4 ++++ .../directive-on-window/view.js | 8 +++++++ .../interactivity/directive-on-window.spec.ts | 21 +++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-on-window/render.php b/packages/e2e-tests/plugins/interactive-blocks/directive-on-window/render.php index 651b3298b64ed1..c72d80e892b15a 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/directive-on-window/render.php +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-on-window/render.php @@ -21,4 +21,8 @@

0

+
+

no

+

no

+
diff --git a/packages/e2e-tests/plugins/interactive-blocks/directive-on-window/view.js b/packages/e2e-tests/plugins/interactive-blocks/directive-on-window/view.js index b99f63b02517a7..57c75e9c4cb633 100644 --- a/packages/e2e-tests/plugins/interactive-blocks/directive-on-window/view.js +++ b/packages/e2e-tests/plugins/interactive-blocks/directive-on-window/view.js @@ -25,6 +25,8 @@ const { state } = store( 'directive-on-window', { counter: 0, isVisible: true, isEventAttached: 'no', + resizeHandler: 'no', + resizeSecondHandler: 'no', }, callbacks: { resizeHandler() { @@ -39,5 +41,11 @@ const { state } = store( 'directive-on-window', { state.isEventAttached = 'no'; state.isVisible = ! state.isVisible; }, + resizeHandler: () => { + state.resizeHandler = 'yes'; + }, + resizeSecondHandler: () => { + state.resizeSecondHandler = 'yes'; + } } } ); diff --git a/test/e2e/specs/interactivity/directive-on-window.spec.ts b/test/e2e/specs/interactivity/directive-on-window.spec.ts index 3afd1a9942fa8e..ed090839c49ade 100644 --- a/test/e2e/specs/interactivity/directive-on-window.spec.ts +++ b/test/e2e/specs/interactivity/directive-on-window.spec.ts @@ -65,4 +65,25 @@ test.describe( 'data-wp-on-window', () => { await page.setViewportSize( { width: 200, height: 600 } ); await expect( counter ).toHaveText( '2' ); } ); + test( 'should work with multiple event handlers on the same event type', async ( { + page, + } ) => { + const resizeHandler = page.getByTestId( 'resizeHandler' ); + const resizeSecondHandler = page.getByTestId( 'resizeSecondHandler' ); + + // Initial value. + await expect( resizeHandler ).toHaveText( 'no' ); + await expect( resizeSecondHandler ).toHaveText( 'no' ); + + // Make sure the event listener is attached. + await page + .getByTestId( 'isEventAttached' ) + .filter( { hasText: 'yes' } ) + .waitFor(); + + // This keyboard press should increase the counter. + await page.setViewportSize( { width: 600, height: 600 } ); + await expect( resizeHandler ).toHaveText( 'yes' ); + await expect( resizeSecondHandler ).toHaveText( 'yes' ); + } ); } ); From 69b0ce678d471aa87a642b12f7bb6033d79e1dd3 Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Mon, 6 May 2024 12:31:53 +0200 Subject: [PATCH 3/5] Move to only one pass --- packages/interactivity/src/directives.js | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/packages/interactivity/src/directives.js b/packages/interactivity/src/directives.js index d16eeb4dd66e4e..e8e03b3c2b340e 100644 --- a/packages/interactivity/src/directives.js +++ b/packages/interactivity/src/directives.js @@ -207,24 +207,17 @@ const cssStringToObject = ( val ) => { */ const getGlobalEventDirective = ( type ) => { return ( { directives, evaluate } ) => { - const events = new Map(); directives[ `on-${ type }` ] .filter( ( { suffix } ) => suffix !== 'default' ) .forEach( ( entry ) => { - const event = entry.suffix.split( '--' )[ 0 ]; - if ( ! events.has( event ) ) events.set( event, new Set() ); - events.get( event ).add( entry ); - } ); - events.forEach( ( entries, eventType ) => { - entries.forEach( ( entry ) => { + const event = entry.suffix.split( '--', 1 )[ 0 ]; useInit( () => { - const cb = ( event ) => evaluate( entry, event ); + const cb = () => evaluate( entry, event ); const globalVar = type === 'window' ? window : document; - globalVar.addEventListener( eventType, cb ); - return () => globalVar.removeEventListener( eventType, cb ); + globalVar.addEventListener( event, cb ); + return () => globalVar.removeEventListener( event, cb ); }, [] ); } ); - } ); }; }; From b7ffc092da1fe98e89c1fdbe6380860e2f23da84 Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Mon, 6 May 2024 22:10:34 +0200 Subject: [PATCH 4/5] Fix event deletion --- packages/interactivity/src/directives.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/interactivity/src/directives.js b/packages/interactivity/src/directives.js index e8e03b3c2b340e..818c9ab358f0d0 100644 --- a/packages/interactivity/src/directives.js +++ b/packages/interactivity/src/directives.js @@ -212,7 +212,7 @@ const getGlobalEventDirective = ( type ) => { .forEach( ( entry ) => { const event = entry.suffix.split( '--', 1 )[ 0 ]; useInit( () => { - const cb = () => evaluate( entry, event ); + const cb = ( cbEvent ) => evaluate( entry, cbEvent ); const globalVar = type === 'window' ? window : document; globalVar.addEventListener( event, cb ); return () => globalVar.removeEventListener( event, cb ); From 19cd289f49649b295b3c2dc01b6e8bb4fb37398a Mon Sep 17 00:00:00 2001 From: Carlos Bravo Date: Tue, 7 May 2024 13:25:56 +0200 Subject: [PATCH 5/5] Add changelog and rename var --- packages/interactivity/CHANGELOG.md | 4 ++++ packages/interactivity/src/directives.js | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/interactivity/CHANGELOG.md b/packages/interactivity/CHANGELOG.md index 72b38ed4a4ea4a..fa4fee5976b0cd 100644 --- a/packages/interactivity/CHANGELOG.md +++ b/packages/interactivity/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Bug Fixes + +- Allow multiple event handlers for the same type with `data-wp-on-document` and `data-wp-on-window`. ([#61009](https://github.com/WordPress/gutenberg/pull/61009)) + ## 5.6.0 (2024-05-02) ## 5.5.0 (2024-04-19) diff --git a/packages/interactivity/src/directives.js b/packages/interactivity/src/directives.js index 818c9ab358f0d0..c09cecb4afc127 100644 --- a/packages/interactivity/src/directives.js +++ b/packages/interactivity/src/directives.js @@ -210,12 +210,12 @@ const getGlobalEventDirective = ( type ) => { directives[ `on-${ type }` ] .filter( ( { suffix } ) => suffix !== 'default' ) .forEach( ( entry ) => { - const event = entry.suffix.split( '--', 1 )[ 0 ]; + const eventName = entry.suffix.split( '--', 1 )[ 0 ]; useInit( () => { - const cb = ( cbEvent ) => evaluate( entry, cbEvent ); + const cb = ( event ) => evaluate( entry, event ); const globalVar = type === 'window' ? window : document; - globalVar.addEventListener( event, cb ); - return () => globalVar.removeEventListener( event, cb ); + globalVar.addEventListener( eventName, cb ); + return () => globalVar.removeEventListener( eventName, cb ); }, [] ); } ); };