From eee608ac453e21dd96729d8bd1ed42381cd8c1c9 Mon Sep 17 00:00:00 2001 From: josias-r Date: Tue, 17 Jan 2023 08:56:30 +0100 Subject: [PATCH] fix: allow click actions inside the popover description --- src/lib/common/utils.ts | 8 ++++++-- src/lib/core/popover.ts | 34 ++++++++++++++++++++++------------ 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/lib/common/utils.ts b/src/lib/common/utils.ts index ece7f89..5f96d78 100644 --- a/src/lib/common/utils.ts +++ b/src/lib/common/utils.ts @@ -15,13 +15,15 @@ export function easeInOutQuad( * to make sure no external-library every knows the click happened * @param element Element (or its children) that should be listened for click events * @param handler the function that will get executed once a click happens on the requested element + * @param preventDefaultConditon Allow to conditionally let a click event through (stopPropagation will still get called, but the default action will not be prevented) * * Note: For all current use-cases: garbage collection will take of "removeEventListener", since element will get removed from the dom without reference at some point * For future use-cases where this is not possible anymore, we could return a "removeAllEventListeners" method */ export function attachHighPrioClick( element: HTMLElement | SVGElement, - handler: (e: MouseEvent | PointerEvent) => void + handler: (e: MouseEvent | PointerEvent) => void, + preventDefaultConditon?: (target: HTMLElement) => boolean | undefined | void ) { const listener = ( e: MouseEvent | PointerEvent, @@ -29,7 +31,9 @@ export function attachHighPrioClick( ) => { const target = e.target as HTMLElement; if (element.contains(target)) { - e.preventDefault(); + if (!preventDefaultConditon || preventDefaultConditon(target)) { + e.preventDefault(); + } e.stopPropagation(); e.stopImmediatePropagation(); diff --git a/src/lib/core/popover.ts b/src/lib/core/popover.ts index e8ae0a9..16d81c6 100644 --- a/src/lib/core/popover.ts +++ b/src/lib/core/popover.ts @@ -307,19 +307,29 @@ export default class Popover { document.body.appendChild(popoverWrapper); // add btn eventlisteners (using util method, to ensure no external libraries will ever "hear" the click) - attachHighPrioClick(popoverWrapper, (e) => { - const target = e.target as HTMLElement; - - if (popoverNextBtn.contains(target)) { - this.options.onNextClick(); - } - if (popoverPrevBtn.contains(target)) { - this.options.onPreviousClick(); - } - if (popoverCloseBtn.contains(target)) { - this.options.onCloseClick(); + attachHighPrioClick( + popoverWrapper, + (e) => { + const target = e.target as HTMLElement; + + if (popoverNextBtn.contains(target)) { + this.options.onNextClick(); + } + if (popoverPrevBtn.contains(target)) { + this.options.onPreviousClick(); + } + if (popoverCloseBtn.contains(target)) { + this.options.onCloseClick(); + } + }, + (target) => { + // we allow the defaultAction for the description element, in case it contains links, etc. + if (popoverDescription.contains(target)) { + return false; + } + return true; } - }); + ); this.popover = { popoverWrapper,