/* global window, document, localStorage */ const $ = selector => Array.from(document.querySelectorAll(selector)); const $$ = selector => Array.from(document.querySelector(selector)); (() => { "use strict"; /** * Initialize the theme toggle button functionality. * Toggles between 'dark' and 'light' themes and persists the state in localStorage. */ function initThemeToggle() { const themeToggleButton = document.getElementById("theme-toggle-btn"); if (!themeToggleButton) return; themeToggleButton.classList.toggle("btn-ghost", !("theme" in localStorage)); themeToggleButton.addEventListener("click", () => { const documentRoot = document.documentElement; const isSystemTheme = themeToggleButton.classList.contains("btn-ghost"); const isDarkTheme = documentRoot.classList.contains("dark"); const newTheme = isSystemTheme ? "dark" : (isDarkTheme ? "light" : "system"); if (newTheme === "system") { documentRoot.classList.toggle("dark", window.matchMedia("(prefers-color-scheme: dark)").matches); documentRoot.setAttribute("data-theme", window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"); localStorage.removeItem("theme"); } else { if (newTheme === "light") { documentRoot.classList.remove("dark"); } else if (newTheme === "dark") { documentRoot.classList.add("dark"); } documentRoot.setAttribute("data-theme", newTheme); localStorage.setItem("theme", newTheme); } themeToggleButton.classList.toggle("btn-ghost", newTheme === "system"); }); } /** * Initialize event listeners for forms containing multiselect fields. * When the form is submitted, process each 'card-multiselect' to create hidden inputs. */ function initCardMultiselectHandling() { const forms = document.querySelectorAll("form"); forms.forEach(form => { if (form.querySelector("select.card-multiselect")) { form.addEventListener("submit", () => { processMultiselectForm(form); }); } }); } /** * Process multiselect fields within a form before submission by: * - Creating hidden inputs for each selected option with value in 'card_id:quantity' format. * - Removing the original name attribute to avoid duplicate submissions. * * @param {HTMLFormElement} form - The form element to process. */ function processMultiselectForm(form) { const multiselectFields = form.querySelectorAll("select.card-multiselect"); multiselectFields.forEach(selectField => { const originalFieldName = selectField.getAttribute("data-original-name") || selectField.getAttribute("name"); if (!originalFieldName) return; selectField.setAttribute("data-original-name", originalFieldName); // Remove any previously generated hidden inputs for this multiselect. form .querySelectorAll(`input[data-generated-for-card-multiselect="${originalFieldName}"]`) .forEach(input => input.remove()); // For each selected option, create a hidden input. selectField.querySelectorAll("option:checked").forEach(option => { const cardId = option.value; const quantity = option.getAttribute("data-quantity") || "1"; const hiddenInput = document.createElement("input"); hiddenInput.type = "hidden"; hiddenInput.name = originalFieldName; hiddenInput.value = `${cardId}:${quantity}`; hiddenInput.setAttribute("data-generated-for-card-multiselect", originalFieldName); form.appendChild(hiddenInput); }); // Prevent the browser from submitting the select field directly. selectField.removeAttribute("name"); }); } /** * Reset stale selections in all card multiselect fields. * This is triggered on the window's 'pageshow' event to clear any lingering selections. */ function resetCardMultiselectState() { const multiselectFields = document.querySelectorAll("select.card-multiselect"); multiselectFields.forEach(selectField => { // Deselect all options. selectField.querySelectorAll("option").forEach(option => { option.selected = false; }); // If the select field has an associated Choices.js instance, clear its selection. if (selectField.choicesInstance) { const activeSelections = selectField.choicesInstance.getValue(true); if (activeSelections.length > 0) { selectField.choicesInstance.removeActiveItemsByValue(activeSelections); } selectField.choicesInstance.setValue([]); } }); } // On DOMContentLoaded, initialize theme toggling and form processing. document.addEventListener("DOMContentLoaded", () => { initThemeToggle(); initCardMultiselectHandling(); }); // On pageshow, only reset multiselect state if the page was loaded from bfcache. window.addEventListener("pageshow", function(event) { if (event.persisted) { resetCardMultiselectState(); } }); // Expose tradeOfferCard globally if not already defined. if (!window.tradeOfferCard) { window.tradeOfferCard = function() { return { flipped: false, show_back: false, collapsed: false, /* * flipWithCollapse() now applies the height transition directly on the visible card face. * It measures the current face (front or back) and the target face's height, * then animates the current face's height change before toggling the flip. * * Make sure your template markup includes: * - x-ref="front" on the front card face * - x-ref="back" on the back card face */ flipWithCollapse() { // Determine the currently visible face and the target face. const currentFace = this.flipped ? this.$refs.back : this.$refs.front; const targetFace = this.flipped ? this.$refs.front : this.$refs.back; const container = this.$refs.container; // Temporarily force target face to display to measure its height. const originalHeight = targetFace.style.height; const originalDisplay = targetFace.style.display; const originalPosition = targetFace.style.position; const originalVisibility = targetFace.style.visibility; targetFace.style.height = 'auto'; targetFace.style.display = 'block'; targetFace.style.position = 'absolute'; targetFace.style.visibility = 'hidden'; const targetHeight = targetFace.offsetHeight + 18; targetFace.style.height = originalHeight; targetFace.style.display = originalDisplay; targetFace.style.position = originalPosition; targetFace.style.visibility = originalVisibility; container.setAttribute('x-collapse.duration.500ms.min.' + targetHeight + 'px', ''); this.collapsed = true; setTimeout(() => { this.show_back = this.flipped; this.flipped = !this.flipped; setTimeout(() => { this.show_back = !this.show_back; }, 250) setTimeout(() => { this.collapsed = false; setTimeout(() => { container.removeAttribute('x-collapse.duration.500ms.min.' + targetHeight + 'px'); }, 550); }, 550); }, 550); } } }; } })();