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 592 pasteCouponAction: function(event) 593 { 594 setTimeout(BX.delegate(function() { 595 this.addCouponAction(event); 596 }, this), 10); 597 }, 598 599 removeCouponAction: function() 600 { 601 var value = BX.proxy_context && BX.util.trim(BX.proxy_context.getAttribute('data-coupon')); 602 if (value) 603 { 604 this.actionPool.removeCoupon(value); 605 } 606 }, 607 608 initializeActionPool: function() 609 { 610 this.actionPool = new BX.Sale.BasketActionPool(this); 611 }, 612 613 initializeFilter: function() 614 { 615 this.filter = new BX.Sale.BasketFilter(this); 616 }, 617 618 /** 619 * Send ajax request with basket data and executes callback by action 620 */ 621 sendRequest: function(action, data) 622 { 623 this.lastAction = action; 624 625 if (this.lastAction === 'recalculateAjax') 626 { 627 // we use it to reload all items if applied discounts changed 628 data.lastAppliedDiscounts = BX.util.array_keys(this.result.FULL_DISCOUNT_LIST).join(','); 629 630 if (this.params.USE_ENHANCED_ECOMMERCE === 'Y') 631 { 632 this.checkAnalytics(data); 633 } 634 } 635 636 BX.ajax({ 637 method: 'POST', 638 dataType: 'json', 639 url: this.ajaxUrl, 640 data: this.getData(data), 641 onsuccess: BX.delegate(function(result) { 642 this.actionPool.doProcessing(false); 643 644 if (!BX.type.isPlainObject(result)) 645 return; 646 647 this.actionPool.setRefreshStatus(result.BASKET_REFRESHED); 648 649 if (result.RESTORED_BASKET_ITEMS) 650 { 651 this.restoreBasketItems(result.RESTORED_BASKET_ITEMS); 652 } 653 654 if (result.DELETED_BASKET_ITEMS) 655 { 656 this.deleteBasketItems(result.DELETED_BASKET_ITEMS, this.params.SHOW_RESTORE === 'Y'); 657 } 658 659 if (result.MERGED_BASKET_ITEMS) 660 { 661 this.deleteBasketItems(result.MERGED_BASKET_ITEMS, false, true); 662 } 663 664 this.applyBasketResult(result.BASKET_DATA); 665 this.editBasketItems(this.getItemsToEdit()); 666 this.editTotal(); 667 668 this.applyPriceAnimation(); 669 this.editWarnings(); 670 671 this.actionPool.switchTimer(); 672 673 if (this.isBasketIntegrated() && this.isBasketChanged()) 674 { 675 BX.Sale.OrderAjaxComponent.sendRequest(); 676 } 677 }, this), 678 onfailure: BX.delegate(function() { 679 this.actionPool.doProcessing(false); 680 }, this) 681 }); 682 }, 683 684 isBasketIntegrated: function() 685 { 686 return this.params.BASKET_WITH_ORDER_INTEGRATION === 'Y'; 687 }, 688 689 isBasketChanged: function() 690 { 691 return this.changedItems.length; 692 }, 693 694 addPriceAnimationData: function(nodeId, start, finish, currency) 695 { 696 if (!BX.type.isPlainObject(this.priceAnimationData)) 697 { 698 this.clearPriceAnimationData(); 699 } 700
701 this.priceAnimationData.start[nodeId] = parseFloat(start); 702 this.priceAnimationData.finish[nodeId] = parseFloat(finish); 703 this.priceAnimationData.currency[nodeId] = currency; 704 this.priceAnimationData.int[nodeId] = (parseFloat(start) === parseInt(start)) && (parseFloat(finish) === parseInt(finish)); 705 }, 706 707 clearPriceAnimationData: function() 708 { 709 this.priceAnimationData = { 710 start: {}, 711 finish: {}, 712 currency: {}, 713 int: {} 714 }; 715 }, 716 717 applyBasketResult: function(result) 718 { 719 this.changedItems = []; 720 this.clearPriceAnimationData(); 721 722 if (!BX.type.isPlainObject(result)) 723 { 724 return; 725 } 726 727 if (result.BASKET_ITEM_RENDER_DATA) 728 { 729 var i, newData; 730 731 for (i in result.BASKET_ITEM_RENDER_DATA) 732 { 733 if (result.BASKET_ITEM_RENDER_DATA.hasOwnProperty(i)) 734 { 735 newData = result.BASKET_ITEM_RENDER_DATA[i]; 736 newData.WARNINGS = this.checkBasketItemWarnings(newData, result.WARNING_MESSAGE_WITH_CODE); 737 738 if (this.items[newData.ID]) 739 { 740 if (JSON.stringify(this.items[newData.ID]) === JSON.stringify(newData)) 741 { 742 continue; 743 } 744 } 745 else 746 { 747 this.addSortedItem(newData.ID, true); 748 } 749 750 this.changedItems.push(newData.ID); 751 752 newData = this.checkBasketItemsAnimation(newData); 753 this.items[newData.ID] = newData; 754 } 755 } 756 757 this.changedItems = BX.util.array_unique(this.changedItems.concat(this.getChangedSimilarOffers())); 758 759 if (this.isBasketChanged()) 760 { 761 this.sortSortedItems(true); 762 } 763 } 764 765 if (result.TOTAL_RENDER_DATA) 766 { 767 result.TOTAL_RENDER_DATA = this.checkTotalAnimation(result.TOTAL_RENDER_DATA); 768 } 769 770 this.result = result; 771 }, 772 773 itemSortFunction: function(a, b) 774 { 775 if (!this.items.hasOwnProperty(a) || !this.items.hasOwnProperty(b)) 776 { 777 return 0; 778 } 779 780 return parseFloat(this.items[a].SORT) - parseFloat(this.items[b].SORT); 781 }, 782 783 getChangedSimilarOffers: function() 784 { 785 var changedSimilarOffers = []; 786 787 var otherSimilarItemsQuantity, totalSimilarItemsQuantity; 788 var hashMap = this.getHashMap(); 789 790 for (var hash in hashMap) 791 { 792 if (hashMap.hasOwnProperty(hash)) 793 { 794 if (hashMap[hash].length > 1) 795 { 796 for (var i = 0; i < hashMap[hash].length; i++) 797 { 798 otherSimilarItemsQuantity = 0; 799 totalSimilarItemsQuantity = 0; 800 801 for (var k = 0; k < hashMap[hash].length; k ++) 802 { 803 if (hashMap[hash][k] != hashMap[hash][i]) 804 { 805 otherSimilarItemsQuantity += parseFloat(this.items[hashMap[hash][k]].QUANTITY); 806 } 807 808 totalSimilarItemsQuantity += parseFloat(this.items[hashMap[hash][k]].QUANTITY); 809 } 810 811 if ( 812 !this.items[hashMap[hash][i]].HAS_SIMILAR_ITEMS 813 || this.items[hashMap[hash][i]].SIMILAR_ITEMS_QUANTITY != otherSimilarItemsQuantity 814 || this.items[hashMap[hash][i]].TOTAL_SIMILAR_ITEMS_QUANTITY != totalSimilarItemsQuantity 815 ) 816 { 817 changedSimilarOffers.push(hashMap[hash][i]); 818 819 this.items[hashMap[hash][i]].HAS_SIMILAR_ITEMS = true; 820 this.items[hashMap[hash][i]].SIMILAR_ITEMS_QUANTITY = otherSimilarItemsQuantity; 821 this.items[hashMap[hash][i]].TOTAL_SIMILAR_ITEMS_QUANTITY = totalSimilarItemsQuantity; 822 823 this.items[hashMap[hash][i]].ALL_AVAILABLE_QUANTITY = this.items[hashMap[hash][i]].AVAILABLE_QUANTITY; 824 this.items[hashMap[hash][i]].AVAILABLE_QUANTITY = this.items[hashMap[hash][i]].ALL_AVAILABLE_QUANTITY - otherSimilarItemsQuantity; 825 } 826 } 827 } 828 else if (hashMap[hash][0] && this.items[hashMap[hash][0]].HAS_SIMILAR_ITEMS) 829 { 830 changedSimilarOffers.push(hashMap[hash][0]); 831 832 delete this.items[hashMap[hash][0]].HAS_SIMILAR_ITEMS; 833 delete this.items[hashMap[hash][0]].SIMILAR_ITEMS_QUANTITY; 834 delete this.items[hashMap[hash][0]].TOTAL_SIMILAR_ITEMS_QUANTITY; 835 836 this.items[hashMap[hash][0]].AVAILABLE_QUANTITY = this.items[hashMap[hash][0]].ALL_AVAILABLE_QUANTITY; 837 delete this.items[hashMap[hash][0]].ALL_AVAILABLE_QUANTITY; 838 } 839 } 840 } 841 842 return changedSimilarOffers; 843 }, 844 845 getHashMap: function() 846 { 847 var hashMap = {}; 848 849 for (var id in this.items) 850 { 851 if (this.items.hasOwnProperty(id) && this.isItemAvailable(id)) 852 { 853 if (!hashMap.hasOwnProperty(this.items[id].HASH)) 854 { 855 hashMap[this.items[id].HASH] = []; 856 } 857 858 hashMap[this.items[id].HASH].push(id); 859 } 860 } 861 862 return hashMap; 863 }, 864 865 isItemAvailable: function(itemId) 866 { 867 var sortedItems = this.filter.isActive() ? this.filter.realSortedItems : this.sortedItems; 868 869 return !this.items[itemId].NOT_AVAILABLE 870 && !this.items[itemId].SHOW_RESTORE 871 && BX.util.in_array(itemId, sortedItems); 872 }, 873 874 checkTotalAnimation: function(totalData) 875 { 876 if (this.result && this.result.TOTAL_RENDER_DATA && parseFloat(this.result.TOTAL_RENDER_DATA.PRICE) > parseFloat(totalData.PRICE)) 877 { 878 totalData.PRICE_NEW = totalData.PRICE; 879 totalData.PRICE = this.result.TOTAL_RENDER_DATA.PRICE; 880 881 totalData.PRICE_FORMATED_NEW = totalData.PRICE_FORMATED; 882 totalData.PRICE_FORMATED = this.result.TOTAL_RENDER_DATA.PRICE_FORMATED; 883 884 this.addPriceAnimationData(this.ids.total, totalData.PRICE, totalData.PRICE_NEW, totalData.CURRENCY); 885 } 886 887 return totalData; 888 }, 889 890 checkBasketItemsAnimation: function(itemData) 891 { 892 var itemId = itemData.ID; 893 894 if (this.items[itemId]) 895 { 896 var quantityNode = BX(this.ids.quantity + itemId); 897 if ( 898 BX.type.isDomNode(quantityNode) 899 && !this.actionPool.isItemInPool(itemId) 900 && parseFloat(quantityNode.value) !== parseFloat(itemData.QUANTITY) 901 ) 902 { 903 itemData.QUANTITY_ANIMATION = true; 904 this.actionPool.clearLastActualQuantityPool(itemId); 905 } 906 907 if (parseFloat(this.items[itemId].PRICE) > parseFloat(itemData.PRICE)) 908 { 909 itemData.PRICE_NEW = itemData.PRICE; 910 itemData.PRICE = this.items[itemId].PRICE; 911 912 itemData.PRICE_FORMATED_NEW = itemData.PRICE_FORMATED; 913 itemData.PRICE_FORMATED = this.items[itemId].PRICE_FORMATED; 914 915 this.addPriceAnimationData(this.ids.price + itemId, itemData.PRICE, itemData.PRICE_NEW, itemData.CURRENCY); 916 } 917 918 if ( 919 BX.util.in_array('SUM', this.params.COLUMNS_LIST) 920 && parseFloat(this.items[itemId].SUM_PRICE) > parseFloat(itemData.SUM_PRICE) 921 && parseFloat(this.items[itemId].QUANTITY) === parseFloat(itemData.QUANTITY) 922 ) 923 { 924 itemData.SUM_PRICE_NEW = itemData.SUM_PRICE;
925 itemData.SUM_PRICE = this.items[itemId].SUM_PRICE; 926 927 itemData.SUM_PRICE_FORMATED_NEW = itemData.SUM_PRICE_FORMATED; 928 itemData.SUM_PRICE_FORMATED = this.items[itemId].SUM_PRICE_FORMATED; 929 930 this.addPriceAnimationData(this.ids.sumPrice + itemId, itemData.SUM_PRICE, itemData.SUM_PRICE_NEW, itemData.CURRENCY); 931 } 932 } 933 934 return itemData; 935 }, 936 937 getData: function(data) 938 { 939 data = data || {}; 940 941 data[this.params.ACTION_VARIABLE] = this.lastAction; 942 data.via_ajax = 'Y'; 943 data.site_id = this.siteId; 944 data.site_template_id = this.siteTemplateId; 945 data.sessid = BX.bitrix_sessid(); 946 data.template = this.template; 947 data.signedParamsString = this.signedParamsString; 948 949 return data; 950 }, 951 952 startLoader: function() 953 { 954 // if (!this.loadingScreen) 955 // { 956 // this.loadingScreen = new BX.PopupWindow('loading_screen', null, { 957 // events: { 958 // onAfterPopupShow: BX.delegate(function() { 959 // BX.cleanNode(this.loadingScreen.popupContainer); 960 // BX.removeClass(this.loadingScreen.popupContainer, 'popup-window'); 961 // this.loadingScreen.popupContainer.appendChild( 962 // BX.create('IMG', {props: {src: this.templateFolder + '/images/loader.gif'}}) 963 // ); 964 // this.loadingScreen.popupContainer.removeAttribute('style'); 965 // this.loadingScreen.popupContainer.style.display = 'block'; 966 // }, this) 967 // } 968 // }); 969 // BX.addClass(this.loadingScreen.popupContainer, 'bx-step-opacity'); 970 // } 971 // 972 // this.loadingScreen.show(); 973 }, 974 975 /** 976 * Hiding loader image with overlay. 977 */ 978 endLoader: function() 979 { 980 // if (this.loadingScreen && this.loadingScreen.isShown()) 981 // { 982 // this.loadingScreen.close(); 983 // } 984 }, 985 986 editWarnings: function() 987 { 988 this.editGeneralWarnings(); 989 this.editBasketItemWarnings(); 990 this.toggleWarningBlock(); 991 this.showWarningItemsCount(); 992 }, 993 994 editGeneralWarnings: function() 995 { 996 var warningsNode = this.getEntity(this.getCacheNode(this.ids.warning), 'basket-general-warnings'); 997 998 if (BX.type.isDomNode(warningsNode)) 999 { 1000 var generalWarningText = warningsNode.innerHTML; 1001 1002 if (this.result.WARNING_MESSAGE_WITH_CODE) 1003 { 1004 for (var code in this.result.WARNING_MESSAGE_WITH_CODE) 1005 { 1006 if (this.result.WARNING_MESSAGE_WITH_CODE.hasOwnProperty(code)) 1007 { 1008 if ( 1009 !this.items[code] 1010 && generalWarningText.indexOf(this.result.WARNING_MESSAGE_WITH_CODE[code]) === -1 1011 ) 1012 { 1013 generalWarningText += this.result.WARNING_MESSAGE_WITH_CODE[code] + '<br/>'; 1014 } 1015 } 1016 } 1017 } 1018 1019 if (generalWarningText) 1020 { 1021 warningsNode.innerHTML = generalWarningText; 1022 warningsNode.style.display = ''; 1023 } 1024 else 1025 { 1026 warningsNode.style.display = 'none'; 1027 warningsNode.innerHTML = ''; 1028 } 1029 } 1030 }, 1031 1032 editBasketItemWarnings: function() 1033 { 1034 var itemsWarningsNode = this.getEntity(this.getCacheNode(this.ids.warning), 'basket-item-warnings'); 1035 1036 if (BX.type.isDomNode(itemsWarningsNode)) 1037 { 1038 if (this.warningItems.length) 1039 { 1040 var warningCount = this.getEntity(itemsWarningsNode, 'basket-items-warning-count'); 1041 if (BX.type.isDomNode(warningCount)) 1042 { 1043 warningCount.innerHTML = this.warningItems.length + ' ' + this.getGoodsMessage(this.warningItems.length); 1044 } 1045 1046 itemsWarningsNode.style.display = ''; 1047 } 1048 else if (itemsWarningsNode.style.display !== 'none') 1049 { 1050 itemsWarningsNode.style.display = 'none'; 1051 1052 if (this.filter.isActive()) 1053 { 1054 this.toggleFilter('all'); 1055 } 1056 } 1057 } 1058 }, 1059 1060 toggleWarningBlock: function() 1061 { 1062 var warningNode = this.getCacheNode(this.ids.warning); 1063 1064 if (BX.type.isDomNode(warningNode)) 1065 { 1066 var generalWarningNode = this.getEntity(warningNode, 'basket-general-warnings'); 1067 var itemsWarningsNode = this.getEntity(warningNode, 'basket-item-warnings'); 1068 1069 if ( 1070 (!BX.type.isDomNode(generalWarningNode) || generalWarningNode.style.display === 'none') 1071 && (!BX.type.isDomNode(itemsWarningsNode) || itemsWarningsNode.style.display === 'none') 1072 ) 1073 { 1074 warningNode.style.display = 'none'; 1075 } 1076 else 1077 { 1078 warningNode.style.display = ''; 1079 } 1080 } 1081 }, 1082 1083 checkBasketItemWarnings: function(itemData, warnings) 1084 { 1085 if (!itemData) 1086 return; 1087 1088 var itemWarnings; 1089 1090 if (this.items[itemData.ID] && this.lastAction === 'refreshAjax') 1091 { 1092 itemWarnings = this.items[itemData.ID].WARNINGS; 1093 } 1094 else 1095 {
1096 itemWarnings = []; 1097 } 1098 1099 if (BX.type.isArray(warnings[itemData.ID]) && warnings[itemData.ID].length) 1100 { 1101 for (var i in warnings[itemData.ID]) 1102 { 1103 if (warnings[itemData.ID].hasOwnProperty(i) && !BX.util.in_array(warnings[itemData.ID][i], itemWarnings)) 1104 { 1105 itemWarnings.push(warnings[itemData.ID][i]); 1106 } 1107 } 1108 } 1109 1110 if (itemWarnings.length) 1111 { 1112 if (!BX.util.in_array(itemData.ID, this.warningItems)) 1113 { 1114 this.warningItems.push(itemData.ID); 1115 } 1116 } 1117 else if (BX.util.in_array(itemData.ID, this.warningItems)) 1118 { 1119 this.warningItems.splice(BX.util.array_search(itemData.ID, this.warningItems), 1); 1120 } 1121 1122 return itemWarnings; 1123 }, 1124 1125 removeAllWarnings: function(event) 1126 { 1127 this.clearGeneralWarnings(); 1128 this.clearBasketItemsWarnings(); 1129 1130 this.editWarnings(); 1131 1132 event && event.preventDefault(); 1133 }, 1134 1135 clearGeneralWarnings: function() 1136 { 1137 this.result.WARNING_MESSAGE_WITH_CODE = {}; 1138 1139 var generalWarningNode = this.getEntity(this.getCacheNode(this.ids.warning), 'basket-general-warnings'); 1140 1141 if (BX.type.isDomNode(generalWarningNode)) 1142 { 1143 generalWarningNode.innerHTML = ''; 1144 } 1145 }, 1146 1147 clearBasketItemsWarnings: function() 1148 { 1149 var itemsToEdit = []; 1150 1151 for (var i in this.warningItems) 1152 { 1153 if (this.warningItems.hasOwnProperty(i)) 1154 { 1155 this.items[this.warningItems[i]].WARNINGS = []; 1156 1157 if (this.isItemShown(this.warningItems[i])) 1158 { 1159 itemsToEdit.push(this.warningItems[i]); 1160 } 1161 } 1162 } 1163 1164 this.warningItems = []; 1165 this.editBasketItems(itemsToEdit); 1166 }, 1167 1168 isItemShown: function(itemId) 1169 { 1170 return BX.util.in_array(itemId, this.shownItems); 1171 }, 1172 1173 initializeBasketItems: function() 1174 { 1175 if (Object.keys(this.items).length === 0) 1176 return; 1177 1178 for (var i = 0; i < this.sortedItems.length; i++) 1179 { 1180 if (this.useDynamicScroll && this.shownItems.length >= this.maxItemsShowCount) 1181 { 1182 break; 1183 } 1184 1185 this.createBasketItem(this.sortedItems[i]); 1186 } 1187 }, 1188 1189 createBasketItem: function(itemId) 1190 { 1191 if (!this.items[itemId]) 1192 { 1193 return; 1194 } 1195 1196 var basketItemTemplate = this.getTemplate('basket-item-template'); 1197 if (basketItemTemplate) 1198 { 1199 var basketItemHtml = this.renderBasketItem(basketItemTemplate, this.items[itemId]); 1200 var sortIndex = BX.util.array_search(itemId, this.sortedItems); 1201 1202 if (this.shownItems.length && sortIndex >= 0) 1203 { 1204 if (sortIndex < BX.util.array_search(this.shownItems[0], this.sortedItems)) 1205 { 1206 // insert before 1207 BX(this.ids.item + this.shownItems[0]).insertAdjacentHTML('beforebegin', basketItemHtml); 1208 this.shownItems.unshift(itemId); 1209 } 1210 else if (sortIndex > BX.util.array_search(this.shownItems[this.shownItems.length - 1], this.sortedItems)) 1211 { 1212 // insert after 1213 BX(this.ids.item + this.shownItems[this.shownItems.length - 1]).insertAdjacentHTML('afterend', basketItemHtml); 1214 this.shownItems.push(itemId); 1215 } 1216 else 1217 { 1218 // insert between 1219 BX(this.ids.item + this.sortedItems[sortIndex + 1]).insertAdjacentHTML('beforebegin', basketItemHtml); 1220 this.shownItems.splice(sortIndex + 1, 0, itemId); 1221 } 1222 } 1223 else 1224 { 1225 this.getCacheNode(this.ids.itemListTable).insertAdjacentHTML('beforeend', basketItemHtml); 1226 this.shownItems.push(itemId); 1227 } 1228 1229 this.bindBasketItemEvents(this.items[itemId]); 1230 1231 if (this.filter.isActive()) 1232 { 1233 this.filter.highlightSearchMatch(this.items[itemId]); 1234 } 1235 } 1236 }, 1237 1238 getItemsToEdit: function() 1239 { 1240 var itemIds = []; 1241 1242 if (this.isBasketChanged()) 1243 { 1244 for (var i in this.changedItems) 1245 { 1246 if (this.changedItems.hasOwnProperty(i) && this.isItemShown(this.changedItems[i])) 1247 { 1248 itemIds.push(this.changedItems[i]); 1249 } 1250 } 1251 } 1252 1253 return itemIds; 1254 }, 1255 1256 getItemsAfter: function() 1257 { 1258 var itemIdsAfter = []; 1259 1260 if (this.useDynamicScroll) 1261 { 1262 var lastShownItemId = this.shownItems[this.shownItems.length - 1] || false; 1263 1264 if (lastShownItemId) 1265 { 1266 var i = 0; 1267 var index = BX.util.array_search(lastShownItemId, this.sortedItems); 1268 1269 while (this.sortedItems[++index] && i++ < this.maxItemsShowCount) 1270 { 1271 itemIdsAfter.push(this.sortedItems[index]); 1272 } 1273 } 1274 } 1275 1276 return itemIdsAfter; 1277 }, 1278 1279 editBasketItems: function(itemIds) 1280 { 1281 if (!itemIds || itemIds.length === 0) 1282 { 1283 return; 1284 } 1285 1286 var i, item; 1287 1288 for (i in itemIds) 1289 {
1290 if (!itemIds.hasOwnProperty(i) || !BX.type.isPlainObject(this.items[itemIds[i]])) 1291 { 1292 continue; 1293 } 1294 1295 item = this.items[itemIds[i]]; 1296 1297 if (this.actionPool.isItemInPool(item.ID)) 1298 { 1299 if (!BX.util.in_array(item.ID, this.postponedItems)) 1300 { 1301 this.postponedItems.push(item.ID); 1302 } 1303 1304 continue; 1305 } 1306 1307 if (BX.type.isDomNode(BX(this.ids.item + item.ID))) 1308 { 1309 this.redrawBasketItemNode(item.ID); 1310 this.applyQuantityAnimation(item.ID); 1311 } 1312 else 1313 { 1314 this.createBasketItem(item.ID); 1315 } 1316 } 1317 }, 1318 1319 editPostponedBasketItems: function() 1320 { 1321 if (!this.postponedItems.length) 1322 return; 1323 1324 var itemsToEdit = []; 1325 1326 for (var i in this.postponedItems) 1327 { 1328 if (this.postponedItems.hasOwnProperty(i) && this.isItemShown(this.postponedItems[i])) 1329 { 1330 itemsToEdit.push(this.postponedItems[i]); 1331 } 1332 } 1333 1334 this.postponedItems = []; 1335 this.editBasketItems(itemsToEdit); 1336 }, 1337 1338 applyQuantityAnimation: function(itemId) 1339 { 1340 var basketItemNode = BX(this.ids.item + itemId); 1341 1342 if (BX.type.isDomNode(basketItemNode) && this.items[itemId]) 1343 { 1344 if (this.items[itemId].QUANTITY_ANIMATION) 1345 { 1346 BX.addClass(BX(this.ids.quantity + itemId), 'basket-updated'); 1347 } 1348 } 1349 }, 1350 1351 applyPriceAnimation: function() 1352 { 1353 if (!this.priceAnimationData || Object.keys(this.priceAnimationData.start).length === 0) 1354 return; 1355 1356 var animationData = this.priceAnimationData, 1357 nodeCache = {}; 1358 1359 new BX.easing({ 1360 duration: this.params.USE_PRICE_ANIMATION === 'Y' ? this.duration.priceAnimation : 1, 1361 start: animationData.start, 1362 finish: animationData.finish, 1363 transition: BX.easing.makeEaseOut(BX.easing.transitions.quad), 1364 step: BX.delegate(function(state){ 1365 for (var nodeId in animationData.start) 1366 { 1367 if (animationData.start.hasOwnProperty(nodeId)) 1368 { 1369 if (!nodeCache[nodeId]) 1370 { 1371 if (nodeId === this.ids.total) 1372 { 1373 nodeCache[nodeId] = this.getEntities(this.getCacheNode(this.ids.basketRoot), this.ids.total); 1374 } 1375 else 1376 { 1377 var node = BX(nodeId); 1378 nodeCache[nodeId] = node ? [node] : []; 1379 } 1380 } 1381 1382 if (!animationData.int[nodeId]) 1383 { 1384 // fix price blinking 1385 state[nodeId] = (state[nodeId] + (state[nodeId] % 1000) / 1000).toFixed(5); 1386 } 1387 1388 for (var i = 0; i < nodeCache[nodeId].length; i++) 1389 { 1390 nodeCache[nodeId][i].innerHTML = this.getFormatPrice(state[nodeId], animationData.currency[nodeId]); 1391 } 1392 } 1393 } 1394 }, this), 1395 complete: BX.delegate(function() { 1396 var nodeId, formattedPrice, itemId, type; 1397 1398 for (nodeId in animationData.start) 1399 { 1400 if (animationData.start.hasOwnProperty(nodeId)) 1401 { 1402 formattedPrice = this.getFormatPrice(animationData.finish[nodeId], animationData.currency[nodeId]); 1403 1404 for (var i = 0; i < nodeCache[nodeId].length; i++) 1405 { 1406 nodeCache[nodeId][i].innerHTML = formattedPrice; 1407 } 1408 1409 if (nodeId.indexOf(this.ids.sumPrice) !== -1) 1410 { 1411 type = 'SUM_PRICE'; 1412 itemId = nodeId.substr(this.ids.sumPrice.length); 1413 } 1414 else if (nodeId.indexOf(this.ids.price) !== -1) 1415 { 1416 type = 'PRICE'; 1417 itemId = nodeId.substr(this.ids.price.length); 1418 } 1419 else if (nodeId.indexOf(this.ids.total) !== -1) 1420 { 1421 type = 'TOTAL'; 1422 itemId = ''; 1423 } 1424 else 1425 { 1426 itemId = ''; 1427 type = ''; 1428 } 1429 1430 if (BX.type.isNotEmptyString(type)) 1431 { 1432 if (itemId) 1433 { 1434 this.items[itemId][type] = animationData.finish[nodeId]; 1435 delete this.items[itemId][type + '_NEW']; 1436 this.items[itemId][type + '_FORMATED'] = formattedPrice; 1437 delete this.items[itemId][type + '_FORMATED_NEW']; 1438 } 1439 else if (type === 'TOTAL') 1440 { 1441 this.result.TOTAL_RENDER_DATA.PRICE = animationData.finish[nodeId]; 1442 delete this.result.TOTAL_RENDER_DATA.PRICE_NEW; 1443 this.result.TOTAL_RENDER_DATA.PRICE_FORMATED = formattedPrice; 1444 delete this.result.TOTAL_RENDER_DATA.PRICE_FORMATED_NEW; 1445 } 1446 } 1447 } 1448 } 1449 1450 this.filter.highlightFoundItems(); 1451 }, this) 1452 }).animate(); 1453 }, 1454 1455 getFormatPrice: function(price, currency) 1456 { 1457 return BX.Currency.currencyFormat(price, currency, true); 1458 }, 1459 1460 deleteBasketItems: function(items, restore, final) 1461 { 1462 if (!items || !items.length) 1463 { 1464 return; 1465 } 1466 1467 for (var i in items) 1468 { 1469 if (items.hasOwnProperty(i)) 1470 { 1471 this.deleteBasketItem(items[i], restore, final); 1472 } 1473 } 1474 }, 1475 1476 deleteBasketItem: function(itemId, restore, final) 1477 { 1478 // delete not available item with no chance to restore 1479 if (this.items[itemId].NOT_AVAILABLE && restore) 1480 { 1481 restore = false;
1482 final = true; 1483 } 1484 1485 if (restore) 1486 { 1487 this.items[itemId].SHOW_RESTORE = true; 1488 this.items[itemId].SHOW_LOADING = false; 1489 this.redrawBasketItemNode(itemId); 1490 } 1491 else 1492 { 1493 this.changeShownItem(itemId); 1494 BX.remove(BX(this.ids.item + itemId)); 1495 } 1496 1497 if (final) 1498 { 1499 this.changeSortedItem(itemId, false, true); 1500 this.changeShownItem(itemId, false, true); 1501 } 1502 }, 1503 1504 addSortedItem: function(itemId, all) 1505 { 1506 this.sortedItems.push(itemId.toString()); 1507 1508 if (all && this.filter.isActive()) 1509 { 1510 this.filter.realSortedItems.push(itemId.toString()); 1511 } 1512 }, 1513 1514 changeSortedItem: function(itemId, newItemId, all) 1515 { 1516 var index = BX.util.array_search(itemId, this.sortedItems); 1517 1518 if (index >= 0) 1519 { 1520 if (newItemId) 1521 { 1522 this.sortedItems.splice(index, 1, newItemId.toString()); 1523 } 1524 else 1525 { 1526 this.sortedItems.splice(index, 1); 1527 } 1528 } 1529 1530 if (all && this.filter.isActive()) 1531 { 1532 index = BX.util.array_search(itemId, this.filter.realSortedItems); 1533 1534 if (index >= 0) 1535 { 1536 if (newItemId) 1537 { 1538 this.filter.realSortedItems.splice(index, 1, newItemId.toString()); 1539 } 1540 else 1541 { 1542 this.filter.realSortedItems.splice(index, 1); 1543 } 1544 } 1545 } 1546 }, 1547 1548 sortSortedItems: function(all) 1549 { 1550 this.sortedItems.sort(BX.proxy(this.itemSortFunction, this)); 1551 1552 if (all && this.filter.isActive()) 1553 { 1554 this.filter.realSortedItems.sort(BX.proxy(this.itemSortFunction, this)); 1555 } 1556 }, 1557 1558 changeShownItem: function(itemId, newItemId, all) 1559 { 1560 var index = BX.util.array_search(itemId, this.shownItems); 1561 1562 if (index >= 0) 1563 { 1564 if (newItemId) 1565 { 1566 this.shownItems.splice(index, 1, newItemId.toString()); 1567 } 1568 else 1569 { 1570 this.shownItems.splice(index, 1); 1571 } 1572 } 1573 1574 if (all && this.filter.isActive()) 1575 { 1576 index = BX.util.array_search(itemId, this.filter.realShownItems); 1577 1578 if (index >= 0) 1579 { 1580 if (newItemId) 1581 { 1582 this.filter.realShownItems.splice(index, 1, newItemId.toString()); 1583 } 1584 else 1585 { 1586 this.filter.realShownItems.splice(index, 1); 1587 } 1588 } 1589 } 1590 }, 1591 1592 redrawBasketItemNode: function(itemId) 1593 { 1594 var basketItemNode = BX(this.ids.item + itemId); 1595 1596 if (!this.items[itemId] || !BX.type.isDomNode(basketItemNode)) 1597 return; 1598 1599 var basketItemTemplate = this.getTemplate('basket-item-template'); 1600 if (basketItemTemplate) 1601 { 1602 var nodeAligner = BX(this.ids.itemHeightAligner + itemId), 1603 oldHeight; 1604 1605 if (BX.type.isDomNode(nodeAligner)) 1606 { 1607 oldHeight = nodeAligner.clientHeight; 1608 } 1609 1610 var basketItemHtml = this.renderBasketItem(basketItemTemplate, this.items[itemId]); 1611 basketItemNode.insertAdjacentHTML('beforebegin', basketItemHtml); 1612 BX.remove(basketItemNode); 1613 1614 if (oldHeight) 1615 { 1616 nodeAligner = BX(this.ids.itemHeightAligner + itemId); 1617 1618 if (BX.type.isDomNode(nodeAligner) && nodeAligner.clientHeight < oldHeight) 1619 { 1620 nodeAligner.style.minHeight = oldHeight + 'px'; 1621 setTimeout(function(){nodeAligner.style.minHeight = '0px';}, 1); 1622 } 1623 } 1624 1625 this.bindBasketItemEvents(this.items[itemId]); 1626 1627 if (this.filter.isActive()) 1628 { 1629 this.filter.highlightSearchMatch(this.items[itemId]); 1630 } 1631 } 1632 }, 1633 1634 restoreBasketItems: function(items) 1635 { 1636 if (!items || Object.keys(items).length === 0) 1637 { 1638 return; 1639 } 1640 1641 var oldItemId, newItemId, basketItemNode; 1642 1643 for (oldItemId in items) 1644 { 1645 if (items.hasOwnProperty(oldItemId)) 1646 { 1647 newItemId = items[oldItemId]; 1648 1649 if (this.isItemShown(oldItemId)) 1650 { 1651 this.changeShownItem(oldItemId, newItemId, true); 1652 1653 basketItemNode = BX(this.ids.item + oldItemId); 1654 if (BX.type.isDomNode(basketItemNode)) 1655 { 1656 basketItemNode.id = this.ids.item + newItemId; 1657 basketItemNode.setAttribute('data-id', newItemId); 1658 } 1659 } 1660 1661 this.changeSortedItem(oldItemId, false, true); 1662 } 1663 } 1664 }, 1665 1666 bindBasketItemEvents: function(itemData) 1667 { 1668 if (!itemData) 1669 return; 1670 1671 var itemNode = BX(this.ids.item + itemData.ID); 1672 if (BX.type.isDomNode(itemNode)) 1673 { 1674 this.bindQuantityEvents(itemNode, itemData); 1675 this.bindSkuEvents(itemNode, itemData); 1676 this.bindImageEvents(itemNode, itemData); 1677 this.bindActionEvents(itemNode, itemData); 1678 this.bindRestoreAction(itemNode, itemData); 1679 this.bindItemWarningEvents(itemNode, itemData); 1680 } 1681 }, 1682 1683 bindQuantityEvents: function(node, data) 1684 { 1685 if (!node || !data || !this.isItemAvailable(data.ID)) 1686 return; 1687 1688 var entity; 1689 1690 var block = this.getEntity(node, 'basket-item-quantity-block'); 1691 if (block) 1692 { 1693 var startEventName = this.isTouch ? 'touchstart' : 'mousedown'; 1694 var endEventName = this.isTouch ? 'touchend' : 'mouseup'; 1695 1696 entity = this.getEntity(block, 'basket-item-quantity-minus'); 1697 BX.bind(entity, startEventName, BX.proxy(this.startQuantityInterval, this)); 1698 BX.bind(entity, endEventName, BX.proxy(this.clearQuantityInterval, this)); 1699 BX.bind(entity, 'mouseout', BX.proxy(this.clearQuantityInterval, this)); 1700 BX.bind(entity, 'click', BX.proxy(this.quantityMinus, this)); 1701 1702 entity = this.getEntity(block, 'basket-item-quantity-plus'); 1703 BX.bind(entity, startEventName, BX.proxy(this.startQuantityInterval, this)); 1704 BX.bind(entity, endEventName, BX.proxy(this.clearQuantityInterval, this)); 1705 BX.bind(entity, 'mouseout', BX.proxy(this.clearQuantityInterval, this)); 1706 BX.bind(entity, 'click', BX.proxy(this.quantityPlus, this)); 1707 1708 entity = this.getEntity(block, 'basket-item-quantity-field'); 1709 BX.bind(entity, 'change', BX.proxy(this.quantityChange, this)); 1710 } 1711 }, 1712 1713 startQuantityInterval: function() 1714 { 1715 var target = BX.proxy_context; 1716 var func = target.getAttribute('data-entity') === 'basket-item-quantity-minus' 1717 ? BX.proxy(this.quantityMinus, this) 1718 : BX.proxy(this.quantityPlus, this); 1719 1720 this.quantityDelay = setTimeout( 1721 BX.delegate(function() { 1722 this.quantityTimer = setInterval(function(){func(target);}, 150); 1723 }, this), 1724 300 1725 ); 1726 }, 1727 1728 clearQuantityInterval: function() 1729 { 1730 clearTimeout(this.quantityDelay); 1731 clearInterval(this.quantityTimer); 1732 }, 1733 1734 quantityPlus: function(target) 1735 { 1736 if (!BX.type.isDomNode(target)) 1737 { 1738 target = BX.proxy_context; 1739 this.clearQuantityInterval(); 1740 } 1741 1742 var itemData = this.getItemDataByTarget(target); 1743 if (itemData) 1744 { 1745 var quantityField = BX(this.ids.quantity + itemData.ID); 1746 var isQuantityFloat = this.isQuantityFloat(itemData); 1747 1748 var currentQuantity = isQuantityFloat ? parseFloat(quantityField.value) : Math.round(quantityField.value); 1749 var measureRatio = isQuantityFloat ? parseFloat(itemData.MEASURE_RATIO) : parseInt(itemData.MEASURE_RATIO); 1750 1751 var quantity = parseFloat((currentQuantity + measureRatio).toFixed(5)); 1752 quantity = this.getCorrectQuantity(itemData, quantity); 1753 1754 this.setQuantity(itemData, quantity); 1755 } 1756 }, 1757 1758 quantityMinus: function(target) 1759 { 1760 target = BX.type.isDomNode(target) ? target : BX.proxy_context; 1761 1762 var itemData = this.getItemDataByTarget(target); 1763 if (itemData) 1764 { 1765 var quantityField = BX(this.ids.quantity + itemData.ID); 1766 var isQuantityFloat = this.isQuantityFloat(itemData); 1767 1768 var currentQuantity = isQuantityFloat ? parseFloat(quantityField.value) : Math.round(quantityField.value); 1769 var measureRatio = isQuantityFloat ? parseFloat(itemData.MEASURE_RATIO) : parseInt(itemData.MEASURE_RATIO); 1770 1771 var quantity = parseFloat((currentQuantity - measureRatio).toFixed(5)); 1772 quantity = this.getCorrectQuantity(itemData, quantity); 1773 1774 this.setQuantity(itemData, quantity); 1775 } 1776 }, 1777 1778 quantityChange: function() 1779 { 1780 var itemData = this.getItemDataByTarget(BX.proxy_context); 1781 if (itemData) 1782 { 1783 var quantityField, quantity; 1784 1785 quantityField = BX(this.ids.quantity + itemData.ID); 1786 quantity = this.getCorrectQuantity(itemData, quantityField.value); 1787 1788 this.setQuantity(itemData, quantity); 1789 } 1790 }, 1791 1792 isQuantityFloat: function(item) 1793 { 1794 return this.params.QUANTITY_FLOAT === 'Y' || (parseInt(item.MEASURE_RATIO) !== parseFloat(item.MEASURE_RATIO)); 1795 }, 1796 1797 getCorrectQuantity: function(itemData, quantity) 1798 { 1799 var isQuantityFloat = this.isQuantityFloat(itemData), 1800 measureRatio = isQuantityFloat ? parseFloat(itemData.MEASURE_RATIO) : parseInt(itemData.MEASURE_RATIO), 1801 availableQuantity = 0; 1802 1803 quantity = (isQuantityFloat ? parseFloat(quantity) : parseInt(quantity, 10)) || 0; 1804 if (quantity < 0) 1805 { 1806 quantity = 0; 1807 } 1808 1809 if (measureRatio > 0 && quantity < measureRatio) 1810 { 1811 quantity = measureRatio; 1812 } 1813 1814 if (itemData.CHECK_MAX_QUANTITY === 'Y') 1815 { 1816 availableQuantity = isQuantityFloat ? parseFloat(itemData.AVAILABLE_QUANTITY) : parseInt(itemData.AVAILABLE_QUANTITY); 1817 if (availableQuantity > 0 && quantity > availableQuantity) 1818 { 1819 quantity = availableQuantity; 1820 } 1821 } 1822 1823 var reminder = (quantity / measureRatio - ((quantity / measureRatio).toFixed(0))).toFixed(5), 1824 remain; 1825 1826 if (parseFloat(reminder) === 0) 1827 { 1828 return quantity; 1829 } 1830 1831 if (measureRatio !== 0 && measureRatio !== 1) 1832 { 1833 remain = (quantity * this.precisionFactor) % (measureRatio * this.precisionFactor) / this.precisionFactor; 1834 1835 if (measureRatio > 0 && remain > 0) 1836 { 1837 if ( 1838 remain >= measureRatio / 2 1839 && ( 1840 availableQuantity === 0 1841 || (quantity + measureRatio - remain) <= availableQuantity 1842 ) 1843 ) 1844 { 1845 quantity += (measureRatio - remain); 1846 } 1847 else 1848 { 1849 quantity -= remain; 1850 } 1851 } 1852 } 1853 1854 quantity = isQuantityFloat ? parseFloat(quantity) : parseInt(quantity, 10); 1855 1856 return quantity; 1857 }, 1858 1859 setQuantity: function(itemData, quantity) 1860 { 1861 var quantityField = BX(this.ids.quantity + itemData.ID), 1862 currentQuantity; 1863 1864 if (quantityField) 1865 { 1866 quantity = parseFloat(quantity); 1867 currentQuantity = parseFloat(quantityField.getAttribute('data-value')); 1868 1869 quantityField.value = quantity; 1870 1871 if (parseFloat(itemData.QUANTITY) !== parseFloat(quantity)) 1872 { 1873 this.animatePriceByQuantity(itemData, quantity); 1874 this.actionPool.changeQuantity(itemData.ID, quantity, currentQuantity); 1875 } 1876 } 1877 }, 1878 1879 animatePriceByQuantity: function(itemData, quantity) 1880 { 1881 var priceNode = BX(this.ids.sumPrice + itemData.ID); 1882 if (!BX.type.isDomNode(priceNode)) 1883 return; 1884 1885 var quantityMultiplier = quantity / parseFloat(itemData.MEASURE_RATIO); 1886 1887 var startPrice = parseFloat(itemData.SUM_PRICE), 1888 finalPrice = parseFloat(itemData.PRICE) * quantityMultiplier, 1889 isInt = parseInt(startPrice) === parseFloat(startPrice) 1890 && parseInt(finalPrice) === parseFloat(finalPrice); 1891 1892 if (startPrice !== finalPrice) 1893 { 1894 this.items[itemData.ID].QUANTITY = quantity;
1895 this.items[itemData.ID].SUM_PRICE = finalPrice; 1896 1897 new BX.easing({ 1898 duration: this.params.USE_PRICE_ANIMATION === 'Y' ? this.duration.priceAnimation : 1, 1899 start: {price: startPrice}, 1900 finish: {price: finalPrice}, 1901 transition: BX.easing.makeEaseOut(BX.easing.transitions.quad), 1902 step: BX.delegate(function(state){ 1903 if (!isInt) 1904 { 1905 // fix price blinking 1906 state.price = (state.price + (state.price % 1000) / 1000).toFixed(5); 1907 } 1908 1909 priceNode.innerHTML = this.getFormatPrice(state.price, itemData.CURRENCY); 1910 }, this), 1911 complete: BX.delegate(function() { 1912 var node, price; 1913 1914 priceNode.innerHTML = this.getFormatPrice(finalPrice, itemData.CURRENCY); 1915 1916 node = BX(this.ids.sumPriceOld + itemData.ID); 1917 if (BX.type.isDomNode(node)) 1918 { 1919 price = parseFloat(itemData.FULL_PRICE) * quantityMultiplier; 1920 node.innerHTML = this.getFormatPrice(price, itemData.CURRENCY); 1921 } 1922 1923 node = BX(this.ids.sumPriceDiff + itemData.ID); 1924 if (BX.type.isDomNode(node)) 1925 { 1926 price = parseFloat(itemData.DISCOUNT_PRICE) * quantityMultiplier; 1927 node.innerHTML = this.getFormatPrice(price, itemData.CURRENCY); 1928 } 1929 }, this) 1930 }).animate(); 1931 } 1932 }, 1933 1934 getItemDataByTarget: function(target) 1935 { 1936 var data = false; 1937 var id; 1938 1939 var itemNode = BX.findParent(target, {attrs: {'data-entity': 'basket-item'}}); 1940 if (itemNode) 1941 { 1942 id = itemNode.getAttribute('data-id'); 1943 data = this.items[id]; 1944 } 1945 1946 return data; 1947 }, 1948 1949 bindSkuEvents: function(node, data) 1950 { 1951 if (!node || !data) 1952 return; 1953 1954 var blocks = this.getEntities(node, 'basket-item-sku-block'); 1955 var blockEntities, i, l, ii, ll; 1956 1957 for (i = 0, l = blocks.length; i < l; i++) 1958 { 1959 blockEntities = this.getEntities(blocks[i], 'basket-item-sku-field'); 1960 1961 for (ii = 0, ll = blockEntities.length; ii < ll; ii++) 1962 { 1963 BX.bind(blockEntities[ii], 'click', BX.proxy(this.changeSku, this)); 1964 } 1965 } 1966 }, 1967 1968 changeSku: function() 1969 { 1970 var i, l; 1971 1972 var target = BX.proxy_context; 1973 1974 if (BX.hasClass(target, 'selected')) 1975 return; 1976 1977 var itemData = this.getItemDataByTarget(target); 1978 if (itemData) 1979 { 1980 var basketItemNode = BX(this.ids.item + itemData.ID); 1981 if (basketItemNode) 1982 { 1983 var currentSkuListNodes = this.getEntities(target.parentNode, 'basket-item-sku-field'); 1984 for (i = 0, l = currentSkuListNodes.length; i < l; i++) 1985 { 1986 if (currentSkuListNodes[i].isEqualNode(target)) 1987 { 1988 BX.addClass(currentSkuListNodes[i], 'selected'); 1989 } 1990 else 1991 { 1992 BX.removeClass(currentSkuListNodes[i], 'selected'); 1993 } 1994 } 1995 1996 this.actionPool.changeSku( 1997 itemData.ID, 1998 this.getSkuPropertyValues(basketItemNode), 1999 this.getInitialSkuPropertyValues(basketItemNode) 2000 ); 2001 } 2002 } 2003 }, 2004 2005 getSkuPropertyValues: function(basketItemNode) 2006 { 2007 var propertyValues = {}; 2008 2009 var propNodes = this.getEntities(basketItemNode, 'basket-item-sku-field', '.selected'); 2010 for (var i = 0, l = propNodes.length; i < l; i++) 2011 { 2012 propertyValues[propNodes[i].getAttribute('data-property')] = BX.util.htmlspecialcharsback(propNodes[i].getAttribute('data-value-id')); 2013 } 2014 2015 return propertyValues; 2016 }, 2017 2018 getInitialSkuPropertyValues: function(basketItemNode) 2019 { 2020 var propertyValues = {}; 2021 2022 var propNodes = this.getEntities(basketItemNode, 'basket-item-sku-field', '[data-initial="true"]'); 2023 for (var i = 0, l = propNodes.length; i < l; i++) 2024 { 2025 propertyValues[propNodes[i].getAttribute('data-property')] = BX.util.htmlspecialcharsback(propNodes[i].getAttribute('data-value-id')); 2026 } 2027 2028 return propertyValues; 2029 }, 2030 2031 bindImageEvents: function(node, data) 2032 { 2033 if (!node || !data) 2034 return; 2035 2036 var images = node.querySelectorAll('.basket-item-custom-block-photo-item'); 2037 for (var i = 0, l = images.length; i < l; i++) 2038 { 2039 BX.bind(images[i], 'click', BX.proxy(this.showPropertyImagePopup, this)); 2040 } 2041 }, 2042 2043 showPropertyImagePopup: function() 2044 { 2045 var target, propertyCode, imageIndex, item, imageSrc, i; 2046 2047 target = BX.proxy_context; 2048 item = this.getItemDataByTarget(target); 2049 2050 propertyCode = target.getAttribute('data-column-property-code'); 2051 imageIndex = target.getAttribute('data-image-index'); 2052 2053 if (item && item.COLUMN_LIST) 2054 { 2055 for (i in item.COLUMN_LIST) 2056 { 2057 if ( 2058 item.COLUMN_LIST.hasOwnProperty(i) 2059 && item.COLUMN_LIST[i].CODE === propertyCode 2060 && item.COLUMN_LIST[i].VALUE[imageIndex] 2061 ) 2062 { 2063 imageSrc = item.COLUMN_LIST[i].VALUE[imageIndex].IMAGE_SRC_ORIGINAL; 2064 break; 2065 } 2066 } 2067 } 2068 2069 if (!imageSrc) 2070 { 2071 return; 2072 } 2073 2074 if (this.imagePopup) 2075 { 2076 this.imagePopup.destroy(); 2077 } 2078 2079 var imageId = 'bx-soa-image-popup-content'; 2080 var that = this; 2081 2082 this.imagePopup = new BX.PopupWindow('bx-soa-image-popup', null, { 2083 lightShadow: true, 2084 offsetTop: 0, 2085 offsetLeft: 0, 2086 closeIcon: {top: '3px', right: '10px'}, 2087 autoHide: true, 2088 bindOptions: {position: 'bottom'}, 2089 closeByEsc: true, 2090 zIndex: 100, 2091 events: { 2092 onPopupShow: function() { 2093 BX.create('IMG', { 2094 props: {src: imageSrc}, 2095 events: { 2096 load: function() { 2097 var content = BX(imageId); 2098 if (content) 2099 { 2100 var windowSize = BX.GetWindowInnerSize(), 2101 ratio = that.isMobile ? 0.5 : 0.9, 2102 contentHeight, contentWidth; 2103 2104 BX.cleanNode(content); 2105 content.appendChild(this); 2106 2107 contentHeight = content.offsetHeight; 2108 contentWidth = content.offsetWidth; 2109 2110 if (contentHeight >
2110 windowSize.innerHeight * ratio) 2111 { 2112 content.style.height = windowSize.innerHeight * ratio + 'px'; 2113 content.style.width = contentWidth * (windowSize.innerHeight * ratio / contentHeight) + 'px'; 2114 contentHeight = content.offsetHeight; 2115 contentWidth = content.offsetWidth; 2116 } 2117 2118 if (contentWidth > windowSize.innerWidth * ratio) 2119 { 2120 content.style.width = windowSize.innerWidth * ratio + 'px'; 2121 content.style.height = contentHeight * (windowSize.innerWidth * ratio / contentWidth) + 'px'; 2122 } 2123 2124 content.style.height = content.offsetHeight + 'px'; 2125 content.style.width = content.offsetWidth + 'px'; 2126 2127 that.imagePopup.adjustPosition(); 2128 } 2129 } 2130 } 2131 }); 2132 }, 2133 onPopupClose: function() { 2134 this.destroy(); 2135 } 2136 }, 2137 content: BX.create('DIV', {props: {id: imageId}}) 2138 }); 2139 this.imagePopup.show(); 2140 }, 2141 2142 bindActionEvents: function(node, data) 2143 { 2144 if (!node || !data) 2145 return; 2146 2147 var entity; 2148 2149 if (BX.util.in_array('DELETE', this.params.COLUMNS_LIST)) 2150 { 2151 entity = this.getEntities(node, 'basket-item-delete'); 2152 for (var i = 0, l = entity.length; i < l; i++) 2153 { 2154 BX.bind(entity[i], 'click', BX.proxy(this.deleteAction, this)); 2155 } 2156 } 2157 2158 if (BX.util.in_array('DELAY', this.params.COLUMNS_LIST)) 2159 { 2160 entity = this.getEntity(node, 'basket-item-add-delayed'); 2161 BX.bind(entity, 'click', BX.proxy(this.addDelayedAction, this)); 2162 } 2163 2164 entity = this.getEntity(node, 'basket-item-remove-delayed'); 2165 BX.bind(entity, 'click', BX.proxy(this.removeDelayedAction, this)); 2166 2167 entity = this.getEntity(node, 'basket-item-merge-sku-link'); 2168 BX.bind(entity, 'click', BX.proxy(this.mergeAction, this)); 2169 2170 entity = this.getEntity(node, 'basket-item-show-similar-link'); 2171 BX.bind(entity, 'click', BX.delegate(function() {this.toggleFilter('similar');}, this)); 2172 }, 2173 2174 deleteAction: function() 2175 { 2176 var itemData = this.getItemDataByTarget(BX.proxy_context); 2177 if (itemData) 2178 { 2179 this.actionPool.deleteItem(itemData.ID); 2180 2181 this.items[itemData.ID].SHOW_LOADING = true; 2182 2183 if (this.params.SHOW_RESTORE === 'Y' && this.isItemAvailable(itemData.ID)) 2184 { 2185 this.items[itemData.ID].SHOW_RESTORE = true; 2186 } 2187 2188 this.redrawBasketItemNode(itemData.ID); 2189 } 2190 }, 2191 2192 addDelayedAction: function() 2193 { 2194 var itemData = this.getItemDataByTarget(BX.proxy_context); 2195 if (itemData) 2196 { 2197 this.actionPool.addDelayed(itemData.ID); 2198 2199 this.items[itemData.ID].SHOW_LOADING = true; 2200 this.redrawBasketItemNode(itemData.ID); 2201 } 2202 }, 2203 2204 removeDelayedAction: function() 2205 { 2206 var itemData = this.getItemDataByTarget(BX.proxy_context); 2207 if (itemData) 2208 { 2209 this.actionPool.removeDelayed(itemData.ID); 2210 2211 this.items[itemData.ID].SHOW_LOADING = true; 2212 this.redrawBasketItemNode(itemData.ID); 2213 } 2214 }, 2215 2216 mergeAction: function() 2217 { 2218 var itemData = this.getItemDataByTarget(BX.proxy_context); 2219 if (itemData) 2220 { 2221 this.actionPool.mergeSku(itemData.ID); 2222 } 2223 }, 2224 2225 bindRestoreAction: function(node, itemData) 2226 { 2227 if (!node || !itemData || this.params.SHOW_RESTORE !== 'Y') 2228 return; 2229 2230 BX.bind( 2231 this.getEntity(node, 'basket-item-restore-button'), 2232 'click', 2233 BX.delegate(function() { 2234 this.actionPool.restoreItem(itemData.ID, { 2235 PRODUCT_ID: itemData.PRODUCT_ID, 2236 QUANTITY: itemData.QUANTITY, 2237 PROPS: itemData.PROPS_ALL, 2238 SORT: itemData.SORT, 2239 MODULE: itemData.MODULE, 2240 PRODUCT_PROVIDER_CLASS: itemData.PRODUCT_PROVIDER_CLASS 2241 }); 2242 2243 this.items[itemData.ID].SHOW_RESTORE = false; 2244 this.items[itemData.ID].SHOW_LOADING = true; 2245 this.redrawBasketItemNode(itemData.ID); 2246 }, this) 2247 ); 2248 BX.bind( 2249 this.getEntity(node, 'basket-item-close-restore-button'), 2250 'click', 2251 BX.delegate(function() { 2252 this.deleteBasketItem(itemData.ID, false, true); 2253 }, this) 2254 ); 2255 }, 2256 2257 bindItemWarningEvents: function(node, data) 2258 { 2259 if (!node || !data) 2260 return; 2261 2262 BX.bind( 2263 this.getEntity(BX(this.ids.item + data.ID), 'basket-item-warning-close'), 2264 'click', 2265 BX.proxy(this.closeItemWarnings, this) 2266 ); 2267 }, 2268 2269 closeItemWarnings: function() 2270 { 2271 var target = BX.proxy_context; 2272 2273 if (BX.type.isDomNode(target)) 2274 { 2275 var itemData = this.getItemDataByTarget(target); 2276 2277 this.items[itemData.ID].WARNINGS = []; 2278 this.warningItems.splice(BX.util.array_search(itemData.ID, this.warningItems), 1); 2279 2280 this.redrawBasketItemNode(itemData.ID); 2281 this.editWarnings(); 2282 } 2283 }, 2284 2285 renderBasketItem: function(template, data) 2286 { 2287 var clonedData = BX.clone(data); 2288 2289 if (BX.type.isPlainObject(clonedData)) 2290 { 2291 clonedData.USE_FILTER = this.useItemsFilter 2292 && !this.filter.currentFilter.similarHash.length; 2293 } 2294 2295 return Mustache.render(template, clonedData); 2296 }, 2297 2298 render: function(template, data) 2299 { 2300 return Mustache.render(template, data); 2301 }, 2302 2303 checkAnalytics: function(data) 2304 { 2305 if (!data || !data.basket) 2306 return; 2307 2308 var itemId, itemsDiff = {}; 2309 2310 for (var i in data.basket) 2311 { 2312 if (data.basket.hasOwnProperty(i)) 2313 { 2314 if (i.indexOf('QUANTITY_') >= 0) 2315 { 2316 itemId = i.substr(9); 2317 2318 if (this.items[itemId]) 2319 { 2320 itemsDiff[itemId] = parseFloat(data.basket[i]) - parseFloat(BX(this.ids.quantity + itemId).getAttribute('data-value')); 2321 } 2322 } 2323 else if (i.indexOf('DELETE_') >= 0) 2324 { 2325 itemId = i.substr(7); 2326 2327 if (this.items[itemId]) 2328 {
2329 itemsDiff[itemId] = -parseFloat(this.items[itemId].QUANTITY); 2330 } 2331 } 2332 else if (i.indexOf('RESTORE_') >= 0) 2333 { 2334 itemId = i.substr(8); 2335 2336 if (this.items[itemId]) 2337 { 2338 itemsDiff[itemId] = parseFloat(this.items[itemId].QUANTITY); 2339 } 2340 } 2341 } 2342 } 2343 2344 this.setAnalyticsDataLayer(itemsDiff); 2345 }, 2346 2347 setAnalyticsDataLayer: function(itemsDiff) 2348 { 2349 if (!itemsDiff || Object.keys(itemsDiff).length === 0) 2350 return; 2351 2352 window[this.params.DATA_LAYER_NAME] = window[this.params.DATA_LAYER_NAME] || []; 2353 2354 var plus = [], minus = []; 2355 2356 for (var itemId in itemsDiff) 2357 { 2358 if (itemsDiff.hasOwnProperty(itemId)) 2359 { 2360 if (itemsDiff[itemId] > 0) 2361 { 2362 plus.push(this.getItemAnalyticsInfo(itemId, itemsDiff[itemId])); 2363 } 2364 else if (itemsDiff[itemId] < 0) 2365 { 2366 minus.push(this.getItemAnalyticsInfo(itemId, itemsDiff[itemId])); 2367 } 2368 } 2369 } 2370 2371 if (plus.length) 2372 { 2373 window[this.params.DATA_LAYER_NAME].push({ 2374 event: 'addToCart', 2375 ecommerce: { 2376 currencyCode: this.items[itemId].CURRENCY || '', 2377 add: { 2378 products: plus 2379 } 2380 } 2381 }); 2382 } 2383 2384 if (minus.length) 2385 { 2386 window[this.params.DATA_LAYER_NAME].push({ 2387 event: 'removeFromCart', 2388 ecommerce: { 2389 currencyCode: this.items[itemId].CURRENCY || '', 2390 remove: { 2391 products: minus 2392 } 2393 } 2394 }); 2395 } 2396 }, 2397 2398 getItemAnalyticsInfo: function(itemId, diff) 2399 { 2400 if (!this.items[itemId]) 2401 return {}; 2402 2403 var brand = (this.items[itemId].BRAND || '').split(', ').join('/'); 2404 var variants = []; 2405 2406 var selectedSku = this.getEntities(BX(this.ids.item + itemId), 'basket-item-sku-field', '.selected'); 2407 for (var i = 0, l = selectedSku.length; i < l; i++) 2408 { 2409 variants.push(selectedSku[i].getAttribute('data-sku-name')); 2410 } 2411 2412 return { 2413 'name': this.items[itemId].NAME || '', 2414 'id': this.items[itemId].PRODUCT_ID || '', 2415 'price': this.items[itemId].PRICE || 0, 2416 'brand': brand, 2417 'variant': variants.join('/'), 2418 'quantity': Math.abs(diff) 2419 }; 2420 } 2421 }; 2422})();
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.