if (!window.Giftify) { window.Giftify = { checkoutButton: false, validationErrors: {}, init: function() { this.reset(); this.insertStyle(); this.initiateButton(); }, reset: function() { var xhr = new XMLHttpRequest(); xhr.open('POST', window.Shopify.routes.root + 'cart/update.js'); xhr.setRequestHeader('Content-Type', 'application/json;charset=UTF-8'); xhr.send(JSON.stringify({ attributes: { 'Giftify • To': '', 'Giftify • From': '', 'Giftify • Message': '' } })); }, insertStyle: function() { var head = document.head || document.getElementsByTagName('head')[0], style = document.createElement('style'); style.type = 'text/css'; var validationCSS = '.giftify-popup__field--error input, .giftify-popup__field--error textarea { border-color: #dc3545; } .giftify-popup__error { color: #dc3545; font-size: 12px; margin-top: 4px; display: none; } .giftify-popup__field--error .giftify-popup__error { display: block; }'; style.appendChild(document.createTextNode("\n .giftify-wrapper { width: 100% }\n .giftify-button { \n margin: 5px 0px 25px 0px; \n display: inline-block;\n transition: all .2s ease;\n }\n a.giftify-button,\n .giftify-button[role=\"button\"] {\n text-decoration: none;\n }\n /* Mini cart specific alignment - scoped to cart drawer/mini cart only */\n .cart-drawer .giftify-button-container,\n .mini-cart .giftify-button-container,\n [class*=\"cart-drawer\"] .giftify-button-container,\n [class*=\"mini-cart\"] .giftify-button-container {\n width: 100%;\n display: block;\n margin-bottom: 10px;\n }\n .cart-drawer .giftify-actions-container,\n .mini-cart .giftify-actions-container,\n [class*=\"cart-drawer\"] .giftify-actions-container,\n [class*=\"mini-cart\"] .giftify-actions-container {\n width: 100%;\n display: flex;\n gap: 10px;\n }\n .cart-drawer .giftify-actions-container > *,\n .mini-cart .giftify-actions-container > *,\n [class*=\"cart-drawer\"] .giftify-actions-container > *,\n [class*=\"mini-cart\"] .giftify-actions-container > * {\n flex: 1;\n }\n .cart-drawer .giftify-button-container .giftify-button,\n .mini-cart .giftify-button-container .giftify-button,\n [class*=\"cart-drawer\"] .giftify-button-container .giftify-button,\n [class*=\"mini-cart\"] .giftify-button-container .giftify-button {\n display: block;\n width: 100%;\n box-sizing: border-box;\n }\n .giftify-button span {\n background: #781033;\n color: #ffffff;\n border-radius: 50px;\n border: 2px solid #781033;\n padding: 10px 20px 10px 20px; \n display: flex;\n white-space: nowrap;\n transition: all .2s ease;\n align-items: center;\n justify-content: center;\n }\n .giftify-button svg { \n fill: #ffffff;\n display: inline-block; \n margin-right: 5px;\n width: 24px;\n height: 24px;\n transition: all .2s ease;\n }\n .giftify-button:hover span {\n background: #781033;\n color: #ffffff;\n border-color: #781033;\n }\n .giftify-button:hover svg {\n fill: #ffffff;\n }\n .giftify-popup {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 999;\n opacity: 0;\n visibility: hidden;\n pointer-events: none;\n transition: all .5s ease;\n }\n .giftify-popup.giftify-popup--loading {\n pointer-events: none;\n }\n .giftify-popup.giftify-popup--active {\n opacity: 1;\n visibility: visible;\n pointer-events: all;\n }\n .giftify-popup.giftify-popup--active .giftify-popup__inside {\n transition-delay: .3s;\n opacity: 1;\n margin-top: 0;\n }\n .giftify-popup .giftify-popup__bg {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0,0,0,.6);\n z-index: 1;\n display: block;\n }\n .giftify-popup__inside {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n background: #fff;\n width: 90%;\n max-width: 460px;\n display: flex;\n align-items: stretch;\n z-index: 2;\n transition: margin .5s Cubic-bezier(0.3, 0, 0.3, 1), opacity .3s ease;\n margin-top: 50px;\n opacity: 0;\n }\n .giftify-popup__close {\n position: absolute;\n top: 0;\n right: 0;\n width: 48px;\n height: 48px;\n z-index: 3;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n .giftify-popup__close svg {\n fill: #191919;\n width: 24px;\n }\n .giftify-popup__grid {\n display: flex;\n width: 100%;\n flex-wrap: nowrap;\n }\n .giftify-popup .giftify-popup__right {\n width: 50%;\n display: block;\n background-size: cover;\n background-position: center;\n background-repeat: no-repeat;\n }\n .giftify-popup__left {\n width: 100%;\n padding: 50px 50px 75px;\n position: relative;\n }\n .giftify-popup__header {\n text-align: center;\n }\n .giftify-popup__header img {\n max-height: 50px;\n }\n .giftify-popup__title {\n color: #191919;\n font-size: 32px;\n margin: 20px 0;\n }\n .giftify-popup__steps + div {\n font-size: 13px;\n position: absolute;\n left: 0;\n width: 100%;\n bottom: 10px;\n text-align: center;\n }\n .giftify-popup__steps + div a {\n color: #191919;\n border-bottom: 1px solid transparent;\n }\n .giftify-popup__steps + div a:hover {\n border-bottom-color: #191919;\n }\n .giftify-popup__step {\n display: none;\n }\n .giftify-popup__step--active {\n display: block;\n }\n .giftify-popup__action {\n margin-top: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n .giftify-popup .giftify-popup__button { \n margin: 5px; \n display: inline-block;\n transition: all .2s ease;\n padding: 0;\n border: 0;\n cursor: pointer;\n }\n .giftify-popup button.giftify-popup__button,\n .giftify-popup .giftify-popup__button[type=\"button\"],\n .giftify-popup .giftify-popup__button[type=\"submit\"] {\n border-radius: 0;\n background: none;\n }\n .giftify-popup__button span {\n border-radius: 50px;\n padding: 10px 20px 10px 20px; \n display: flex;\n white-space: nowrap;\n transition: all .2s ease;\n position: relative;\n }\n .giftify-popup__next span {\n background: #781033;\n color: #ffffff;\n border: 2px solid #781033;\n position: relative;\n }\n .giftify-popup__next:hover span {\n background: #ffffff;\n color: #781033;\n border-color: #781033;\n }\n .giftify-popup__prev span {\n background: #ffffff;\n color: #781033;\n border: 2px solid #d2d2d2;\n }\n .giftify-popup__prev:hover span {\n background: #d2d2d2;\n color: #191919;\n border-color: #d2d2d2;\n }\n .giftify-popup__next span::after {\n content: \"\";\n position: absolute;\n top: 50%;\n left: 50%;\n width: 20px;\n height: 20px;\n border: 3px solid #ffffff;\n border-top: 3px solid transparent!important;\n border-radius: 50%;\n margin-left: -10px;\n margin-top: -10px;\n opacity: 0;\n -webkit-animation: giftify_spin .7s linear infinite;\n animation: giftify_spin .7s linear infinite;\n }\n @-webkit-keyframes giftify_spin { \n 100% { -webkit-transform: rotate(360deg); } \n }\n @keyframes giftify_spin { \n 100% { \n -webkit-transform: rotate(360deg); \n transform:rotate(360deg); \n } \n }\n .giftify-popup__step ol {\n counter-reset: giftify;\n list-style: none;\n padding: 0;\n }\n .giftify-popup__step li {\n color: #191919;\n font-size: 16px;\n counter-increment: giftify;\n position: relative;\n padding-left: 30px;\n display: block;\n }\n .giftify-popup__step li + li {\n margin-top: 5px;\n }\n .giftify-popup__step li::before {\n content: counter(giftify)\".\";\n font-weight: bold;\n top: 0;\n left: 0;\n position: absolute;\n }\n .giftify-popup__label { \n font-weight: bold;\n text-align: center;\n }\n .giftify-popup__field {\n margin: 5px 0 10px;\n }\n .giftify-popup__grid > .giftify-popup__field {\n width: 50%;\n padding-right: 2px;\n }\n .giftify-popup__grid > .giftify-popup__field + .giftify-popup__field {\n padding-left: 2px;\n }\n .giftify-popup__field > * {\n width: 100%;\n }\n .giftify-popup__field input,\n .giftify-popup__field textarea {\n padding: 10px;\n border: 1px solid #d2d2d2;\n }\n .giftify-popup--loading .giftify-popup__next span {\n color: transparent!important;\n }\n .giftify-popup--loading .giftify-popup__next span::after {\n opacity: 1;\n }\n @media (max-width: 768px) {\n .giftify-popup .giftify-popup__inside {\n width: 95%;\n max-width: 95%;\n max-height: 90vh;\n overflow-y: auto;\n top: 50%;\n transform: translate(-50%, -50%);\n -webkit-overflow-scrolling: touch;\n }\n .giftify-popup .giftify-popup__grid {\n flex-direction: column;\n display: flex;\n }\n .giftify-popup .giftify-popup__left {\n width: 100%;\n padding: 30px 20px 50px;\n flex: 1 1 auto;\n }\n .giftify-popup .giftify-popup__right {\n width: 100%;\n min-height: 200px;\n order: -1;\n flex: 0 0 auto;\n }\n .giftify-popup__title {\n font-size: 24px;\n margin: 15px 0;\n line-height: 1.3;\n }\n .giftify-popup__step li {\n font-size: 14px;\n line-height: 1.5;\n }\n .giftify-popup .giftify-popup__grid > .giftify-popup__field {\n width: 100%;\n padding-right: 0;\n padding-left: 0;\n }\n .giftify-popup .giftify-popup__grid > .giftify-popup__field + .giftify-popup__field {\n padding-left: 0;\n margin-top: 10px;\n }\n .giftify-popup .giftify-popup__action {\n flex-direction: column;\n gap: 10px;\n }\n .giftify-popup .giftify-popup__button {\n width: 100%;\n margin: 0;\n }\n .giftify-popup__button span {\n width: 100%;\n justify-content: center;\n }\n .giftify-popup__close {\n width: 44px;\n height: 44px;\n min-width: 44px;\n min-height: 44px;\n }\n .giftify-popup__close svg {\n width: 20px;\n }\n }\n @media (max-width: 480px) {\n .giftify-popup .giftify-popup__inside {\n width: 100%;\n max-width: 100%;\n max-height: calc(100vh - env(safe-area-inset-top) - env(safe-area-inset-bottom));\n border-radius: 0;\n top: 50%;\n transform: translate(-50%, -50%);\n }\n .giftify-popup .giftify-popup__left {\n padding: 25px 20px 50px;\n padding-top: max(25px, env(safe-area-inset-top));\n padding-bottom: max(50px, env(safe-area-inset-bottom));\n padding-left: max(20px, env(safe-area-inset-left));\n padding-right: max(20px, env(safe-area-inset-right));\n }\n .giftify-popup .giftify-popup__right {\n min-height: 180px;\n max-height: 40vh;\n width: 100%;\n }\n .giftify-popup__title {\n font-size: 22px;\n margin: 12px 0;\n line-height: 1.3;\n }\n .giftify-popup__step li {\n font-size: 14px;\n padding-left: 28px;\n line-height: 1.6;\n margin-bottom: 8px;\n }\n .giftify-popup__step li + li {\n margin-top: 8px;\n }\n .giftify-popup__field input,\n .giftify-popup__field textarea {\n padding: 12px;\n font-size: 16px;\n -webkit-appearance: none;\n border-radius: 4px;\n }\n .giftify-popup .giftify-popup__button {\n min-height: 44px;\n width: 100%;\n }\n .giftify-popup .giftify-popup__button span {\n min-height: 44px;\n width: 100%;\n padding-top: 12px;\n padding-bottom: 12px;\n }\n .giftify-popup .giftify-popup__close {\n top: max(10px, env(safe-area-inset-top));\n right: max(10px, env(safe-area-inset-right));\n width: 44px;\n height: 44px;\n }\n .giftify-popup__header {\n margin-bottom: 20px;\n }\n .giftify-popup__header img {\n max-height: 40px;\n }\n .giftify-popup__label {\n margin-top: 15px;\n margin-bottom: 8px;\n font-size: 14px;\n }\n .giftify-popup__action {\n margin-top: 25px;\n gap: 12px;\n }\n }\n .giftify-popup__giftwrap {\n margin: 20px 0;\n padding: 15px;\n background: #f8f9fa;\n border-radius: 8px;\n border: 1px solid #e0e0e0;\n }\n .giftify-popup__giftwrap-label {\n display: flex;\n align-items: flex-start;\n cursor: pointer;\n user-select: none;\n }\n .giftify-popup__giftwrap-label input[type=\"checkbox\"] {\n margin: 3px 10px 0 0;\n width: 18px;\n height: 18px;\n cursor: pointer;\n flex-shrink: 0;\n }\n .giftify-popup__giftwrap-text {\n font-size: 16px;\n font-weight: 500;\n color: #191919;\n display: block;\n margin-bottom: 4px;\n }\n .giftify-popup__giftwrap-desc {\n font-size: 13px;\n color: #6c757d;\n display: block;\n }\n @media (max-width: 390px) {\n .giftify-popup .giftify-popup__left {\n padding: 20px 18px 45px;\n }\n .giftify-popup .giftify-popup__title {\n font-size: 20px;\n margin: 10px 0;\n }\n .giftify-popup .giftify-popup__step li {\n font-size: 13px;\n padding-left: 26px;\n }\n .giftify-popup .giftify-popup__right {\n min-height: 160px;\n max-height: 35vh;\n width: 100%;\n }\n .giftify-popup .giftify-popup__grid {\n flex-direction: column;\n }\n }\n " + validationCSS)); head.appendChild(style); }, validateEmail: function(email) { const trimmedEmail = email.trim(); const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/; if (!emailRegex.test(trimmedEmail)) { return false; } if (trimmedEmail.endsWith('.')) { return false; } const parts = trimmedEmail.split('@'); if (parts.length !== 2) { return false; } const domain = parts[1]; const domainParts = domain.split('.'); if (domainParts.length < 2) { return false; } const tld = domainParts[domainParts.length - 1]; if (tld.length < 2 || !/^[a-zA-Z]+$/.test(tld)) { return false; } if (domainParts.some(part => part.length === 0)) { return false; } return true; }, validateField: function(field) { const fieldWrapper = field.closest('.giftify-popup__field'); const fieldName = field.name; const fieldValue = field.value.trim(); let isValid = true; let errorMessage = ''; fieldWrapper.classList.remove('giftify-popup__field--error'); this.validationErrors[fieldName] = null; if (!fieldValue && field.hasAttribute('required')) { isValid = false; errorMessage = 'This field is required'; } else if (field.type === 'email' && fieldValue && !this.validateEmail(fieldValue)) { isValid = false; errorMessage = 'Please enter a valid email address'; } if (!isValid) { fieldWrapper.classList.add('giftify-popup__field--error'); this.validationErrors[fieldName] = errorMessage; this.showFieldError(fieldWrapper, errorMessage); } else { this.hideFieldError(fieldWrapper); } return isValid; }, showFieldError: function(fieldWrapper, message) { let errorEl = fieldWrapper.querySelector('.giftify-popup__error'); if (!errorEl) { errorEl = document.createElement('div'); errorEl.className = 'giftify-popup__error'; fieldWrapper.appendChild(errorEl); } errorEl.textContent = message; }, hideFieldError: function(fieldWrapper) { const errorEl = fieldWrapper.querySelector('.giftify-popup__error'); if (errorEl) { errorEl.remove(); } }, validateForm: function(form) { const fields = form.querySelectorAll('input[required], input[type="email"], textarea[required]'); let isFormValid = true; fields.forEach(field => { if (!this.validateField(field)) { isFormValid = false; } }); return isFormValid; }, createWrappersForCheckoutButtons: function(checkoutButtons) { var self = this; if (!checkoutButtons || checkoutButtons.length === 0) return false; self.checkoutButton = checkoutButtons[0]; var needsRender = false; checkoutButtons.forEach(function(checkoutButton) { var existingWrapper = checkoutButton.parentNode.querySelector('.giftify-wrapper'); if (!existingWrapper) { var el = document.createElement('div'); el.classList.add('giftify-wrapper'); checkoutButton.parentNode.insertAfter(el, checkoutButton); needsRender = true; } }); return needsRender; }, checkWrappersForButtons: function() { var wrappers = document.querySelectorAll('.giftify-wrapper'); return Array.from(wrappers).some(function(wrapper) { return !wrapper.querySelector('a.giftify-button'); }); }, wrapActionButtons: function(wrapper) { var self = this; var parent = wrapper.parentNode; if (!parent) return; // Check if already wrapped if (parent.querySelector('.giftify-actions-container')) return; // Function to find and wrap buttons function findAndWrapButtons() { // Find checkout button var checkoutButton = window.Giftify.checkoutButton || parent.querySelector('[name="checkout"]'); // Find chat button - simple search var chatButton = parent.querySelector('[class*="chat" i], [id*="chat" i], [aria-label*="chat" i]'); if (!chatButton) { var allBtns = parent.querySelectorAll('button, a'); for (var j = 0; j < allBtns.length; j++) { var btn = allBtns[j]; var text = (btn.textContent || '').toLowerCase(); if (text.indexOf('chat') !== -1 && btn !== checkoutButton && !btn.closest('.giftify-wrapper')) { chatButton = btn; break; } } } // Only proceed if we have buttons to wrap if (!checkoutButton && !chatButton) return false; // Check if actions container already exists var actionsContainer = parent.querySelector('.giftify-actions-container'); if (actionsContainer) return true; // Create actions container actionsContainer = document.createElement('div'); actionsContainer.classList.add('giftify-actions-container'); if (wrapper.nextSibling) { parent.insertBefore(actionsContainer, wrapper.nextSibling); } else { parent.appendChild(actionsContainer); } // Move buttons to container if (checkoutButton && checkoutButton.parentNode === parent) { actionsContainer.appendChild(checkoutButton); } if (chatButton && chatButton !== checkoutButton && chatButton.parentNode === parent) { actionsContainer.appendChild(chatButton); } return true; } // Try immediately first if (findAndWrapButtons()) { return; // Successfully wrapped, no need for observer } // Use MutationObserver to watch for buttons appearing var observer = new MutationObserver(function(mutations) { if (findAndWrapButtons()) { observer.disconnect(); // Stop observing once buttons are wrapped } }); // Start observing the parent for child additions observer.observe(parent, { childList: true, subtree: true }); // Also check periodically as fallback (with timeout to prevent infinite watching) var checkCount = 0; var maxChecks = 20; // 20 checks = 10 seconds max var checkInterval = setInterval(function() { checkCount++; if (findAndWrapButtons() || checkCount >= maxChecks) { clearInterval(checkInterval); observer.disconnect(); } }, 500); }, initiateButton: function() { var self = this; // Function to try initializing the button function tryInitiateButton() { var wrappers = document.querySelectorAll('.giftify-wrapper'), checkoutButtons = document.querySelectorAll('[name="checkout"]'); if (wrappers.length) { self.renderButton(); return true; } else if (checkoutButtons.length) { if (self.createWrappersForCheckoutButtons(checkoutButtons)) { self.renderButton(); return true; } } return false; } // Try immediately if DOM is ready if (document.readyState === 'loading') { // Wait for DOM to be ready document.addEventListener('DOMContentLoaded', function() { if (!tryInitiateButton()) { // If button still not found, set up observer self.observeForCheckoutButton(); } }); } else { // DOM is already ready, try immediately if (!tryInitiateButton()) { // If button still not found, set up observer this.observeForCheckoutButton(); } } }, observeForCheckoutButton: function() { var self = this; // Wait for body to exist if it doesn't yet if (!document.body) { var bodyCheck = setInterval(function() { if (document.body) { clearInterval(bodyCheck); self.observeForCheckoutButton(); } }, 100); return; } // Variables for cleanup - defined here so both observer and interval can access them var checkInterval = null; var observer = null; // Function to handle checkout button found function handleCheckoutButtonsFound() { var checkoutButtons = document.querySelectorAll('[name="checkout"]'); if (checkoutButtons.length) { // Button found! Initialize it var needsRender = self.createWrappersForCheckoutButtons(checkoutButtons); if (needsRender) { self.renderButton(); cleanup(); // Stop both observer and interval return true; } else { // Check if wrappers exist but don't have buttons if (self.checkWrappersForButtons()) { self.renderButton(); cleanup(); // Stop both observer and interval return true; } } } return false; } // Use MutationObserver to watch for checkout buttons appearing observer = new MutationObserver(function(mutations) { handleCheckoutButtonsFound(); }); // Start observing the document body for changes observer.observe(document.body, { childList: true, subtree: true }); // Also check periodically as a fallback (in case observer misses it) checkInterval = setInterval(function() { handleCheckoutButtonsFound(); }, 500); // Create cleanup function using shared helper var cleanup = self.createObserverCleanup(observer, checkInterval); // Stop checking after 10 seconds to avoid infinite polling setTimeout(function() { cleanup(); // Stop both observer and interval }, 10000); }, renderButton: function(wrappers = null) { if (!wrappers) { wrappers = document.querySelectorAll('.giftify-wrapper'); } if (wrappers && wrappers.length) { // Check if button already exists globally to prevent duplication var existingButton = document.querySelector('a.giftify-button'); if (existingButton) return; // Button already exists, don't create duplicates // Only create button in the first wrapper that doesn't have one var firstWrapper = null; for (var i = 0; i < wrappers.length; i++) { if (!wrappers[i].querySelector('a.giftify-button')) { firstWrapper = wrappers[i]; break; } } if (firstWrapper) { // Create container for gift button var giftContainer = document.createElement('div'); giftContainer.classList.add('giftify-button-container'); var buttonEl = document.createElement('a'); buttonEl.href = '#'; buttonEl.setAttribute('role', 'button'); buttonEl.setAttribute('tabindex', '0'); var iconStrValue = ""; var buttonTextValue = "SEND AS A GIFT"; buttonEl.setAttribute('aria-label', buttonTextValue); var buttonContent = ''; buttonEl.innerHTML = buttonContent; buttonEl.classList.add('giftify-button'); buttonEl.addEventListener('click', window.Giftify.openPopup); buttonEl.addEventListener('keydown', function(e) { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); window.Giftify.openPopup(e); } }); giftContainer.appendChild(buttonEl); firstWrapper.appendChild(giftContainer); // Wrap checkout and chat buttons in actions container using MutationObserver this.wrapActionButtons(firstWrapper); } } if (!document.querySelector('.giftify-popup')) { var saved = { to: { name: '', email: '' }, from: { name: '', email: '' }, message: '', giftwrap: { checked: false } }; if (localStorage.getItem('giftify')) { saved = JSON.parse(localStorage.getItem('giftify')); } var popupHTML = "\n
\n