1(function () { 2 'use strict'; 3 4 var PLACEHOLDER = '/templates/stek/images/cart-item-img.png'; 5 var STORAGE_KEY = 'km_minicart_meta_v1'; 6 var metaByKey = {}; 7 8 function toArray(obj) { 9 if (!obj) return []; 10 return Array.isArray(obj) ? obj : Object.keys(obj).map(function (k) { 11 return obj[k]; 12 }); 13 } 14 15 function loadMeta() { 16 try { 17 var raw = localStorage.getItem(STORAGE_KEY); 18 if (!raw) return; 19 var parsed = JSON.parse(raw); 20 if (parsed && typeof parsed === 'object') metaByKey = parsed; 21 } catch (e) {} 22 } 23 24 function saveMeta() { 25 try { 26 localStorage.setItem(STORAGE_KEY, JSON.stringify(metaByKey)); 27 } catch (e) {} 28 } 29 30 function esc(s) { 31 return String(s) 32 .replace(/&/g, '&') 33 .replace(/</g, '<') 34 .replace(/>/g, '>') 35 .replace(/"/g, '"'); 36 } 37 38 function cartCountNodes() { 39 return document.querySelectorAll('a.basket-action-icon[href*="/emarket/cart"] .basket-action-icon-count'); 40 } 41 42 function setCount(n) { 43 n = Math.max(0, parseInt(n, 10) || 0); 44 cartCountNodes().forEach(function (el) { 45 el.textContent = String(n); 46 }); 47 } 48 49 function optionKeys(item) { 50 var keys = []; 51 var opts = item && item.options && item.options.option ? toArray(item.options.option) : []; 52 opts.forEach(function (o) { 53 if (!o) return; 54 if (o.id != null && String(o.id) !== '') keys.push(String(o.id)); 55 if (o.name != null && String(o.name) !== '') keys.push(String(o.name)); 56 if (o.float != null && String(o.float) !== '') keys.push(String(o.float)); 57 if (o.value != null && String(o.value) !== '') keys.push(String(o.value)); 58 }); 59 return keys; 60 } 61 62 function itemKeys(item) { 63 // СнаÑала gid/option â инаÑе один parent id подменÑÐµÑ ÑоÑо ÑазнÑÑ Ð¾ÑÑаÑков 64 var keys = optionKeys(item); 65 if (item && item.id != null) keys.push(String(item.id)); 66 if (item && item.page && item.page.id != null) keys.push(String(item.page.id)); 67 return keys; 68 } 69 70 function metaFor(item) { 71 var keys = itemKeys(item); 72 for (var i = 0; i < keys.length; i++) { 73 if (metaByKey[keys[i]] && (metaByKey[keys[i]].thumb || metaByKey[keys[i]].title)) { 74 return metaByKey[keys[i]]; 75 } 76 } 77 return null; 78 } 79 80 function remember(meta) { 81 if (!meta) return; 82 var title = String(meta.title || '').trim(); 83 var thumb = String(meta.thumb || meta.img || '').trim(); 84 if (!title && !thumb) return; 85 var keys = []; 86 if (meta.key != null && String(meta.key) !== '') keys.push(String(meta.key)); 87 if (meta.gid != null && String(meta.gid) !== '') { 88 keys.push(String(meta.gid)); 89 } else if (meta.id != null && String(meta.id) !== '') { 90 // parent id ÑолÑко без gid â инаÑе ÑазнÑе оÑÑаÑки одного ÐºÐ°Ð¼Ð½Ñ Ð´ÐµÐ»ÑÑ Ð¾Ð´Ð½Ð¾ ÑоÑо 91 keys.push(String(meta.id)); 92 } 93 if (!keys.length) return; 94 keys.forEach(function (key) { 95 var prev = metaByKey[key] || {}; 96 metaByKey[key] = { 97 title: title || prev.title || '', 98 thumb: thumb || prev.thumb || '' 99 }; 100 }); 101 saveMeta(); 102 } 103 104 function itemTitle(item) { 105 var meta = metaFor(item); 106 if (meta && meta.title) return meta.title; 107 if (item.page && item.page.name) return item.page.name; 108 if (item.name) return item.name; 109 return 'ТоваÑ'; 110 } 111 112 function itemLink(item) { 113 if (item.page && item.page.link) return item.page.link; 114 return '/emarket/cart/'; 115 } 116 117 function itemThumb(item) { 118 var meta = metaFor(item); 119 if (meta && meta.thumb) return meta.thumb; 120 if (item.page && item.page.thumbnail) return item.page.thumbnail; 121 if (item.thumbnail) return item.thumbnail; 122 if (item.page && item.page.image) return item.page.image; 123 return PLACEHOLDER; 124 } 125 126 function itemPrice(item) { 127 var price = item.price || item['total-price']; 128 if (!price) return ''; 129 var val = price.actual || price.original; 130 if (!val) return ''; 131 var suffix = price.suffix || ' â½'; 132 return String(val) + suffix; 133 } 134 135 function indexLeftoverCards() { 136 document.querySelectorAll('.leftovers-stone-card[data-gid], .leftovers-stone-card[data-product]').forEach(function (card) { 137 remember({ 138 id: card.getAttribute('data-product') || '', 139 gid: card.getAttribute('data-gid') || '', 140 title: card.getAttribute('data-title') || '', 141 thumb: card.getAttribute('data-img') || '' 142 }); 143 }); 144 } 145 146 function renderMinicart(data) { 147 var items = data && data.items && data.items.item ? toArray(data.items.item) : []; 148 var hasItems = items.length > 0; 149 150 document.querySelectorAll('.km-minicart__body').forEach(function (body) { 151 var empty = body.querySelector('.km-minicart__empty'); 152 var list = body.querySelector('.km-minicart__list'); 153 if (!empty || !list) return; 154 155 if (!hasItems) { 156 empty.hidden = false;
157 list.hidden = true; 158 list.innerHTML = ''; 159 return; 160 } 161 162 empty.hidden = true; 163 list.hidden = false; 164 list.innerHTML = items.map(function (item) { 165 var title = esc(itemTitle(item)); 166 var link = esc(itemLink(item)); 167 var thumb = esc(itemThumb(item)); 168 var itemId = item && item.id != null ? String(item.id) : ''; 169 var price = itemPrice(item); 170 var qty = parseInt(item.amount, 10); 171 if (isNaN(qty) || qty < 1) qty = 1; 172 var priceHtml = price ? '<span class="km-minicart__price">' + price + '</span>' : ''; 173 var qtyHtml = '<span class="km-minicart__qty">' + qty + ' ÑÑ.</span>'; 174 var removeHtml = itemId 175 ? '<button type="button" class="km-minicart__remove" data-remove-item="' + 176 esc(itemId) + 177 '" aria-label="УдалиÑÑ Ð¸Ð· коÑзинÑ" title="УдалиÑÑ">Ã</button>' 178 : ''; 179 return ( 180 '<li class="km-minicart__item">' + 181 '<a class="km-minicart__thumb" href="' + link + '">' + 182 '<img src="' + thumb + '" alt="" width="48" height="48" loading="lazy">' + 183 '</a>' + 184 '<div class="km-minicart__meta">' + 185 '<a class="km-minicart__title" href="' + link + '">' + title + '</a>' + 186 '<div class="km-minicart__line">' + priceHtml + qtyHtml + '</div>' + 187 '</div>' + 188 removeHtml + 189 '</li>' 190 ); 191 }).join(''); 192 }); 193 } 194 195 function syncLeftoverButtons(data) { 196 var inCart = {}; 197 var items = data && data.items && data.items.item ? toArray(data.items.item) : []; 198 items.forEach(function (item) { 199 itemKeys(item).forEach(function (key) { 200 inCart[key] = true; 201 }); 202 }); 203 204 document.querySelectorAll('[data-add-cart], [data-popup-add-cart], [data-add-cart-main]').forEach(function (btn) { 205 var card = btn.closest('.leftovers-stone-card, .leftovers-popup, .leftovers-stone'); 206 var gid = (card && card.getAttribute('data-gid')) || ''; 207 var productId = 208 (card && (card.getAttribute('data-product') || card.getAttribute('data-product-id'))) || 209 btn.getAttribute('data-product') || 210 ''; 211 var isIn = 212 (gid && inCart[gid]) || 213 (productId && inCart[productId] && btn.hasAttribute('data-add-cart-main')); 214 215 if (isIn) { 216 if (!btn.getAttribute('data-label')) { 217 btn.setAttribute('data-label', (btn.textContent || '').trim() || 'ÐобавиÑÑ Ð² коÑзинÑ'); 218 } 219 btn.setAttribute('data-in-cart', '1'); 220 btn.textContent = 'РкоÑзине'; 221 } else if (btn.getAttribute('data-in-cart') === '1') { 222 btn.removeAttribute('data-in-cart'); 223 btn.textContent = btn.getAttribute('data-label') || 'ÐобавиÑÑ Ð² коÑзинÑ'; 224 } 225 }); 226 } 227 228 function removeItem(itemId, btn) { 229 itemId = String(itemId || '').trim(); 230 if (!itemId) return Promise.resolve(); 231 if (btn) btn.disabled = true; 232 return fetch('/udata/emarket/basket/remove/item/' + encodeURIComponent(itemId) + '/.json', { 233 method: 'POST', 234 credentials: 'same-origin', 235 headers: { 'X-Requested-With': 'XMLHttpRequest' } 236 }) 237 .then(function () { 238 return refresh(); 239 }) 240 .catch(function (err) { 241 console.error('kmCart remove error:', err); 242 if (btn) btn.disabled = false; 243 }); 244 } 245 246 function refresh() { 247 indexLeftoverCards(); 248 return fetch('/udata/emarket/cart/.json', { 249 method: 'GET', 250 credentials: 'same-origin', 251 headers: { 'X-Requested-With': 'XMLHttpRequest' } 252 }) 253 .then(function (res) { 254 return res.json(); 255 }) 256 .then(function (data) { 257 var amount = data && data.summary ? parseInt(data.summary.amount, 10) || 0 : 0; 258 setCount(amount); 259 renderMinicart(data); 260 syncLeftoverButtons(data); 261 return data; 262 }) 263 .catch(function (err) { 264 console.error('kmCart refresh error:', err); 265 }); 266 } 267 268 loadMeta(); 269 270 document.addEventListener('click', function (e) { 271 var btn = e.target.closest('.km-minicart__remove[data-remove-item]'); 272 if (!btn) return; 273 e.preventDefault(); 274 e.stopPropagation(); 275 removeItem(btn.getAttribute('data-remove-item'), btn); 276 }); 277 278 window.kmCart = { 279 refresh: refresh, 280 setCount: setCount, 281 remember: remember, 282 removeItem: removeItem 283 }; 284 285 if (document.readyState === 'loading') { 286 document.addEventListener('DOMContentLoaded', refresh); 287 } else { 288 refresh(); 289 } 290})();
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.