1function ProductSanar() { 2 this.selector = { // ÐÑе даннÑе о ÑелекÑоÑÐ°Ñ 3 basketConteiners: '.basket-table', 4 basketDeleteConteiners: '.basket-table__delete', 5 basketConteinersActive: '.product-block.active', 6 basketProductConteinersActive: '.product-act.active', 7 mainConteiners: '.product-block, .product-content__nw_act', 8 productConteiners: '.product-act', 9 basketConteiner: '.basket-table[data-id="#ID#"]', 10 mainConteiner: '.product-block[data-id="#ID#"], .product-content__nw_act[data-id="#ID#"]', 11 productConteiner: '.product-act[data-id="#ID#"]', 12 basketCount: '.count-cart', 13 basketFullPrice: '.full_price', 14 basketAddBtn: '.add-basket', 15 basketPlusBtn: '.plus-cart', 16 basketMinusBtn: '.minus-cart', 17 basketDeleteBtn: '.delete-cart', 18 basketDeleteNoReturnBtn: '.full-delete', 19 basketReturnBtn: '.return-item', 20 basketName: '.item-name', 21 basketInformer: '.basket-informer span.text', 22 basketTotal: '.basket-total p', 23 basketSuccessAdd: '#success-add', 24 favoriteBtn: '.set-fav', 25 favoriteActiveBtn: '.active.set-fav', 26 oneClickBtn: '.oneclick', 27 modalOneClick: '#oneclick', 28 oneClickInput: 'input[name="PRODUCT"]' 29 }; 30 this.intervals = {}; 31 this.stateItems = {}; 32 this.stateLoading = true; 33 this.pathPostFile = '/local/include/product.php'; 34 this.addListener = () => { 35 document.addEventListener('click', e => { 36 let currentTarget = e.target; 37 if (currentTarget.matches(this.selector.basketPlusBtn)) { 38 this.setCount(e, 'plus'); 39 } 40 if (currentTarget.matches(this.selector.basketMinusBtn)) { 41 this.setCount(e, 'minus'); 42 } 43 if (currentTarget.matches(this.selector.basketDeleteBtn)) { 44 this.deleteFromBasket(e); 45 } 46 if (currentTarget.matches(this.selector.basketReturnBtn)) { 47 this.returnToBasket(e); 48 } 49 if (currentTarget.matches(this.selector.basketAddBtn)) { 50 this.addBasket(e); 51 } 52 if (currentTarget.matches(this.selector.basketDeleteNoReturnBtn)) { 53 this.deleteFromBasketNoReturn(e); 54 } 55 if (currentTarget.matches(this.selector.favoriteBtn)) { 56 this.setFavorite(e); 57 } 58 if (currentTarget.matches(this.selector.oneClickBtn)) { 59 let 60 modalContent = document.querySelector(this.selector.modalOneClick), 61 modal = bootstrap.Modal.getOrCreateInstance(modalContent), 62 oneClickInput = modalContent.querySelector(this.selector.oneClickInput); 63 oneClickInput.value = currentTarget.dataset.id; 64 modal.show(); 65 } 66 }); 67 document.addEventListener('DOMContentLoaded', () => {
68 this.getState(); 69 }) 70 }; 71 this.setFavorite = (event) => { 72 let 73 currentTarget = event.target, 74 parentElement = this._findParentElement(currentTarget, this.selector.mainConteiners), 75 data = { 76 ID: parentElement.dataset.id, 77 METHOD: 'SET_FAVORITES', 78 }; 79 this._request(this.pathPostFile, data, this.setState); 80 } 81 this.addBasket = (event) => { 82 let 83 currentTarget = event.target, 84 parentElement = (this._findParentElement(currentTarget, this.selector.mainConteiners)) ? this._findParentElement(currentTarget, this.selector.mainConteiners) : this._findParentElement(currentTarget, this.selector.productConteiners), 85 data = { 86 METHOD: 'ADD_BASKET', 87 COUNT: (currentTarget.dataset.measureRatio) ? currentTarget.dataset.measureRatio : 1, 88 ID: parentElement.dataset.id 89 }; 90 if (!parentElement.classList.contains('active')) { 91 event.preventDefault(); 92 if (parentElement.classList.contains('product-act')) { 93 let basketCount = parentElement.querySelector(this.selector.basketCount); 94 data.COUNT = basketCount.innerHTML; 95 let 96 modalContent = document.querySelector(this.selector.basketSuccessAdd), 97 modal = bootstrap.Modal.getOrCreateInstance(modalContent); 98 modal.show(); 99 } 100 this._request(this.pathPostFile, data, this.setState); 101 } 102 }; 103 this.deleteFromBasketNoReturn = (event) => { 104 let 105 currentTarget = event.target, 106 parentBasketElement = this._findParentElement(currentTarget, this.selector.basketDeleteConteiners); 107 parentBasketElement.remove(); 108 let basketConteiners = document.querySelector('.basket-table'); 109 if (basketConteiners === null || basketConteiners === undefined) { 110 window.location.reload(); 111 } 112 }; 113 this.setCount = (event, type) => { 114 let 115 currentTarget = event.target, 116 parentElement = (this._findParentElement(currentTarget, this.selector.mainConteiners)) ? this._findParentElement(currentTarget, this.selector.mainConteiners) : this._findParentElement(currentTarget, this.selector.productConteiners), 117 parentBasketElement = this._findParentElement(currentTarget, this.selector.basketConteiners), 118 data = { 119 METHOD: 'EDIT_BASKET', 120 }; 121 122 if (parentElement) { 123 if (parentElement.classList.contains('active')) { 124 let basketCount = parentElement.querySelector(this.selector.basketCount); 125 data.ID = parentElement.dataset.id; 126 if (type !== 'minus') { 127 if (basketCount.dataset.measureRatio.toString().includes('.')) { 128 data.COUNT = (parseFloat(basketCount.innerHTML) + parseFloat(basketCount.dataset.measureRatio)).toFixed(2); 129 } else { 130 data.COUNT = parseInt(basketCount.innerHTML) + parseInt(basketCount.dataset.measureRatio); 131 } 132 } else { 133 if (basketCount.dataset.measureRatio.toString().includes('.')) { 134 data.COUNT = (parseFloat(basketCount.innerHTML) - parseFloat(basketCount.dataset.measureRatio)).toFixed(2); 135 } else { 136 data.COUNT = parseInt(basketCount.innerHTML) - parseInt(basketCount.dataset.measureRatio); 137 } 138 139 if (data.COUNT < parseFloat(basketCount.dataset.measureRatio)) { 140 this.deleteFromBasket(event); 141 return; 142 } 143 } 144 this._request(this.pathPostFile, data, this.setState); 145 } else { 146 let basketCount = parentElement.querySelector(this.selector.basketCount); 147 if (type !== 'minus') { 148 if (basketCount.dataset.measureRatio.toString().includes('.')) { 149 basketCount.innerHTML = parseFloat((parseFloat(basketCount.innerHTML) + parseFloat(basketCount.dataset.measureRatio)).toFixed(2)); 150 } else { 151 basketCount.innerHTML = parseInt(basketCount.innerHTML) + parseInt(basketCount.dataset.measureRatio); 152 } 153 } else { 154 if (parseFloat(basketCount.innerHTML) > parseFloat(basketCount.dataset.measureRatio)) { 155 if (basketCount.dataset.measureRatio.toString().includes('.')) { 156 basketCount.innerHTML = parseFloat((parseFloat(basketCount.innerHTML) - parseFloat(basketCount.dataset.measureRatio)).toFixed(2)); 157 } else { 158 basketCount.innerHTML = parseInt(basketCount.innerHTML) - parseInt(basketCount.dataset.measureRatio); 159 } 160 } 161 } 162 } 163 164 } else if (parentBasketElement) { 165 let basketCount = parentBasketElement.querySelector(this.selector.basketCount); 166 data.ID = parentBasketElement.dataset.id; 167 if (type !== 'minus') { 168 data.COUNT = parseFloat(basketCount.innerHTML) + parseFloat(basketCount.dataset.measureRatio); 169 } else { 170 data.COUNT = parseFloat(basketCount.innerHTML) - parseFloat(basketCount.dataset.measureRatio); 171 if (data.COUNT < parseFloat(basketCount.dataset.measureRatio)) { 172 this.deleteFromBasket(event); 173 return; 174 } 175 } 176 this._request(this.pathPostFile, data, this.setState); 177 } 178 179 }; 180 this.deleteFromBasket = (event) => { 181 let 182 currentTarget = event.target, 183 parentElement = (this._findParentElement(currentTarget, this.selector.mainConteiners)) ? this._findParentElement(currentTarget, this.selector.mainConteiners) : this._findParentElement(currentTarget, this.selector.productC
183onteiners), 184 parentBasketElement = this._findParentElement(currentTarget, this.selector.basketConteiners), 185 data = { 186 METHOD: 'DELETE_BASKET', 187 }, 188 actionDelete = (response) => { 189 if (parentBasketElement) { 190 let name = parentBasketElement.querySelector(this.selector.basketName).innerHTML; 191 parentBasketElement.replaceChildren(); 192 parentBasketElement.classList.add('basket-table__delete'); 193 parentBasketElement.classList.remove('basket-table'); 194 let 195 table = document.createElement('table'), 196 tbody = document.createElement('tbody'), 197 tr = document.createElement('tr'), 198 td = document.createElement('td'), 199 div = document.createElement('div'), 200 a = document.createElement('a'); 201 table.append(tbody); 202 tbody.append(tr); 203 td.innerHTML = 'Ð¢Ð¾Ð²Ð°Ñ ' + name + ' бÑл Ñдален из коÑзинÑ'; 204 tr.append(td); 205 td = document.createElement('td'); 206 div.classList.add('basket-table__act'); 207 a.classList.add('link', 'return-item'); 208 a.innerHTML = 'ÐоÑÑÑановиÑÑ'; 209 a.href = 'javascript:void(0)'; 210 div.append(a); 211 a = document.createElement('a'); 212 a.classList.add('delete', 'full-delete'); 213 a.insertAdjacentHTML("beforeend", `<svg xmlns="http://www.w3.org/2000/svg" width="15" height="16" viewBox="0 0 15 16"> <path id="Path_94" data-name="Path 94" d="M241.119,148.27H237.71V147.6a1.978,1.978,0,0,0-.6-1.414,2.069,2.069,0,0,0-1.447-.586h-2.727a2.069,2.069,0,0,0-1.447.586,1.978,1.978,0,0,0-.6,1.414v.667h-3.409a.667.667,0,1,0,0,1.333h1.364v.04l.607,10.077a1.982,1.982,0,0,0,.64,1.339,2.071,2.071,0,0,0,1.406.544h5.608a2.071,2.071,0,0,0,1.406-.544,1.982,1.982,0,0,0,.64-1.339l.6-10.077v-.04h1.364a.667.667,0,1,0,0-1.333Zm-8.864-.667a.674.674,0,0,1,.682-.667h2.727a.69.69,0,0,1,.482.2.659.659,0,0,1,.2.471v.667h-4.091Zm5.533,12.04a.675.675,0,0,1-.682.627h-5.612a.675.675,0,0,1-.682-.627l-.6-10.04h8.182Z" transform="translate(-226.8 -145.603)" fill="#99b3c5"></path></svg>`); 214 a.href = 'javascript:void(0)'; 215 div.append(a); 216 td.append(div); 217 tr.append(td); 218 parentBasketElement.append(table); 219 } 220 this.setState(response) 221 }; 222 if (parentElement) { 223 data.ID = parentElement.dataset.id; 224 } else if (parentBasketElement) { 225 data.ID = parentBasketElement.dataset.id; 226 } 227 this._request(this.pathPostFile, data, actionDelete); 228 }; 229 this.returnToBasket = (event) => { 230 let 231 currentTarget = event.target, 232 parentBasketElement = this._findParentElement(currentTarget, this.selector.basketDeleteConteiners), 233 data = { 234 METHOD: 'ADD_BASKET', 235 }, 236 returnAction = (response) => { 237 let currentState = this.stateItems[parentBasketElement.dataset.id].basket, 238 template = ` 239 <table> 240 <tbody> 241 <tr> 242 <td> 243 <div class="basket-table__product"> 244 <div class="image"> 245 <a href="#URL#"> 246 <img src="#IMAGE#" alt=""> 247 </a> 248 </div> 249 <div class="text"> 250 <a class="link item-name" href="#URL#">#NAME#</a> 251 </div> 252 </div> 253 </td> 254 <td class="price">#PRICE# ÑÑб. <strong>/#MEASURE#</strong></td> 255 <td> 256 <div class="input-group spinner"> 257 <button class="btn increase minus-cart" type="button"> 258 <img src="/local/templates/redesign/assets/images/minusblack.svg" alt=""> 259 </button> 260 <span class="spinner-input count-cart" data-measure-ratio="#RATIO#">#COUNT#</span> 261 <button class="btn decrease plus-cart" type="button"> 262 <img src="/local/templates/redesign/assets/images/plus.svg" alt=""> 263 </button> 264 </div> 265 </td> 266 <td> 267 <div class="basket-table__act"> 268 <p class="full_price">#FULL_PRICE# ÑÑб.</p> 269 <a class="delete delete-cart" href="javascript:void(0)"> 270 <svg xmlns="http://www.w3.org/2000/svg" width="15" height="16" viewB
270ox="0 0 15 16"> 271 <path id="Path_94" data-name="Path 94" d="M241.119,148.27H237.71V147.6a1.978,1.978,0,0,0-.6-1.414,2.069,2.069,0,0,0-1.447-.586h-2.727a2.069,2.069,0,0,0-1.447.586,1.978,1.978,0,0,0-.6,1.414v.667h-3.409a.667.667,0,1,0,0,1.333h1.364v.04l.607,10.077a1.982,1.982,0,0,0,.64,1.339,2.071,2.071,0,0,0,1.406.544h5.608a2.071,2.071,0,0,0,1.406-.544,1.982,1.982,0,0,0,.64-1.339l.6-10.077v-.04h1.364a.667.667,0,1,0,0-1.333Zm-8.864-.667a.674.674,0,0,1,.682-.667h2.727a.69.69,0,0,1,.482.2.659.659,0,0,1,.2.471v.667h-4.091Zm5.533,12.04a.675.675,0,0,1-.682.627h-5.612a.675.675,0,0,1-.682-.627l-.6-10.04h8.182Z" transform="translate(-226.8 -145.603)" fill="#99b3c5"></path> 272 </svg> 273 </a> 274 </div> 275 </td> 276 </tr> 277 </tbody> 278 </table> 279 `; 280 parentBasketElement.replaceChildren(); 281 parentBasketElement.classList.remove('basket-table__delete'); 282 parentBasketElement.classList.add('basket-table'); 283 template = this._replaceMacros(template, '#URL#', currentState.URL); 284 template = this._replaceMacros(template, '#NAME#', currentState.NAME); 285 template = this._replaceMacros(template, '#IMAGE#', currentState.IMAGE); 286 template = this._replaceMacros(template, '#PRICE#', this._number_format(parseFloat(currentState.PRICE), 2, '.', ' ')); 287 template = this._replaceMacros(template, '#FULL_PRICE#', this._number_format(parseFloat(currentState.PRICE * currentState.QUANTITY), 2, '.', ' ')); 288 template = this._replaceMacros(template, '#COUNT#', parseInt(currentState.QUANTITY)); 289 template = this._replaceMacros(template, '#RATIO#', parseInt(currentState.RATIO)); 290 template = this._replaceMacros(template, '#MEASURE#', currentState.MEASURE); 291 parentBasketElement.insertAdjacentHTML("beforeend", template); 292 this.setState(response); 293 }; 294 let currentState = this.stateItems[parentBasketElement.dataset.id].basket; 295 data.ID = parentBasketElement.dataset.id; 296 data.COUNT = currentState.QUANTITY; 297 this._request(this.pathPostFile, data, returnAction); 298 }; 299 this.setState = (response) => { 300 let 301 data = JSON.parse(response), 302 basketInformer = document.querySelectorAll(this.selector.basketInformer), 303 basketTotal = document.querySelectorAll(this.selector.basketTotal), 304 basketProductConteinersActive = document.querySelectorAll(this.selector.basketProductConteinersActive), 305 basketConteinersActive = document.querySelectorAll(this.selector.basketConteinersActive), 306 favoriteActiveBtn = document.querySelectorAll(this.selector.favoriteActiveBtn); 307 308 basketInformer.forEach(elem => { 309 if (data.totalPrice > 0) { 310 this._replaceIntRecursive(elem, data.totalPrice); 311 elem.closest('.basket-informer').classList.add('active'); 312 } else { 313 elem.textContent = 'ÐоÑзина'; 314 elem.closest('.basket-informer').classList.remove('active'); 315 } 316 317 }); 318 319 basketTotal.forEach(elem => { 320 this._replaceIntRecursive(elem, data.totalPrice, true); 321 }); 322 for (let key in data.basket) { 323 if (this.stateItems[key] === undefined) { 324 this.stateItems[key] = {}; 325 } 326 this.stateItems[key].basket = data.basket[key] 327 } 328 basketConteinersActive.forEach(elem => { 329 let isActive = false; 330 for (let key in data.basket) { 331 if (elem.dataset.id == key) { 332 isActive = true; 333 } 334 } 335 if (!isActive) { 336 elem.classList.remove('active'); 337 delete this.stateItems[elem.dataset.id]; 338 } 339 }); 340 basketProductConteinersActive.forEach(elem => { 341 let isActive = false; 342 for (let key in data.basket) { 343 if (elem.dataset.id == key) { 344 isActive = true; 345 } 346 } 347 if (!isActive) { 348 elem.classList.remove('active'); 349 delete this.stateItems[elem.dataset.id]; 350 } 351 }); 352 353 favoriteActiveBtn.forEach(elem => { 354 elem.classList.remove('active'); 355 }) 356 for (let key in data.favorite) { 357 let mainConteiner = document.querySelectorAll(this._replaceMacros(this.selector.mainConteiner, '#ID#', data.favorite[key])); 358 mainConteiner.forEach(elem => { 359 let favoriteBtn = elem.querySelector(this.selector.favoriteBtn); 360 favoriteBtn.classList.add('active'); 361 }); 362 } 363 //ÑÑÑанавливаем полÑÑеннÑе даннÑе 364 for (let key in this.stateItems) { 365 // коÑзина 366 let 367 basketConteiner = document.querySelectorAll(this._replaceMacros(this.selector.basketConteiner, '#ID#', key)), 368 mainConteiner = document.querySelectorAll(this._replaceMacros(this.selector.mainConteiner, '#ID#', key)),
369 productConteiner = document.querySelectorAll(this._replaceMacros(this.selector.productConteiner, '#ID#', key)); 370 productConteiner.forEach(elem => { 371 elem.classList.add('active'); 372 let basketCount = elem.querySelector(this.selector.basketCount); 373 basketCount.innerHTML = parseFloat(this.stateItems[key].basket.QUANTITY); 374 }) 375 basketConteiner.forEach(elem => { 376 let basketCount = elem.querySelector(this.selector.basketCount); 377 let basketFullPrice = elem.querySelector(this.selector.basketFullPrice); 378 this._replaceIntRecursive(basketFullPrice, this.stateItems[key].basket.QUANTITY * this.stateItems[key].basket.PRICE); 379 basketCount.innerHTML = parseFloat(this.stateItems[key].basket.QUANTITY); 380 }); 381 mainConteiner.forEach(elem => { 382 elem.classList.add('active'); 383 let basketCount = elem.querySelector(this.selector.basketCount); 384 basketCount.innerHTML = parseFloat(this.stateItems[key].basket.QUANTITY); 385 }); 386 } 387 }; 388 this.getState = () => { 389 this._request(this.pathPostFile, {}, this.setState); 390 }; 391 this._replaceIntRecursive = (elem, newNum, needTotal = false) => { 392 let _self = this; 393 let value = parseFloat(elem.innerText.replaceAll(' ', '').replaceAll('ÐÑого:', '')); 394 395 if (newNum < value) { 396 let speed = (value - newNum) / 100; 397 recursiveMinus(speed, _self, needTotal); 398 } else { 399 let speed = (newNum - value) / 100; 400 recursivePlus(speed, _self, needTotal); 401 } 402 403 function recursiveMinus(speed, _self, needTotal = false) { 404 setTimeout(() => { 405 let value = parseFloat(elem.innerText.replaceAll(' ', '').replaceAll('ÐÑого:', '')); 406 let totalText = ''; 407 if (needTotal) { 408 totalText = 'ÐÑого: '; 409 } 410 if ((value - speed) > newNum) { 411 elem.innerText = totalText + _self._number_format(parseFloat(value - speed), 2, '.', ' ') + ' â½'; 412 } else { 413 elem.innerText = totalText + _self._number_format(parseFloat(newNum), 2, '.', ' ') + ' â½'; 414 } 415 if ((value - speed) > newNum) { 416 recursiveMinus(speed, _self, needTotal); 417 } 418 }, 1); 419 } 420 421 function recursivePlus(speed, _self, needTotal = false) { 422 setTimeout(() => { 423 let value = parseFloat(elem.innerText.replaceAll(' ', '').replaceAll('ÐÑого:', '')); 424 let totalText = ''; 425 if (needTotal) { 426 totalText = 'ÐÑого: '; 427 } 428 if ((value + speed) < newNum) { 429 elem.innerText = totalText + _self._number_format(parseFloat(value + speed), 2, '.', ' ') + ' â½'; 430 } else { 431 elem.innerText = totalText + _self._number_format(parseFloat(newNum), 2, '.', ' ') + ' â½'; 432 } 433 if ((value + speed) < newNum) { 434 recursivePlus(speed, _self, needTotal); 435 } 436 }, 1); 437 } 438 }; 439 this.start = () => { 440 this.addListener(); 441 }; 442 this.start(); 443} 444 445ProductSanar.prototype._replaceMacros = (text, macros, value) => { 446 return text.replaceAll(macros, value); 447} 448 449ProductSanar.prototype._request = (url, data, action) => { 450 let 451 request = new XMLHttpRequest(), 452 sendData = new FormData(); 453 for (let key in data) { 454 sendData.append(key, data[key]); 455 } 456 request.open("POST", url); 457 request.addEventListener('load', () => { 458 action(request.response); 459 }); 460 request.send(sendData); 461}; 462 463ProductSanar.prototype._getRequest = (url, data, action) => { 464 let 465 request = new XMLHttpRequest(), 466 sendData = '?'; 467 for (let key in data) { 468 if (sendData == '?') { 469 sendData += key + '=' + data[key]; 470 } else { 471 sendData += '&' + key + '=' + data[key]; 472 } 473 } 474 request.open("GET", url + sendData); 475 request.addEventListener('load', () => { 476 action(request.response); 477 }); 478 request.send(); 479}; 480 481ProductSanar.prototype._number_format = (number, decimals = 0, dec_point = '.', thousands_sep = ',') => { 482 483 let sign = number < 0 ? '-' : ''; 484 485 let s_number = Math.abs(parseInt(number = (+number || 0).toFixed(decimals))) + ""; 486 let len = s_number.length; 487 let tchunk = len > 3 ? len % 3 : 0; 488 489 let ch_first = (tchunk ? s_number.substr(0, tchunk) + thousands_sep : ''); 490 let ch_rest = s_number.substr(tchunk) 491 .replace(/(\d\d\d)(?=\d)/g, '$1' + thousands_sep); 492 let ch_last = decimals 493 ? dec_point + (Math.abs(number) - s_number) 494 .toFixed(decimals) 495 .slice(2) 496 : ''; 497 498 return sign + ch_first + ch_rest + ch_last; 499}; 500 501ProductSanar.prototype._findParentElement = (elem, selector) => { 502 if (selector) { 503 while (elem !== undefined && elem !== null) { 504 elem = getParent(elem); 505 if (elem !== undefined && elem !== null) { 506 if (elem.matches(selector)) { 507 return elem; 508 } 509 } 510 } 511 return; 512 } else { 513 return; 514 } 515 516 function getParent(elem) { 517 return elem.parentElement; 518 } 519} 520 521 522let productSanar = new ProductSanar();
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.