Compare commits
No commits in common. "81a58f865672d41d29f8be9485266319d2fc9cff" and "0a9193aed75b230566da1264d4466de4fd2c2ac3" have entirely different histories.
81a58f8656
...
0a9193aed7
6 changed files with 48 additions and 45 deletions
|
@ -1,31 +0,0 @@
|
||||||
class OutfitLayer extends HTMLElement {
|
|
||||||
#internals;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.#internals = this.attachInternals();
|
|
||||||
}
|
|
||||||
|
|
||||||
connectedCallback() {
|
|
||||||
setTimeout(() => this.#initializeImage(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
#initializeImage() {
|
|
||||||
this.image = this.querySelector("img");
|
|
||||||
if (!this.image) {
|
|
||||||
throw new Error(`<outfit-layer> must contain an <img> 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.#internals.states.clear();
|
|
||||||
this.#internals.states.add(newStatus);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
customElements.define("outfit-layer", OutfitLayer);
|
|
|
@ -49,7 +49,7 @@ body.items-show
|
||||||
|
|
||||||
margin: 0 auto .75em
|
margin: 0 auto .75em
|
||||||
|
|
||||||
outfit-layer
|
.outfit-layer
|
||||||
display: block
|
display: block
|
||||||
position: absolute
|
position: absolute
|
||||||
inset: 0
|
inset: 0
|
||||||
|
@ -58,7 +58,7 @@ body.items-show
|
||||||
width: 100%
|
width: 100%
|
||||||
height: 100%
|
height: 100%
|
||||||
|
|
||||||
&:has(outfit-layer:state(loading))
|
&:has(.outfit-layer[data-status="loading"])
|
||||||
background: gray
|
background: gray
|
||||||
|
|
||||||
.species-color-picker
|
.species-color-picker
|
||||||
|
|
|
@ -244,5 +244,15 @@ module ItemsHelper
|
||||||
def item_header_user_lists_form_state
|
def item_header_user_lists_form_state
|
||||||
cookies.fetch("DTIItemPageUserListsFormState", "closed")
|
cookies.fetch("DTIItemPageUserListsFormState", "closed")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def outfit_viewer_layers(swf_assets)
|
||||||
|
swf_assets.map { |a| outfit_viewer_layer(a) }.join("\n").html_safe
|
||||||
|
end
|
||||||
|
|
||||||
|
def outfit_viewer_layer(swf_asset)
|
||||||
|
content_tag :div, class: "outfit-layer" do
|
||||||
|
image_tag swf_asset.image_url, alt: ""
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
32
app/javascript/item-page.js
Normal file
32
app/javascript/item-page.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
// 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 },
|
||||||
|
);
|
|
@ -1,9 +0,0 @@
|
||||||
.outfit-viewer
|
|
||||||
- outfit.visible_layers.each do |swf_asset|
|
|
||||||
%outfit-layer{
|
|
||||||
data: {
|
|
||||||
"asset-id": swf_asset.id,
|
|
||||||
"zone": swf_asset.zone.label,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
= image_tag swf_asset.image_url, alt: ""
|
|
|
@ -14,7 +14,8 @@
|
||||||
sorry!
|
sorry!
|
||||||
|
|
||||||
= turbo_frame_tag "item-preview" do
|
= turbo_frame_tag "item-preview" do
|
||||||
= render partial: "outfit_viewer", locals: {outfit: @preview_outfit}
|
.outfit-viewer
|
||||||
|
= outfit_viewer_layers @preview_outfit.visible_layers
|
||||||
|
|
||||||
= form_for item_path(@item), method: :get, class: "species-color-picker",
|
= form_for item_path(@item), method: :get, class: "species-color-picker",
|
||||||
data: {"is-valid": @preview_error.nil?} do |f|
|
data: {"is-valid": @preview_error.nil?} do |f|
|
||||||
|
@ -39,6 +40,6 @@
|
||||||
%li= link_to(contributor.name, user_contributions_path(contributor)) + format_contribution_count(count)
|
%li= link_to(contributor.name, user_contributions_path(contributor)) + format_contribution_count(count)
|
||||||
%footer= t '.contributors.footer'
|
%footer= t '.contributors.footer'
|
||||||
|
|
||||||
- content_for :javascripts do
|
- content_for :javascripts_body do
|
||||||
= javascript_include_tag 'outfit-viewer', async: true
|
= javascript_include_tag 'item-page', defer: true
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue