From 3d0259dfcb66289ea8120f1e11dd275d5bf22529 Mon Sep 17 00:00:00 2001 From: Alex Kaminskii Date: Tue, 30 Aug 2022 17:09:31 +0200 Subject: [PATCH] feat(frontend): maintain :hover inside iframes --- .../StatedScreen/Screen/BaseScreen.ts | 53 ++++++++++++++----- .../managers/MouseMoveManager.ts | 5 +- 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/frontend/app/player/MessageDistributor/StatedScreen/Screen/BaseScreen.ts b/frontend/app/player/MessageDistributor/StatedScreen/Screen/BaseScreen.ts index 81ced7774..39dda161d 100644 --- a/frontend/app/player/MessageDistributor/StatedScreen/Screen/BaseScreen.ts +++ b/frontend/app/player/MessageDistributor/StatedScreen/Screen/BaseScreen.ts @@ -15,6 +15,43 @@ export const INITIAL_STATE: State = { } +function getElementsFromInternalPoint(doc: Document, { x, y }: Point): Element[] { + // @ts-ignore (IE, Edge) + if (typeof doc.msElementsFromRect === 'function') { + // @ts-ignore + return Array.prototype.slice.call(doc.msElementsFromRect(x,y)) || [] + } + + if (typeof doc.elementsFromPoint === 'function') { + return doc.elementsFromPoint(x, y) + } + const el = doc.elementFromPoint(x, y) + return el ? [ el ] : [] +} + +function getElementsFromInternalPointDeep(doc: Document, point: Point): Element[] { + const elements = getElementsFromInternalPoint(doc, point) + // is it performant though?? + for (let i = 0; i < elements.length; i++) { + const el = elements[i] + if (isIframe(el)){ + const iDoc = el.contentDocument + if (iDoc) { + const iPoint: Point = { + x: point.x - el.clientLeft, + y: point.y - el.clientTop, + } + elements.push(...getElementsFromInternalPointDeep(iDoc, iPoint)) + } + } + } + return elements +} + +function isIframe(el: Element): el is HTMLIFrameElement { + return el.tagName === "IFRAME" +} + export default abstract class BaseScreen { public readonly overlay: HTMLDivElement; private readonly iframe: HTMLIFrameElement; @@ -113,18 +150,10 @@ export default abstract class BaseScreen { return this.document?.elementFromPoint(x, y) || null; } - getElementsFromInternalPoint({ x, y }: Point): Element[] { - // @ts-ignore (IE, Edge) - if (typeof this.document?.msElementsFromRect === 'function') { - // @ts-ignore - return Array.prototype.slice.call(this.document?.msElementsFromRect(x,y)) || []; - } - - if (typeof this.document?.elementsFromPoint === 'function') { - return this.document?.elementsFromPoint(x, y) || []; - } - const el = this.document?.elementFromPoint(x, y); - return el ? [ el ] : []; + getElementsFromInternalPoint(point: Point): Element[] { + const doc = this.document + if (!doc) { return [] } + return getElementsFromInternalPointDeep(doc, point) } getElementFromPoint(point: Point): Element | null { diff --git a/frontend/app/player/MessageDistributor/managers/MouseMoveManager.ts b/frontend/app/player/MessageDistributor/managers/MouseMoveManager.ts index f92d53ee9..ca9e3b740 100644 --- a/frontend/app/player/MessageDistributor/managers/MouseMoveManager.ts +++ b/frontend/app/player/MessageDistributor/managers/MouseMoveManager.ts @@ -12,7 +12,6 @@ export default class MouseMoveManager extends ListWalker { constructor(private screen: StatedScreen) {super()} private updateHover(): void { - // @ts-ignore TODO const curHoverElements = this.screen.getCursorTargets(); const diffAdd = curHoverElements.filter(elem => !this.hoverElements.includes(elem)); const diffRemove = this.hoverElements.filter(elem => !curHoverElements.includes(elem)); @@ -39,6 +38,4 @@ export default class MouseMoveManager extends ListWalker { this.updateHover(); } } - - -} \ No newline at end of file +}