1;(function() { 2 'use strict'; 3 4 BX.namespace('BX.Sale.BasketComponent'); 5 6 BX.Sale.BasketComponent = { 7 maxItemsShowCount: 30, 8 precisionFactor: Math.pow(10, 6), 9 stickyHeaderOffset: 0, 10 11 duration: { 12 priceAnimation: 300, 13 filterTimer: 300 14 }, 15 16 ids: { 17 item: 'basket-item-', 18 quantity: 'basket-item-quantity-', 19 price: 'basket-item-price-', 20 sumPrice: 'basket-item-sum-price-', 21 sumPriceOld: 'basket-item-sum-price-old-', 22 sumPriceDiff: 'basket-item-sum-price-difference-', 23 itemHeightAligner: 'basket-item-height-aligner-', 24 total: 'basket-total-price', 25 basketRoot: 'basket-root', 26 itemListWrapper: 'basket-items-list-wrapper', 27 itemListContainer: 'basket-items-list-container', 28 itemList: 'basket-item-list', 29 itemListTable: 'basket-item-table', 30 itemListEmptyResult: 'basket-item-list-empty-result', 31 itemListOverlay: 'basket-items-list-overlay', 32 warning: 'basket-warning' 33 }, 34 35 initializePrimaryFields: function() 36 { 37 this.templates = {}; 38 this.nodes = {}; 39 40 /** Object of all basket items (itemId => itemArray) */ 41 this.items = {}; 42 43 /** Array of all basket items to show sorted by field SORT */ 44 this.sortedItems = []; 45 46 /** Array of basket items showed on screen */ 47 this.shownItems = []; 48 49 /** Array of basket items changed since last request */ 50 this.changedItems = []; 51 52 /** Array of basket items postponed by pool to edit */ 53 this.postponedItems = []; 54 55 /** Array of basket items with warnings */ 56 this.warningItems = []; 57 58 this.isMobile = BX.browser.IsMobile(); 59 this.isTouch = BX.hasClass(document.documentElement, 'bx-touch'); 60 61 this.lastAction = 'initialLoad'; 62 this.coupons = null; 63 64 this.imagePopup = null; 65 this.loadingScreen = null; 66 67 this.quantityDelay = null; 68 this.quantityTimer = null; 69 }, 70 71 init: function(parameters) 72 { 73 this.initializePrimaryFields(); 74 75 this.params = parameters.params || {}; 76 this.template = parameters.template || ''; 77 this.signedParamsString = parameters.signedParamsString || ''; 78 this.siteId = parameters.siteId || ''; 79 this.siteTemplateId = parameters.siteTemplateId || ''; 80 this.ajaxUrl = this.params.AJAX_PATH || ''; 81 this.templateFolder = parameters.templateFolder || ''; 82 83 this.useDynamicScroll = this.params.USE_DYNAMIC_SCROLL === 'Y'; 84 this.useItemsFilter = this.params.SHOW_FILTER === 'Y' && !this.isMobile; 85 86 this.initializeFilter(); 87 this.applyBasketResult(parameters.result); 88 this.initializeActionPool(); 89 90 if (this.useItemsFilter) 91 { 92 this.checkHeaderDisplay(); 93 this.bindHeaderEvents(); 94 } 95 96 this.initializeBasketItems(); 97 this.editTotal(); 98 this.editWarnings(); 99 100 this.getCacheNode(this.ids.basketRoot).style.opacity = 1; 101 102 this.bindInitialEvents(); 103 }, 104 105 getTemplate: function(templateName) 106 { 107 if (!this.templates.hasOwnProperty(templateName)) 108 { 109 var template = BX(templateName); 110 this.templates[templateName] = BX.type.isDomNode(template) ? template.innerHTML : ''; 111 } 112 113 return this.templates[templateName]; 114 }, 115 116 getCacheNode: function(id) 117 { 118 if (!this.nodes.hasOwnProperty(id)) 119 { 120 this.nodes[id] = BX(id); 121 } 122 123 return this.nodes[id]; 124 }, 125 126 getEntity: function(parent, entity, additionalFilter) 127 { 128 if (!parent || !entity) 129 return null; 130 131 additionalFilter = additionalFilter || ''; 132 133 return parent.querySelector(additionalFilter + '[data-entity="' + entity + '"]'); 134 }, 135 136 getEntities: function(parent, entity, additionalFilter) 137 { 138 if (!parent || !entity) 139 return {length: 0}; 140 141 additionalFilter = additionalFilter || ''; 142 143 return parent.querySelectorAll(additionalFilter + '[data-entity="' + entity + '"]'); 144 }, 145 146 bindInitialEvents: function() 147 { 148 this.bindWarningEvents(); 149 150 BX.bind(window, 'scroll', BX.proxy(this.checkStickyHeaders, this)); 151 BX.bind(window, 'scroll', BX.proxy(this.lazyLoad, this)); 152 153 BX.bind(window, 'resize', BX.throttle(this.checkStickyHeaders, 20, this)); 154 }, 155 156 bindWarningEvents: function() 157 { 158 var showItemsNode = this.getEntity(BX(this.ids.warning), 'basket-items-warning-count'); 159 160 if (BX.type.isDomNode(showItemsNode)) 161 { 162 showItemsNode.style.display = ''; 163 BX.bind(showItemsNode, 'click', BX.delegate(function() {this.toggleFilter('warning');}, this)); 164 } 165 166 BX.bind( 167 this.getEntity(BX(this.ids.warning), 'basket-items-warning-notification-close'), 168 'click', 169 BX.proxy(this.removeAllWarnings, this) 170 ); 171 }, 172 173 toggleFilter: function(event) 174 { 175 var target = BX.type.isNotEmptyString(event) ? 176 this.getEntity( 177 this.getCacheNode(this.ids.itemListWrapper), 178 'basket-items-count', 179 '[data-filter="' + event + '"]' 180 ) 181 : BX.getEventTarget(event); 182 183 if (!BX.type.isDomNode(target) || BX.hasClass(target, 'active')) 184 return; 185 186 var entityName = target.getAttribute('data-filter'); 187 var entities = target.parentNode.querySelectorAll('[data-filter]'); 188 189 for (var i = 0; i < entities.length; i++) 190 { 191 if (entities[i].getAttribute('data-filter') === entityName) 192 { 193 BX.addClass(entities[i], 'active'); 194 } 195 else if (BX.hasClass(entities[i], 'active')) 196 { 197 BX.removeClass(entities[i], 'active'); 198 } 199 } 200 201 this.filter.showFilterByName(entityName); 202 }, 203 204 scrollToFirstItem: function() 205 { 206 var headerNode = this.getEntity(this.getCacheNode(this.ids.itemListWrapper), 'basket-items-list-header'); 207 208 if (BX.type.isDomNode(headerNode)) 209 { 210 var itemListTopPosition = BX.pos(this.getCacheNode(this.ids.itemListContainer)).top; 211 var headerBottomPosition = BX.pos(headerNode).bottom; 212 213 if (itemListTopPosition < headerBottomPosition) 214 { 215 window.scrollTo(0, itemListTopPosition - this.stickyHeaderOffset); 216 } 217 } 218 }, 219 220 showItemsOverlay: function() 221 {
222 var overlay = this.getCacheNode(this.ids.itemListOverlay); 223 224 if (BX.type.isDomNode(overlay)) 225 { 226 overlay.style.display = ''; 227 } 228 }, 229 230 hideItemsOverlay: function() 231 { 232 var overlay = this.getCacheNode(this.ids.itemListOverlay); 233 234 if (BX.type.isDomNode(overlay)) 235 { 236 overlay.style.display = 'none'; 237 } 238 }, 239 240 checkHeaderDisplay: function() 241 { 242 var header = this.getCacheNode(this.ids.itemListWrapper); 243 244 if (BX.type.isDomNode(header)) 245 { 246 BX.removeClass(header, 'basket-items-list-wrapper-light'); 247 } 248 }, 249 250 bindHeaderEvents: function() 251 { 252 var entities = this.getEntities(this.getCacheNode(this.ids.itemListWrapper), 'basket-items-count'); 253 254 for (var i = 0; i < entities.length; i++) 255 { 256 BX.bind(entities[i], 'click', BX.proxy(this.toggleFilter, this)); 257 } 258 }, 259 260 checkStickyHeaders: function() 261 { 262 if (this.isMobile) 263 return; 264 265 var node, position; 266 var border = 2, offset = 0; 267 var scrollTop = this.getDocumentScrollTop(); 268 var basketPosition = BX.pos(this.getCacheNode(this.ids.basketRoot)); 269 var basketScrolledToEnd = scrollTop + 200 >= basketPosition.bottom; 270 271 if (BX.util.in_array('top', this.params.TOTAL_BLOCK_DISPLAY)) 272 { 273 var totalBlockNode = this.getEntity(this.getCacheNode(this.ids.basketRoot), 'basket-total-block'); 274 if (BX.type.isDomNode(totalBlockNode)) 275 { 276 node = this.getEntity(totalBlockNode, 'basket-checkout-aligner'); 277 if (BX.type.isDomNode(node)) 278 { 279 position = BX.pos(totalBlockNode); 280 281 if (scrollTop >= position.top) 282 { 283 offset += node.clientHeight; 284 285 if (!BX.hasClass(node, 'basket-checkout-container-fixed')) 286 { 287 totalBlockNode.style.height = position.height + 'px'; 288 289 node.style.width = node.clientWidth + border + 'px'; 290 BX.addClass(node, 'basket-checkout-container-fixed'); 291 } 292 } 293 else if (BX.hasClass(node, 'basket-checkout-container-fixed')) 294 { 295 totalBlockNode.style.height = ''; 296 297 node.style.width = ''; 298 BX.removeClass(node, 'basket-checkout-container-fixed'); 299 } 300 301 if (basketScrolledToEnd) 302 { 303 if (!BX.hasClass(node, 'basket-checkout-container-fixed-hide')) 304 { 305 BX.addClass(node, 'basket-checkout-container-fixed-hide'); 306 } 307 } 308 else if (BX.hasClass(node, 'basket-checkout-container-fixed-hide')) 309 { 310 BX.removeClass(node, 'basket-checkout-container-fixed-hide'); 311 } 312 } 313 } 314 } 315 316 if (this.useItemsFilter) 317 { 318 var itemWrapperNode = this.getCacheNode(this.ids.itemListWrapper); 319 320 node = this.getEntity(itemWrapperNode, 'basket-items-list-header'); 321 if (BX.type.isDomNode(node)) 322 { 323 position = BX.pos(itemWrapperNode); 324 325 if ((scrollTop + offset >= position.top) && !basketScrolledToEnd) 326 { 327 if (!BX.hasClass(node, 'basket-items-list-header-fixed')) 328 { 329 node.style.width = node.clientWidth + border + 'px'; 330 331 itemWrapperNode.style.paddingTop = node.clientHeight + 'px'; 332 333 BX.addClass(node, 'basket-items-list-header-fixed'); 334 } 335 336 if (offset) 337 { 338 node.style.top = offset + 'px'; 339 } 340 341 offset += node.clientHeight; 342 } 343 else if (BX.hasClass(node, 'basket-items-list-header-fixed')) 344 { 345 itemWrapperNode.style.paddingTop = ''; 346 347 node.style.width = ''; 348 node.style.top = ''; 349 350 BX.removeClass(node, 'basket-items-list-header-fixed'); 351 } 352 } 353 } 354 355 this.stickyHeaderOffset = offset; 356 }, 357 358 getDocumentScrollTop: function() 359 { 360 return window.scrollY 361 || window.pageYOffset 362 || document.body.scrollTop + (document.documentElement && document.documentElement.scrollTop || 0); 363 }, 364 365 lazyLoad: function() 366 { 367 var itemsNodePosition = BX.pos(this.getCacheNode(this.ids.itemListContainer)); 368 369 if (this.getDocumentScrollTop() + window.innerHeight >= itemsNodePosition.bottom - 400) 370 { 371 var itemIds = this.getItemsAfter(); 372 if (itemIds.length) 373 { 374 this.editBasketItems(itemIds); 375 } 376 } 377 }, 378 379 fireCustomEvents: function() 380 { 381 if (this.result.EVENT_ONCHANGE_ON_START === 'Y') 382 { 383 BX.onCustomEvent('OnBasketChange'); 384 } 385 386 if (this.params.HIDE_COUPON !== 'Y') 387 { 388 if (this.coupons !== null && this.coupons !== this.result.COUPON_LIST) 389 { 390 BX.onCustomEvent('OnCouponApply'); 391 } 392 393 this.coupons = this.result.COUPON_LIST; 394 } 395 }, 396 397 editTotal: function() 398 { 399 this.fillTotalBlocks(); 400 this.showItemsCount(); 401 this.showWarningItemsCount(); 402 this.showNotAvailableItemsCount(); 403 this.showDelayedItemsCount(); 404 }, 405 406 fillTotalBlocks: function() 407 { 408 var totalNodes = this.getEntities(this.getCacheNode(this.ids.basketRoot), 'basket-total-block'); 409 410 if (totalNodes && totalNodes.length) 411 { 412 var totalTemplate = this.getTemplate('basket-total-template'); 413 if (totalTemplate) 414 { 415 var totalRender = this.render(totalTemplate, this.result.TOTAL_RENDER_DATA); 416 417 for (var i in totalNodes) 418 { 419 if (totalNodes.hasOwnProperty(i) && BX.type.isDomNode(totalNodes[i])
419) 420 { 421 totalNodes[i].innerHTML = totalRender; 422 423 this.bindTotalEvents(totalNodes[i]); 424 } 425 } 426 } 427 } 428 429 this.checkStickyHeaders(); 430 }, 431 432 showItemsCount: function() 433 { 434 var itemCountNode = this.getEntity( 435 this.getCacheNode(this.ids.itemListWrapper), 436 'basket-items-count', 437 '[data-filter="all"]' 438 ); 439 440 if (BX.type.isDomNode(itemCountNode)) 441 { 442 itemCountNode.innerHTML = BX.message('SBB_IN_BASKET') + ' ' + this.result.BASKET_ITEMS_COUNT + ' ' + this.getGoodsMessage(this.result.BASKET_ITEMS_COUNT); 443 itemCountNode.style.display = ''; 444 } 445 }, 446 447 showSimilarCount: function(state) 448 { 449 var itemCountNode = this.getEntity( 450 this.getCacheNode(this.ids.itemListWrapper), 451 'basket-items-count', 452 '[data-filter="similar"]' 453 ); 454 455 if (BX.type.isDomNode(itemCountNode)) 456 { 457 if (state) 458 { 459 itemCountNode.innerHTML = this.sortedItems.length + ' ' 460 + this.getGoodsMessage(this.result.BASKET_ITEMS_COUNT, 'SBB_SIMILAR_ITEM'); 461 itemCountNode.style.display = ''; 462 } 463 else 464 { 465 itemCountNode.style.display = 'none'; 466 } 467 } 468 }, 469 470 showWarningItemsCount: function() 471 { 472 var itemCountNode = this.getEntity( 473 this.getCacheNode(this.ids.itemListWrapper), 474 'basket-items-count', 475 '[data-filter="warning"]' 476 ); 477 478 if (BX.type.isDomNode(itemCountNode)) 479 { 480 if (this.warningItems.length) 481 { 482 itemCountNode.innerHTML = this.warningItems.length + ' ' + BX.message('SBB_BASKET_ITEMS_WARNING'); 483 itemCountNode.style.display = ''; 484 } 485 else 486 { 487 itemCountNode.style.display = 'none'; 488 } 489 } 490 }, 491 492 showNotAvailableItemsCount: function() 493 { 494 var itemCountNode = this.getEntity( 495 this.getCacheNode(this.ids.itemListWrapper), 496 'basket-items-count', 497 '[data-filter="not-available"]' 498 ); 499 500 if (BX.type.isDomNode(itemCountNode)) 501 { 502 if (parseInt(this.result.NOT_AVAILABLE_BASKET_ITEMS_COUNT)) 503 { 504 itemCountNode.innerHTML = this.result.NOT_AVAILABLE_BASKET_ITEMS_COUNT + ' ' 505 + this.getGoodsMessage(this.result.NOT_AVAILABLE_BASKET_ITEMS_COUNT, 'SBB_NOT_AVAILABLE_ITEM'); 506 itemCountNode.style.display = ''; 507 } 508 else 509 { 510 itemCountNode.style.display = 'none'; 511 } 512 } 513 }, 514 515 showDelayedItemsCount: function() 516 { 517 var itemCountNode = this.getEntity( 518 this.getCacheNode(this.ids.itemListWrapper), 519 'basket-items-count', 520 '[data-filter="delayed"]' 521 ); 522 523 if (BX.type.isDomNode(itemCountNode)) 524 { 525 if (parseInt(this.result.DELAYED_BASKET_ITEMS_COUNT)) 526 { 527 itemCountNode.innerHTML = this.result.DELAYED_BASKET_ITEMS_COUNT + ' ' 528 + this.getGoodsMessage(this.result.DELAYED_BASKET_ITEMS_COUNT, 'SBB_DELAYED_ITEM'); 529 itemCountNode.style.display = ''; 530 } 531 else 532 { 533 itemCountNode.style.display = 'none'; 534 } 535 } 536 }, 537 538 getGoodsMessage: function(count, customMessage) 539 { 540 var mesCode; 541 var countReminder = (count > 10 && count < 20) ? 0 : count % 10; 542 543 if (countReminder === 1) 544 { 545 mesCode = customMessage || 'SBB_GOOD'; 546 } 547 else if (countReminder >= 2 && countReminder <= 4) 548 { 549 mesCode = customMessage ? customMessage + '_2' : 'SBB_GOOD_2'; 550 } 551 else 552 { 553 mesCode = customMessage ? customMessage + 'S' : 'SBB_GOODS'; 554 } 555 556 return BX.message(mesCode); 557 }, 558 559 bindTotalEvents: function(node) 560 { 561 if (!this.result.TOTAL_RENDER_DATA.DISABLE_CHECKOUT) 562 { 563 BX.bind(this.getEntity(node, 'basket-checkout-button'), 'click', BX.proxy(this.checkOutAction, this)); 564 } 565 566 BX.bind(this.getEntity(node, 'basket-coupon-input'), 'change', BX.proxy(this.addCouponAction, this)); 567 BX.bind(this.getEntity(node, 'basket-coupon-input'), 'paste', BX.proxy(this.pasteCouponAction, this)); 568 569 var couponNodes = this.getEntities(node, 'basket-coupon-delete'); 570 for (var i = 0, l = couponNodes.length; i < l; i++) 571 { 572 BX.bind(couponNodes[i], 'click', BX.proxy(this.removeCouponAction, this)); 573 } 574 575 }, 576 577 checkOutAction: function() 578 { 579 document.location.href = this.params.PATH_TO_ORDER; 580 }, 581 582 addCouponAction: function(event) 583 { 584 var target = BX.getEventTarget(event); 585 if (target && target.value) 586 { 587 this.actionPool.addCoupon(target.value); 588 target.disabled = true; 589 } 590 591 if(modalReminder){ 592 modalReminder.resetTimer(); 593 } 594 }, 595 596 pasteCouponAction: function(event) 597 { 598 setTimeout(BX.delegate(function() { 599 this.addCouponAction(event); 600 }, this), 10); 601 }, 602 603 removeCouponAction: function() 604 { 605 var value = BX.proxy_context && BX.util.trim(BX.proxy_context.getAttribute('data-coupon')); 606 if (value) 607 { 608 this.actionPool.removeCoupon(value); 609 } 610 }, 611 612 initializeActionPool: function() 613 { 614 this.actionPool = new BX.Sale.BasketActionPool(this); 615 }, 616 617 initializeFilter: function() 618 { 619 this.filter = new BX.Sale.BasketFilter(this); 620 }, 621 622 /** 623 * Send ajax request with basket data and executes callback by action 624 */ 625 sendRequest: function(action, data) 626 { 627 this.lastAction = action; 628 629 if (this.lastAction === 'recalculateAjax') 630 { 631 // we use it to reload all items if applied discounts changed 632 data.lastAppliedDiscounts = BX.util.array_keys(this.result.FULL_DISCOUNT_LIST).join(','); 633 634 if (this.params.USE_ENHANCED_ECOMMERCE === 'Y') 635 { 636 this.checkAnalytics(data); 637 } 638 } 639 640 BX.ajax({ 641 method: 'POST', 642 dataType: 'json', 643 url: this.ajaxUrl, 644 data: this.getData(data), 645 onsuccess: BX.delegate(function(result) { 646 this.actionPool.doProcessing(false); 647 648 if (!BX.type.isPlainObject(result)) 649 return; 650 651 this.actionPool.setRefreshStatus(result.BASKET_REFRESHED); 652 653 if (result.RESTORED_BASKET_ITEMS) 654 { 655 this.restoreBasketItems(result.RESTORED_BASKET_ITEMS); 656 } 657 658 if (result.DELETED_BASKET_ITEMS) 659 { 660 this.deleteBasketItems(result.DELETED_BASKET_ITEMS, this.params.SHOW_RESTORE === 'Y'); 661 } 662 663 if (result.MERGED_BASKET_ITEMS) 664 { 665 this.deleteBasketItems(result.MERGED_BASKET_ITEMS, false, true); 666 } 667 668 this.applyBasketResult(result.BASKET_DATA); 669 this.editBasketItems(this.getItemsToEdit()); 670 this.editTotal(); 671 672 this.applyPriceAnimation(); 673 this.editWarnings(); 674 675 this.actionPool.switchTimer(); 676 677 if (this.isBasketIntegrated() && this.isBasketChanged()) 678 { 679 BX.Sale.OrderAjaxComponent.sendRequest(); 680 } 681 }, this), 682 onfailure: BX.delegate(function() { 683 this.actionPool.doProcessing(false); 684 }, this) 685 }); 686 }, 687 688 isBasketIntegrated: function() 689 { 690 return this.params.BASKET_WITH_ORDER_INTEGRATION === 'Y'; 691 }, 692 693 isBasketChanged: function() 694 { 695 return this.changedItems.length; 696 }, 697 698 addPriceAnimationData: function(nodeId, start, finish, currency) 699 { 700 if (!BX.type.isPlainObject(this.priceAnimationData)) 701 { 702 this.clearPriceAnimationData(); 703 } 704
705 this.priceAnimationData.start[nodeId] = parseFloat(start); 706 this.priceAnimationData.finish[nodeId] = parseFloat(finish); 707 this.priceAnimationData.currency[nodeId] = currency; 708 this.priceAnimationData.int[nodeId] = (parseFloat(start) === parseInt(start)) && (parseFloat(finish) === parseInt(finish)); 709 }, 710 711 clearPriceAnimationData: function() 712 { 713 this.priceAnimationData = { 714 start: {}, 715 finish: {}, 716 currency: {}, 717 int: {} 718 }; 719 }, 720 721 applyBasketResult: function(result) 722 { 723 this.changedItems = []; 724 this.clearPriceAnimationData(); 725 726 if (!BX.type.isPlainObject(result)) 727 { 728 return; 729 } 730 731 if (result.BASKET_ITEM_RENDER_DATA) 732 { 733 var i, newData; 734 735 for (i in result.BASKET_ITEM_RENDER_DATA) 736 { 737 if (result.BASKET_ITEM_RENDER_DATA.hasOwnProperty(i)) 738 { 739 newData = result.BASKET_ITEM_RENDER_DATA[i]; 740 newData.WARNINGS = this.checkBasketItemWarnings(newData, result.WARNING_MESSAGE_WITH_CODE); 741 742 if (this.items[newData.ID]) 743 { 744 if (JSON.stringify(this.items[newData.ID]) === JSON.stringify(newData)) 745 { 746 continue; 747 } 748 } 749 else 750 { 751 this.addSortedItem(newData.ID, true); 752 } 753 754 this.changedItems.push(newData.ID); 755 756 newData = this.checkBasketItemsAnimation(newData); 757 this.items[newData.ID] = newData; 758 } 759 } 760 761 this.changedItems = BX.util.array_unique(this.changedItems.concat(this.getChangedSimilarOffers())); 762 763 if (this.isBasketChanged()) 764 { 765 this.sortSortedItems(true); 766 } 767 } 768 769 if (result.TOTAL_RENDER_DATA) 770 { 771 result.TOTAL_RENDER_DATA = this.checkTotalAnimation(result.TOTAL_RENDER_DATA); 772 } 773 774 this.result = result; 775 }, 776 777 itemSortFunction: function(a, b) 778 { 779 if (!this.items.hasOwnProperty(a) || !this.items.hasOwnProperty(b)) 780 { 781 return 0; 782 } 783 784 return parseFloat(this.items[a].SORT) - parseFloat(this.items[b].SORT); 785 }, 786 787 getChangedSimilarOffers: function() 788 { 789 var changedSimilarOffers = []; 790 791 var otherSimilarItemsQuantity, totalSimilarItemsQuantity; 792 var hashMap = this.getHashMap(); 793 794 for (var hash in hashMap) 795 { 796 if (hashMap.hasOwnProperty(hash)) 797 { 798 if (hashMap[hash].length > 1) 799 { 800 for (var i = 0; i < hashMap[hash].length; i++) 801 { 802 otherSimilarItemsQuantity = 0; 803 totalSimilarItemsQuantity = 0; 804 805 for (var k = 0; k < hashMap[hash].length; k ++) 806 { 807 if (hashMap[hash][k] != hashMap[hash][i]) 808 { 809 otherSimilarItemsQuantity += parseFloat(this.items[hashMap[hash][k]].QUANTITY); 810 } 811 812 totalSimilarItemsQuantity += parseFloat(this.items[hashMap[hash][k]].QUANTITY); 813 } 814 815 if ( 816 !this.items[hashMap[hash][i]].HAS_SIMILAR_ITEMS 817 || this.items[hashMap[hash][i]].SIMILAR_ITEMS_QUANTITY != otherSimilarItemsQuantity 818 || this.items[hashMap[hash][i]].TOTAL_SIMILAR_ITEMS_QUANTITY != totalSimilarItemsQuantity 819 ) 820 { 821 changedSimilarOffers.push(hashMap[hash][i]); 822 823 this.items[hashMap[hash][i]].HAS_SIMILAR_ITEMS = true; 824 this.items[hashMap[hash][i]].SIMILAR_ITEMS_QUANTITY = otherSimilarItemsQuantity; 825 this.items[hashMap[hash][i]].TOTAL_SIMILAR_ITEMS_QUANTITY = totalSimilarItemsQuantity; 826 827 this.items[hashMap[hash][i]].ALL_AVAILABLE_QUANTITY = this.items[hashMap[hash][i]].AVAILABLE_QUANTITY; 828 this.items[hashMap[hash][i]].AVAILABLE_QUANTITY = this.items[hashMap[hash][i]].ALL_AVAILABLE_QUANTITY - otherSimilarItemsQuantity; 829 } 830 } 831 } 832 else if (hashMap[hash][0] && this.items[hashMap[hash][0]].HAS_SIMILAR_ITEMS) 833 { 834 changedSimilarOffers.push(hashMap[hash][0]); 835 836 delete this.items[hashMap[hash][0]].HAS_SIMILAR_ITEMS; 837 delete this.items[hashMap[hash][0]].SIMILAR_ITEMS_QUANTITY; 838 delete this.items[hashMap[hash][0]].TOTAL_SIMILAR_ITEMS_QUANTITY; 839 840 this.items[hashMap[hash][0]].AVAILABLE_QUANTITY = this.items[hashMap[hash][0]].ALL_AVAILABLE_QUANTITY; 841 delete this.items[hashMap[hash][0]].ALL_AVAILABLE_QUANTITY; 842 } 843 } 844 } 845 846 return changedSimilarOffers; 847 }, 848 849 getHashMap: function() 850 { 851 var hashMap = {}; 852 853 for (var id in this.items) 854 { 855 if (this.items.hasOwnProperty(id) && this.isItemAvailable(id)) 856 { 857 if (!hashMap.hasOwnProperty(this.items[id].HASH)) 858 { 859 hashMap[this.items[id].HASH] = []; 860 } 861 862 hashMap[this.items[id].HASH].push(id); 863 } 864 } 865 866 return hashMap; 867 }, 868 869 isItemAvailable: function(itemId) 870 { 871 var sortedItems = this.filter.isActive() ? this.filter.realSortedItems : this.sortedItems; 872 873 return !this.items[itemId].NOT_AVAILABLE 874 && !this.items[itemId].SHOW_RESTORE 875 && BX.util.in_array(itemId, sortedItems); 876 }, 877 878 checkTotalAnimation: function(totalData) 879 { 880 if (this.result && this.result.TOTAL_RENDER_DATA && parseFloat(this.result.TOTAL_RENDER_DATA.PRICE) > parseFloat(totalData.PRICE)) 881 { 882 totalData.PRICE_NEW = totalData.PRICE; 883 totalData.PRICE = this.result.TOTAL_RENDER_DATA.PRICE; 884 885 totalData.PRICE_FORMATED_NEW = totalData.PRICE_FORMATED; 886 totalData.PRICE_FORMATED = this.result.TOTAL_RENDER_DATA.PRICE_FORMATED; 887 888 this.addPriceAnimationData(this.ids.total, totalData.PRICE, totalData.PRICE_NEW, totalData.CURRENCY); 889 } 890 891 return totalData; 892 }, 893 894 checkBasketItemsAnimation: function(itemData) 895 { 896 var itemId = itemData.ID; 897 898 if (this.items[itemId]) 899 { 900 var quantityNode = BX(this.ids.quantity + itemId); 901 if ( 902 BX.type.isDomNode(quantityNode) 903 && !this.actionPool.isItemInPool(itemId) 904 && parseFloat(quantityNode.value) !== parseFloat(itemData.QUANTITY) 905 ) 906 { 907 itemData.QUANTITY_ANIMATION = true; 908 this.actionPool.clearLastActualQuantityPool(itemId); 909 } 910 911 if (parseFloat(this.items[itemId].PRICE) > parseFloat(itemData.PRICE)) 912 { 913 itemData.PRICE_NEW = itemData.PRICE; 914 itemData.PRICE = this.items[itemId].PRICE; 915 916 itemData.PRICE_FORMATED_NEW = itemData.PRICE_FORMATED; 917 itemData.PRICE_FORMATED = this.items[itemId].PRICE_FORMATED; 918 919 this.addPriceAnimationData(this.ids.price + itemId, itemData.PRICE, itemData.PRICE_NEW, itemData.CURRENCY); 920 } 921 922 if ( 923 BX.util.in_array('SUM', this.params.COLUMNS_LIST) 924 && parseFloat(this.items[itemId].SUM_PRICE) > parseFloat(itemData.SUM_PRICE) 925 && parseFloat(this.items[itemId].QUANTITY) === parseFloat(itemData.QUANTITY) 926 ) 927 { 928 itemData.SUM_PRICE_NEW = itemData.SUM_PRICE;
929 itemData.SUM_PRICE = this.items[itemId].SUM_PRICE; 930 931 itemData.SUM_PRICE_FORMATED_NEW = itemData.SUM_PRICE_FORMATED; 932 itemData.SUM_PRICE_FORMATED = this.items[itemId].SUM_PRICE_FORMATED; 933 934 this.addPriceAnimationData(this.ids.sumPrice + itemId, itemData.SUM_PRICE, itemData.SUM_PRICE_NEW, itemData.CURRENCY); 935 } 936 } 937 938 return itemData; 939 }, 940 941 getData: function(data) 942 { 943 data = data || {}; 944 945 data[this.params.ACTION_VARIABLE] = this.lastAction; 946 data.via_ajax = 'Y'; 947 data.site_id = this.siteId; 948 data.site_template_id = this.siteTemplateId; 949 data.sessid = BX.bitrix_sessid(); 950 data.template = this.template; 951 data.signedParamsString = this.signedParamsString; 952 953 return data; 954 }, 955 956 startLoader: function() 957 { 958 // if (!this.loadingScreen) 959 // { 960 // this.loadingScreen = new BX.PopupWindow('loading_screen', null, { 961 // events: { 962 // onAfterPopupShow: BX.delegate(function() { 963 // BX.cleanNode(this.loadingScreen.popupContainer); 964 // BX.removeClass(this.loadingScreen.popupContainer, 'popup-window'); 965 // this.loadingScreen.popupContainer.appendChild( 966 // BX.create('IMG', {props: {src: this.templateFolder + '/images/loader.gif'}}) 967 // ); 968 // this.loadingScreen.popupContainer.removeAttribute('style'); 969 // this.loadingScreen.popupContainer.style.display = 'block'; 970 // }, this) 971 // } 972 // }); 973 // BX.addClass(this.loadingScreen.popupContainer, 'bx-step-opacity'); 974 // } 975 // 976 // this.loadingScreen.show(); 977 }, 978 979 /** 980 * Hiding loader image with overlay. 981 */ 982 endLoader: function() 983 { 984 // if (this.loadingScreen && this.loadingScreen.isShown()) 985 // { 986 // this.loadingScreen.close(); 987 // } 988 }, 989 990 editWarnings: function() 991 { 992 this.editGeneralWarnings(); 993 this.editBasketItemWarnings(); 994 this.toggleWarningBlock(); 995 this.showWarningItemsCount(); 996 }, 997 998 editGeneralWarnings: function() 999 { 1000 var warningsNode = this.getEntity(this.getCacheNode(this.ids.warning), 'basket-general-warnings'); 1001 1002 if (BX.type.isDomNode(warningsNode)) 1003 { 1004 var generalWarningText = warningsNode.innerHTML; 1005 1006 if (this.result.WARNING_MESSAGE_WITH_CODE) 1007 { 1008 for (var code in this.result.WARNING_MESSAGE_WITH_CODE) 1009 { 1010 if (this.result.WARNING_MESSAGE_WITH_CODE.hasOwnProperty(code)) 1011 { 1012 if ( 1013 !this.items[code] 1014 && generalWarningText.indexOf(this.result.WARNING_MESSAGE_WITH_CODE[code]) === -1 1015 ) 1016 { 1017 generalWarningText += this.result.WARNING_MESSAGE_WITH_CODE[code] + '<br/>'; 1018 } 1019 } 1020 } 1021 } 1022 1023 if (generalWarningText) 1024 { 1025 warningsNode.innerHTML = generalWarningText; 1026 warningsNode.style.display = ''; 1027 } 1028 else 1029 { 1030 warningsNode.style.display = 'none'; 1031 warningsNode.innerHTML = ''; 1032 } 1033 } 1034 }, 1035 1036 editBasketItemWarnings: function() 1037 { 1038 var itemsWarningsNode = this.getEntity(this.getCacheNode(this.ids.warning), 'basket-item-warnings'); 1039 1040 if (BX.type.isDomNode(itemsWarningsNode)) 1041 { 1042 if (this.warningItems.length) 1043 { 1044 var warningCount = this.getEntity(itemsWarningsNode, 'basket-items-warning-count'); 1045 if (BX.type.isDomNode(warningCount)) 1046 { 1047 warningCount.innerHTML = this.warningItems.length + ' ' + this.getGoodsMessage(this.warningItems.length); 1048 } 1049 1050 itemsWarningsNode.style.display = ''; 1051 } 1052 else if (itemsWarningsNode.style.display !== 'none') 1053 { 1054 itemsWarningsNode.style.display = 'none'; 1055 1056 if (this.filter.isActive()) 1057 { 1058 this.toggleFilter('all'); 1059 } 1060 } 1061 } 1062 }, 1063 1064 toggleWarningBlock: function() 1065 { 1066 var warningNode = this.getCacheNode(this.ids.warning); 1067 1068 if (BX.type.isDomNode(warningNode)) 1069 { 1070 var generalWarningNode = this.getEntity(warningNode, 'basket-general-warnings'); 1071 var itemsWarningsNode = this.getEntity(warningNode, 'basket-item-warnings'); 1072 1073 if ( 1074 (!BX.type.isDomNode(generalWarningNode) || generalWarningNode.style.display === 'none') 1075 && (!BX.type.isDomNode(itemsWarningsNode) || itemsWarningsNode.style.display === 'none') 1076 ) 1077 { 1078 warningNode.style.display = 'none'; 1079 } 1080 else 1081 { 1082 warningNode.style.display = ''; 1083 } 1084 } 1085 }, 1086 1087 checkBasketItemWarnings: function(itemData, warnings) 1088 { 1089 if (!itemData) 1090 return; 1091 1092 var itemWarnings; 1093 1094 if (this.items[itemData.ID] && this.lastAction === 'refreshAjax') 1095 { 1096 itemWarnings = this.items[itemData.ID].WARNINGS; 1097 } 1098 else 1099 {
1100 itemWarnings = []; 1101 } 1102 1103 if (BX.type.isArray(warnings[itemData.ID]) && warnings[itemData.ID].length) 1104 { 1105 for (var i in warnings[itemData.ID]) 1106 { 1107 if (warnings[itemData.ID].hasOwnProperty(i) && !BX.util.in_array(warnings[itemData.ID][i], itemWarnings)) 1108 { 1109 itemWarnings.push(warnings[itemData.ID][i]); 1110 } 1111 } 1112 } 1113 1114 if (itemWarnings.length) 1115 { 1116 if (!BX.util.in_array(itemData.ID, this.warningItems)) 1117 { 1118 this.warningItems.push(itemData.ID); 1119 } 1120 } 1121 else if (BX.util.in_array(itemData.ID, this.warningItems)) 1122 { 1123 this.warningItems.splice(BX.util.array_search(itemData.ID, this.warningItems), 1); 1124 } 1125 1126 return itemWarnings; 1127 }, 1128 1129 removeAllWarnings: function(event) 1130 { 1131 this.clearGeneralWarnings(); 1132 this.clearBasketItemsWarnings(); 1133 1134 this.editWarnings(); 1135 1136 event && event.preventDefault(); 1137 }, 1138 1139 clearGeneralWarnings: function() 1140 { 1141 this.result.WARNING_MESSAGE_WITH_CODE = {}; 1142 1143 var generalWarningNode = this.getEntity(this.getCacheNode(this.ids.warning), 'basket-general-warnings'); 1144 1145 if (BX.type.isDomNode(generalWarningNode)) 1146 { 1147 generalWarningNode.innerHTML = ''; 1148 } 1149 }, 1150 1151 clearBasketItemsWarnings: function() 1152 { 1153 var itemsToEdit = []; 1154 1155 for (var i in this.warningItems) 1156 { 1157 if (this.warningItems.hasOwnProperty(i)) 1158 { 1159 this.items[this.warningItems[i]].WARNINGS = []; 1160 1161 if (this.isItemShown(this.warningItems[i])) 1162 { 1163 itemsToEdit.push(this.warningItems[i]); 1164 } 1165 } 1166 } 1167 1168 this.warningItems = []; 1169 this.editBasketItems(itemsToEdit); 1170 }, 1171 1172 isItemShown: function(itemId) 1173 { 1174 return BX.util.in_array(itemId, this.shownItems); 1175 }, 1176 1177 initializeBasketItems: function() 1178 { 1179 if (Object.keys(this.items).length === 0) 1180 return; 1181 1182 for (var i = 0; i < this.sortedItems.length; i++) 1183 { 1184 if (this.useDynamicScroll && this.shownItems.length >= this.maxItemsShowCount) 1185 { 1186 break; 1187 } 1188 1189 this.createBasketItem(this.sortedItems[i]); 1190 } 1191 }, 1192 1193 createBasketItem: function(itemId) 1194 { 1195 if (!this.items[itemId]) 1196 { 1197 return; 1198 } 1199 1200 var basketItemTemplate = this.getTemplate('basket-item-template'); 1201 if (basketItemTemplate) 1202 { 1203 var basketItemHtml = this.renderBasketItem(basketItemTemplate, this.items[itemId]); 1204 var sortIndex = BX.util.array_search(itemId, this.sortedItems); 1205 1206 if (this.shownItems.length && sortIndex >= 0) 1207 { 1208 if (sortIndex < BX.util.array_search(this.shownItems[0], this.sortedItems)) 1209 { 1210 // insert before 1211 BX(this.ids.item + this.shownItems[0]).insertAdjacentHTML('beforebegin', basketItemHtml); 1212 this.shownItems.unshift(itemId); 1213 } 1214 else if (sortIndex > BX.util.array_search(this.shownItems[this.shownItems.length - 1], this.sortedItems)) 1215 { 1216 // insert after 1217 BX(this.ids.item + this.shownItems[this.shownItems.length - 1]).insertAdjacentHTML('afterend', basketItemHtml); 1218 this.shownItems.push(itemId); 1219 } 1220 else 1221 { 1222 // insert between 1223 BX(this.ids.item + this.sortedItems[sortIndex + 1]).insertAdjacentHTML('beforebegin', basketItemHtml); 1224 this.shownItems.splice(sortIndex + 1, 0, itemId); 1225 } 1226 } 1227 else 1228 { 1229 this.getCacheNode(this.ids.itemListTable).insertAdjacentHTML('beforeend', basketItemHtml); 1230 this.shownItems.push(itemId); 1231 } 1232 1233 this.bindBasketItemEvents(this.items[itemId]); 1234 1235 if (this.filter.isActive()) 1236 { 1237 this.filter.highlightSearchMatch(this.items[itemId]); 1238 } 1239 } 1240 }, 1241 1242 getItemsToEdit: function() 1243 { 1244 var itemIds = []; 1245 1246 if (this.isBasketChanged()) 1247 { 1248 for (var i in this.changedItems) 1249 { 1250 if (this.changedItems.hasOwnProperty(i) && this.isItemShown(this.changedItems[i])) 1251 { 1252 itemIds.push(this.changedItems[i]); 1253 } 1254 } 1255 } 1256 1257 return itemIds; 1258 }, 1259 1260 getItemsAfter: function() 1261 { 1262 var itemIdsAfter = []; 1263 1264 if (this.useDynamicScroll) 1265 { 1266 var lastShownItemId = this.shownItems[this.shownItems.length - 1] || false; 1267 1268 if (lastShownItemId) 1269 { 1270 var i = 0; 1271 var index = BX.util.array_search(lastShownItemId, this.sortedItems); 1272 1273 while (this.sortedItems[++index] && i++ < this.maxItemsShowCount) 1274 { 1275 itemIdsAfter.push(this.sortedItems[index]); 1276 } 1277 } 1278 } 1279 1280 return itemIdsAfter; 1281 }, 1282 1283 editBasketItems: function(itemIds) 1284 { 1285 if (!itemIds || itemIds.length === 0) 1286 { 1287 return; 1288 } 1289 1290 var i, item; 1291 1292 for (i in itemIds) 1293 {
1294 if (!itemIds.hasOwnProperty(i) || !BX.type.isPlainObject(this.items[itemIds[i]])) 1295 { 1296 continue; 1297 } 1298 1299 item = this.items[itemIds[i]]; 1300 1301 if (this.actionPool.isItemInPool(item.ID)) 1302 { 1303 if (!BX.util.in_array(item.ID, this.postponedItems)) 1304 { 1305 this.postponedItems.push(item.ID); 1306 } 1307 1308 continue; 1309 } 1310 1311 if (BX.type.isDomNode(BX(this.ids.item + item.ID))) 1312 { 1313 this.redrawBasketItemNode(item.ID); 1314 this.applyQuantityAnimation(item.ID); 1315 } 1316 else 1317 { 1318 this.createBasketItem(item.ID); 1319 } 1320 } 1321 }, 1322 1323 editPostponedBasketItems: function() 1324 { 1325 if (!this.postponedItems.length) 1326 return; 1327 1328 var itemsToEdit = []; 1329 1330 for (var i in this.postponedItems) 1331 { 1332 if (this.postponedItems.hasOwnProperty(i) && this.isItemShown(this.postponedItems[i])) 1333 { 1334 itemsToEdit.push(this.postponedItems[i]); 1335 } 1336 } 1337 1338 this.postponedItems = []; 1339 this.editBasketItems(itemsToEdit); 1340 }, 1341 1342 applyQuantityAnimation: function(itemId) 1343 { 1344 var basketItemNode = BX(this.ids.item + itemId); 1345 1346 if (BX.type.isDomNode(basketItemNode) && this.items[itemId]) 1347 { 1348 if (this.items[itemId].QUANTITY_ANIMATION) 1349 { 1350 BX.addClass(BX(this.ids.quantity + itemId), 'basket-updated'); 1351 } 1352 } 1353 }, 1354 1355 applyPriceAnimation: function() 1356 { 1357 if (!this.priceAnimationData || Object.keys(this.priceAnimationData.start).length === 0) 1358 return; 1359 1360 var animationData = this.priceAnimationData, 1361 nodeCache = {}; 1362 1363 new BX.easing({ 1364 duration: this.params.USE_PRICE_ANIMATION === 'Y' ? this.duration.priceAnimation : 1, 1365 start: animationData.start, 1366 finish: animationData.finish, 1367 transition: BX.easing.makeEaseOut(BX.easing.transitions.quad), 1368 step: BX.delegate(function(state){ 1369 for (var nodeId in animationData.start) 1370 { 1371 if (animationData.start.hasOwnProperty(nodeId)) 1372 { 1373 if (!nodeCache[nodeId]) 1374 { 1375 if (nodeId === this.ids.total) 1376 { 1377 nodeCache[nodeId] = this.getEntities(this.getCacheNode(this.ids.basketRoot), this.ids.total); 1378 } 1379 else 1380 { 1381 var node = BX(nodeId); 1382 nodeCache[nodeId] = node ? [node] : []; 1383 } 1384 } 1385 1386 if (!animationData.int[nodeId]) 1387 { 1388 // fix price blinking 1389 state[nodeId] = (state[nodeId] + (state[nodeId] % 1000) / 1000).toFixed(5); 1390 } 1391 1392 for (var i = 0; i < nodeCache[nodeId].length; i++) 1393 { 1394 nodeCache[nodeId][i].innerHTML = this.getFormatPrice(state[nodeId], animationData.currency[nodeId]); 1395 } 1396 } 1397 } 1398 }, this), 1399 complete: BX.delegate(function() { 1400 var nodeId, formattedPrice, itemId, type; 1401 1402 for (nodeId in animationData.start) 1403 { 1404 if (animationData.start.hasOwnProperty(nodeId)) 1405 { 1406 formattedPrice = this.getFormatPrice(animationData.finish[nodeId], animationData.currency[nodeId]); 1407 1408 for (var i = 0; i < nodeCache[nodeId].length; i++) 1409 { 1410 nodeCache[nodeId][i].innerHTML = formattedPrice; 1411 } 1412 1413 if (nodeId.indexOf(this.ids.sumPrice) !== -1) 1414 { 1415 type = 'SUM_PRICE'; 1416 itemId = nodeId.substr(this.ids.sumPrice.length); 1417 } 1418 else if (nodeId.indexOf(this.ids.price) !== -1) 1419 { 1420 type = 'PRICE'; 1421 itemId = nodeId.substr(this.ids.price.length); 1422 } 1423 else if (nodeId.indexOf(this.ids.total) !== -1) 1424 { 1425 type = 'TOTAL'; 1426 itemId = ''; 1427 } 1428 else 1429 { 1430 itemId = ''; 1431 type = ''; 1432 } 1433 1434 if (BX.type.isNotEmptyString(type)) 1435 { 1436 if (itemId) 1437 { 1438 this.items[itemId][type] = animationData.finish[nodeId]; 1439 delete this.items[itemId][type + '_NEW']; 1440 this.items[itemId][type + '_FORMATED'] = formattedPrice; 1441 delete this.items[itemId][type + '_FORMATED_NEW']; 1442 } 1443 else if (type === 'TOTAL') 1444 { 1445 this.result.TOTAL_RENDER_DATA.PRICE = animationData.finish[nodeId]; 1446 delete this.result.TOTAL_RENDER_DATA.PRICE_NEW; 1447 this.result.TOTAL_RENDER_DATA.PRICE_FORMATED = formattedPrice; 1448 delete this.result.TOTAL_RENDER_DATA.PRICE_FORMATED_NEW; 1449 } 1450 } 1451 } 1452 } 1453 1454 this.filter.highlightFoundItems(); 1455 }, this) 1456 }).animate(); 1457 }, 1458 1459 getFormatPrice: function(price, currency) 1460 { 1461 return BX.Currency.currencyFormat(price, currency, true); 1462 }, 1463 1464 deleteBasketItems: function(items, restore, final) 1465 { 1466 if (!items || !items.length) 1467 { 1468 return; 1469 } 1470 1471 for (var i in items) 1472 { 1473 if (items.hasOwnProperty(i)) 1474 { 1475 this.deleteBasketItem(items[i], restore, final); 1476 } 1477 } 1478 }, 1479 1480 deleteBasketItem: function(itemId, restore, final) 1481 { 1482 // check if item exists 1483 if (!this.items[itemId]) 1484 { 1485 return; 1486 } 1487 1488 // delete not available item with no chance to restore 1489 if (this.items[itemId].NOT_AVAILABLE && restore) 1490 { 1491 restore = false;
1492 final = true; 1493 } 1494 1495 if (restore) 1496 { 1497 this.items[itemId].SHOW_RESTORE = true; 1498 this.items[itemId].SHOW_LOADING = false; 1499 this.redrawBasketItemNode(itemId); 1500 } 1501 else 1502 { 1503 this.changeShownItem(itemId); 1504 BX.remove(BX(this.ids.item + itemId)); 1505 } 1506 1507 if (final) 1508 { 1509 this.changeSortedItem(itemId, false, true); 1510 this.changeShownItem(itemId, false, true); 1511 } 1512 }, 1513 1514 addSortedItem: function(itemId, all) 1515 { 1516 this.sortedItems.push(itemId.toString()); 1517 1518 if (all && this.filter.isActive()) 1519 { 1520 this.filter.realSortedItems.push(itemId.toString()); 1521 } 1522 }, 1523 1524 changeSortedItem: function(itemId, newItemId, all) 1525 { 1526 var index = BX.util.array_search(itemId, this.sortedItems); 1527 1528 if (index >= 0) 1529 { 1530 if (newItemId) 1531 { 1532 this.sortedItems.splice(index, 1, newItemId.toString()); 1533 } 1534 else 1535 { 1536 this.sortedItems.splice(index, 1); 1537 } 1538 } 1539 1540 if (all && this.filter.isActive()) 1541 { 1542 index = BX.util.array_search(itemId, this.filter.realSortedItems); 1543 1544 if (index >= 0) 1545 { 1546 if (newItemId) 1547 { 1548 this.filter.realSortedItems.splice(index, 1, newItemId.toString()); 1549 } 1550 else 1551 { 1552 this.filter.realSortedItems.splice(index, 1); 1553 } 1554 } 1555 } 1556 }, 1557 1558 sortSortedItems: function(all) 1559 { 1560 this.sortedItems.sort(BX.proxy(this.itemSortFunction, this)); 1561 1562 if (all && this.filter.isActive()) 1563 { 1564 this.filter.realSortedItems.sort(BX.proxy(this.itemSortFunction, this)); 1565 } 1566 }, 1567 1568 changeShownItem: function(itemId, newItemId, all) 1569 { 1570 var index = BX.util.array_search(itemId, this.shownItems); 1571 1572 if (index >= 0) 1573 { 1574 if (newItemId) 1575 { 1576 this.shownItems.splice(index, 1, newItemId.toString()); 1577 } 1578 else 1579 { 1580 this.shownItems.splice(index, 1); 1581 } 1582 } 1583 1584 if (all && this.filter.isActive()) 1585 { 1586 index = BX.util.array_search(itemId, this.filter.realShownItems); 1587 1588 if (index >= 0) 1589 { 1590 if (newItemId) 1591 { 1592 this.filter.realShownItems.splice(index, 1, newItemId.toString()); 1593 } 1594 else 1595 { 1596 this.filter.realShownItems.splice(index, 1); 1597 } 1598 } 1599 } 1600 }, 1601 1602 redrawBasketItemNode: function(itemId) 1603 { 1604 if(modalReminder){ 1605 modalReminder.resetTimer(); 1606 } 1607 1608 var basketItemNode = BX(this.ids.item + itemId); 1609 1610 if (!this.items[itemId] || !BX.type.isDomNode(basketItemNode)) 1611 return; 1612 1613 var basketItemTemplate = this.getTemplate('basket-item-template'); 1614 if (basketItemTemplate) 1615 { 1616 var nodeAligner = BX(this.ids.itemHeightAligner + itemId), 1617 oldHeight; 1618 1619 if (BX.type.isDomNode(nodeAligner)) 1620 { 1621 oldHeight = nodeAligner.clientHeight; 1622 } 1623 1624 var basketItemHtml = this.renderBasketItem(basketItemTemplate, this.items[itemId]); 1625 basketItemNode.insertAdjacentHTML('beforebegin', basketItemHtml); 1626 BX.remove(basketItemNode); 1627 1628 if (oldHeight) 1629 { 1630 nodeAligner = BX(this.ids.itemHeightAligner + itemId); 1631 1632 if (BX.type.isDomNode(nodeAligner) && nodeAligner.clientHeight < oldHeight) 1633 { 1634 nodeAligner.style.minHeight = oldHeight + 'px'; 1635 setTimeout(function(){nodeAligner.style.minHeight = '0px';}, 1); 1636 } 1637 } 1638 1639 this.bindBasketItemEvents(this.items[itemId]); 1640 1641 if (this.filter.isActive()) 1642 { 1643 this.filter.highlightSearchMatch(this.items[itemId]); 1644 } 1645 } 1646 }, 1647 1648 restoreBasketItems: function(items) 1649 { 1650 if (!items || Object.keys(items).length === 0) 1651 { 1652 return; 1653 } 1654 1655 var oldItemId, newItemId, basketItemNode; 1656 1657 for (oldItemId in items) 1658 { 1659 if (items.hasOwnProperty(oldItemId)) 1660 { 1661 newItemId = items[oldItemId]; 1662 1663 if (this.isItemShown(oldItemId)) 1664 { 1665 this.changeShownItem(oldItemId, newItemId, true); 1666 1667 basketItemNode = BX(this.ids.item + oldItemId); 1668 if (BX.type.isDomNode(basketItemNode)) 1669 { 1670 basketItemNode.id = this.ids.item + newItemId; 1671 basketItemNode.setAttribute('data-id', newItemId); 1672 } 1673 } 1674 1675 this.changeSortedItem(oldItemId, false, true); 1676 } 1677 } 1678 }, 1679 1680 bindBasketItemEvents: function(itemData) 1681 { 1682 if (!itemData) 1683 return; 1684 1685 var itemNode = BX(this.ids.item + itemData.ID); 1686 if (BX.type.isDomNode(itemNode)) 1687 { 1688 this.bindQuantityEvents(itemNode, itemData); 1689 this.bindSkuEvents(itemNode, itemData); 1690 this.bindImageEvents(itemNode, itemData); 1691 this.bindActionEvents(itemNode, itemData); 1692 this.bindRestoreAction(itemNode, itemData); 1693 this.bindItemWarningEvents(itemNode, itemData); 1694 } 1695 }, 1696 1697 bindQuantityEvents: function(node, data) 1698 { 1699 if (!node || !data || !this.isItemAvailable(data.ID)) 1700 return; 1701 1702 var entity; 1703 1704 var block = this.getEntity(node, 'basket-item-quantity-block'); 1705 if (block) 1706 { 1707 var startEventName = this.isTouch ? 'touchstart' : 'mousedown'; 1708 var endEventName = this.isTouch ? 'touchend' : 'mouseup'; 1709 1710 entity = this.getEntity(block, 'basket-item-quantity-minus'); 1711 BX.bind(entity, startEventName, BX.proxy(this.startQuantityInterval, this)); 1712 BX.bind(entity, endEventName, BX.proxy(this.clearQuantityInterval, this)); 1713 BX.bind(entity, 'mouseout', BX.proxy(this.clearQuantityInterval, this)); 1714 BX.bind(entity, 'click', BX.proxy(this.quantityMinus, this)); 1715 1716 entity = this.getEntity(block, 'basket-item-quantity-plus'); 1717 BX.bind(entity, startEventName, BX.proxy(this.startQuantityInterval, this)); 1718 BX.bind(entity, endEventName, BX.proxy(this.clearQuantityInterval, this)); 1719 BX.bind(entity, 'mouseout', BX.proxy(this.clearQuantityInterval, this)); 1720 BX.bind(entity, 'click', BX.proxy(this.quantityPlus, this)); 1721 1722 entity = this.getEntity(block, 'basket-item-quantity-field'); 1723 BX.bind(entity, 'change', BX.proxy(this.quantityChange, this)); 1724 } 1725 }, 1726 1727 startQuantityInterval: function() 1728 { 1729 var target = BX.proxy_context; 1730 var func = target.getAttribute('data-entity') === 'basket-item-quantity-minus' 1731 ? BX.proxy(this.quantityMinus, this) 1732 : BX.proxy(this.quantityPlus, this); 1733 1734 this.quantityDelay = setTimeout( 1735 BX.delegate(function() { 1736 this.quantityTimer = setInterval(function(){func(target);}, 150); 1737 }, this), 1738 300 1739 ); 1740 }, 1741 1742 clearQuantityInterval: function() 1743 { 1744 clearTimeout(this.quantityDelay); 1745 clearInterval(this.quantityTimer); 1746 }, 1747 1748 quantityPlus: function(target) 1749 { 1750 if (!BX.type.isDomNode(target)) 1751 { 1752 target = BX.proxy_context; 1753 this.clearQuantityInterval(); 1754 } 1755 1756 var itemData = this.getItemDataByTarget(target); 1757 if (itemData) 1758 { 1759 var quantityField = BX(this.ids.quantity + itemData.ID); 1760 var isQuantityFloat = this.isQuantityFloat(itemData); 1761 1762 var currentQuantity = isQuantityFloat ? parseFloat(quantityField.value) : Math.round(quantityField.value); 1763 var measureRatio = isQuantityFloat ? parseFloat(itemData.MEASURE_RATIO) : parseInt(itemData.MEASURE_RATIO); 1764 1765 var quantity = parseFloat((currentQuantity + measureRatio).toFixed(5)); 1766 quantity = this.getCorrectQuantity(itemData, quantity); 1767 1768 this.setQuantity(itemData, quantity); 1769 } 1770 }, 1771 1772 quantityMinus: function(target) 1773 { 1774 target = BX.type.isDomNode(target) ? target : BX.proxy_context; 1775 1776 var itemData = this.getItemDataByTarget(target); 1777 if (itemData) 1778 { 1779 var quantityField = BX(this.ids.quantity + itemData.ID); 1780 var isQuantityFloat = this.isQuantityFloat(itemData); 1781 1782 var currentQuantity = isQuantityFloat ? parseFloat(quantityField.value) : Math.round(quantityField.value); 1783 var measureRatio = isQuantityFloat ? parseFloat(itemData.MEASURE_RATIO) : parseInt(itemData.MEASURE_RATIO); 1784 1785 var quantity = parseFloat((currentQuantity - measureRatio).toFixed(5)); 1786 quantity = this.getCorrectQuantity(itemData, quantity); 1787 1788 this.setQuantity(itemData, quantity); 1789 } 1790 }, 1791 1792 quantityChange: function() 1793 { 1794 var itemData = this.getItemDataByTarget(BX.proxy_context); 1795 if (itemData) 1796 { 1797 var quantityField, quantity; 1798 1799 quantityField = BX(this.ids.quantity + itemData.ID); 1800 quantity = this.getCorrectQuantity(itemData, quantityField.value); 1801 1802 this.setQuantity(itemData, quantity); 1803 } 1804 }, 1805 1806 isQuantityFloat: function(item) 1807 { 1808 return this.params.QUANTITY_FLOAT === 'Y' || (parseInt(item.MEASURE_RATIO) !== parseFloat(item.MEASURE_RATIO)); 1809 }, 1810 1811 getCorrectQuantity: function(itemData, quantity) 1812 { 1813 var isQuantityFloat = this.isQuantityFloat(itemData), 1814 measureRatio = isQuantityFloat ? parseFloat(itemData.MEASURE_RATIO) : parseInt(itemData.MEASURE_RATIO), 1815 availableQuantity = 0; 1816 1817 quantity = (isQuantityFloat ? parseFloat(quantity) : parseInt(quantity, 10)) || 0; 1818 if (quantity < 0) 1819 { 1820 quantity = 0; 1821 } 1822 1823 if (measureRatio > 0 && quantity < measureRatio) 1824 { 1825 quantity = measureRatio; 1826 } 1827 1828 if (itemData.CHECK_MAX_QUANTITY === 'Y') 1829 { 1830 availableQuantity = isQuantityFloat ? parseFloat(itemData.AVAILABLE_QUANTITY) : parseInt(itemData.AVAILABLE_QUANTITY); 1831 if (availableQuantity > 0 && quantity > availableQuantity) 1832 { 1833 quantity = availableQuantity; 1834 } 1835 } 1836 1837 var reminder = (quantity / measureRatio - ((quantity / measureRatio).toFixed(0))).toFixed(5), 1838 remain; 1839 1840 if (parseFloat(reminder) === 0) 1841 { 1842 return quantity; 1843 } 1844 1845 if (measureRatio !== 0 && measureRatio !== 1) 1846 { 1847 remain = (quantity * this.precisionFactor) % (measureRatio * this.precisionFactor) / this.precisionFactor; 1848 1849 if (measureRatio > 0 && remain > 0) 1850 { 1851 if ( 1852 remain >= measureRatio / 2 1853 && ( 1854 availableQuantity === 0 1855 || (quantity + measureRatio - remain) <= availableQuantity 1856 ) 1857 ) 1858 { 1859 quantity += (measureRatio - remain); 1860 } 1861 else 1862 { 1863 quantity -= remain; 1864 } 1865 } 1866 } 1867 1868 quantity = isQuantityFloat ? parseFloat(quantity) : parseInt(quantity, 10); 1869 1870 return quantity; 1871 }, 1872 1873 setQuantity: function(itemData, quantity) 1874 { 1875 var quantityField = BX(this.ids.quantity + itemData.ID), 1876 currentQuantity; 1877 1878 if (quantityField) 1879 { 1880 quantity = parseFloat(quantity); 1881 currentQuantity = parseFloat(quantityField.getAttribute('data-value')); 1882 1883 quantityField.value = quantity; 1884 1885 if (parseFloat(itemData.QUANTITY) !== parseFloat(quantity)) 1886 { 1887 this.animatePriceByQuantity(itemData, quantity); 1888 this.actionPool.changeQuantity(itemData.ID, quantity, currentQuantity); 1889 } 1890 } 1891 }, 1892 1893 animatePriceByQuantity: function(itemData, quantity) 1894 { 1895 var priceNode = BX(this.ids.sumPrice + itemData.ID); 1896 if (!BX.type.isDomNode(priceNode)) 1897 return; 1898 1899 var quantityMultiplier = quantity / parseFloat(itemData.MEASURE_RATIO); 1900 1901 var startPrice = parseFloat(itemData.SUM_PRICE), 1902 finalPrice = parseFloat(itemData.PRICE) * quantityMultiplier, 1903 isInt = parseInt(startPrice) === parseFloat(startPrice) 1904 && parseInt(finalPrice) === parseFloat(finalPrice); 1905 1906 if (startPrice !== finalPrice) 1907 { 1908 this.items[itemData.ID].QUANTITY = quantity;
1909 this.items[itemData.ID].SUM_PRICE = finalPrice; 1910 1911 new BX.easing({ 1912 duration: this.params.USE_PRICE_ANIMATION === 'Y' ? this.duration.priceAnimation : 1, 1913 start: {price: startPrice}, 1914 finish: {price: finalPrice}, 1915 transition: BX.easing.makeEaseOut(BX.easing.transitions.quad), 1916 step: BX.delegate(function(state){ 1917 if (!isInt) 1918 { 1919 // fix price blinking 1920 state.price = (state.price + (state.price % 1000) / 1000).toFixed(5); 1921 } 1922 1923 priceNode.innerHTML = this.getFormatPrice(state.price, itemData.CURRENCY); 1924 }, this), 1925 complete: BX.delegate(function() { 1926 var node, price; 1927 1928 priceNode.innerHTML = this.getFormatPrice(finalPrice, itemData.CURRENCY); 1929 1930 node = BX(this.ids.sumPriceOld + itemData.ID); 1931 if (BX.type.isDomNode(node)) 1932 { 1933 price = parseFloat(itemData.FULL_PRICE) * quantityMultiplier; 1934 node.innerHTML = this.getFormatPrice(price, itemData.CURRENCY); 1935 } 1936 1937 node = BX(this.ids.sumPriceDiff + itemData.ID); 1938 if (BX.type.isDomNode(node)) 1939 { 1940 price = parseFloat(itemData.DISCOUNT_PRICE) * quantityMultiplier; 1941 node.innerHTML = this.getFormatPrice(price, itemData.CURRENCY); 1942 } 1943 }, this) 1944 }).animate(); 1945 } 1946 }, 1947 1948 getItemDataByTarget: function(target) 1949 { 1950 var data = false; 1951 var id; 1952 1953 var itemNode = BX.findParent(target, {attrs: {'data-entity': 'basket-item'}}); 1954 if (itemNode) 1955 { 1956 id = itemNode.getAttribute('data-id'); 1957 data = this.items[id]; 1958 } 1959 1960 return data; 1961 }, 1962 1963 bindSkuEvents: function(node, data) 1964 { 1965 if (!node || !data) 1966 return; 1967 1968 var blocks = this.getEntities(node, 'basket-item-sku-block'); 1969 var blockEntities, i, l, ii, ll; 1970 1971 for (i = 0, l = blocks.length; i < l; i++) 1972 { 1973 blockEntities = this.getEntities(blocks[i], 'basket-item-sku-field'); 1974 1975 for (ii = 0, ll = blockEntities.length; ii < ll; ii++) 1976 { 1977 BX.bind(blockEntities[ii], 'click', BX.proxy(this.changeSku, this)); 1978 } 1979 } 1980 }, 1981 1982 changeSku: function() 1983 { 1984 var i, l; 1985 1986 var target = BX.proxy_context; 1987 1988 if (BX.hasClass(target, 'selected')) 1989 return; 1990 1991 var itemData = this.getItemDataByTarget(target); 1992 if (itemData) 1993 { 1994 var basketItemNode = BX(this.ids.item + itemData.ID); 1995 if (basketItemNode) 1996 { 1997 var currentSkuListNodes = this.getEntities(target.parentNode, 'basket-item-sku-field'); 1998 for (i = 0, l = currentSkuListNodes.length; i < l; i++) 1999 { 2000 if (currentSkuListNodes[i].isEqualNode(target)) 2001 { 2002 BX.addClass(currentSkuListNodes[i], 'selected'); 2003 } 2004 else 2005 { 2006 BX.removeClass(currentSkuListNodes[i], 'selected'); 2007 } 2008 } 2009 2010 this.actionPool.changeSku( 2011 itemData.ID, 2012 this.getSkuPropertyValues(basketItemNode), 2013 this.getInitialSkuPropertyValues(basketItemNode) 2014 ); 2015 } 2016 } 2017 }, 2018 2019 getSkuPropertyValues: function(basketItemNode) 2020 { 2021 var propertyValues = {}; 2022 2023 var propNodes = this.getEntities(basketItemNode, 'basket-item-sku-field', '.selected'); 2024 for (var i = 0, l = propNodes.length; i < l; i++) 2025 { 2026 propertyValues[propNodes[i].getAttribute('data-property')] = BX.util.htmlspecialcharsback(propNodes[i].getAttribute('data-value-id')); 2027 } 2028 2029 return propertyValues; 2030 }, 2031 2032 getInitialSkuPropertyValues: function(basketItemNode) 2033 { 2034 var propertyValues = {}; 2035 2036 var propNodes = this.getEntities(basketItemNode, 'basket-item-sku-field', '[data-initial="true"]'); 2037 for (var i = 0, l = propNodes.length; i < l; i++) 2038 { 2039 propertyValues[propNodes[i].getAttribute('data-property')] = BX.util.htmlspecialcharsback(propNodes[i].getAttribute('data-value-id')); 2040 } 2041 2042 return propertyValues; 2043 }, 2044 2045 bindImageEvents: function(node, data) 2046 { 2047 if (!node || !data) 2048 return; 2049 2050 var images = node.querySelectorAll('.basket-item-custom-block-photo-item'); 2051 for (var i = 0, l = images.length; i < l; i++) 2052 { 2053 BX.bind(images[i], 'click', BX.proxy(this.showPropertyImagePopup, this)); 2054 } 2055 }, 2056 2057 showPropertyImagePopup: function() 2058 { 2059 var target, propertyCode, imageIndex, item, imageSrc, i; 2060 2061 target = BX.proxy_context; 2062 item = this.getItemDataByTarget(target); 2063 2064 propertyCode = target.getAttribute('data-column-property-code'); 2065 imageIndex = target.getAttribute('data-image-index'); 2066 2067 if (item && item.COLUMN_LIST) 2068 { 2069 for (i in item.COLUMN_LIST) 2070 { 2071 if ( 2072 item.COLUMN_LIST.hasOwnProperty(i) 2073 && item.COLUMN_LIST[i].CODE === propertyCode 2074 && item.COLUMN_LIST[i].VALUE[imageIndex] 2075 ) 2076 { 2077 imageSrc = item.COLUMN_LIST[i].VALUE[imageIndex].IMAGE_SRC_ORIGINAL; 2078 break; 2079 } 2080 } 2081 } 2082 2083 if (!imageSrc) 2084 { 2085 return; 2086 } 2087 2088 if (this.imagePopup) 2089 { 2090 this.imagePopup.destroy(); 2091 } 2092 2093 var imageId = 'bx-soa-image-popup-content'; 2094 var that = this; 2095 2096 this.imagePopup = new BX.PopupWindow('bx-soa-image-popup', null, { 2097 lightShadow: true, 2098 offsetTop: 0, 2099 offsetLeft: 0, 2100 closeIcon: {top: '3px', right: '10px'}, 2101 autoHide: true, 2102 bindOptions: {position: 'bottom'}, 2103 closeByEsc: true, 2104 zIndex: 100, 2105 events: { 2106 onPopupShow: function() { 2107 BX.create('IMG', { 2108 props: {src: imageSrc}, 2109 events: { 2110 load: function() { 2111 var content = BX(imageId); 2112 if (content) 2113 { 2114 var windowSize = BX.GetWindowInnerSize(), 2115 ratio = that.isMobile ? 0.5 : 0.9, 2116 contentHeight, contentWidth; 2117 2118 BX.cleanNode(content); 2119 content.appendChild(this); 2120 2121 contentHeight = content.offsetHeight; 2122 contentWidth = content.offsetWidth; 2123 2124 if (contentHeight >
2124 windowSize.innerHeight * ratio) 2125 { 2126 content.style.height = windowSize.innerHeight * ratio + 'px'; 2127 content.style.width = contentWidth * (windowSize.innerHeight * ratio / contentHeight) + 'px'; 2128 contentHeight = content.offsetHeight; 2129 contentWidth = content.offsetWidth; 2130 } 2131 2132 if (contentWidth > windowSize.innerWidth * ratio) 2133 { 2134 content.style.width = windowSize.innerWidth * ratio + 'px'; 2135 content.style.height = contentHeight * (windowSize.innerWidth * ratio / contentWidth) + 'px'; 2136 } 2137 2138 content.style.height = content.offsetHeight + 'px'; 2139 content.style.width = content.offsetWidth + 'px'; 2140 2141 that.imagePopup.adjustPosition(); 2142 } 2143 } 2144 } 2145 }); 2146 }, 2147 onPopupClose: function() { 2148 this.destroy(); 2149 } 2150 }, 2151 content: BX.create('DIV', {props: {id: imageId}}) 2152 }); 2153 this.imagePopup.show(); 2154 }, 2155 2156 bindActionEvents: function(node, data) 2157 { 2158 if (!node || !data) 2159 return; 2160 2161 var entity; 2162 2163 if (BX.util.in_array('DELETE', this.params.COLUMNS_LIST)) 2164 { 2165 entity = this.getEntities(node, 'basket-item-delete'); 2166 for (var i = 0, l = entity.length; i < l; i++) 2167 { 2168 BX.bind(entity[i], 'click', BX.proxy(this.deleteAction, this)); 2169 } 2170 } 2171 2172 if (BX.util.in_array('DELAY', this.params.COLUMNS_LIST)) 2173 { 2174 entity = this.getEntity(node, 'basket-item-add-delayed'); 2175 BX.bind(entity, 'click', BX.proxy(this.addDelayedAction, this)); 2176 } 2177 2178 entity = this.getEntity(node, 'basket-item-remove-delayed'); 2179 BX.bind(entity, 'click', BX.proxy(this.removeDelayedAction, this)); 2180 2181 entity = this.getEntity(node, 'basket-item-merge-sku-link'); 2182 BX.bind(entity, 'click', BX.proxy(this.mergeAction, this)); 2183 2184 entity = this.getEntity(node, 'basket-item-show-similar-link'); 2185 BX.bind(entity, 'click', BX.delegate(function() {this.toggleFilter('similar');}, this)); 2186 }, 2187 2188 deleteAction: function() 2189 { 2190 var itemData = this.getItemDataByTarget(BX.proxy_context); 2191 if (itemData) 2192 { 2193 this.actionPool.deleteItem(itemData.ID); 2194 2195 this.items[itemData.ID].SHOW_LOADING = true; 2196 2197 if (this.params.SHOW_RESTORE === 'Y' && this.isItemAvailable(itemData.ID)) 2198 { 2199 this.items[itemData.ID].SHOW_RESTORE = true; 2200 } 2201 2202 this.redrawBasketItemNode(itemData.ID); 2203 } 2204 }, 2205 2206 addDelayedAction: function() 2207 { 2208 var itemData = this.getItemDataByTarget(BX.proxy_context); 2209 if (itemData) 2210 { 2211 this.actionPool.addDelayed(itemData.ID); 2212 2213 this.items[itemData.ID].SHOW_LOADING = true; 2214 this.redrawBasketItemNode(itemData.ID); 2215 } 2216 }, 2217 2218 removeDelayedAction: function() 2219 { 2220 var itemData = this.getItemDataByTarget(BX.proxy_context); 2221 if (itemData) 2222 { 2223 this.actionPool.removeDelayed(itemData.ID); 2224 2225 this.items[itemData.ID].SHOW_LOADING = true; 2226 this.redrawBasketItemNode(itemData.ID); 2227 } 2228 }, 2229 2230 mergeAction: function() 2231 { 2232 var itemData = this.getItemDataByTarget(BX.proxy_context); 2233 if (itemData) 2234 { 2235 this.actionPool.mergeSku(itemData.ID); 2236 } 2237 }, 2238 2239 bindRestoreAction: function(node, itemData) 2240 { 2241 if (!node || !itemData || this.params.SHOW_RESTORE !== 'Y') 2242 return; 2243 2244 BX.bind( 2245 this.getEntity(node, 'basket-item-restore-button'), 2246 'click', 2247 BX.delegate(function() { 2248 this.actionPool.restoreItem(itemData.ID, { 2249 PRODUCT_ID: itemData.PRODUCT_ID, 2250 QUANTITY: itemData.QUANTITY, 2251 PROPS: itemData.PROPS_ALL, 2252 SORT: itemData.SORT, 2253 MODULE: itemData.MODULE, 2254 PRODUCT_PROVIDER_CLASS: itemData.PRODUCT_PROVIDER_CLASS 2255 }); 2256 2257 this.items[itemData.ID].SHOW_RESTORE = false; 2258 this.items[itemData.ID].SHOW_LOADING = true; 2259 this.redrawBasketItemNode(itemData.ID); 2260 }, this) 2261 ); 2262 BX.bind( 2263 this.getEntity(node, 'basket-item-close-restore-button'), 2264 'click', 2265 BX.delegate(function() { 2266 this.deleteBasketItem(itemData.ID, false, true); 2267 }, this) 2268 ); 2269 }, 2270 2271 bindItemWarningEvents: function(node, data) 2272 { 2273 if (!node || !data) 2274 return; 2275 2276 BX.bind( 2277 this.getEntity(BX(this.ids.item + data.ID), 'basket-item-warning-close'), 2278 'click', 2279 BX.proxy(this.closeItemWarnings, this) 2280 ); 2281 }, 2282 2283 closeItemWarnings: function() 2284 { 2285 var target = BX.proxy_context; 2286 2287 if (BX.type.isDomNode(target)) 2288 { 2289 var itemData = this.getItemDataByTarget(target); 2290 2291 this.items[itemData.ID].WARNINGS = []; 2292 this.warningItems.splice(BX.util.array_search(itemData.ID, this.warningItems), 1); 2293 2294 this.redrawBasketItemNode(itemData.ID); 2295 this.editWarnings(); 2296 } 2297 }, 2298 2299 renderBasketItem: function(template, data) 2300 { 2301 var clonedData = BX.clone(data); 2302 2303 if (BX.type.isPlainObject(clonedData)) 2304 { 2305 clonedData.USE_FILTER = this.useItemsFilter 2306 && !this.filter.currentFilter.similarHash.length; 2307 } 2308 2309 return Mustache.render(template, clonedData); 2310 }, 2311 2312 render: function(template, data) 2313 { 2314 return Mustache.render(template, data); 2315 }, 2316 2317 checkAnalytics: function(data) 2318 { 2319 if (!data || !data.basket) 2320 return; 2321 2322 var itemId, itemsDiff = {}; 2323 2324 for (var i in data.basket) 2325 { 2326 if (data.basket.hasOwnProperty(i)) 2327 { 2328 if (i.indexOf('QUANTITY_') >= 0) 2329 { 2330 itemId = i.substr(9); 2331 2332 if (this.items[itemId]) 2333 { 2334 itemsDiff[itemId] = parseFloat(data.basket[i]) - parseFloat(BX(this.ids.quantity + itemId).getAttribute('data-value')); 2335 } 2336 } 2337 else if (i.indexOf('DELETE_') >= 0) 2338 { 2339 itemId = i.substr(7); 2340 2341 if (this.items[itemId]) 2342 {
2343 itemsDiff[itemId] = -parseFloat(this.items[itemId].QUANTITY); 2344 } 2345 } 2346 else if (i.indexOf('RESTORE_') >= 0) 2347 { 2348 itemId = i.substr(8); 2349 2350 if (this.items[itemId]) 2351 { 2352 itemsDiff[itemId] = parseFloat(this.items[itemId].QUANTITY); 2353 } 2354 } 2355 } 2356 } 2357 2358 this.setAnalyticsDataLayer(itemsDiff); 2359 }, 2360 2361 setAnalyticsDataLayer: function(itemsDiff) 2362 { 2363 if (!itemsDiff || Object.keys(itemsDiff).length === 0) 2364 return; 2365 2366 window[this.params.DATA_LAYER_NAME] = window[this.params.DATA_LAYER_NAME] || []; 2367 2368 var plus = [], minus = []; 2369 2370 for (var itemId in itemsDiff) 2371 { 2372 if (itemsDiff.hasOwnProperty(itemId)) 2373 { 2374 if (itemsDiff[itemId] > 0) 2375 { 2376 plus.push(this.getItemAnalyticsInfo(itemId, itemsDiff[itemId])); 2377 } 2378 else if (itemsDiff[itemId] < 0) 2379 { 2380 minus.push(this.getItemAnalyticsInfo(itemId, itemsDiff[itemId])); 2381 } 2382 } 2383 } 2384 2385 if (plus.length) 2386 { 2387 window[this.params.DATA_LAYER_NAME].push({ 2388 event: 'addToCart', 2389 ecommerce: { 2390 currencyCode: this.items[itemId].CURRENCY || '', 2391 add: { 2392 products: plus 2393 } 2394 } 2395 }); 2396 } 2397 2398 if (minus.length) 2399 { 2400 window[this.params.DATA_LAYER_NAME].push({ 2401 event: 'removeFromCart', 2402 ecommerce: { 2403 currencyCode: this.items[itemId].CURRENCY || '', 2404 remove: { 2405 products: minus 2406 } 2407 } 2408 }); 2409 } 2410 }, 2411 2412 getItemAnalyticsInfo: function(itemId, diff) 2413 { 2414 if (!this.items[itemId]) 2415 return {}; 2416 2417 var brand = (this.items[itemId].BRAND || '').split(', ').join('/'); 2418 var variants = []; 2419 2420 var selectedSku = this.getEntities(BX(this.ids.item + itemId), 'basket-item-sku-field', '.selected'); 2421 for (var i = 0, l = selectedSku.length; i < l; i++) 2422 { 2423 variants.push(selectedSku[i].getAttribute('data-sku-name')); 2424 } 2425 2426 return { 2427 'name': this.items[itemId].NAME || '', 2428 'id': this.items[itemId].PRODUCT_ID || '', 2429 'price': this.items[itemId].PRICE || 0, 2430 'brand': brand, 2431 'variant': variants.join('/'), 2432 'quantity': Math.abs(diff) 2433 }; 2434 } 2435 }; 2436})();
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.