/* TABBY */ (function() { const INSTALLMENTS = 4; const FREQUENTLY_BOUGHT_TITLE = { ar: 'قد يعجبك أيضاً', en: 'You may also like' }; function findInShadow(root, selector) { if (!root) return null; const light = root.querySelector(selector); if (light) return light; const sr = root.shadowRoot; if (sr) { const inShadow = sr.querySelector(selector); if (inShadow) return inShadow; const allEls = sr.querySelectorAll('*'); for (const el of allEls) { if (el.shadowRoot) { const deep = findInShadow(el, selector); if (deep) return deep; } } } return null; } const COMPANIES = [{ key: 'tamara', name: { ar: 'تمارا', en: 'Tamara' }, logo: 'https://nussuq-dev.com/sonbol/tamara.webp', findTarget: sallaEl => { const tamaraWidget = sallaEl.querySelector('tamara-widget'); if (!tamaraWidget) return null; const learnMore = findInShadow(tamaraWidget, '.tamara-inline-learn-more-link'); if (learnMore) return learnMore; return tamaraWidget; } , }, { key: 'tabby', name: { ar: 'تابي', en: 'Tabby' }, logo: 'https://nussuq-dev.com/sonbol/tabby.png', findTarget: sallaEl => { const newTarget = sallaEl.querySelector('[data-test="widget-learn-more"]'); if (newTarget) return newTarget; const wrap = sallaEl.querySelector('#tabbyPromo') || document.querySelector('#tabbyPromo'); if (!wrap) return null; const portal = wrap.querySelector('span.styles__containerPortal--c9f84'); if (!portal) return null; const lightTarget = portal.querySelector('[data-test="widget-learn-more"]'); if (lightTarget) return lightTarget; return portal.shadowRoot ? portal.shadowRoot.querySelector('[data-test="widget-learn-more"]') : null; } , }, ]; const TEXT = { ar: (n, amount) => `${n} دفعات بدون فوائد بقيمة ${amount} `, en: (n, amount) => `${n} interest-free payments of ${amount} SAR`, }; function getLang() { const lang = (document.documentElement.lang || '').toLowerCase(); return lang.startsWith('ar') || document.body.classList.contains('rtl') ? 'ar' : 'en'; } const fmt = n => Number.isInteger(n) ? String(n) : n.toFixed(2); function dispatchClick(el) { try { el.click(); } catch (e) {} try { el.dispatchEvent(new MouseEvent('click',{ bubbles: false, cancelable: true, composed: false, view: window, })); } catch (e) {} } function buildWidget(price, lang, sallaEl) { const isRTL = lang === 'ar'; const per = fmt(Math.round((price / INSTALLMENTS) * 100) / 100); const wrap = document.createElement('div'); wrap.id = 'drs-inst-widget'; wrap.style.cssText = `direction:${isRTL ? 'rtl' : 'ltr'};margin:8px 0;`; wrap.innerHTML = `
${COMPANIES.map(c => ` `).join('')}
${TEXT[lang](INSTALLMENTS, per)}
`; wrap.querySelectorAll('.drs-logo-card').forEach(card => { card.addEventListener('click', e => { e.preventDefault(); e.stopPropagation(); const company = COMPANIES.find(c => c.key === card.dataset.provider); const target = company && company.findTarget(sallaEl); if (target) dispatchClick(target); } ); } ); return wrap; } function injectInstallment() { if (document.getElementById('drs-inst-widget')) return; const sallaEl = document.querySelector('salla-installment'); if (!sallaEl) return; let price = parseFloat(sallaEl.getAttribute('price') || '0'); if (!price) { const tamaraWidget = sallaEl.querySelector('tamara-widget'); price = parseFloat(tamaraWidget?.getAttribute('amount') || '0'); } if (!price) return; sallaEl.style.cssText = 'position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);opacity:0;'; sallaEl.parentNode.insertBefore(buildWidget(price, getLang(), sallaEl), sallaEl.nextSibling); } function patchFrequentlyBought() { const newTitle = FREQUENTLY_BOUGHT_TITLE[getLang()]; if (!newTitle) return; document.querySelectorAll('h2,h3,p,span').forEach(el => { if (!el.dataset.drsPatched && !el.children.length && el.textContent.trim() === 'عادة ما يتم شراؤه مع') { el.textContent = newTitle; el.dataset.drsPatched = '1'; } } ); } function run() { injectInstallment(); patchFrequentlyBought(); } new MutationObserver(run).observe(document.body, { childList: true, subtree: true }); document.readyState === 'loading' ? document.addEventListener('DOMContentLoaded', run) : run(); setTimeout(run, 1000); setTimeout(run, 2500); } )(); // ─── Product Page Countdown Timer ─────────────────────────────────────────── (function () { "use strict"; const CONFIG = { duration: 27 * 60, storageKey: "salla_product_countdown_end", labelAr: "ينتهي العرض خلال", labelEn: "Offer ends in", // ── Icons (SVG strings) ────────────────────────────────────────────── // Replace any string here to change the icon. // Set to '' to hide the icon entirely. icons: { clock: ` `, }, }; function isRTL() { return ( document.documentElement.dir === "rtl" || document.documentElement.lang === "ar" ); } function injectStyles() { if (document.getElementById("countdown-timer-styles")) return; const style = document.createElement("style"); style.id = "countdown-timer-styles"; style.textContent = ` .countdown-timer-wrapper { background: #D11D1D10 !important; font-size: 15px; line-height: 4; padding: 0 !important; font-weight: 600; color: #1a1a1a; padding: 0; justify-content: flex-start; height:50px; border-radius: 10px; overflow: hidden; } .countdown-label { display: flex; align-items: flex-start; gap: 0; color: #000; border-radius: 0 6px 6px 0; overflow: hidden; } .countdown-label span {display:none} .countdown-label .countdown-icon { color: #fff; background: #D11D1D; width: 4rem; display: flex; align-items: center; justify-content: center; font-size: 2rem; line-height: 4rem !important; margin: 0; height:100%; } .countdown-label .countdown-icon svg { display: block; width: 1.4rem; height: 1.4rem; } .countdown-display { display: inline-flex; align-items: anchor-center; gap: 4px; direction: ltr; font-variant-numeric: tabular-nums; color: #1a202c; font-weight: 600; font-size: 15px; line-height: 1; margin: 0 1rem;} .countdown-display span { min-width: 40px; text-align: center; font-size: 1.3rem; } .countdown-separator { color: #a0aec0; } `; document.head.appendChild(style); } function buildIconHTML(svgString) { if (!svgString || !svgString.trim()) return ""; return `${svgString.trim()}`; } function createCountdownElement() { const wrapper = document.createElement("div"); wrapper.className = "countdown-timer-wrapper mb-4 flex justify-between sm:grid sm:grid-cols-3 bg-white rounded-md"; wrapper.setAttribute("data-countdown-timer", "true"); wrapper.innerHTML = `
${buildIconHTML(CONFIG.icons.clock)} ${isRTL() ? CONFIG.labelAr : CONFIG.labelEn}
00:30:00
`; return wrapper; } function findTargetElement() { const barcodeIcons = document.querySelectorAll(".sicon-barcode"); for (const icon of barcodeIcons) { const parentDiv = icon.closest(".mb-4.flex.justify-between"); if (parentDiv) return parentDiv; } return null; } function findInstallmentElement() { return document.querySelector( "salla-installment, .salla-installment, [data-salla-installment]", ); } function insertCountdown() { if (document.querySelector("[data-countdown-timer]")) return true; const installment = findInstallmentElement(); const target = findTargetElement(); if (!installment && !target) return false; injectStyles(); const countdown = createCountdownElement(); if (installment && installment.parentNode) { installment.parentNode.insertBefore(countdown, installment); } else { target.parentNode.insertBefore(countdown, target.nextSibling); } startTimer(); return true; } function getEndTime() { let endTime = parseInt(localStorage.getItem(CONFIG.storageKey), 10); const now = Date.now(); if (!endTime || endTime <= now) { endTime = now + CONFIG.duration * 1000; localStorage.setItem(CONFIG.storageKey, endTime.toString()); } return endTime; } function updateDisplay() { const hoursEl = document.querySelector(".countdown-hours"); const minutesEl = document.querySelector(".countdown-minutes"); const secondsEl = document.querySelector(".countdown-seconds"); if (!hoursEl || !minutesEl || !secondsEl) return; const endTime = getEndTime(); const now = Date.now(); const remaining = Math.max(0, Math.floor((endTime - now) / 1000)); const hours = Math.floor(remaining / 3600); const minutes = Math.floor((remaining % 3600) / 60); const seconds = remaining % 60; hoursEl.textContent = String(hours).padStart(2, "0"); minutesEl.textContent = String(minutes).padStart(2, "0"); secondsEl.textContent = String(seconds).padStart(2, "0"); if (remaining <= 0) { localStorage.removeItem(CONFIG.storageKey); } } let timerInterval = null; function startTimer() { if (timerInterval) clearInterval(timerInterval); updateDisplay(); timerInterval = setInterval(updateDisplay, 1000); } function init() { if (insertCountdown()) return; const observer = new MutationObserver(function (mutations, obs) { if (insertCountdown()) { obs.disconnect(); } }); observer.observe(document.body, { childList: true, subtree: true, }); setTimeout(() => observer.disconnect(), 10000); } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", init); } else { init(); } })(); // ─── Cart Discount Timer (Standalone) ─────────────────────────────────────── (function () { "use strict"; var DURATION = 10 * 60 * 1000; var STORAGE_KEY = "discountTimerEnd"; var TIMER_ID = "cart-page-discount-timer"; var interval = null; var endTime = null; // ─── Styles ─────────────────────────────────────────────────────────────── function addStyles() { if (document.getElementById("cart-timer-styles")) return; var s = document.createElement("style"); s.id = "cart-timer-styles"; s.textContent = ".s-cart-coupons-wrapper{padding-bottom:0!important}" + "#" + TIMER_ID + "{margin:.25rem 0}" + ".dt-row{display:flex;align-items:baseline;gap:6px;flex-wrap:wrap}" + ".dt-label{font-size:14px;opacity:.75;white-space:nowrap}" + ".dt-display{display:inline-flex;align-items:baseline;gap:1px;direction:ltr}" + ".dt-value{font-size:14px;color:#dc2626;font-variant-numeric:tabular-nums}" + ".dt-colon{font-size:14px;color:#dc2626;animation:dt-blink 1s step-end infinite}" + "@keyframes dt-blink{0%,100%{opacity:1}50%{opacity:0}}"; document.head.appendChild(s); } // ─── Page detection ─────────────────────────────────────────────────────── function isCartPage() { return /(^|\/)cart(\/|$)/i.test(window.location.pathname); } // ─── DOM injection ──────────────────────────────────────────────────────── function inject() { if (document.getElementById(TIMER_ID)) return; var anchors = [ ".s-cart-coupons-wrapper", ".s-cart-summary-coupon-wrapper", "#coupon-input", "#total-discount", ".discounted", ".cart-summary", ]; var anchor = null; for (var i = 0; i < anchors.length; i++) { anchor = document.querySelector(anchors[i]); if (anchor) break; } var html = ''; if (anchor) anchor.insertAdjacentHTML("afterend", html); else document.body.insertAdjacentHTML("beforeend", html); } // ─── Display helpers ────────────────────────────────────────────────────── function setDisplay(m, s) { var me = document.getElementById("cart-timer-minutes"); var se = document.getElementById("cart-timer-seconds"); if (me) me.textContent = String(m).padStart(2, "0"); if (se) se.textContent = String(s).padStart(2, "0"); } function setVisible(v) { var el = document.getElementById(TIMER_ID); if (el) el.style.display = v ? "block" : "none"; } // ─── Timer logic ────────────────────────────────────────────────────────── function tick() { if (!endTime) return; var rem = endTime - Date.now(); if (rem <= 0) { clearInterval(interval); interval = null; endTime = null; localStorage.removeItem(STORAGE_KEY); setDisplay(0, 0); return; } setDisplay(Math.floor(rem / 60000), Math.floor((rem % 60000) / 1000)); } function startTimer() { // If already running, don't restart if (interval && endTime) return; // Try to restore saved end time; otherwise start fresh var saved = parseInt(localStorage.getItem(STORAGE_KEY), 10); if (saved && saved - Date.now() > 0) { endTime = saved; } else { endTime = Date.now() + DURATION; localStorage.setItem(STORAGE_KEY, String(endTime)); } setVisible(true); tick(); interval = setInterval(tick, 1000); } function stopTimer() { if (interval) { clearInterval(interval); interval = null; } endTime = null; localStorage.removeItem(STORAGE_KEY); setVisible(false); } // ─── Coupon state detection ─────────────────────────────────────────────── function hasActiveCoupon(cart) { if (cart) { return Boolean(cart.coupon) && Number(cart.total_discount || 0) > 0; } // Fallback: inspect DOM var el = document.querySelector("#total-discount b") || document.querySelector(".discounted b") || document.getElementById("total-discount"); return /[-−]\s*\d/.test((el && el.textContent) || ""); } function fetchCart() { if (typeof salla === "undefined" || !salla.cart || !salla.cart.details) { return Promise.resolve(null); } return salla.cart .details() .then(function (r) { return (r && r.data && r.data.cart) || (r && r.data) || r; }) .catch(function () { return null; }); } function sync() { inject(); fetchCart().then(function (cart) { if (hasActiveCoupon(cart)) startTimer(); else if (interval || endTime || localStorage.getItem(STORAGE_KEY)) stopTimer(); }); } // ─── Initialization ─────────────────────────────────────────────────────── function init() { if (typeof salla === "undefined") return; salla.onReady().then(function () { if (!isCartPage()) return; addStyles(); inject(); // Bind to cart events if (salla.cart && salla.cart.event) { ["onDetailsFetched", "onItemAdded", "onItemUpdated", "onItemDeleted"].forEach( function (m) { if (typeof salla.cart.event[m] === "function") { salla.cart.event[m](sync); } } ); } // Bind to coupon events if (salla.event) { salla.event.on("cart::coupon.applied", function () { setTimeout(sync, 300); }); salla.event.on("cart::coupon.removed", stopTimer); } // Initial sync setTimeout(sync, 500); }); } if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", init, { once: true }); } else { setTimeout(init, 0); } })();