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