1(function () { 2 'use strict'; 3 4 var root = document.getElementById('cart-page-root'); 5 if (!root) { 6 return; 7 } 8 9 var content = document.getElementById('cart-page-content'); 10 if (!content) { 11 return; 12 } 13 14 var apiWaitAttempts = 0; 15 16 function escapeHtml(text) { 17 return String(text || '') 18 .replace(/&/g, '&') 19 .replace(/</g, '<') 20 .replace(/>/g, '>') 21 .replace(/"/g, '"') 22 .replace(/'/g, '''); 23 } 24 25 function fmtMoney(raw) { 26 var n = Number(raw); 27 if (!isFinite(n)) { 28 n = 0; 29 } 30 return n.toFixed(2); 31 } 32 33 function cartApi() { 34 return window.blogShopCart || null; 35 } 36 37 function render() { 38 var api = cartApi(); 39 if (!api || typeof api.getItems !== 'function') { 40 content.innerHTML = '<p class="placeholder">Cart is loading...</p>'; 41 if (apiWaitAttempts < 20) { 42 apiWaitAttempts += 1; 43 window.setTimeout(render, 100); 44 } 45 return; 46 } 47 apiWaitAttempts = 0; 48 49 var items = api.getItems(); 50 if (!Array.isArray(items) || !items.length) { 51 content.innerHTML = '' 52 + '<section class="cart-page-empty">' 53 + '<p>Your shopping cart is empty.</p>' 54 + '<a href="/list" class="cart-page-link-button">Browse Product Gallery</a>' 55 + '</section>'; 56 return; 57 } 58 59 var subtotal = 0; 60 var cryptoSubtotal = 0; 61 var rows = items.map(function (item) { 62 var qty = Number(item.qty || 1); 63 if (!isFinite(qty) || qty < 1) { 64 qty = 1; 65 } 66 var unit = Number(item.unit_price || 0); 67 if (!isFinite(unit)) { 68 unit = 0; 69 } 70 var unitCrypto = Number(item.unit_crypto_price || unit); 71 if (!isFinite(unitCrypto)) { 72 unitCrypto = unit; 73 } 74 var line = unit * qty; 75 var lineCrypto = unitCrypto * qty; 76 subtotal += line; 77 cryptoSubtotal += lineCrypto; 78 var key = String(item.item_key || item.slug || ''); 79 var variant = item.variant_name 80 ? '<div class="cart-page-item-variant">' + escapeHtml(item.variant_name) + '</div>' 81 : ''; 82 return '' 83 + '<li class="cart-page-row" data-cart-key="' + escapeHtml(key) + '">' 84 + '<div class="cart-page-row-main">' 85 + '<a class="cart-page-item-title" href="' + escapeHtml(item.path || ('/' + (item.slug || ''))) + '">' + escapeHtml(item.title || item.slug || 'Item') + '</a>' 86 + variant 87 + '<div class="cart-page-item-price">$' + fmtMoney(line) + ' <span>(~$' + fmtMoney(lineCrypto) + ' crypto)</span></div>' 88 + '</div>' 89 + '<div class="cart-page-row-actions">' 90 + '<button type="button" data-cart-page-action="decrement" data-cart-key="' + escapeHtml(key) + '">-</button>' 91 + '<span>Qty ' + String(qty) + '</span>' 92 + '<button type="button" data-cart-page-action="increment" data-cart-key="' + escapeHtml(key) + '">+</button>' 93 + '<button type="button" data-cart-page-action="remove" data-cart-key="' + escapeHtml(key) + '">Remove</button>' 94 + '</div>' 95 + '</li>'; 96 }).join(''); 97 98 content.innerHTML = '' 99 + '<section class="cart-page-list-wrap">' 100 + '<ul class="cart-page-list">' + rows + '</ul>' 101 + '<div class="cart-page-summary">' 102 + '<div class="cart-page-summary-row"><span>Subtotal</span><strong>$' + fmtMoney(subtotal) + '</strong></div>' 103 + '<div class="cart-page-summary-row"><span>Estimated crypto total</span><strong>$' + fmtMoney(cryptoSubtotal) + '</strong></div>' 104 + '<div class="cart-page-summary-actions">' 105 + '<button type="button" id="cart-page-clear">Clear Cart</button>' 106 + '<a href="/checkout" class="cart-page-link-button cart-page-link-button-primary">Continue to Checkout</a>' 107 + '</div>' 108 + '</div>' 109 + '</section>'; 110 } 111 112 content.addEventListener('click', function (event) { 113 var target = event.target; 114 if (!(target instanceof HTMLElement)) { 115 return; 116 } 117 var api = cartApi(); 118 if (!api) { 119 return; 120 } 121 122 if (target.id === 'cart-page-clear') { 123 if (typeof api.clear === 'function') { 124 api.clear(); 125 } 126 render(); 127 return; 128 } 129 130 var button = target.closest('button[data-cart-page-action]'); 131 if (!(button instanceof HTMLButtonElement)) { 132 return; 133 } 134 var action = String(button.getAttribute('data-cart-page-action') || ''); 135 var key = String(button.getAttribute('data-cart-key') || ''); 136 var items = (typeof api.getItems === 'function') ? api.getItems() : []; 137 var row = null;
138 items.forEach(function (item) { 139 if (row || String(item.item_key || item.slug || '') !== key) { 140 return; 141 } 142 row = item; 143 }); 144 if (!row || typeof api.setItemQty !== 'function') { 145 return; 146 } 147 if (action === 'increment') { 148 api.setItemQty(key, Number(row.qty || 1) + 1); 149 } else if (action === 'decrement') { 150 api.setItemQty(key, Number(row.qty || 1) - 1); 151 } else if (action === 'remove') { 152 api.setItemQty(key, 0); 153 } 154 render(); 155 }); 156 157 window.addEventListener('blog-cart-updated', render); 158 render(); 159})();
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.