1(function(){ 2 3 var PTS_PER_DOLLAR = 20; 4 function esc(s){ return String(s == null ? "" : s).replace(/[&<>"]/g, function(ch){ return ({"&":"&","<":"<",">":">",'"':"""})[ch]; }); } 5 function api(action, body){ 6 return fetch("/apps/notpo?action=" + action, body ? { method:"POST", headers:{"Content-Type":"application/json"}, body: JSON.stringify(body) } : { credentials:"same-origin" }).then(function(r){ return r.json(); }); 7 } 8 function cartSubtotal(){ 9 return fetch("/cart.js", { credentials:"same-origin" }).then(function(r){ return r.json(); }).then(function(c){ return (c.items_subtotal_price || 0) / 100; }).catch(function(){ return 0; }); 10 } 11 function codeValue(c){ return Math.round(c.points_spent / PTS_PER_DOLLAR); } 12 function applyUrl(code, to){ return "/discount/" + encodeURIComponent(code) + "?redirect=" + (to || "/cart"); } 13 14 if (window.__notpoCart) return; window.__notpoCart = true; 15 var css = document.createElement("style"); 16 css.textContent = ".notpo-cp{margin:0 0 12px;padding:14px 16px;border:2px dashed #9fcac3;border-radius:12px;background:#e6f4f1;color:#12302c;font-size:14px;line-height:1.4;text-align:left}.notpo-cp button{font:inherit;cursor:pointer;border:0;border-radius:999px;padding:10px 16px;margin-top:8px;width:100%;background:#0f766e;color:#fff}.notpo-cp button:disabled{opacity:.6;cursor:wait}.notpo-cp a{color:#0f766e}"; 17 document.head.appendChild(css); 18 var me = null, sub = 0, html = "", hidden = true; 19 function boxes(){ 20 // Rebuy Smart Cart (the slide-out cart on evolvh.com): insert above its Checkout button. 21 Array.prototype.forEach.call(document.querySelectorAll(".rebuy-cart__checkout-button"), function(btn){ 22 var prev = btn.previousElementSibling; 23 if (prev && prev.classList.contains("notpo-cart-points")) return; 24 var d = document.createElement("div"); d.className = "notpo-cart-points"; btn.parentNode.insertBefore(d, btn); 25 }); 26 var list = Array.prototype.slice.call(document.querySelectorAll("#notpo-cart-points, .notpo-cart-points")); 27 if (!list.length && /^\/cart\/?$/.test(location.pathname)) { 28 var btn = document.querySelector('form[action*="/cart"] [name="checkout"]'); 29 if (btn) { var d = document.createElement("div"); d.className = "notpo-cart-points"; btn.parentNode.insertBefore(d, btn); list = [d]; } 30 } 31 return list; 32 } 33 function build(){ 34 hidden = true; 35 if (!me || !me.signed_in || !me.member || !(Number(me.balance) >= 10)) return ""; 36 hidden = false; 37 var byPts = Math.floor(me.balance / PTS_PER_DOLLAR), max = Math.min(byPts, Math.floor(sub * 0.1)); 38 var fit = (me.codes || []).filter(function(c){ return codeValue(c) <= max; }).sort(function(a, b){ return codeValue(b) - codeValue(a); })[0]; 39 if (fit && codeValue(fit) === max && max >= 1) return 'You have <b>$' + max + ' off</b> ready to use.<div style="margin-top:2px">Rewards can cover up to 10% of your cart total during The Fall Tiered Sale</div><div style="margin-top:2px">Remaining rewards: <b>' + me.balance.toLocaleString() + ' points</b> ($' + (me.balance / PTS_PER_DOLLAR).toFixed(2) + ' value)</div><button type="button" data-apply="' + esc(fit.discount_code) + '">Apply $' + max + ' off & Checkout</button><div style="margin-top:6px;font-size:12px"><a href="/apps/notpo">See your rewards</a></div>'; 40 if (max >= 1) return 'You have <b>$' + max + ' off</b> ready to use.<div style="margin-top:2px">Rewards can cover up to 10% of your cart total during The Fall Tiered Sale</div><div style="margin-top:2px">Remaining rewards: <b>' + (me.balance - max * PTS_PER_DOLLAR).toLocaleString() + ' points</b> ($' + ((me.balance - max * PTS_PER_DOLLAR) / PTS_PER_DOLLAR).toFixed(2) + ' value)</div><button type="button" data-amount="' + max + '">Apply $' + max + ' off & Checkout</button><div style="margin-top:6px;font-size:12px"><a href="https://evolvh.com/apps/notpo">Go to Rewards</a></div>'; 41 return 'You have <b>' + me.balance.toLocaleString() + ' points</b>. <a href="/apps/notpo">See your rewards</a>'; 42 } 43 function paint(force){
44 boxes().forEach(function(b){ 45 if (!b.classList.contains("notpo-cp")) b.classList.add("notpo-cp"); 46 b.style.display = hidden ? "none" : ""; 47 if (force || b.getAttribute("data-notpo") !== html) { b.innerHTML = html; b.setAttribute("data-notpo", html); } 48 }); 49 } 50 function refresh(){ cartSubtotal().then(function(s){ var changed = s !== sub; sub = s; var h = build(); if (changed || h !== html) { html = h; paint(true); } else paint(false); }); } 51 document.addEventListener("click", function(e){ 52 var b = e.target.closest && e.target.closest(".notpo-cp button"); if (!b) return; 53 e.preventDefault(); e.stopPropagation(); 54 b.disabled = true; 55 if (b.dataset.apply) { location.href = applyUrl(b.dataset.apply, "/checkout"); return; } 56 var amount = parseInt(b.dataset.amount, 10); b.textContent = "Creating your codeâ¦"; 57 api("redeem_amount", { amount: amount }).then(function(r){ 58 if (r.ok) { location.href = applyUrl(r.code, "/checkout"); } 59 else { b.textContent = r.error === "insufficient_points" ? "Not enough points" : "Something went wrong â your points were not spent"; setTimeout(function(){ api("me").then(function(m){ me = m; refresh(); }); }, 2500); } 60 }); 61 }, true); 62 var pending = false; 63 new MutationObserver(function(){ if (pending) return; pending = true; setTimeout(function(){ pending = false; paint(false); if (me !== null) refresh(); }, 150); }).observe(document.documentElement, { childList: true, subtree: true }); 64 ["cart:updated","cart:refresh","cart-drawer:open","drawer:open"].forEach(function(ev){ document.addEventListener(ev, function(){ refresh(); }); }); 65 paint(false); 66 api("me").then(function(m){ me = m; refresh(); setInterval(function(){ if (!document.hidden) refresh(); }, 3000); }).catch(function(){ me = { signed_in: false }; refresh(); }); 67})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.