diff --git a/app/assets/javascripts/outfit-viewer.js b/app/assets/javascripts/outfit-viewer.js new file mode 100644 index 00000000..cd298ed6 --- /dev/null +++ b/app/assets/javascripts/outfit-viewer.js @@ -0,0 +1,23 @@ +class OutfitLayer extends HTMLElement { + connectedCallback() { + setTimeout(() => this.#initializeImage(), 0); + } + + #initializeImage() { + this.image = this.querySelector("img"); + if (!this.image) { + throw new Error(` must contain an tag`); + } + + this.image.addEventListener("load", () => this.#setStatus("loaded")); + this.image.addEventListener("error", () => this.#setStatus("error")); + + this.#setStatus(this.image.complete ? "loaded" : "loading"); + } + + #setStatus(newStatus) { + this.setAttribute("status", newStatus); + } +} + +customElements.define("outfit-layer", OutfitLayer); diff --git a/app/assets/stylesheets/items/_show.sass b/app/assets/stylesheets/items/_show.sass index 0d866409..dbfcbf78 100644 --- a/app/assets/stylesheets/items/_show.sass +++ b/app/assets/stylesheets/items/_show.sass @@ -49,7 +49,7 @@ body.items-show margin: 0 auto .75em - .outfit-layer + outfit-layer display: block position: absolute inset: 0 @@ -58,7 +58,7 @@ body.items-show width: 100% height: 100% - &:has(.outfit-layer[data-status="loading"]) + &:has(outfit-layer[status="loading"]) background: gray .species-color-picker diff --git a/app/javascript/item-page.js b/app/javascript/item-page.js deleted file mode 100644 index 11ce034a..00000000 --- a/app/javascript/item-page.js +++ /dev/null @@ -1,32 +0,0 @@ -// When we load in a new preview, set the status on the images. We use this in -// our CSS to show a loading state when needed. -function setImageStatuses() { - for (const layer of document.querySelectorAll(".outfit-layer")) { - const isLoaded = layer.querySelector("img").complete; - layer.setAttribute("data-status", isLoaded ? "loaded" : "loading"); - } -} -document.addEventListener("turbo:frame-render", () => setImageStatuses()); -document.addEventListener("turbo:load", () => setImageStatuses()); - -// When a preview image loads or fails, update its status. (Note that `load` -// does not fire for images that were loaded from cache, which is why we need -// both this and `setImageStatuses` when rendering new images!) -document.addEventListener( - "load", - ({ target }) => { - if (target.matches(".outfit-layer img")) { - target.closest(".outfit-layer").setAttribute("data-status", "loaded"); - } - }, - { capture: true }, -); -document.addEventListener( - "error", - ({ target }) => { - if (target.matches(".outfit-layer img")) { - target.closest(".outfit-layer").setAttribute("data-status", "error"); - } - }, - { capture: true }, -); diff --git a/app/views/items/show.html.haml b/app/views/items/show.html.haml index 08b024f3..6b17f3e6 100644 --- a/app/views/items/show.html.haml +++ b/app/views/items/show.html.haml @@ -16,7 +16,7 @@ = turbo_frame_tag "item-preview" do .outfit-viewer - @preview_outfit.visible_layers.each do |swf_asset| - .outfit-layer + %outfit-layer = image_tag swf_asset.image_url, alt: "" = form_for item_path(@item), method: :get, class: "species-color-picker", @@ -43,5 +43,5 @@ %footer= t '.contributors.footer' - content_for :javascripts do - = javascript_include_tag 'item-page', async: true + = javascript_include_tag 'outfit-viewer', async: true