From c90bff53a3fdeae7dacd56abc655d2da05dde30d Mon Sep 17 00:00:00 2001 From: "Gustavo \"Guz\" L de Mello" Date: Tue, 4 Nov 2025 18:38:07 -0300 Subject: [PATCH] chore(ipub): move IPUBBody and IPUBCover definitions to top --- .epub/example/OEBPS/scripts/ipub.js | 226 +++++++++++++++------------- 1 file changed, 120 insertions(+), 106 deletions(-) diff --git a/.epub/example/OEBPS/scripts/ipub.js b/.epub/example/OEBPS/scripts/ipub.js index b8a8f01..906f277 100644 --- a/.epub/example/OEBPS/scripts/ipub.js +++ b/.epub/example/OEBPS/scripts/ipub.js @@ -19,6 +19,126 @@ class IPUBElement extends HTMLElement { this.id = hashFromHTML(this); } } + +} + +globalThis.addEventListener("load", () => { + console.info("IPUB: Starting IPUB elements"); + + console.log("IPUB: Defining custom element "); + globalThis.customElements.define(IPUBBody.elementName, IPUBBody); +}); + +class IPUBBody extends IPUBElement { + static elementName = `ipub-body`; + + connectedCallback() { + super.connectedCallback(); + + this.setAttribute("aria-busy", "true"); + + // TODO?: Move IPUBCover's "can-play" logic to here + + console.log("IPUBBody: Defining custom element "); + globalThis.customElements.define(IPUBCover.elementName, IPUBCover); + + /** @type {IPUBCover} */ + const cover = this.querySelector("ipub-cover"); + if (!cover) { + // TODO: automatically create IPUBCover element if it doesn't exists + console.error("IPUBBody: Document doesn't has element"); + this.#initElements(); + this.setAttribute("aria-busy", "false"); + return; + } + + cover.onclose = () => { + this.#initElements(); + }; + cover.cover(); + + this.setAttribute("aria-busy", "false"); + } + + /** + * @private + */ + #initElements() { + for (const e of [ + IPUBAudio, + IPUBBackground, + IPUBImage, + IPUBInteraction, + IPUBSoundtrack, + ]) { + console.info(`IPUBBody: Defining custom element <${e.elementName}>`); + globalThis.customElements.define(e.elementName, e); + } + +} + +class IPUBCover extends IPUBElement { + static elementName = `ipub-cover`; + + /** + * @type {() => void} callback + */ + onclose = () => {}; + + connectedCallback() { + super.connectedCallback(); + } + + cover() { + console.debug("IPUBCover: Setting up cover"); + this.setAttribute("aria-busy", "true"); + + const dialog = this.querySelector("dialog"); + + // HACK: Test if we can autoplay interactions, soundtracks, etc + + /** @type {HTMLMediaElement | null} */ + const media = + this.parentElement.querySelector("audio") ?? + this.parentElement.querySelector("video"); + + if (!media) { + console.log("IPUBCover: no media element found, removing cover"); + dialog.close(); + this.onclose(); + return; + } + + const pastVolume = media.volume; + media.volume = 0.1; // don't let the user hear the test audio + + media + .play() + .then(() => { + media.pause(); + media.volume = pastVolume; + media.currentTime = 0; + + console.debug("IPUBCover: Can autoplay interactions, removing cover"); + dialog.close(); + this.onclose(); + }) + .catch(() => { + console.debug( + "IPUBCover: Cannot autoplay interactions, covering content", + ); + + dialog.show(); + + dialog.parentElement.addEventListener("click", () => { + dialog.close(); + this.onclose(); + }); + + this.setAttribute("aria-busy", "false"); + return; + }); + } } class IPUBAudio extends IPUBElement { @@ -321,112 +441,6 @@ class IPUBBackground extends IPUBElement { } } } - -class IPUBBody extends IPUBElement { - static elementName = "ipub-body"; - - static defineContentElements() { - for (const e of [ - IPUBAudio, - IPUBBackground, - IPUBImage, - IPUBInteraction, - IPUBSoundtrack, - ]) { - console.info(`IPUBBody: Defining custom element <${e.elementName}>`); - globalThis.customElements.define(e.elementName, e); - } - } - - connectedCallback() { - super.connectedCallback(); - - this.setAttribute("aria-busy", "true"); - - // TODO?: Move IPUBCover's "can-play" logic to here - - console.log("IPUBBody: Defining custom element "); - globalThis.customElements.define(IPUBCover.elementName, IPUBCover); - - /** @type {IPUBCover} */ - const cover = this.querySelector("ipub-cover"); - if (!cover) { - // TODO: automatically create IPUBCover element if it doesn't exists - console.error("IPUBBody: Document doesn't has element"); - IPUBBody.defineContentElements(); - } - cover.onclose = IPUBBody.defineContentElements; - - this.setAttribute("aria-busy", "false"); - } -} - -globalThis.addEventListener("load", () => { - console.info("IPUB: Starting IPUB elements"); - - console.log("IPUB: Defining custom element "); - globalThis.customElements.define(IPUBBody.elementName, IPUBBody); -}); - -class IPUBCover extends IPUBElement { - static elementName = "ipub-cover"; - - /** - * @type {() => void} callback - */ - onclose = () => {}; - - connectedCallback() { - super.connectedCallback(); - - console.debug("IPUBCover: Setting up cover"); - this.setAttribute("aria-busy", "true"); - - const dialog = this.querySelector("dialog"); - - // HACK: Test if we can autoplay interactions, soundtracks, etc - - /** @type {HTMLMediaElement | null} */ - const media = - this.parentElement.querySelector("audio") ?? - this.parentElement.querySelector("video"); - - if (!media) { - return; - } - - const pastVolume = media.volume; - media.volume = 0.1; // don't let the user hear the test audio - - media - .play() - .then(() => { - media.pause(); - media.volume = pastVolume; - media.currentTime = 0; - - console.debug("IPUBCover: Can autoplay interactions, removing cover"); - dialog.close(); - this.onclose(); - }) - .catch(() => { - console.debug( - "IPUBCover: Cannot autoplay interactions, covering content", - ); - - dialog.show(); - - dialog.parentElement.addEventListener("click", () => { - dialog.close(); - this.onclose(); - }); - - this.setAttribute("aria-busy", "false"); - return; - }); - } -} - class IPUBImage extends IPUBElement { static elementName = "ipub-image"; }