From 2e48376c5a3629c77e8bf3dfa1932293fe045df8 Mon Sep 17 00:00:00 2001 From: Emi Matchu Date: Thu, 5 Sep 2024 17:34:54 -0700 Subject: [PATCH] Auto-submit the species color picker on change, for new item previews --- app/assets/javascripts/items/show.js | 28 +++++++++++++++++++++---- app/assets/stylesheets/items/_show.sass | 27 +++++++++++++++++++++--- app/views/items/show.html.haml | 26 +++++++++++------------ 3 files changed, 61 insertions(+), 20 deletions(-) diff --git a/app/assets/javascripts/items/show.js b/app/assets/javascripts/items/show.js index ff0e8eb7..723a18ec 100644 --- a/app/assets/javascripts/items/show.js +++ b/app/assets/javascripts/items/show.js @@ -3,17 +3,36 @@ document.addEventListener("change", (e) => { if (!e.target.matches("species-face-picker")) return; try { - const mainPicker = document.querySelector("#item-preview .species-color-picker"); + const mainPickerForm = document.querySelector( + "#item-preview species-color-picker form"); const mainSpeciesField = - mainPicker.querySelector("[name='preview[species_id]']"); + mainPickerForm.querySelector("[name='preview[species_id]']"); mainSpeciesField.value = e.target.value; - mainPicker.requestSubmit(); // `submit` doesn't get captured by Turbo! + mainPickerForm.requestSubmit(); // `submit` doesn't get captured by Turbo! } catch (error) { - e.preventDefault(); console.error("Couldn't update species picker: ", error); } }); +class SpeciesColorPicker extends HTMLElement { + #internals; + + constructor() { + super(); + this.#internals = this.attachInternals(); + } + + connectedCallback() { + // Listen for changes to auto-submit the form, then tell CSS about it! + this.addEventListener("change", this.#handleChange); + this.#internals.states.add("auto-loading"); + } + + #handleChange(e) { + this.querySelector("form").requestSubmit(); + } +} + class SpeciesFacePicker extends HTMLElement { connectedCallback() { this.addEventListener("click", this.#handleClick); @@ -52,5 +71,6 @@ class SpeciesFacePickerOptions extends HTMLElement { } } +customElements.define("species-color-picker", SpeciesColorPicker); customElements.define("species-face-picker", SpeciesFacePicker); customElements.define("species-face-picker-options", SpeciesFacePickerOptions); diff --git a/app/assets/stylesheets/items/_show.sass b/app/assets/stylesheets/items/_show.sass index 3778b63b..2ae0a2b0 100644 --- a/app/assets/stylesheets/items/_show.sass +++ b/app/assets/stylesheets/items/_show.sass @@ -151,16 +151,31 @@ body.items-show .error-indicator display: block - .species-color-picker + species-color-picker .error-icon cursor: help margin-right: .25em - &[data-is-valid="false"] + form[data-is-valid="false"] select border-color: $error-border-color color: $error-color + // If JS is enabled, but auto-loading isn't ready yet (script loading or + // failed?), hide the submit button for .75sec, to give it time to load. + @media (scripting: enabled) + input[type=submit] + position: absolute + margin-left: .5em + opacity: 0 + animation: fade-in .25s forwards + animation-delay: .75s + + // Once the auto-loading behavior is ready, remove the submit button. + &:state(auto-loading) + input[type=submit] + display: none + species-face-picker display: block position: relative @@ -280,7 +295,7 @@ body.items-show width: 350px height: 350px - .species-color-picker + species-color-picker grid-area: picker species-face-picker @@ -290,3 +305,9 @@ body.items-show .item-zones-info grid-area: zones + +@keyframes fade-in + from + opacity: 0 + to + opacity: 1 diff --git a/app/views/items/show.html.haml b/app/views/items/show.html.haml index 41453820..e2c778eb 100644 --- a/app/views/items/show.html.haml +++ b/app/views/items/show.html.haml @@ -19,20 +19,20 @@ .error-indicator 💥 We couldn't load all of this outfit. Try again? - = form_for item_path(@item), method: :get, class: "species-color-picker", - data: {"is-valid": @preview_error.nil?} do |f| - - if @preview_error == :pet_type_does_not_exist - %span.error-icon{title: "We haven't seen this kind of pet before."} ⚠️ - - elsif @preview_error == :no_item_data - %span.error-icon{title: "We haven't seen this item on this pet before."} ⚠️ + %species-color-picker + = form_for item_path(@item), method: :get, data: {"is-valid": @preview_error.nil?} do |f| + - if @preview_error == :pet_type_does_not_exist + %span.error-icon{title: "We haven't seen this kind of pet before."} ⚠️ + - elsif @preview_error == :no_item_data + %span.error-icon{title: "We haven't seen this item on this pet before."} ⚠️ - = select_tag "preview[color_id]", - options_from_collection_for_select(Color.funny.alphabetical, - "id", "human_name", @selected_preview_pet_type.color_id) - = select_tag "preview[species_id]", - options_from_collection_for_select(Species.alphabetical, - "id", "human_name", @selected_preview_pet_type.species_id) - = submit_tag "Go", name: nil + = select_tag "preview[color_id]", + options_from_collection_for_select(Color.funny.alphabetical, + "id", "human_name", @selected_preview_pet_type.color_id) + = select_tag "preview[species_id]", + options_from_collection_for_select(Species.alphabetical, + "id", "human_name", @selected_preview_pet_type.species_id) + = submit_tag "Go", name: nil %species-face-picker %noscript