« get me outta code hell

client: hoverable-tooltip: avoid elementFromPoint for hit detection - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/static/js/client/hoverable-tooltip.js
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2026-04-27 13:06:56 -0300
committer(quasar) nebula <qznebula@protonmail.com>2026-04-27 13:06:56 -0300
commitb74fa37385c147de772f689b003bd3d46eab912e (patch)
tree33450fb78250436d387996407132df528dd666c4 /src/static/js/client/hoverable-tooltip.js
parentb4dce2cbdfc295402d29badfcc6b7f0db0e91493 (diff)
client: hoverable-tooltip: avoid elementFromPoint for hit detection
Diffstat (limited to 'src/static/js/client/hoverable-tooltip.js')
-rw-r--r--src/static/js/client/hoverable-tooltip.js48
1 files changed, 32 insertions, 16 deletions
diff --git a/src/static/js/client/hoverable-tooltip.js b/src/static/js/client/hoverable-tooltip.js
index 2d1ac552..863f4d64 100644
--- a/src/static/js/client/hoverable-tooltip.js
+++ b/src/static/js/client/hoverable-tooltip.js
@@ -6,7 +6,6 @@ import {
   cssProp,
   dispatchInternalEvent,
   getVisuallyContainingElement,
-  pointIsOverAnyOf,
 } from '../client-util.js';
 
 import {info as stickyHeadingInfo} from './sticky-heading.js';
@@ -387,11 +386,14 @@ function handleTooltipHoverableTouchEnded(hoverable, domEvent) {
   // Don't proceed if none of the (just-ended) touches ended over the
   // hoverable.
 
-  const pointIsOverThisHoverable = pointIsOverAnyOf([hoverable]);
-
-  const anyTouchEndedOverHoverable =
-    touches.some(({clientX, clientY}) =>
-      pointIsOverThisHoverable(clientX, clientY));
+  let anyTouchEndedOverHoverable = false;
+  for (const touch of touches) {
+    const point = WikiRect.fromPoint(touch.clientX, touch.clientY);
+    if (WikiRect.fromElementContaining(hoverable, point)) {
+      anyTouchEndedOverHoverable = true;
+      break;
+    }
+  }
 
   if (!anyTouchEndedOverHoverable) {
     return;
@@ -738,8 +740,12 @@ export function getTooltipFromHoverablePlacementOpportunityAreas(hoverable) {
   const baselineRects =
     getTooltipBaselineOpportunityAreas(tooltip);
 
+  const basicHoverableRect =
+    WikiRect.fromElementUnderMouse(hoverable) ??
+    WikiRect.fromRect(hoverable.getClientRects()[0]);
+
   const hoverableRect =
-    WikiRect.fromElementUnderMouse(hoverable).toExtended(5, 10);
+    basicHoverableRect.toExtended(5, 10);
 
   const tooltipRect =
     peekTooltipClientRect(tooltip);
@@ -1066,12 +1072,17 @@ export function addPageListeners() {
 
     if (empty(touches)) return;
 
-    const pointIsOverHoverableOrTooltip =
-      pointIsOverAnyOf(getHoverablesAndTooltips());
+    let anyTouchOverAnyHoverableOrTooltip = false;
+    for (const touch of touches) outer: {
+      const point = WikiRect.fromPoint(touch.clientX, touch.clientY);
 
-    const anyTouchOverAnyHoverableOrTooltip =
-      touches.some(({clientX, clientY}) =>
-        pointIsOverHoverableOrTooltip(clientX, clientY));
+      for (const element of getHoverablesAndTooltips()) {
+        if (WikiRect.fromElementContaining(element, point)) {
+          anyTouchOverAnyHoverableOrTooltip = true;
+          break outer;
+        }
+      }
+    }
 
     if (!anyTouchOverAnyHoverableOrTooltip) {
       hideCurrentlyShownTooltip();
@@ -1079,12 +1090,17 @@ export function addPageListeners() {
   });
 
   document.body.addEventListener('click', domEvent => {
-    const {clientX, clientY} = domEvent;
+    const point = WikiRect.fromPoint(domEvent.clientX, domEvent.clientY);
 
-    const pointIsOverHoverableOrTooltip =
-      pointIsOverAnyOf(getHoverablesAndTooltips());
+    let pointIsOverHoverableOrTooltip = false;
+    for (const element of getHoverablesAndTooltips()) {
+      if (WikiRect.fromElementContaining(element, point)) {
+        pointIsOverHoverableOrTooltip = true;
+        break;
+      }
+    }
 
-    if (!pointIsOverHoverableOrTooltip(clientX, clientY)) {
+    if (!pointIsOverHoverableOrTooltip) {
       // Hide with "intent to replace" - we aren't actually going to replace
       // the tooltip with a new one, but this intent indicates that it should
       // be hidden right away, instead of showing. What we're really replacing,