/* ===== MH Contact us about this product — button + modal (self-contained) ===== */ document.addEventListener("DOMContentLoaded", () => { if (!document.body.classList.contains("ex-a-5377939")) return; const MODAL_ID = "product-inquiry-modal"; const STYLE_ID = "product-inquiry-styles"; const BUTTON_LABEL = "Contact Us About This Product"; const form = document.querySelector(".contact-form.product-inquiry-form"); // Needs the EvoX product inquiry form on the page; also guards against running twice if (!form || document.getElementById(MODAL_ID)) return; /* ---------- 1. CSS ---------- */ const css = ` .pi-btn, #${MODAL_ID} { --pi-accent: var(--evo-btn-default-bg, #f02427); --pi-dark: var(--evo-brand-default, #111111); --pi-accent-ring: rgba(240, 36, 39, 0.15); --pi-border: #d2d2cc; --pi-muted: #c8c8c4; --pi-text: #3d3d3a; } @supports (color: color-mix(in srgb, red 50%, transparent)) { #${MODAL_ID} { --pi-accent-ring: color-mix(in srgb, var(--pi-accent) 15%, transparent); } } /* Button under Add to cart */ .pi-btn { clear: both; display: flex; align-items: center; justify-content: center; width: 100%; min-height: 44px; margin-top: 8px; padding: 10px 16px; border: 0; border-radius: 4px; background: var(--pi-accent); color: #ffffff; font: inherit; font-size: 15px; font-weight: 700; line-height: 1.2; text-align: center; white-space: normal; cursor: pointer; transition: filter 0.15s; } .pi-btn:hover, .pi-btn:focus { color: #ffffff; filter: brightness(0.92); } .pi-btn:focus-visible { outline: 3px solid var(--pi-dark); outline-offset: 2px; } .tileparent .pi-btn, .tileparent-list .pi-btn { min-height: 38px; font-size: 13px; padding: 8px 12px; } /* Modal shell */ #${MODAL_ID} .modal-dialog { width: auto; max-width: 560px; margin: 6vh auto; padding: 0 12px; } #${MODAL_ID} .modal-content { border: 0; border-radius: 14px; overflow: hidden; box-shadow: 0 24px 60px rgba(0, 0, 0, 0.4); } #${MODAL_ID} .pi-modal__header { display: flex; align-items: center; gap: 14px; padding: 20px 20px 20px 24px; background: var(--pi-dark); color: #ffffff; border-bottom: 4px solid var(--pi-accent); } #${MODAL_ID} .pi-modal__header::before, #${MODAL_ID} .pi-modal__header::after { display: none; } #${MODAL_ID} .pi-modal__badge { display: flex; align-items: center; justify-content: center; flex-shrink: 0; width: 44px; height: 44px; border-radius: 10px; background: var(--pi-accent); color: #ffffff; } #${MODAL_ID} .pi-modal__heading { display: flex; flex-direction: column; gap: 4px; flex: 1; min-width: 0; } #${MODAL_ID} .pi-modal__title { margin: 0; padding: 0; font-size: 20px; font-weight: 700; line-height: 1.2; text-align: left; color: #ffffff; } #${MODAL_ID} .pi-modal__product { overflow: hidden; font-size: 13px; color: var(--pi-muted); white-space: nowrap; text-overflow: ellipsis; } #${MODAL_ID} .pi-modal__close { display: flex; align-items: center; justify-content: center; flex-shrink: 0; width: 44px; height: 44px; padding: 0; background: transparent; border: 1px solid #3a3a3a; border-radius: 10px; color: #ffffff; cursor: pointer; transition: background-color 0.15s; } #${MODAL_ID} .pi-modal__close:hover { background: #262626; } #${MODAL_ID} .pi-modal__close:focus-visible { outline: 3px solid var(--pi-accent); outline-offset: 2px; } #${MODAL_ID} .pi-modal__body { padding: 20px 24px 24px; } /* Form layout */ #${MODAL_ID} form.product-inquiry-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; } #${MODAL_ID} form.product-inquiry-form > * { grid-column: 1 / -1; margin: 0; } #${MODAL_ID} form.product-inquiry-form > .pi-half { grid-column: auto; } #${MODAL_ID} .form-group { margin: 0; } #${MODAL_ID} .form-group > br { display: none; } /* Read-only product summary */ #${MODAL_ID} .pi-product-box { display: grid; grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); gap: 12px; padding: 12px 14px; border-radius: 10px; background: #f4f4f2; } #${MODAL_ID} .pi-product-box input[readonly] { background: #ffffff; border-color: transparent; color: var(--pi-text); cursor: default; } #${MODAL_ID} .pi-product-box input[readonly]:focus { box-shadow: none; border-color: var(--pi-border); } /* Fields */ #${MODAL_ID} label { display: block; margin: 0 0 6px; font-size: 13px; font-weight: 600; color: var(--pi-dark); } #${MODAL_ID} input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="submit"]):not([type="button"]), #${MODAL_ID} select, #${MODAL_ID} textarea:not(.g-recaptcha-response) { width: 100%; max-width: 100%; height: 44px; box-sizing: border-box; padding: 0 12px; border: 1px solid var(--pi-border); border-radius: 8px; background: #ffffff; color: var(--pi-dark); font: inherit; font-size: 15px; box-shadow: none; transition: border-color 0.15s, box-shadow 0.15s; } #${MODAL_ID} textarea:not(.g-recaptcha-response) { height: auto; min-height: 110px; padding: 10px 12px; resize: vertical; } #${MODAL_ID} input:focus, #${MODAL_ID} select:focus, #${MODAL_ID} textarea:focus { outline: none; border-color: var(--pi-accent); box-shadow: 0 0 0 4px var(--pi-accent-ring); } /* Submit */ #${MODAL_ID} [type="submit"] { display: flex; align-items: center; justify-content: center; gap: 8px; width: 100%; height: 50px; margin-top: 14px; padding: 0 20px; border: 0; border-radius: 10px; background: var(--pi-accent); color: #ffffff; font: inherit; font-size: 18px; font-weight: 700; text-shadow: none; box-shadow: none; cursor: pointer; transition: filter 0.15s; } #${MODAL_ID} [type="submit"]:hover { filter: brightness(0.92); color: #ffffff; } #${MODAL_ID} [type="submit"]:focus-visible { outline: 3px solid var(--pi-dark); outline-offset: 2px; } #${MODAL_ID} .response-message { margin: 0; border-radius: 8px; } /* Responsive */ @media only screen and (max-width: 767px) { #${MODAL_ID} input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="submit"]):not([type="button"]), #${MODAL_ID} select, #${MODAL_ID} textarea:not(.g-recaptcha-response) { font-size: 16px; } } @media only screen and (max-width: 600px) { #${MODAL_ID} .modal-dialog { margin: 12px auto; } #${MODAL_ID} .pi-modal__header { padding: 16px 16px 16px 18px; gap: 12px; } #${MODAL_ID} .pi-modal__badge { width: 38px; height: 38px; } #${MODAL_ID} .pi-modal__title { font-size: clamp(1.05rem, 4.5vw, 1.25rem); } #${MODAL_ID} .pi-modal__body { padding: 18px; } } @media only screen and (max-width: 500px) { #${MODAL_ID} form.product-inquiry-form > .pi-half { grid-column: 1 / -1; } #${MODAL_ID} .pi-product-box { grid-template-columns: minmax(0, 1fr); } } @media only screen and (max-width: 400px) { #${MODAL_ID} .pi-modal__badge { display: none; } #${MODAL_ID} .g-recaptcha { transform: scale(0.85); transform-origin: 0 0; height: 66px; } } @media (prefers-reduced-motion: reduce) { .pi-btn, #${MODAL_ID} input, #${MODAL_ID} textarea, #${MODAL_ID} select { transition: none; } }`; if (!document.getElementById(STYLE_ID)) { const style = document.createElement("style"); style.id = STYLE_ID; style.textContent = css; document.head.append(style); } /* ---------- 2. Modal (Bootstrap 3 markup) ---------- */ const chatIcon = ``; const closeIcon = ``; document.body.insertAdjacentHTML( "beforeend", ``, ); const modal = document.getElementById(MODAL_ID); const productLine = modal.querySelector(".pi-modal__product"); /* ---------- 3. Move the form into the modal and lay it out ---------- */ modal.querySelector(".modal-body").append(form); form.classList.remove("hide"); const fieldGroup = (name) => { const field = form.querySelector(`[name="${name}"]`); return field ? field.closest(".form-group") : null; }; const titleInput = form.querySelector('[name="product_title"]'); const skuInput = form.querySelector('[name="sku"]'); const titleGroup = fieldGroup("product_title"); const skuGroup = fieldGroup("sku"); // Product title + item code are filled in automatically, so show them as a read-only summary if (titleGroup && skuGroup) { const productBox = document.createElement("div"); productBox.className = "pi-product-box"; titleGroup.before(productBox); productBox.append(titleGroup, skuGroup); } if (titleInput) titleInput.readOnly = true; if (skuInput) skuInput.readOnly = true; ["name", "business", "phone", "email"].forEach((name) => { const group = fieldGroup(name); if (group) group.classList.add("pi-half"); }); /* ---------- 4. Work out a product's title + item code ---------- */ const cleanText = (text) => (text || "").replace(/\s+/g, " ").trim(); const getProductInfo = (group) => { const container = group.closest("[data-sku]"); const sku = container ? cleanText(container.dataset.sku) : ""; // Grid / list tiles have a .product-name const nameEl = container ? container.querySelector(".product-name") : null; let title = nameEl ? cleanText(nameEl.textContent) : ""; // Product page: EvoX exposes the current product on $evodata if (!title) { const view = window.$evodata && window.$evodata.products && window.$evodata.products.view; if (view && (!sku || view.sku === sku)) title = cleanText(view.name); } // Last resort on a product page: the page heading if (!title) { const heading = document.querySelector("h1"); title = heading ? cleanText(heading.textContent) : ""; } return { title, sku }; }; /* ---------- 5. Add a button after Add to cart in every .buttons.group ---------- */ const addButtons = () => { let added = 0; document.querySelectorAll(".buttons.group:not([data-pi-ready])").forEach((group) => { group.setAttribute("data-pi-ready", ""); // Skip Quick View and other modals if (group.closest(".modal")) return; const cartButton = group.querySelector(".btn-add-to-cart") || Array.from(group.querySelectorAll(".btn")).pop(); if (!cartButton) return; const { title, sku } = getProductInfo(group); const button = document.createElement("button"); button.type = "button"; button.className = "pi-btn"; button.textContent = BUTTON_LABEL; button.dataset.piTitle = title; button.dataset.piSku = sku; button.setAttribute("data-toggle", "modal"); button.setAttribute("data-target", `#${MODAL_ID}`); button.setAttribute("aria-haspopup", "dialog"); cartButton.insertAdjacentElement("afterend", button); added += 1; }); // Let the theme's equal-height tiles recalculate with the new button in place if (added) window.dispatchEvent(new Event("resize")); }; addButtons(); // Tiles loaded later (pagination, filters, AJAX) get a button too let scanQueued = false; const observer = new MutationObserver(() => { if (scanQueued) return; scanQueued = true; requestAnimationFrame(() => { scanQueued = false; addButtons(); }); }); observer.observe(document.body, { childList: true, subtree: true }); /* ---------- 6. Fill the form for the clicked product ---------- */ const setValue = (input, value) => { if (!input) return; input.value = value; input.dispatchEvent(new Event("input", { bubbles: true })); input.dispatchEvent(new Event("change", { bubbles: true })); }; let lastSku = null; document.addEventListener("click", (event) => { const button = event.target.closest(".pi-btn"); if (!button) return; const title = button.dataset.piTitle || ""; const sku = button.dataset.piSku || ""; setValue(titleInput, title); setValue(skuInput, sku); productLine.textContent = title; // Clear an old success/error message when switching to a different product if (lastSku !== null && lastSku !== sku) { const response = form.querySelector(".response-message"); if (response) response.classList.add("hide"); } lastSku = sku; }); /* ---------- 7. Focus the first field the customer needs to fill ---------- */ if (window.jQuery) { window.jQuery(modal).on("shown.bs.modal", () => { const firstField = form.querySelector('[name="name"]') || form.querySelector("textarea"); if (firstField) firstField.focus(); }); } }); /* ===== End ===== */