From ebbc7d9fbb67b54335fb131ac2d867f59fdc10a7 Mon Sep 17 00:00:00 2001 From: Denys Bohdan Date: Thu, 18 Nov 2021 18:09:11 +0200 Subject: [PATCH] STSCOM-895: Make useClickOutside catch click event on capture phase (#1665) --- CHANGELOG.md | 4 ++++ hooks/tests/useClickOutside-test.js | 18 +++++++++++++++++- hooks/useClickOutside/useClickOutside.js | 7 +++++-- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15ecbd321..dfb6078ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change history for stripes-components +## IN PROGRESS + +* Make `useClickOutside` click handler work on `capture` event phase. Refs STCOM-895. + ## [10.0.2](https://github.com/folio-org/stripes-components/tree/v10.0.2) (2021-11-15) [Full Changelog](https://github.com/folio-org/stripes-components/compare/v10.0.1...v10.0.2) diff --git a/hooks/tests/useClickOutside-test.js b/hooks/tests/useClickOutside-test.js index d7f896cfb..3dcd2aa86 100644 --- a/hooks/tests/useClickOutside-test.js +++ b/hooks/tests/useClickOutside-test.js @@ -34,7 +34,13 @@ describe('useClickOutside', () => { return (
- Inside element +
); }; @@ -73,4 +79,14 @@ describe('useClickOutside', () => { expect(onClickSpy.calledOnceWith(false)).to.be.true; }); }); + + describe('when other click handler removes click target from DOM', () => { + beforeEach(async () => { + await useClickOutsideInteractor.clickInsideElement(); + }); + + it('should still give correct results', () => { + expect(onClickSpy.calledOnceWith(false)).to.be.true; + }); + }); }); diff --git a/hooks/useClickOutside/useClickOutside.js b/hooks/useClickOutside/useClickOutside.js index 93dc5c120..fe4253021 100644 --- a/hooks/useClickOutside/useClickOutside.js +++ b/hooks/useClickOutside/useClickOutside.js @@ -7,9 +7,12 @@ const useClickOutside = (ref, onClick) => { onClick(e, isOutside); }; - document.addEventListener('click', handleClick); + // need to catch event in capture phase to process click event before other handlers + // this is to fix a case when other click handler might remove e.target from DOM + // and when this handler runs - `contains` will return false because e.target is no longer in DOM + document.addEventListener('click', handleClick, true); return () => { - document.removeEventListener('click', handleClick); + document.removeEventListener('click', handleClick, true); }; }, [ref, onClick]); };