1/** 2 * ÐÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ Ð¸Ð½Ð¸ÑиализиÑÑÐµÑ ÑабоÑÑ ÐºÐ½Ð¾Ð¿Ð¾Ðº "РкоÑзинÑ", а Ñакже Ñамой коÑÐ·Ð¸Ð½Ñ 3 */ 4new class Cart extends RsJsCore.classes.component { 5 6 constructor(settings) 7 { 8 super(); 9 let defaults = { 10 cartBlockMain: '#rs-cart', 11 cartBlock:'.rs-cart-block', 12 context: '[data-id]', 13 14 addToCart: '.rs-to-cart', 15 reserve: '.rs-reserve', 16 alreadyInCartClass: 'added', 17 addFromDialogClass: 'rs-buy', 18 alreadyInCartClassTimeout:5, 19 20 noShowModalCartClass: 'rs-no-modal-cart', 21 22 offerFormName: '[name="offer"]', 23 amountFormName: '[name="amount"]', 24 multiOfferFormName: '[name^="multioffers"]', 25 concomitantFormName: '[name^="concomitant"]', 26 27 cartTotalPrice: '.rs-cart-items-price', 28 cartTotalItems: '.rs-cart-items-count', 29 cartMobileTotalItems: '.rs-mobile-cart-items-count', 30 cartActiveClass: 'active', 31 32 checkoutButton: '.rs-go-checkout', 33 checkoutButtonActiveClass: 'active', 34 35 cartAmountField: '.rs-amount', 36 cartPage: '#rs-cart-page', 37 cartForm: '#rs-cart-form', 38 cartItem: '.rs-cart-item', 39 cartPageInfo: '.rs-cart-page-info', 40 cartPageInfoText: '', 41 cartItemRemove: '.rs-remove', 42 cartItemRemoveConcomitant: '.rs-remove-concomitant', 43 cartItemOffer: '.rs-offer', 44 cartItemMultiOffer: '.rs-multioffer', 45 cartGoBackButton: '.rs-go-back', 46 cartItemHiddenOffers: '.rs-hidden-multioffer', 47 cartClean: '.rs-clean', 48 cartApplyCoupon: '.rs-apply-coupon', 49 productWrapper: '.rs-product-item', 50 inLoadingClass: 'in-loading', 51 cartConcomitantCheckbox: '.rs-concomitant-checkbox', 52 53 //УмнÑе кнопки, пÑевÑаÑаÑÑиеÑÑ Ð² колиÑеÑÑво 54 55 }; 56 57 this.settings = {...defaults, ...this.getExtendsSettings(), ...settings}; 58 } 59 60 init() { 61 this.utils.on('click', this.settings.addToCart, event => this.addToCart(event)); 62 this.utils.on('click', this.settings.reserve, event => this.reserve(event)); 63 this.utils.on('click', this.settings.checkoutButton, event => this.checkout(event)); 64 65 this.cartBlockMain = document.querySelector(this.settings.cartBlockMain); 66 67 let cartPage = document.querySelector(this.settings.cartPage); 68 if (cartPage) { 69 this.initCart(cartPage.parentNode); 70 71 // Ð¡Ð¾Ñ ÑанÑем ÑодеÑжимое блока доÑÑавки и оплаÑÑ 72 const cartInfo = this.cartPage.querySelector(this.settings.cartPageInfo); 73 74 if (cartInfo) { 75 this.settings.cartPageInfoText = cartInfo.innerHTML; 76 } 77 } 78 79 //УмнÑе кнопки РкоÑÐ·Ð¸Ð½Ñ Ñ ÐºÐ¾Ð»Ð¸ÑеÑÑвом 80 this.utils.on('click', this.settings.smartAmountBuyButton, event => this.smartAmountAdd(event)); 81 } 82 83 /** 84 * ÐобавлÑÐµÑ ÑÐ¾Ð²Ð°Ñ Ð² коÑÐ·Ð¸Ð½Ñ Ð¸ оÑкÑÑÐ²Ð°ÐµÑ Ð¾ÐºÐ½Ð¾ ÑпÑоÑенной коÑÐ·Ð¸Ð½Ñ 85 * 86 * @param event 87 */ 88 addToCart(event) { 89 let button = event.rsTarget; 90 let context = button.closest(this.settings.context); 91 this.changeStateToAdded(button); 92 let formData = this.getProductParams(context); 93 94 if (this.needShowSelectMultiofferDialog(button)) { 95 let url = button.dataset.selectMultiofferHref; 96 this.plugins.openDialog.show({ 97 url: url 98 }); 99 } else { 100 let url = button.dataset.href ? button.dataset.href : button.getAttribute('href'); 101 102 let noShowModalCart = !this.cartBlockMain 103 || this.cartBlockMain.classList.contains(this.settings.noShowModalCartClass) 104 || button.classList.contains(this.settings.noShowModalCartClass); 105 106 this.requestToCart(url, formData, noShowModalCart); 107 108 // if (button.classList.contains(this.settings.addFromDialogClass) && noShowModalCart) { 109 // this.plugins.modal.close(); 110 // } 111 } 112 } 113 114 /** 115 * ÐÑзÑÐ²Ð°ÐµÑ Ð¾ÐºÐ½Ð¾ вÑбоÑа комплекÑаÑии или окно ÑезеÑвиÑÐ¾Ð²Ð°Ð½Ð¸Ñ ÑоваÑа 116 * 117 * @param event 118 */ 119 reserve(event) { 120 let button = event.rsTarget; 121 let url; 122 123 if (this.needShowSelectMultiofferDialog(button)) { 124 url = button.dataset.selectMultiofferHref; 125 } else { 126 url = button.dataset.href; 127 } 128 129 if (url) { 130 this.plugins.openDialog.show({ 131 url: url 132 }); 133 } 134 } 135 136 /** 137 * ÐозвÑаÑÐ°ÐµÑ true, еÑли по нажаÑÐ¸Ñ Ð½Ð° даннÑÑ ÐºÐ½Ð¾Ð¿ÐºÑ Ð² 138 * ÑекÑÑей ÑиÑÑаÑии нÑжно оÑобÑазиÑÑ Ð´Ð¸Ð°Ð»Ð¾Ð³ вÑбоÑа комплекÑаÑий 139 * 140 * @param button 141 */ 142 needShowSelectMultiofferDialog(button) 143 { 144 if (!button.dataset.selectMultiofferHref) return false;
145 let showOffersInListThemeOption = button.closest('[data-sol]'); 146 return !showOffersInListThemeOption || !window.matchMedia('(min-width: 992px)').matches; 147 } 148 149 /** 150 * ÐÑполнÑÐµÑ Ð·Ð°Ð¿ÑÐ¾Ñ Ð·Ð° ÑеÑÐ²ÐµÑ 151 * @param url 152 * @param formData 153 * @param noShowModalCartClass 154 */ 155 requestToCart(url, formData, noShowModalCart) { 156 this.utils.fetchJSON(url, { 157 method:'POST', 158 body: formData 159 }).then((response) => { 160 this.updateCartBlock(response); 161 162 if (!noShowModalCart) { 163 this.plugins.modal.open(response.html, (event) => { 164 this.initCart(event.target); 165 }); 166 } 167 }); 168 } 169 170 /** 171 * ÐниÑиализиÑÑÐµÑ ÑобÑÑÐ¸Ñ Ð²Ð½ÑÑÑи коÑÐ·Ð¸Ð½Ñ 172 * 173 * @param context 174 */ 175 initCart(context) { 176 console.log(context) 177 178 this.cartPage = context.querySelector(this.settings.cartPage); 179 180 if (this.cartPage) { 181 this.utils.on('change', this.settings.cartAmountField, event => this.refresh(), this.cartPage); 182 this.utils.on('click', this.settings.cartItemRemove, event => this.removeProduct(event), this.cartPage); 183 this.utils.on('click', this.settings.cartItemRemoveConcomitant, event => this.removeConcomitant(event), this.cartPage); 184 this.utils.on('change', this.settings.cartConcomitantCheckbox, () => this.refresh(), this.cartPage); 185 this.utils.on('click', this.settings.cartGoBackButton, () => this.goBack(), this.cartPage); 186 this.utils.on('change', this.settings.cartItemOffer, () => this.refresh(), this.cartPage); 187 this.utils.on('change', this.settings.cartItemMultiOffer, (event) => this.changeMultiOffer(event), this.cartPage); 188 this.utils.on('click', this.settings.cartClean, event => this.cleanCart(event), this.cartPage); 189 this.utils.on('click', this.settings.cartApplyCoupon, () => this.refresh(), this.cartPage); 190 191 let form = this.cartPage.querySelector(this.settings.cartForm); 192 if (form) { 193 form.addEventListener('submit', (event) => { 194 clearTimeout(this.cartPage.changeTimer); 195 this.refresh(); 196 event.preventDefault(); 197 }); 198 } 199 } 200 } 201 202 /** 203 * 204 * @param context 205 */ 206 getCurrentValueMatrix(context) { 207 let multiofferValues = []; 208 209 context.querySelectorAll('[data-prop-title]').forEach(element => { 210 multiofferValues.push([element.dataset.propTitle, element.value]); 211 }); 212 213 return multiofferValues; 214 } 215 216 changeMultiOffer(event) { 217 let context = event.target.closest(this.settings.cartItem); 218 let values = this.getCurrentValueMatrix(context); 219 220 let hiddenOffers = context.querySelectorAll(this.settings.cartItemHiddenOffers); 221 let offerInput = context.querySelector(this.settings.cartItemOffer); 222 223 let foundOfferInput; 224 hiddenOffers.forEach(element => { 225 if (element.dataset.info) { 226 let info = JSON.parse(element.dataset.info); 227 let counter = 0; 228 info.forEach(inputPair => { 229 values.forEach(valuesPair => { 230 if (inputPair[0] === valuesPair[0] 231 && inputPair[1] === valuesPair[1]) counter++; 232 }); 233 }); 234 235 if (counter === values.length) { 236 foundOfferInput = element; 237 } 238 } 239 }); 240 241 if (foundOfferInput){ //ÐÑли комплекÑаÑÐ¸Ñ Ð½Ð°Ð¹Ð´ÐµÐ½Ð° 242 offerInput.value = foundOfferInput.value; 243 } else { //ÐÑли не найдена комплекÑаÑиÑ, вÑбеÑем нÑлевÑÑ 244 offerInput.value = 0; 245 } 246 247 this.refresh(); 248 } 249 250 /** 251 * УдалÑÐµÑ Ð¾Ð´Ð¸Ð½ ÑÐ¾Ð²Ð°Ñ Ð¸Ð· коÑÐ·Ð¸Ð½Ñ 252 * 253 * @param event 254 */ 255 removeProduct(event) { 256 event.preventDefault(); 257 if (!this.isLoading()) { 258 let removeButton = event.rsTarget; 259 let cartItem = removeButton.closest(this.settings.cartItem); 260 if (cartItem) { 261 cartItem.style.opacity = 0.5; 262 let other = cartItem.parentNode.querySelectorAll('[data-id="' + cartItem.dataset.productId + '"]'); 263 264 if (!other.length) { 265 document.querySelectorAll( 266 this.settings.productWrapper + '[data-id="' + cartItem.dataset.productId + '"] ' + this.settings.addToCart) 267 .forEach(element => { 268 element.classList.remove(this.settings.alreadyInCartClass); 269 }); 270 } 271 } 272 273 this.refresh(removeButton.getAttribute('href')); 274 } 275 } 276 277 /**
278 * ÐбновлÑÐµÑ ÐºÐ¾ÑÐ·Ð¸Ð½Ñ 279 * 280 * @param url 281 * @param callback 282 */ 283 refresh(url, callback) { 284 285 let cartForm = this.cartPage.querySelector(this.settings.cartForm); 286 let formData = new FormData(cartForm); 287 288 if (!url) { 289 url = cartForm.getAttribute('action'); 290 } 291 292 cartForm.querySelectorAll('input, select, button').forEach(element => { 293 element.disabled = true; 294 }); 295 296 this.showLoading(); 297 this.utils.fetchJSON(url, { 298 method:'POST', 299 body: formData 300 }).then(response => { 301 if (response.redirect) { 302 location.href = response.redirect; 303 } 304 305 if (response.cart.items_count === 0 && this.plugins.modal.isOpen()) { 306 this.plugins.modal.close(); 307 } else { 308 let tmpDiv = document.createElement('div'); 309 tmpDiv.innerHTML = response.html; 310 let element = tmpDiv.querySelector(this.settings.cartPage); 311 if (element) { 312 this.cartPage.insertAdjacentElement('afterend', element); 313 let parent = this.cartPage.parentNode; 314 this.cartPage.remove(); 315 this.initCart(parent); 316 parent.dispatchEvent(new CustomEvent('new-content', {bubbles: true})); 317 parent.dispatchEvent(new CustomEvent('cart.change', {"bubbles": true, "cancelable": true})); 318 } 319 } 320 this.updateCartBlock(response); 321 if (callback) callback(response); 322 }); 323 } 324 325 /** 326 * ÐбновлÑÐµÑ Ð¿Ð°ÑамеÑÑÑ 327 * 328 * @param response 329 */ 330 updateCartBlock(response) { 331 if (response) { 332 global.cartProducts = response.cart.session_cart_products; 333 document.querySelectorAll(this.settings.cartBlock).forEach((cartBlock) => { 334 335 let totalItems = cartBlock.querySelector(this.settings.cartTotalItems); 336 let mobileTotalItems = document.querySelector(this.settings.cartMobileTotalItems); 337 let totalPrice = cartBlock.querySelector(this.settings.cartTotalPrice); 338 let checkoutButton = cartBlock.querySelector(this.settings.checkoutButton); 339 340 totalItems && (totalItems.innerText = response.cart.items_count); 341 mobileTotalItems && (mobileTotalItems.innerText = response.cart.items_count); 342 totalPrice && (totalPrice.innerText = response.cart.total_price); 343 344 if (checkoutButton) { 345 if (response.cart.can_checkout && parseFloat(response.cart.items_count) > 0) { 346 checkoutButton.classList.add(this.settings.checkoutButtonActiveClass); 347 } else { 348 checkoutButton.classList.remove(this.settings.checkoutButtonActiveClass); 349 } 350 } 351 352 if (parseFloat(response.cart.items_count) > 0) { 353 cartBlock.classList.add(this.settings.cartActiveClass); 354 } else { 355 cartBlock.classList.remove(this.settings.cartActiveClass); 356 } 357 cartBlock.dispatchEvent(new CustomEvent('cartblock.update', {"bubbles": true, "cancelable": true})); 358 359 if (this.cartPage) { 360 const cartInfo = this.cartPage.querySelector(this.settings.cartPageInfo); 361 362 if (cartInfo) { 363 cartInfo.innerHTML = this.settings.cartPageInfoText; 364 } 365 366 const productSwipers = document.querySelectorAll('.swiper-products'); 367 368 if (productSwipers.length > 0) 369 RsJsCore.components.productsSlider.initSwipers(); 370 } 371 }); 372 } 373 } 374 375 /** 376 * Ðоказ загÑÑзки 377 */ 378 showLoading() { 379 this.cartPage.classList.add(this.settings.inLoadingClass); 380 } 381 382 /** 383 * ÐозвÑаÑÐ°ÐµÑ true, еÑли в наÑÑоÑÑее вÑÐµÐ¼Ñ Ð¸Ð´ÐµÑ Ð·Ð°Ð³ÑÑзка 384 * 385 * @returns {boolean} 386 */ 387 isLoading() { 388 return this.cartPage.classList.contains(this.settings.inLoadingClass); 389 } 390 391 /** 392 * СобиÑÐ°ÐµÑ Ð¿Ð°ÑамеÑÑÑ ÑоваÑа, коÑоÑÑй бÑÐ´ÐµÑ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½ в коÑзин
392Ñ 393 * 394 * @param context 395 */ 396 getProductParams(context) { 397 let data = new FormData(); 398 if (context) { 399 let radioInput = context.querySelector(this.settings.offerFormName + ':checked'); 400 let hiddenInput = context.querySelector(this.settings.offerFormName); 401 let offerId = radioInput ? radioInput.value : (hiddenInput ? hiddenInput.value : 0); 402 403 //ÐомплекÑаÑÐ¸Ñ 404 if (offerId) { 405 data.append('offer', offerId); 406 } 407 408 //ÐолиÑеÑÑво 409 let amountElement = context.querySelector(this.settings.amountFormName); 410 let amount = amountElement && amountElement.value; 411 if (amount) { 412 data.append('amount', amount); 413 } 414 415 //ÐногомеÑнÑе комплекÑаÑии 416 context.querySelectorAll(this.settings.multiOfferFormName + ':checked').forEach(element => { 417 data.append(element.getAttribute('name'), element.value); 418 }); 419 420 //СопÑÑÑÑвÑÑÑие ÑоваÑÑ 421 context.querySelectorAll(this.settings.concomitantFormName + ':checked').forEach(element => { 422 data.append(element.getAttribute('name'), element.value); 423 }); 424 } 425 426 data.append('floatCart', 1); //СообÑаем, ÑÑо возвÑаÑаÑÑ Ð½Ð°Ð´Ð¾ ÑпÑоÑеннÑÑ ÐºÐ¾ÑÐ·Ð¸Ð½Ñ 427 428 return data; 429 } 430 431 /** 432 * ÐзменÑÐµÑ Ð½Ð°Ð´Ð¿Ð¸ÑÑ Ð½Ð° кнопке, пÑи добавлении в коÑÐ·Ð¸Ð½Ñ 433 * 434 * @param button 435 */ 436 changeStateToAdded(button) { 437 if (button.timeoutText) { 438 clearTimeout(button.timeoutText); 439 } 440 441 button.classList.add(this.settings.alreadyInCartClass); 442 if (!button.dataset.storedText && button.dataset.addText) { 443 button.dataset.storedText = button.innerHTML; 444 button.innerHTML = button.dataset.addText; 445 } 446 447 if (this.settings.alreadyInCartClassTimeout) { 448 button.timeoutText = setTimeout(() => { 449 button.classList.remove(this.settings.alreadyInCartClass); 450 if (button.dataset.storedText) { 451 button.innerHTML = button.dataset.storedText; 452 delete button.dataset.storedText; 453 } 454 }, this.settings.alreadyInCartClassTimeout * 1000); 455 } 456 } 457 458 cleanCart(event) { 459 event.preventDefault(); 460 document.querySelectorAll(this.settings.productWrapper + '[data-id] ' + this.settings.addToCart) 461 .forEach((element) => { 462 element.classList.remove(this.settings.alreadyInCartClass) 463 }); 464 465 this.refresh(event.rsTarget.getAttribute('href')); 466 } 467 468 /** 469 * ÐозвÑаÑÐ°ÐµÑ Ð¿Ð¾Ð»ÑзоваÑÐµÐ»Ñ Ð½Ð°Ð·Ð°Ð´ к покÑпкам 470 */ 471 goBack() { 472 history.back(); 473 } 474 475 /** 476 * ÐÑовеÑÑÐµÑ ÐºÐ¾ÑÐ·Ð¸Ð½Ñ Ð½Ð° оÑибки и еÑли Ð¸Ñ Ð½ÐµÑ, Ñо пеÑенапÑавлÑÐµÑ 477 * полÑзоваÑÐµÐ»Ñ Ð½Ð° оÑоÑмление заказа 478 * @param event 479 */ 480 checkout(event) { 481 if (this.cartPage) { 482 let cartForm = this.cartPage.querySelector(this.settings.cartForm); 483 let url = cartForm.getAttribute('action'); 484 let checkoutParam = (url.indexOf('?') > -1 ? '&' : '?') + 'checkout=1'; 485 this.refresh(url + checkoutParam); 486 event.preventDefault(); 487 } 488 } 489 490 onDocumentReady() { 491 this.init(); 492 } 493 494 onContentReady() { 495 //ÐниÑиализиÑÑем ÑмнÑе кнопки Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¸Ñ ÑоваÑа в коÑÐ·Ð¸Ð½Ñ 496 SmartAmount.init(); 497 } 498}; 499 500 501 502/** 503 * ==================================================== 504 * ÐлаÑÑ Ð¾Ð¿Ð¸ÑÑÐ²Ð°ÐµÑ ÑабоÑÑ Ð¾Ð´Ð½Ð¾Ð¹ Ñмной кнопки РкоÑÐ·Ð¸Ð½Ñ 505 */ 506class SmartAmount 507{ 508 constructor(element, settings) { 509 510 let defaults = { 511 smartAmount: '.rs-sa', 512 smartAmountActiveClass: 'item-product-cart-action_amount', 513 smartAmountBuyButton: '.rs-to-cart', 514 smartAmountIncButton: '.rs-sa-inc', 515 smartAmountDecButton: '.rs-sa-dec', 516 smartAmountInput: '.rs-sa-input',
517 productContext: '[data-id]', 518 delayChangeAmount: 700 519 }; 520 521 this.settings = {...settings, ...defaults}; 522 this.smartButton = element; 523 524 this.smartButton.querySelector(this.settings.smartAmountBuyButton) 525 .addEventListener('click', event => this.addProduct(event)); 526 527 this.smartButton.querySelector(this.settings.smartAmountIncButton) 528 .addEventListener('click', event => this.incButton(event)); 529 530 this.smartButton.querySelector(this.settings.smartAmountDecButton) 531 .addEventListener('click', event => this.decButton(event)); 532 533 this.amountInput = this.smartButton.querySelector(this.settings.smartAmountInput); 534 this.amountInput.addEventListener('keyup', event => this.changeAmount(event)); 535 this.amountInput.addEventListener('blur', event => this.blur(event)); 536 this.amountParams = JSON.parse(this.smartButton.dataset.amountParams); 537 538 document.addEventListener('cart.removeProduct', event => this.onRemoveProduct(event)); 539 540 this.restoreFromCache(); 541 } 542 543 restoreFromCache() { 544 let productId = this.smartButton.closest(this.settings.productContext).dataset.id; 545 if (global.cartProducts) { 546 let numList = global.cartProducts[productId]; 547 if (numList) { 548 let total = 0; 549 for (let num in numList) { 550 total = total + numList[num]; 551 } 552 this.amountInput.value = total; 553 this.smartButton.classList.add(this.settings.smartAmountActiveClass); 554 } else { 555 this.amountInput.value = 0; 556 this.smartButton.classList.remove(this.settings.smartAmountActiveClass); 557 } 558 } 559 } 560 561 onRemoveProduct(event) { 562 let productId = this.smartButton.closest(this.settings.productContext).dataset.id; 563 if (event.detail.productId === productId) { 564 this.amountInput.value = 0; 565 this.amountInput.dispatchEvent(new CustomEvent('keyup', { 566 bubbles: true, 567 detail: { 568 noRefreshCart: true 569 } 570 })); 571 } 572 } 573 574 /** 575 * ÐобавлÑÐµÑ ÑÐ¾Ð²Ð°Ñ Ð² коÑзинÑ, пеÑеклÑÑÐ°ÐµÑ ÑоÑÑоÑние кнопки на колиÑеÑÑво 576 */ 577 addProduct() { 578 this.amountInput.value = this.amountParams.amountAddToCart; 579 this.smartButton.classList.add(this.settings.smartAmountActiveClass); 580 this.smartButton.dispatchEvent(new CustomEvent('add-product', {bubbles: true})); 581 } 582 583 /** 584 * УвелиÑÐ¸Ð²Ð°ÐµÑ ÐºÐ¾Ð»Ð¸ÑеÑÑво ÑоваÑа в коÑзине 585 */ 586 incButton() { 587 let oldValue = parseFloat(this.amountInput.value); 588 let newValue = Math.round((oldValue + this.amountParams.amountStep) * 1000) / 1000; 589 let breakpoint = parseFloat(this.amountParams.amountBreakPoint); 590 591 if (newValue < this.amountParams.minAmount) { 592 newValue = this.amountParams.minAmount; 593 } 594 if (oldValue < breakpoint && newValue > breakpoint) { 595 newValue = breakpoint; 596 } 597 if (this.amountParams.maxAmount !== null && newValue > this.amountParams.maxAmount) { 598 newValue = this.amountParams.maxAmount; 599 this.smartButton.dispatchEvent(new CustomEvent('max-limit', {bubbles:true})); 600 } else { 601 this.smartButton.dispatchEvent(new CustomEvent('increase-amount', {bubbles:true})); 602 } 603 this.amountInput.value = newValue; 604 this.amountInput.dispatchEvent(new Event('keyup', {bubbles: true})); 605 } 606 607 /** 608 * УменÑÑÐ°ÐµÑ ÐºÐ¾Ð»Ð¸ÑеÑÑво ÑоваÑа в коÑзине 609 */ 610 decButton() { 611 612 let oldValue = parseFloat(this.amountInput.value); 613 let newValue = Math.round((oldValue - this.amountParams.amountStep) * 1000) / 1000; 614 let breakpoint = parseFloat(this.amountParams.amountBreakPoint); 615 616 if (newValue < this.amountParams.minAmount) { 617 newValue = 0; 618 } 619 620 if (oldValue > breakpoint && newValue < breakpoint) { 621 newValue = breakpoint; 622 } 623 624 if (newValue != 0 || !this.amountParams.forbidRemoveProducts) { 625 this.smartButton.dispatchEvent(new CustomEvent('decrease-amount', {bubbles:true})); 626 this.amountInput.value = newValue; 627 this.amountInput.dispatchEvent(new Event('keyup', {bubbles: true})); 628 } 629 630 return false;
631 } 632 633 /** 634 * ÐзменÑÐµÑ ÐºÐ¾Ð»Ð¸ÑеÑÑво ÑоваÑа на введенное вÑÑÑнÑÑ 635 */ 636 changeAmount(event) { 637 clearTimeout(this.changeTimeout); 638 this.changeTimeout = setTimeout(() => { 639 let noChangesKeycodes = [16, 17, 18, 35, 36, 37, 39]; 640 if (noChangesKeycodes.includes(event.keyCode)) { 641 return false; 642 } 643 644 let amount = this.amountInput.value; 645 646 if (amount === '') { 647 return false; 648 } 649 650 if (this.amountParams.maxAmount !== null && amount > parseFloat(this.amountParams.maxAmount)) { 651 amount = this.amountParams.maxAmount; 652 this.amountInput.value = amount; 653 this.smartButton.dispatchEvent(new CustomEvent('max-limit', {bubbles: true})); 654 } 655 656 if (amount == 0) { 657 this.smartButton.classList.remove(this.settings.smartAmountActiveClass); 658 this.smartButton.dispatchEvent(new CustomEvent('remove-product', {bubbles: true})); 659 } 660 661 if (!event.detail || !event.detail.noRefreshCart) { 662 let formData = new FormData(); 663 formData.append('id', this.smartButton.closest(this.settings.productContext).dataset.id); 664 formData.append('amount', amount); 665 666 RsJsCore.utils.fetchJSON(this.smartButton.dataset.url, { 667 method: 'post', 668 body: formData 669 }).then(response => { 670 if (response.success) { 671 // ÐбновлÑем коÑÐ·Ð¸Ð½Ñ Ð½Ð° ÑкÑане 672 RsJsCore.components.cart.updateCartBlock(response); 673 } 674 }); 675 } 676 }, this.settings.delayChangeAmount); 677 } 678 679 blur() { 680 if (this.amountInput.value === '') { 681 this.amountInput.value = 0; 682 this.amountInput.dispatchEvent(new Event('keyup', {bubbles: true})); 683 } 684 } 685 686 static init(selector) { 687 document.querySelectorAll(selector ? selector : '.rs-sa').forEach(element => { 688 if (!element.smartAmount) { 689 element.smartAmount = new SmartAmount(element); 690 } 691 }); 692 } 693};
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.