diff --git a/package-lock.json b/package-lock.json index e385696b..b53b3241 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@d-i-t-a/reader", - "version": "2.4.9", + "version": "2.4.10", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@d-i-t-a/reader", - "version": "2.4.9", + "version": "2.4.10", "license": "Apache-2.0", "dependencies": { "@babel/plugin-proposal-private-property-in-object": "^7.21.11", diff --git a/package.json b/package.json index fd48cb7f..18dc0abc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@d-i-t-a/reader", - "version": "2.4.9", + "version": "2.4.10", "description": "A viewer application for EPUB files.", "repository": "https://github.com/d-i-t-a/R2D2BC", "license": "Apache-2.0", diff --git a/src/reader.ts b/src/reader.ts index 2a9f10ba..4d7108ff 100644 --- a/src/reader.ts +++ b/src/reader.ts @@ -522,6 +522,16 @@ export default class D2Reader { addAnnotation = async (highlight: Annotation) => { return (await this.annotationModule?.addAnnotation(highlight)) ?? false; }; + /** + * Update annotation + * + * This should be used only when the add/delete of the annotation note + * is not directly handled in the `addAnnotation`/`addCommentToAnnotation` + * callback defined in the configuration of the D2Reader.load() method + * */ + updateAnnotation = async (highlight: Annotation) => { + return (await this.annotationModule?.updateAnnotation(highlight)) ?? false; + }; /** Hide Annotation Layer */ hideAnnotationLayer = () => { diff --git a/src/utils/EventHandler.ts b/src/utils/EventHandler.ts index 4c986998..5d9c3433 100644 --- a/src/utils/EventHandler.ts +++ b/src/utils/EventHandler.ts @@ -54,21 +54,35 @@ export default class EventHandler { public setupEvents(element: HTMLElement | Document | null) { if (element !== null) { - element.addEventListener( - "dblclick", - async (event: TouchEvent) => { + element.addEventListener("click", async (event: TouchEvent) => { + const link = this.checkForLink(event); + if (link) { + await this.handleLinks(event); + event.preventDefault(); + event.stopPropagation(); + } + if (this.clickTimeout !== null) { + clearTimeout(this.clickTimeout); + this.clickTimeout = null; + // Handle double click here + log.log("Double Click Detected"); let htmlElement = event.target as HTMLElement; if (event.target && htmlElement.tagName.toLowerCase() === "img") { await this.popup.showPopover(htmlElement, event); } - }, - true - ); + } else { + this.clickTimeout = window.setTimeout(async () => { + // Handle single click here + log.log("Single Click Detected"); + await this.handleLinks(event); + this.clickTimeout = null; + }, 200); // Adjust timeout duration as needed + } + }); // 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. - element.addEventListener("click", this.handleLinks.bind(this), true); } else { throw "cannot setup events for null"; } @@ -127,79 +141,58 @@ export default class EventHandler { return isEpubInternal; }; - clicks = 0; - clickTimer: any = 0; - dblClickTimeSpan = 300; + private clickTimeout: number | null = null; private handleLinks = async ( event: MouseEvent | TouchEvent ): Promise => { log.log("R2 Click Handler"); - this.clicks++; - if (this.clicks === 1) { - this.clickTimer = setTimeout(async () => { - this.clicks = 0; - const link = this.checkForLink(event); - if (link) { - // Open external links in new tabs. - const isSameOrigin = - window.location.protocol === link.protocol && - window.location.port === link.port && - window.location.hostname === link.hostname; - - // If epub is hosted, rather than streamed, links to a resource inside the same epub should not be opened externally. - const isEpubInternal = this.isReadingOrderInternal(link); - - const isResourceInternal = this.isResourceInternal(link); - if (!isResourceInternal) { - await this.popup.hidePopover(); - } + const link = this.checkForLink(event); + if (link) { + const isSameOrigin = + window.location.protocol === link.protocol && + window.location.port === link.port && + window.location.hostname === link.hostname; - const isInternal = link.href.indexOf("#"); - if (!isEpubInternal && !isResourceInternal) { - window.open(link.href, link.target ?? "_blank"); - event.preventDefault(); - event.stopPropagation(); - } else { - (event.target as HTMLAnchorElement).href = link.href; - if ((isSameOrigin || isEpubInternal) && isInternal !== -1) { - const link = event.target as HTMLLIElement; - if (link) { - const attribute = link.getAttribute("epub:type") === "noteref"; - if (attribute) { - await this.popup.handleFootnote(link, event); - } else if (isResourceInternal && !isEpubInternal) { - await this.popup.showPopover(link, event); - } else { - this.onInternalLink(event); - } - } else { - this.onInternalLink(event); - } - } else if ((isSameOrigin || isEpubInternal) && isInternal === -1) { - // TODO needs some more refactoring when handling other types of links or elements - // link.click(); + const isEpubInternal = this.isReadingOrderInternal(link); + const isResourceInternal = this.isResourceInternal(link); + + if (!isResourceInternal) { + await this.popup.hidePopover(); + } + + const isInternal = link.href.indexOf("#") !== -1; + + if (!isEpubInternal && !isResourceInternal) { + window.open(link.href, link.target ?? "_blank"); + event.preventDefault(); + event.stopPropagation(); + } else { + (event.target as HTMLAnchorElement).href = link.href; + if ((isSameOrigin || isEpubInternal) && isInternal) { + const linkElement = event.target as HTMLLIElement; + if (linkElement) { + const attribute = + linkElement.getAttribute("epub:type") === "noteref"; + if (attribute) { + await this.popup.handleFootnote(linkElement, event); + } else if (isResourceInternal && !isEpubInternal) { + await this.popup.showPopover(linkElement, event); + } else { this.onInternalLink(event); } + } else { + this.onInternalLink(event); } - } else { - setTimeout(() => { - console.log("event.detail", event.detail); - if ( - !this.navigator.highlighter?.isSelectionMenuOpen && - event.detail === 1 - ) { - this.onClickThrough(event); - } - }, 100); + } else if ((isSameOrigin || isEpubInternal) && !isInternal) { + this.onInternalLink(event); } - }, this.dblClickTimeSpan); - } - if (this.clicks === 2) { - // it is the second click in double-click event - clearTimeout(this.clickTimer); - this.clicks = 0; + } + } else { + if (!this.navigator.highlighter?.isSelectionMenuOpen) { + this.onClickThrough(event); + } } }; }