diff --git a/src/modules/search/Popup.ts b/src/modules/search/Popup.ts index ee486775..453e17c0 100644 --- a/src/modules/search/Popup.ts +++ b/src/modules/search/Popup.ts @@ -74,14 +74,14 @@ export class Popup { wrapper.style.overflow = "auto"; } - async showPopover(link: HTMLLIElement, event: MouseEvent | TouchEvent) { + async showPopover(link: HTMLElement, event: MouseEvent | TouchEvent) { const href = link.getAttribute("href"); + const src = link.getAttribute("src"); + function getAbsoluteHref(href: string): string | null { + const currentUrl = document.location.href; + return new URL(href, currentUrl).href; + } if (href) { - function getAbsoluteHref(href: string): string | null { - const currentUrl = document.location.href; - return new URL(href, currentUrl).href; - } - let absolute = getAbsoluteHref(href); if (absolute) { event.preventDefault(); @@ -124,6 +124,61 @@ export class Popup { } }); + let win = this.navigator.iframes[0].contentWindow; + if (!win) { + return; + } + let self = this; + win.onclick = function (ev) { + if (event.target !== ev.target) { + if (d2popover.parentElement) { + self.hidePopover(); + if (win) { + win.onclick = null; + } + } + } + }; + } + } else if (src) { + let absolute = getAbsoluteHref(src); + if (absolute) { + event.preventDefault(); + event.stopPropagation(); + + let popover = this.navigator.iframes[0].contentDocument?.getElementById( + "d2-popover" + ); + if (popover) { + popover.parentElement?.removeChild(popover); + } + + const d2popover = document.createElement("div"); + d2popover.id = "d2-popover"; + d2popover.className = "d2-popover is-active"; + + const wrapper = HTMLUtilities.findRequiredElement( + document, + "#iframe-wrapper" + ); + wrapper.style.overflow = "hidden"; + d2popover.style.top = wrapper.scrollTop + "px"; + d2popover.style.height = wrapper.clientHeight * 0.9 + "px"; + + const d2wrapper = document.createElement("div"); + d2wrapper.className = "d2-popover-wrapper"; + d2popover.appendChild(d2wrapper); + + const d2content = document.createElement("img"); + d2content.className = "d2-popover-content"; + d2wrapper.appendChild(d2content); + + d2content.src = src; + let doc = this.navigator.iframes[0].contentDocument; + if (doc) { + doc.body.appendChild(d2popover); + } + let win = this.navigator.iframes[0].contentWindow; if (!win) { return; diff --git a/src/utils/EventHandler.ts b/src/utils/EventHandler.ts index 71d5f476..4faf2f67 100644 --- a/src/utils/EventHandler.ts +++ b/src/utils/EventHandler.ts @@ -54,6 +54,17 @@ export default class EventHandler { public setupEvents(element: HTMLElement | Document | null) { if (element !== null) { + element.addEventListener( + "dblclick", + async (event: TouchEvent) => { + let htmlElement = event.target as HTMLElement; + if (event.target && htmlElement.tagName.toLowerCase() === "img") { + await this.popup.showPopover(htmlElement, event); + } + }, + true + ); + // Most click handling is done in the touchend and mouseup event handlers, // but if there's a click on an external link we need to cancel the click // event to prevent it from opening in the iframe. diff --git a/src/views/ReflowableBookView.ts b/src/views/ReflowableBookView.ts index 0b6900d7..4a57d290 100644 --- a/src/views/ReflowableBookView.ts +++ b/src/views/ReflowableBookView.ts @@ -258,15 +258,9 @@ export default class ReflowableBookView implements BookView { } goToElement(element: HTMLElement | null, relative?: boolean): void { - const wrapper = HTMLUtilities.findRequiredElement( - document, - "#iframe-wrapper" - ); - if (this.scrollMode) { if (element) { - // Put the element as close to the top as possible. - wrapper.scrollTop = element.offsetTop; + element.scrollIntoView({ block: "center" }); } } else { if (element) {