1(function (window){ 2 'use strict'; 3 4 if (window.JCCatalogItem) 5 return; 6 7 var BasketButton = function(params) 8 { 9 BasketButton.superclass.constructor.apply(this, arguments); 10 this.buttonNode = BX.create('button', { 11 props: {className: 'btn btn-primary btn-buy btn-sm', id: this.id}, 12 style: typeof params.style === 'object' ? params.style : {}, 13 text: params.text, 14 events: this.contextEvents 15 }); 16 17 if (BX.browser.IsIE()) 18 { 19 this.buttonNode.setAttribute("hideFocus", "hidefocus"); 20 } 21 }; 22 BX.extend(BasketButton, BX.PopupWindowButton); 23 24 window.JCCatalogItem = function (arParams) 25 { 26 this.productType = 0; 27 this.showQuantity = true; 28 this.showAbsent = true; 29 this.secondPict = false; 30 this.showOldPrice = false; 31 this.showMaxQuantity = 'N'; 32 this.relativeQuantityFactor = 5; 33 this.showPercent = false; 34 this.showSkuProps = false; 35 this.basketAction = 'ADD'; 36 this.showClosePopup = false; 37 this.useCompare = false; 38 this.showSubscription = false; 39 this.visual = { 40 ID: '', 41 PICT_ID: '', 42 SECOND_PICT_ID: '', 43 QUANTITY_ID: '', 44 QUANTITY_UP_ID: '', 45 QUANTITY_DOWN_ID: '', 46 PRICE_ID: '', 47 PRICE_OLD_ID: '', 48 DSC_PERC: '', 49 SECOND_DSC_PERC: '', 50 DISPLAY_PROP_DIV: '', 51 BASKET_PROP_DIV: '', 52 SUBSCRIBE_ID: '' 53 }; 54 this.product = { 55 checkQuantity: false, 56 maxQuantity: 0, 57 stepQuantity: 1, 58 isDblQuantity: false, 59 canBuy: true, 60 name: '', 61 pict: {}, 62 id: 0, 63 addUrl: '', 64 buyUrl: '' 65 }; 66 67 this.basketMode = ''; 68 this.basketData = { 69 useProps: false, 70 emptyProps: false, 71 quantity: 'quantity', 72 props: 'prop', 73 basketUrl: '', 74 sku_props: '', 75 sku_props_var: 'basket_props', 76 add_url: '', 77 buy_url: '' 78 }; 79 80 this.compareData = { 81 compareUrl: '', 82 compareDeleteUrl: '', 83 comparePath: '' 84 }; 85 86 this.defaultPict = { 87 pict: null, 88 secondPict: null 89 }; 90 this.touch = null; 91 92 this.quantityDelay = null; 93 this.quantityTimer = null; 94 95 this.checkQuantity = false; 96 this.maxQuantity = 0; 97 this.minQuantity = 0; 98 this.stepQuantity = 1; 99 this.isDblQuantity = false; 100 this.canBuy = true; 101 this.precision = 6; 102 this.precisionFactor = Math.pow(10, this.precision); 103 this.bigData = false; 104 this.fullDisplayMode = false; 105 this.viewMode = ''; 106 this.templateTheme = ''; 107 108 this.currentPriceMode = ''; 109 this.currentPrices = []; 110 this.currentPriceSelected = 0; 111 this.currentQuantityRanges = []; 112 this.currentQuantityRangeSelected = 0; 113 114 this.offers = []; 115 this.offerNum = 0; 116 this.treeProps = []; 117 this.selectedValues = {}; 118 119 this.obProduct = null; 120 this.blockNodes = {}; 121 this.obQuantity = null; 122 this.obQuantityUp = null; 123 this.obQuantityDown = null; 124 this.obQuantityLimit = {}; 125 this.obPict = null; 126 this.obSecondPict = null; 127 this.obPrice = null; 128 this.obTree = null; 129 this.obBuyBtn = null; 130 this.obBasketActions = null; 131 this.obNotAvail = null; 132 this.obSubscribe = null; 133 this.obDscPerc = null; 134 this.obSecondDscPerc = null; 135 this.obSkuProps = null; 136 this.obMeasure = null; 137 this.obCompare = null; 138 139 this.obPopupWin = null; 140 this.basketUrl = ''; 141 this.basketParams = {}; 142 this.isTouchDevice = BX.hasClass(document.documentElement, 'bx-touch'); 143 this.hoverTimer = null; 144 this.hoverStateChangeForbidden = false; 145 this.mouseX = null; 146 this.mouseY = null; 147 148 this.useEnhancedEcommerce = false;
149 this.dataLayerName = 'dataLayer'; 150 this.brandProperty = false; 151 152 this.errorCode = 0; 153 154 if (typeof arParams === 'object') 155 { 156 if (arParams.PRODUCT_TYPE) 157 { 158 this.productType = parseInt(arParams.PRODUCT_TYPE, 10); 159 } 160 161 this.showQuantity = arParams.SHOW_QUANTITY; 162 this.showAbsent = arParams.SHOW_ABSENT; 163 this.secondPict = arParams.SECOND_PICT; 164 this.showOldPrice = arParams.SHOW_OLD_PRICE; 165 this.showMaxQuantity = arParams.SHOW_MAX_QUANTITY; 166 this.relativeQuantityFactor = parseInt(arParams.RELATIVE_QUANTITY_FACTOR); 167 this.showPercent = arParams.SHOW_DISCOUNT_PERCENT; 168 this.showSkuProps = arParams.SHOW_SKU_PROPS; 169 this.showSubscription = arParams.USE_SUBSCRIBE; 170 171 if (arParams.ADD_TO_BASKET_ACTION) 172 { 173 this.basketAction = arParams.ADD_TO_BASKET_ACTION; 174 } 175 176 this.showClosePopup = arParams.SHOW_CLOSE_POPUP; 177 this.useCompare = arParams.DISPLAY_COMPARE; 178 this.fullDisplayMode = arParams.PRODUCT_DISPLAY_MODE === 'Y'; 179 this.bigData = arParams.BIG_DATA; 180 this.viewMode = arParams.VIEW_MODE || ''; 181 this.templateTheme = arParams.TEMPLATE_THEME || '';
182 this.useEnhancedEcommerce = arParams.USE_ENHANCED_ECOMMERCE === 'Y'; 183 this.dataLayerName = arParams.DATA_LAYER_NAME; 184 this.brandProperty = arParams.BRAND_PROPERTY; 185 186 this.visual = arParams.VISUAL; 187 188 switch (this.productType) 189 { 190 case 0: // no catalog 191 case 1: // product 192 case 2: // set 193 if (arParams.PRODUCT && typeof arParams.PRODUCT === 'object') 194 { 195 this.currentPriceMode = arParams.PRODUCT.ITEM_PRICE_MODE; 196 this.currentPrices = arParams.PRODUCT.ITEM_PRICES; 197 this.currentPriceSelected = arParams.PRODUCT.ITEM_PRICE_SELECTED; 198 this.currentQuantityRanges = arParams.PRODUCT.ITEM_QUANTITY_RANGES; 199 this.currentQuantityRangeSelected = arParams.PRODUCT.ITEM_QUANTITY_RANGE_SELECTED; 200 201 if (this.showQuantity) 202 { 203 this.product.checkQuantity = arParams.PRODUCT.CHECK_QUANTITY; 204 this.product.isDblQuantity = arParams.PRODUCT.QUANTITY_FLOAT; 205 206 if (this.product.checkQuantity) 207 { 208 this.product.maxQuantity = (this.product.isDblQuantity ? parseFloat(arParams.PRODUCT.MAX_QUANTITY) : parseInt(arParams.PRODUCT.MAX_QUANTITY, 10)); 209 } 210 211 this.product.stepQuantity = (this.product.isDblQuantity ? parseFloat(arParams.PRODUCT.STEP_QUANTITY) : parseInt(arParams.PRODUCT.STEP_QUANTITY, 10)); 212 213 this.checkQuantity = this.product.checkQuantity; 214 this.isDblQuantity = this.product.isDblQuantity; 215 this.stepQuantity = this.product.stepQuantity; 216 this.maxQuantity = this.product.maxQuantity; 217 this.minQuantity = this.currentPriceMode === 'Q' 218 ? parseFloat(this.currentPrices[this.currentPriceSelected].MIN_QUANTITY) 219 : this.stepQuantity; 220 221 if (this.isDblQuantity) 222 { 223 this.stepQuantity = Math.round(this.stepQuantity * this.precisionFactor) / this.precisionFactor; 224 } 225 } 226 227 this.product.canBuy = arParams.PRODUCT.CAN_BUY; 228 229 if (arParams.PRODUCT.MORE_PHOTO_COUNT) 230 { 231 this.product.morePhotoCount = arParams.PRODUCT.MORE_PHOTO_COUNT; 232 this.product.morePhoto = arParams.PRODUCT.MORE_PHOTO; 233 } 234 235 if (arParams.PRODUCT.RCM_ID) 236 { 237 this.product.rcmId = arParams.PRODUCT.RCM_ID; 238 } 239 240 this.canBuy = this.product.canBuy; 241 this.product.name = arParams.PRODUCT.NAME; 242 this.product.pict = arParams.PRODUCT.PICT; 243 this.product.id = arParams.PRODUCT.ID; 244 this.product.DETAIL_PAGE_URL = arParams.PRODUCT.DETAIL_PAGE_URL; 245 246 if (arParams.PRODUCT.ADD_URL) 247 { 248 this.product.addUrl = arParams.PRODUCT.ADD_URL; 249 } 250 251 if (arParams.PRODUCT.BUY_URL) 252 { 253 this.product.buyUrl = arParams.PRODUCT.BUY_URL; 254 } 255 256 if (arParams.BASKET && typeof arParams.BASKET === 'object') 257 { 258 this.basketData.useProps = arParams.BASKET.ADD_PROPS; 259 this.basketData.emptyProps = arParams.BASKET.EMPTY_PROPS; 260 } 261 } 262 else 263 { 264 this.errorCode = -1; 265 } 266 267 break; 268 case 3: // sku 269 if (arParams.PRODUCT && typeof arParams.PRODUCT === 'object') 270 { 271 this.product.name = arParams.PRODUCT.NAME; 272 this.product.id = arParams.PRODUCT.ID; 273 this.product.DETAIL_PAGE_URL = arParams.PRODUCT.DETAIL_PAGE_URL; 274 this.product.morePhotoCount = arParams.PRODUCT.MORE_PHOTO_COUNT; 275 this.product.morePhoto = arParams.PRODUCT.MORE_PHOTO; 276 277 if (arParams.PRODUCT.RCM_ID) 278 { 279 this.product.rcmId = arParams.PRODUCT.RCM_ID; 280 } 281 } 282 283 if (arParams.OFFERS && BX.type.isArray(arParams.OFFERS)) 284 { 285 this.offers = arParams.OFFERS; 286 this.offerNum = 0; 287 288 if (arParams.OFFER_SELECTED) 289 { 290 this.offerNum = parseInt(arParams.OFFER_SELECTED, 10); 291 } 292 293 if (isNaN(this.offerNum)) 294 { 295 this.offerNum = 0; 296 } 297 298 if (arParams.TREE_PROPS) 299 { 300 this.treeProps = arParams.TREE_PROPS; 301 } 302 303 if (arParams.DEFAULT_PICTURE) 304 { 305 this.defaultPict.pict = arParams.DEFAULT_PICTURE.PICTURE; 306 this.defaultPict.secondPict = arParams.DEFAULT_PICTURE.PICTURE_SECOND; 307 } 308 } 309 310 break; 311 default: 312 this.errorCode = -1; 313 }
314 if (arParams.BASKET && typeof arParams.BASKET === 'object') 315 { 316 if (arParams.BASKET.QUANTITY) 317 { 318 this.basketData.quantity = arParams.BASKET.QUANTITY; 319 } 320 321 if (arParams.BASKET.PROPS) 322 { 323 this.basketData.props = arParams.BASKET.PROPS; 324 } 325 326 if (arParams.BASKET.BASKET_URL) 327 { 328 this.basketData.basketUrl = arParams.BASKET.BASKET_URL; 329 } 330 331 if (3 === this.productType) 332 { 333 if (arParams.BASKET.SKU_PROPS) 334 { 335 this.basketData.sku_props = arParams.BASKET.SKU_PROPS; 336 } 337 } 338 339 if (arParams.BASKET.ADD_URL_TEMPLATE) 340 { 341 this.basketData.add_url = arParams.BASKET.ADD_URL_TEMPLATE; 342 } 343 344 if (arParams.BASKET.BUY_URL_TEMPLATE) 345 { 346 this.basketData.buy_url = arParams.BASKET.BUY_URL_TEMPLATE; 347 } 348 349 if (this.basketData.add_url === '' && this.basketData.buy_url === '') 350 { 351 this.errorCode = -1024; 352 } 353 } 354 355 if (this.useCompare) 356 { 357 if (arParams.COMPARE && typeof arParams.COMPARE === 'object') 358 { 359 if (arParams.COMPARE.COMPARE_PATH) 360 { 361 this.compareData.comparePath = arParams.COMPARE.COMPARE_PATH; 362 } 363 364 if (arParams.COMPARE.COMPARE_URL_TEMPLATE) 365 { 366 this.compareData.compareUrl = arParams.COMPARE.COMPARE_URL_TEMPLATE; 367 } 368 else 369 { 370 this.useCompare = false; 371 } 372 373 if (arParams.COMPARE.COMPARE_DELETE_URL_TEMPLATE) 374 { 375 this.compareData.compareDeleteUrl = arParams.COMPARE.COMPARE_DELETE_URL_TEMPLATE; 376 } 377 else 378 { 379 this.useCompare = false; 380 } 381 } 382 else 383 { 384 this.useCompare = false; 385 } 386 } 387 388 this.isFacebookConversionCustomizeProductEventEnabled 389 = arParams.IS_FACEBOOK_CONVERSION_CUSTOMIZE_PRODUCT_EVENT_ENABLED 390 ; 391 } 392 393 if (this.errorCode === 0) 394 { 395 BX.ready(BX.delegate(this.init,this)); 396 } 397 }; 398 399 BX.ready(function() 400 { 401 $(document).on('click.overlay-open', '.js-zoom-overlay', function clickHandler(e) 402 { 403 e.preventDefault(); 404 405 let $it = $(this); 406 let $productCard = $it.closest('.product'); 407 let $popup = $it.attr('href'); 408 let objVar = $it.data('obj-varname'); 409 if ('undefined' === typeof window[objVar]) 410 return; 411 412 let obj = window[objVar]; 413 414 let $productName = $('.js-zoom-product_name', $popup); 415 let $price = $('.product__price .new-price', $popup); 416 let $priceOld = $('.product__price .old-price', $popup); 417 let $buttons = $('.js-zoom-buttons', $popup); 418 let $advantages = $('.js-zoom-product_advantages', $popup); 419 let $pictureSlider = $('.js-zoom-slider', $popup); 420 let $pictureSliderControls = $('.js-zoom-slider-controls', $popup); 421 422 $productName.attr('href', '#'); 423 424 $.overlayLoader(true, { 425 node: $popup, 426 hideSelector: '.js-close-popup', 427 fixedElements: '.js-fixed-element', 428 onShow(node) 429 { 430 let $productNameSrc = $productCard.find('.product__name'); 431 if ($productNameSrc.length > 0) 432 { 433 $productName.text($productNameSrc.text()); 434 if (String($productNameSrc.attr('href')).length > 0) 435 $productName.attr('href', $productNameSrc.attr('href')); 436 } 437 438 $advantages.html($productCard.find('.product__advantages').html()); 439 $price.html($productCard.find('.product__price .new-price').html()); 440 $priceOld 441 .html($productCard.find('.product__price .old-price').html()) 442 .toggle($productCard.find('.product__price .old-price').is(':visible')) 443 ; 444 $pictureSliderControls.children().remove(); 445 $pictureSliderControls.html($productCard.find('.product__zoom-properties').html()); 446 447 if ($pictureSlider.hasClass('slick-initialized')) { 448 $pictureSlider = $pictureSlider.slick('unslick'); 449 } 450 $pictureSlider.children().remove(); 451 452 /* 453 * ÐиÑÑикÑовÑй ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñ Ð²Ñегда добавлÑÐµÑ product.pict в morePhoto 454 if (obj.product && obj.product.pict && obj.product.pict.SRC) 455 { 456 $pictureSlider.append('<img src="' + String(obj.product.pict.SRC) + '" class="zoom-popup__slider-item">'); 457 } 458 */ 459 460 if (obj.product && obj.product.morePhoto && obj.product.morePhoto.length > 0) 461 { 462 for (let pictureIndex = 0; pictureIndex < obj.product.morePhoto.length; pictureIndex++) 463 { 464 $pictureSlider.append('<img src="' + String(obj.product.morePhoto[pictureIndex].SRC) + '" class="zoom-popup__slider-item">'); 465 } 466 467 $pictureSlider.slick({ 468 slidesToShow: 1, 469 slidesToScroll: 1, 470 infinite: true, 471 arrows: true, 472 appendArrows: $pictureSliderControls, 473 dots: false, 474 fade: true, 475 touchThreshold: 100, 476 }); 477 } 478 else 479 { 480 // TODO: default ??? 481 } 482 483 let parentCompare = $('.vitrine__product-control.product__compare', $productCard); 484 if (parentCompare.length > 0) { 485 let buttonCompare = $('.zoom-popup__compare', $buttons); 486 buttonCompare.toggleClass('is-active', parentCompare.hasClass('is-active')); 487 buttonCompare 488 .off("click") 489 .on("click", function(e) { 490 e.preventDefault(); 491 clickCompareButton(parentCompare.get(0), function (element, mode, data) { 492 buttonCompare.toggleClass('is-active', mode === 'add'); 493 }); 494 495 return false;
496 }); 497 } 498 499 let parentFavorite = $('.vitrine__product-control.product__favorite', $productCard); 500 if (parentFavorite.length > 0) { 501 let buttonFavorite = $('.zoom-popup__favorite', $buttons); 502 buttonFavorite.toggleClass('is-active', parentFavorite.hasClass('is-active')); 503 buttonFavorite.addClass('vitrine__product-control product__favorite'); 504 buttonFavorite 505 .off("click") 506 .on("click", function(e) { 507 e.preventDefault(); 508 509 clickFavoriteButton(parentFavorite.get(0), function (element, mode, data) { 510 buttonFavorite.toggleClass('is-active', mode === 'add'); 511 }); 512 513 return false; 514 }); 515 } 516 517 $(document).trigger('popupShown', node); 518 }, 519 onHide(node) 520 { 521 $productName.text(''); 522 $price.text(''); 523 $priceOld.text(''); 524 $advantages.text(''); 525 526 if ($pictureSlider.hasClass('slick-initialized')) { 527 $pictureSlider = $pictureSlider.slick('unslick'); 528 } 529 $pictureSlider.children().remove(); 530 let buttonCompare = $('.zoom-popup__compare', $buttons); 531 buttonCompare.off("click").removeClass('is-active'); 532 533 let buttonFavorite = $('.zoom-popup__favorite', $buttons); 534 buttonFavorite.off("click").removeClass('is-active'); 535 536 $(document).trigger('popupHidden', node); 537 }, 538 }); 539 }); 540 }); 541 542 window.JCCatalogItem.prototype = { 543 init: function() 544 { 545 var i = 0, 546 treeItems = null; 547 548 this.obProduct = BX(this.visual.ID); 549 if (!this.obProduct) 550 { 551 this.errorCode = -1; 552 } 553 554 this.obPict = BX(this.visual.PICT_ID); 555 if (!this.obPict) 556 { 557 this.errorCode = -2; 558 } 559 560 if (this.secondPict && this.visual.SECOND_PICT_ID) 561 { 562 this.obSecondPict = BX(this.visual.SECOND_PICT_ID); 563 } 564 565 this.obPrice = BX(this.visual.PRICE_ID); 566 this.obPriceOld = BX(this.visual.PRICE_OLD_ID); 567 this.obPriceTotal = BX(this.visual.PRICE_TOTAL_ID); 568 if (!this.obPrice) 569 { 570 this.errorCode = -16; 571 } 572 573 if (this.showQuantity && this.visual.QUANTITY_ID) 574 { 575 this.obQuantity = BX(this.visual.QUANTITY_ID); 576 this.blockNodes.quantity = this.obProduct.querySelector('[data-entity="quantity-block"]'); 577 578 if (!this.isTouchDevice) 579 { 580 BX.bind(this.obQuantity, 'focus', BX.proxy(this.onFocus, this)); 581 BX.bind(this.obQuantity, 'blur', BX.proxy(this.onBlur, this)); 582 } 583 584 if (this.visual.QUANTITY_UP_ID) 585 { 586 this.obQuantityUp = BX(this.visual.QUANTITY_UP_ID); 587 } 588 589 if (this.visual.QUANTITY_DOWN_ID) 590 { 591 this.obQuantityDown = BX(this.visual.QUANTITY_DOWN_ID); 592 } 593 } 594 595 if (this.visual.QUANTITY_LIMIT && this.showMaxQuantity !== 'N') 596 { 597 this.obQuantityLimit.all = BX(this.visual.QUANTITY_LIMIT); 598 if (this.obQuantityLimit.all) 599 { 600 this.obQuantityLimit.value = this.obQuantityLimit.all.querySelector('[data-entity="quantity-limit-value"]'); 601 if (!this.obQuantityLimit.value) 602 { 603 this.obQuantityLimit.all = null; 604 } 605 } 606 } 607 608 if (this.productType === 3 && this.fullDisplayMode) 609 { 610 if (this.visual.TREE_ID) 611 { 612 this.obTree = BX(this.visual.TREE_ID); 613 if (!this.obTree) 614 { 615 this.errorCode = -256; 616 } 617 } 618 619 if (this.visual.QUANTITY_MEASURE) 620 { 621 this.obMeasure = BX(this.visual.QUANTITY_MEASURE); 622 } 623 } 624 625 this.obBasketActions = BX(this.visual.BASKET_ACTIONS_ID); 626 if (this.obBasketActions) 627 { 628 if (this.visual.BUY_ID) 629 { 630 this.obBuyBtn = BX(this.visual.BUY_ID); 631 } 632 } 633 634 this.obNotAvail = BX(this.visual.NOT_AVAILABLE_MESS); 635 636 if (this.showSubscription) 637 { 638 this.obSubscribe = BX(this.visual.SUBSCRIBE_ID); 639 } 640 641 if (this.showPercent) 642 { 643 if (this.visual.DSC_PERC) 644 { 645 this.obDscPerc = BX(this.visual.DSC_PERC); 646 } 647 if (this.secondPict && this.visual.SECOND_DSC_PERC) 648 { 649 this.obSecondDscPerc = BX(this.visual.SECOND_DSC_PERC); 650 } 651 } 652 653 if (this.showSkuProps) 654 { 655 if (this.visual.DISPLAY_PROP_DIV) 656 { 657 this.obSkuProps = BX(this.visual.DISPLAY_PROP_DIV); 658 } 659 } 660 661 if (this.errorCode === 0) 662 { 663 if (this.bigData) 664 { 665 var links = BX.findChildren(this.obProduct, {tag:'a'}, true); 666 if (links) 667 { 668 for (i in links) 669 { 670 if (links.hasOwnProperty(i)) 671 { 672 if (links[i].getAttribute('href') == this.product.DETAIL_PAGE_URL) 673 { 674 BX.bind(links[i], 'click', BX.proxy(this.rememberProductRecommendation, this)); 675 } 676 } 677 } 678 } 679 } 680 681 if (this.showQuantity) 682 { 683 var startEventName = this.isTouchDevice ? 'touchstart' : 'mousedown'; 684 var endEventName = this.isTouchDevice ? 'touchend' : 'mouseup'; 685 686 if (this.obQuantityUp) 687 { 688 BX.bind(this.obQuantityUp, startEventName, BX.proxy(this.startQuantityInterval, this)); 689 BX.bind(this.obQuantityUp, endEventName, BX.proxy(this.clearQuantityInterval, this)); 690 BX.bind(this.obQuantityUp, 'mouseout', BX.proxy(this.clearQuantityInterval, this)); 691 BX.bind(this.obQuantityUp, 'click', BX.delegate(this.quantityUp, this)); 692 } 693 694 if (this.obQuantityDown) 695 { 696 BX.bind(this.obQuantityDown, startEventName, BX.proxy(this.startQuantityInterval, this)); 697 BX.bind(this.obQuantityDown, endEventName, BX.proxy(this.clearQuantityInterval, this)); 698 BX.bind(this.obQuantityDown, 'mouseout', BX.proxy(this.clearQuantityInterval, this)); 699 BX.bind(this.obQuantityDown, 'click', BX.delegate(this.quantityDown, this)); 700 } 701 702 if (this.obQuantity) 703 { 704 BX.bind(this.obQuantity, 'change', BX.delegate(this.quantityChange, this)); 705 } 706 } 707 708 switch (this.productType) 709 { 710 case 0: // no catalog 711 case 1: // product 712 case 2: // set 713
714 this.checkQuantityControls(); 715 716 break; 717 case 3: // sku 718 if (this.offers.length > 0) 719 { 720 treeItems = BX.findChildren(this.obTree, {tagName: 'li'}, true); 721 722 if (treeItems && treeItems.length) 723 { 724 for (i = 0; i < treeItems.length; i++) 725 { 726 BX.bind(treeItems[i], 'click', BX.delegate(this.selectOfferProp, this)); 727 } 728 } 729 730 this.setCurrent(); 731 } 732 733 break; 734 } 735 736 if (this.obBuyBtn) 737 { 738 if (this.basketAction === 'ADD') 739 { 740 BX.bind(this.obBuyBtn, 'click', BX.proxy(this.add2Basket, this)); 741 } 742 else 743 { 744 BX.bind(this.obBuyBtn, 'click', BX.proxy(this.buyBasket, this)); 745 } 746 } 747 748 if (this.useCompare) 749 { 750 this.obCompare = BX(this.visual.COMPARE_LINK_ID); 751 if (this.obCompare) 752 { 753 BX.bind(this.obCompare, 'click', BX.proxy(this.compare, this)); 754 } 755 756 BX.addCustomEvent('onCatalogDeleteCompare', BX.proxy(this.checkDeletedCompare, this)); 757 } 758 } 759 }, 760 761 setAnalyticsDataLayer: function(action) 762 { 763 if (!this.useEnhancedEcommerce || !this.dataLayerName) 764 return; 765 766 var item = {}, 767 info = {}, 768 variants = [], 769 i, k, j, propId, skuId, propValues; 770 771 switch (this.productType) 772 { 773 case 0: //no catalog 774 case 1: //product 775 case 2: //set 776 item = { 777 'id': this.product.id, 778 'name': this.product.name, 779 'price': this.currentPrices[this.currentPriceSelected] && this.currentPrices[this.currentPriceSelected].PRICE, 780 'brand': BX.type.isArray(this.brandProperty) ? this.brandProperty.join('/') : this.brandProperty 781 }; 782 break; 783 case 3: //sku 784 for (i in this.offers[this.offerNum].TREE) 785 { 786 if (this.offers[this.offerNum].TREE.hasOwnProperty(i)) 787 { 788 propId = i.substring(5); 789 skuId = this.offers[this.offerNum].TREE[i]; 790 791 for (k in this.treeProps) 792 { 793 if (this.treeProps.hasOwnProperty(k) && this.treeProps[k].ID == propId) 794 { 795 for (j in this.treeProps[k].VALUES) 796 { 797 propValues = this.treeProps[k].VALUES[j]; 798 if (propValues.ID == skuId) 799 { 800 variants.push(propValues.NAME); 801 break; 802 } 803 } 804 805 } 806 } 807 } 808 } 809 810 item = { 811 'id': this.offers[this.offerNum].ID, 812 'name': this.offers[this.offerNum].NAME, 813 'price': this.currentPrices[this.currentPriceSelected] && this.currentPrices[this.currentPriceSelected].PRICE, 814 'brand': BX.type.isArray(this.brandProperty) ? this.brandProperty.join('/') : this.brandProperty, 815 'variant': variants.join('/') 816 }; 817 break; 818 } 819 820 switch (action) 821 { 822 case 'addToCart': 823 info = { 824 'ecommerce': { 825 'currencyCode': this.currentPrices[this.currentPriceSelected] && this.currentPrices[this.currentPriceSelected].CURRENCY || '', 826 'add': { 827 'products': [{ 828 'name': item.name || '', 829 'id': item.id || '', 830 'price': item.price || 0, 831 'brand': item.brand || '', 832 'category': item.category || '', 833 'variant': item.variant || '', 834 'quantity': this.showQuantity && this.obQuantity ? this.obQuantity.value : 1 835 }] 836 } 837 } 838 }; 839 break; 840 } 841 842 window[this.dataLayerName] = window[this.dataLayerName] || []; 843 window[this.dataLayerName].push(info); 844 }, 845 846 hoverOn: function(event) 847 { 848 clearTimeout(this.hoverTimer); 849 this.obProduct.style.height = getComputedStyle(this.obProduct).height; 850 BX.addClass(this.obProduct, 'hover'); 851 852 BX.PreventDefault(event); 853 }, 854 855 hoverOff: function(event) 856 { 857 if (this.hoverStateChangeForbidden) 858 return; 859 860 BX.removeClass(this.obProduct, 'hover'); 861 this.hoverTimer = setTimeout( 862 BX.delegate(function(){ 863 this.obProduct.style.height = 'auto'; 864 }, this), 865 300 866 ); 867 868 BX.PreventDefault(event); 869 }, 870 871 onFocus: function() 872 { 873 this.hoverStateChangeForbidden = true; 874 BX.bind(document, 'mousemove', BX.proxy(this.captureMousePosition, this)); 875 }, 876 877 onBlur: function() 878 { 879 this.hoverStateChangeForbidden = false;
880 BX.unbind(document, 'mousemove', BX.proxy(this.captureMousePosition, this)); 881 882 var cursorElement = document.elementFromPoint(this.mouseX, this.mouseY); 883 if (!cursorElement || !this.obProduct.contains(cursorElement)) 884 { 885 this.hoverOff(); 886 } 887 }, 888 889 captureMousePosition: function(event) 890 { 891 this.mouseX = event.clientX; 892 this.mouseY = event.clientY; 893 }, 894 895 getCookie: function(name) 896 { 897 var matches = document.cookie.match(new RegExp( 898 "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)" 899 )); 900 901 return matches ? decodeURIComponent(matches[1]) : null; 902 }, 903 904 rememberProductRecommendation: function() 905 { 906 // save to RCM_PRODUCT_LOG 907 var cookieName = BX.cookie_prefix + '_RCM_PRODUCT_LOG', 908 cookie = this.getCookie(cookieName), 909 itemFound = false; 910 911 var cItems = [], 912 cItem; 913 914 if (cookie) 915 { 916 cItems = cookie.split('.'); 917 } 918 919 var i = cItems.length; 920 921 while (i--) 922 { 923 cItem = cItems[i].split('-'); 924 925 if (cItem[0] == this.product.id) 926 { 927 // it's already in recommendations, update the date 928 cItem = cItems[i].split('-'); 929 930 // update rcmId and date 931 cItem[1] = this.product.rcmId; 932 cItem[2] = BX.current_server_time; 933 934 cItems[i] = cItem.join('-'); 935 itemFound = true; 936 } 937 else 938 { 939 if ((BX.current_server_time - cItem[2]) > 3600 * 24 * 30) 940 { 941 cItems.splice(i, 1); 942 } 943 } 944 } 945 946 if (!itemFound) 947 { 948 // add recommendation 949 cItems.push([this.product.id, this.product.rcmId, BX.current_server_time].join('-')); 950 } 951 952 // serialize 953 var plNewCookie = cItems.join('.'), 954 cookieDate = new Date(new Date().getTime() + 1000 * 3600 * 24 * 365 * 10).toUTCString(); 955 956 document.cookie = cookieName + "=" + plNewCookie + "; path=/; expires=" + cookieDate + "; domain=" + BX.cookie_domain; 957 }, 958 959 startQuantityInterval: function() 960 { 961 var target = BX.proxy_context; 962 var func = target.id === this.visual.QUANTITY_DOWN_ID 963 ? BX.proxy(this.quantityDown, this) 964 : BX.proxy(this.quantityUp, this); 965 966 this.quantityDelay = setTimeout( 967 BX.delegate(function() { 968 this.quantityTimer = setInterval(func, 150); 969 }, this), 970 300 971 ); 972 }, 973 974 clearQuantityInterval: function() 975 { 976 clearTimeout(this.quantityDelay); 977 clearInterval(this.quantityTimer); 978 }, 979 980 quantityUp: function() 981 { 982 var curValue = 0, 983 boolSet = true; 984 985 if (this.errorCode === 0 && this.showQuantity && this.canBuy) 986 { 987 curValue = (this.isDblQuantity ? parseFloat(this.obQuantity.value) : parseInt(this.obQuantity.value, 10)); 988 if (!isNaN(curValue)) 989 { 990 curValue += this.stepQuantity; 991 if (this.checkQuantity) 992 { 993 if (curValue > this.maxQuantity) 994 { 995 boolSet = false; 996 } 997 } 998 999 if (boolSet) 1000 { 1001 if (this.isDblQuantity) 1002 { 1003 curValue = Math.round(curValue * this.precisionFactor) / this.precisionFactor; 1004 } 1005 1006 this.obQuantity.value = curValue; 1007 1008 this.setPrice(); 1009 } 1010 } 1011 } 1012 }, 1013 1014 quantityDown: function() 1015 { 1016 var curValue = 0, 1017 boolSet = true; 1018 1019 if (this.errorCode === 0 && this.showQuantity && this.canBuy) 1020 { 1021 curValue = (this.isDblQuantity ? parseFloat(this.obQuantity.value) : parseInt(this.obQuantity.value, 10)); 1022 if (!isNaN(curValue)) 1023 { 1024 curValue -= this.stepQuantity; 1025 1026 this.checkPriceRange(curValue); 1027 1028 if (curValue < this.minQuantity) 1029 { 1030 boolSet = false; 1031 } 1032 1033 if (boolSet) 1034 { 1035 if (this.isDblQuantity) 1036 { 1037 curValue = Math.round(curValue * this.precisionFactor) / this.precisionFactor; 1038 } 1039 1040 this.obQuantity.value = curValue; 1041 1042 this.setPrice(); 1043 } 1044 } 1045 } 1046 }, 1047 1048 quantityChange: function() 1049 { 1050 var curValue = 0, 1051 intCount; 1052 1053 if (this.errorCode === 0 && this.showQuantity) 1054 { 1055 if (this.canBuy) 1056 { 1057 curValue = this.isDblQuantity ? parseFloat(this.obQuantity.value) : Math.round(this.obQuantity.value); 1058 if (!isNaN(curValue)) 1059 { 1060 if (this.checkQuantity) 1061 { 1062 if (curValue > this.maxQuantity) 1063 { 1064 curValue = this.maxQuantity; 1065 } 1066 } 1067 1068 this.checkPriceRange(curValue); 1069 1070 intCount = Math.floor( 1071 Math.round(curValue * this.precisionFactor / this.stepQuantity) / this.precisionFactor 1072 ) || 1; 1073 curValue = (intCount <= 1 ? this.stepQuantity : intCount * this.stepQuantity); 1074 curValue = Math.round(curValue * this.precisionFactor) / this.precisionFactor; 1075 1076 if (curValue < this.minQuantity) 1077 { 1078 curValue = this.minQuantity; 1079 } 1080 1081 this.obQuantity.value = curValue; 1082 } 1083 else 1084 { 1085 this.obQuantity.value = this.minQuantity; 1086 } 1087 } 1088 else 1089 { 1090 this.obQuantity.value = this.minQuantity; 1091 } 1092 1093 this.setPrice(); 1094 } 1095 }, 1096 1097 quantitySet: function(index) 1098 { 1099 var resetQuantity, strLimit; 1100 1101 var newOffer = this.offers[index], 1102 oldOffer = this.offers[this.offerNum]; 1103 1104 if (this.errorCode === 0) 1105 { 1106 this.canBuy = newOffer.CAN_BUY; 1107 1108 this.currentPriceMode = newOffer.ITEM_PRICE_MODE; 1109 this.currentPrices = newOffer.ITEM_PRICES; 1110 this.currentPriceSelected = newOffer.ITEM_PRICE_SELECTED; 1111 this.currentQuantityRanges = newOffer.ITEM_QUANTITY_RANGES; 1112 this.currentQuantityRangeSelected = newOffer.ITEM_QUANTITY_RANGE_SELECTED; 1113 1114 if (this.canBuy) 1115 { 1116 if (this.blockNodes.quantity) 1117 { 1118 BX.style(this.blockNodes.quantity, 'display', ''); 1119 } 1120 1121 if (this.obBasketActions) 1122 { 1123 BX.style(this.obBasketActions, 'display', ''); 1124 } 1125 1126 if (this.obNotAvail) 1127 { 1128 BX.style(this.obNotAvail, 'display', 'none'); 1129 } 1130 1131 if (this.obSubscribe) 1132 { 1133 BX.style(this.obSubscribe, 'display', 'none'); 1134 } 1135 } 1136 else 1137 { 1138 if (this.blockNodes.quantity) 1139 { 1140 BX.style(this.blockNodes.quantity, 'display', 'none'); 1141 } 1142 1143 if (this.obBasketActions) 1144 { 1145 BX.style(this.obBasketActions, 'display', 'none'); 1146 } 1147 1148 if (this.obNotAvail) 1149 { 1150 BX.style(this.obNotAvail, 'display', ''); 1151 } 1152 1153 if (this.obSubscribe) 1154 { 1155 if (newOffer.CATALOG_SUBSCRIBE === 'Y') 1156 { 1157 BX.style(this.obSubscribe, 'display', ''); 1158 this.obSubscribe.setAttribute('data-item', newOffer.ID); 1159 BX(this.visual.SUBSCRIBE_ID + '_hidden').click(); 1160 } 1161 else 1162 { 1163 BX.style(this.obSubscribe, 'display', 'none'); 1164 } 1165 } 1166 } 1167 1168 this.isDblQuantity = newOffer.QUANTITY_FLOAT; 1169 this.checkQuantity = newOffer.CHECK_QUANTITY; 1170 1171 if (this.isDblQuantity) 1172 { 1173 this.stepQuantity = Math.round(parseFloat(newOffer.STEP_QUANTITY) * this.precisionFactor) / this.precisionFactor; 1174 this.maxQuantity = parseFloat(newOffer.MAX_QUANTITY); 1175 this.minQuantity = this.currentPriceMode === 'Q' ? parseFloat(this.currentPrices[this.currentPriceSelected].MIN_QUANTITY) : this.stepQuantity; 1176 } 1177 else 1178 { 1179 this.stepQuantity = parseInt(newOffer.STEP_QUANTITY, 10); 1180 this.maxQuantity = parseInt(newOffer.MAX_QUANTITY, 10); 1181 this.minQuantity = this.currentPriceMode === 'Q' ? parseInt(this.currentPrices[this.currentPriceSelected].MIN_QUANTITY) : this.stepQuantity; 1182 } 1183 1184 if (this.showQuantity) 1185 { 1186 var isDifferentMinQuantity = oldOffer.ITEM_PRICES.length 1187 && oldOffer.ITEM_PRICES[oldOffer.ITEM_PRICE_SELECTED] 1188 && oldOffer.ITEM_PRICES[oldOffer.ITEM_PRICE_SELECTED].MIN_QUANTITY != this.minQuantity; 1189 1190 if (this.isDblQuantity) 1191 { 1192 resetQuantity = Math.round(parseFloat(oldOffer.STEP_QUANTITY) * this.precisionFactor) / this.precisionFactor !== this.stepQuantity 1193 || isDifferentMinQuantity 1194 || oldOffer.MEASURE !== newOffer.MEASURE 1195 || ( 1196 this.checkQuantity 1197 && parseFloat(oldOffer.MAX_QUANTITY) > this.maxQuantity 1198 && parseFloat(this.obQuantity.value) > this.maxQuantity 1199 ); 1200 } 1201 else 1202 { 1203 resetQuantity = parseInt(oldOffer.STEP_QUANTITY, 10) !== this.stepQuantity 1204 || isDifferentMinQuantity 1205 || oldOffer.MEASURE !== newOffer.MEASURE 1206 || ( 1207 this.checkQuantity 1208 && parseInt(oldOffer.MAX_QUANTITY, 10) > this.maxQuantity 1209 && parseInt(this.obQuantity.value, 10) > this.maxQuantity 1210 ); 1211 } 1212 1213 this.obQuantity.disabled = !this.canBuy; 1214 1215 if (resetQuantity) 1216 { 1217 this.obQuantity.value = this.minQuantity; 1218 } 1219 1220 if (this.obMeasure) 1221 { 1222 if (newOffer.MEASURE) 1223 { 1224 BX.adjust(this.obMeasure, {html: newOffer.MEASURE}); 1225 } 1226 else 1227 { 1228 BX.adjust(this.obMeasure, {html: ''}); 1229 } 1230 } 1231 } 1232 1233 if (this.obQuantityLimit.all) 1234 { 1235 if (!this.checkQuantity || this.maxQuantity == 0) 1236 { 1237 BX.adjust(this.obQuantityLimit.value, {html: ''}); 1238 BX.adjust(this.obQuantityLimit.all, {style: {display: 'none'}}); 1239 } 1240 else 1241 { 1242 if (this.showMaxQuantity === 'M') 1243 { 1244 strLimit = (this.maxQuantity / this.stepQuantity >= this.relativeQuantityFactor) 1245 ? BX.message('RELATIVE_QUANTITY_MANY') 1246 : BX.message('RELATIVE_QUANTITY_FEW'); 1247 } 1248 else 1249 { 1250 strLimit = this.maxQuantity; 1251 1252 if (newOffer.MEASURE) 1253 { 1254 strLimit += (' ' + newOffer.MEASURE); 1255 } 1256 } 1257 1258 BX.adjust(this.obQuantityLimit.value, {html: strLimit}); 1259 BX.adjust(this.obQuantityLimit.all, {style: {display: ''}}); 1260 } 1261 } 1262 } 1263 }, 1264 1265 eq: function(obj, i) 1266 { 1267 var len = obj.length, 1268 j = +i + (i < 0 ? len : 0); 1269 1270 return j >= 0 && j < len ? obj[j] : {}; 1271 }, 1272 1273 selectOfferProp: function() 1274 { 1275 var i = 0, 1276 value = '', 1277 strTreeValue = '', 1278 arTreeItem = [], 1279 rowItems = null, 1280 target = BX.proxy_context; 1281 1282 if (target && target.hasAttribute('data-treevalue')) 1283 { 1284 if (BX.hasClass(target, 'selected')) 1285 return; 1286 1287 strTreeValue = target.getAttribute('data-treevalue'); 1288 arTreeItem = strTreeValue.split('_'); 1289 if (this.searchOfferPropIndex(arTreeItem[0], arTreeItem[1])) 1290 { 1291 rowItems = BX.findChildren(target.parentNode, {tagName: 'li'}, false); 1292 if (rowItems && 0 < rowItems.length) 1293 { 1294 for (i = 0; i < rowItems.length; i++) 1295 { 1296 value = rowItems[i].getAttribute('data-onevalue'); 1297 if (value === arTreeItem[1]) 1298 { 1299 BX.addClass(rowItems[i], 'selected'); 1300 } 1301 else 1302 { 1303 BX.removeClass(rowItems[i], 'selected'); 1304 } 1305 } 1306 } 1307 1308 if ( 1309 this.isFacebookConversionCustomizeProductEventEnabled 1310 && BX.Type.isArrayFilled(this.offers) 1311 && BX.Type.isObject(this.offers[this.offerNum]) 1312 ) 1313 { 1314 BX.ajax.runAction( 1315 'sale.facebookconversion.customizeProduct', 1316 { 1317 data: { 1318 offerId: this.offers[this.offerNum]['ID'] 1319 } 1320 } 1321 ); 1322 } 1323 } 1324 } 1325 }, 1326 1327 searchOfferPropIndex: function(strPropID, strPropValue) 1328 { 1329 var strName = '', 1330 arShowValues = false, 1331 i, j, 1332 arCanBuyValues = [], 1333 allValues = [], 1334 index = -1, 1335 arFilter = {}, 1336 tmpFilter = []; 1337 1338 for (i = 0; i < this.treeProps.length; i++) 1339 { 1340 if (this.treeProps[i].ID === strPropID) 1341 { 1342 index = i; 1343 break; 1344 } 1345 } 1346 1347 if (-1 < index) 1348 { 1349 for (i = 0; i < index; i++) 1350 { 1351 strName = 'PROP_'+this.treeProps[i].ID; 1352 arFilter[strName] = this.selectedValues[strName]; 1353 } 1354 strName = 'PROP_'+this.treeProps[index].ID; 1355 arShowValues = this.getRowValues(arFilter, strName); 1356 if (!arShowValues) 1357 { 1358 return false;
1359 } 1360 if (!BX.util.in_array(strPropValue, arShowValues)) 1361 { 1362 return false; 1363 } 1364 arFilter[strName] = strPropValue; 1365 for (i = index+1; i < this.treeProps.length; i++) 1366 { 1367 strName = 'PROP_'+this.treeProps[i].ID; 1368 arShowValues = this.getRowValues(arFilter, strName); 1369 if (!arShowValues) 1370 { 1371 return false; 1372 } 1373 allValues = []; 1374 if (this.showAbsent) 1375 { 1376 arCanBuyValues = []; 1377 tmpFilter = []; 1378 tmpFilter = BX.clone(arFilter, true); 1379 for (j = 0; j < arShowValues.length; j++) 1380 { 1381 tmpFilter[strName] = arShowValues[j]; 1382 allValues[allValues.length] = arShowValues[j]; 1383 if (this.getCanBuy(tmpFilter)) 1384 arCanBuyValues[arCanBuyValues.length] = arShowValues[j]; 1385 } 1386 } 1387 else 1388 { 1389 arCanBuyValues = arShowValues; 1390 } 1391 if (this.selectedValues[strName] && BX.util.in_array(this.selectedValues[strName], arCanBuyValues)) 1392 { 1393 arFilter[strName] = this.selectedValues[strName]; 1394 } 1395 else 1396 { 1397 if (this.showAbsent) 1398 arFilter[strName] = (arCanBuyValues.length > 0 ? arCanBuyValues[0] : allValues[0]); 1399 else 1400 arFilter[strName] = arCanBuyValues[0]; 1401 } 1402 this.updateRow(i, arFilter[strName], arShowValues, arCanBuyValues); 1403 } 1404 this.selectedValues = arFilter; 1405 this.changeInfo(); 1406 } 1407 return true; 1408 }, 1409 1410 updateRow: function(intNumber, activeID, showID, canBuyID) 1411 { 1412 var i = 0, 1413 value = '', 1414 isCurrent = false, 1415 rowItems = null; 1416 1417 var lineContainer = this.obTree.querySelectorAll('[data-entity="sku-line-block"]'), 1418 listContainer; 1419 1420 if (intNumber > -1 && intNumber < lineContainer.length) 1421 { 1422 listContainer = lineContainer[intNumber].querySelector('ul'); 1423 rowItems = BX.findChildren(listContainer, {tagName: 'li'}, false); 1424 if (rowItems && 0 < rowItems.length) 1425 { 1426 for (i = 0; i < rowItems.length; i++) 1427 { 1428 value = rowItems[i].getAttribute('data-onevalue'); 1429 isCurrent = value === activeID; 1430 1431 if (isCurrent) 1432 { 1433 BX.addClass(rowItems[i], 'selected'); 1434 } 1435 else 1436 { 1437 BX.removeClass(rowItems[i], 'selected'); 1438 } 1439 1440 if (BX.util.in_array(value, canBuyID)) 1441 { 1442 BX.removeClass(rowItems[i], 'notallowed'); 1443 } 1444 else 1445 { 1446 BX.addClass(rowItems[i], 'notallowed'); 1447 } 1448 1449 rowItems[i].style.display = BX.util.in_array(value, showID) ? '' : 'none'; 1450 1451 if (isCurrent) 1452 { 1453 lineContainer[intNumber].style.display = (value == 0 && canBuyID.length == 1) ? 'none' : ''; 1454 } 1455 } 1456 } 1457 } 1458 }, 1459 1460 getRowValues: function(arFilter, index) 1461 { 1462 var i = 0, 1463 j, 1464 arValues = [], 1465 boolSearch = false, 1466 boolOneSearch = true; 1467 1468 if (0 === arFilter.length) 1469 { 1470 for (i = 0; i < this.offers.length; i++) 1471 { 1472 if (!BX.util.in_array(this.offers[i].TREE[index], arValues)) 1473 { 1474 arValues[arValues.length] = this.offers[i].TREE[index]; 1475 } 1476 } 1477 boolSearch = true; 1478 } 1479 else 1480 { 1481 for (i = 0; i < this.offers.length; i++) 1482 { 1483 boolOneSearch = true; 1484 for (j in arFilter) 1485 { 1486 if (arFilter[j] !== this.offers[i].TREE[j]) 1487 { 1488 boolOneSearch = false; 1489 break; 1490 } 1491 } 1492 if (boolOneSearch) 1493 { 1494 if (!BX.util.in_array(this.offers[i].TREE[index], arValues)) 1495 { 1496 arValues[arValues.length] = this.offers[i].TREE[index]; 1497 } 1498 boolSearch = true; 1499 } 1500 } 1501 } 1502 return (boolSearch ? arValues : false); 1503 }, 1504 1505 getCanBuy: function(arFilter) 1506 { 1507 var i, j, 1508 boolSearch = false, 1509 boolOneSearch = true; 1510 1511 for (i = 0; i < this.offers.length; i++) 1512 { 1513 boolOneSearch = true; 1514 for (j in arFilter) 1515 { 1516 if (arFilter[j] !== this.offers[i].TREE[j]) 1517 { 1518 boolOneSearch = false; 1519 break; 1520 } 1521 } 1522 if (boolOneSearch) 1523 { 1524 if (this.offers[i].CAN_BUY) 1525 { 1526 boolSearch = true; 1527 break; 1528 } 1529 } 1530 } 1531 1532 return boolSearch; 1533 }, 1534 1535 setCurrent: function() 1536 { 1537 var i, 1538 j = 0, 1539 arCanBuyValues = [], 1540 strName = '', 1541 arShowValues = false, 1542 arFilter = {}, 1543 tmpFilter = [], 1544 current = this.offers[this.offerNum].TREE; 1545 1546 for (i = 0; i < this.treeProps.length; i++) 1547 { 1548 strName = 'PROP_'+this.treeProps[i].ID; 1549 arShowValues = this.getRowValues(arFilter, strName); 1550 if (!arShowValues) 1551 { 1552 break; 1553 } 1554 if (BX.util.in_array(current[strName], arShowValues)) 1555 { 1556 arFilter[strName] = current[strName]; 1557 } 1558 else 1559 { 1560 arFilter[strName] = arShowValues[0]; 1561 this.offerNum = 0; 1562 }
1563 if (this.showAbsent) 1564 { 1565 arCanBuyValues = []; 1566 tmpFilter = []; 1567 tmpFilter = BX.clone(arFilter, true); 1568 for (j = 0; j < arShowValues.length; j++) 1569 { 1570 tmpFilter[strName] = arShowValues[j]; 1571 if (this.getCanBuy(tmpFilter)) 1572 { 1573 arCanBuyValues[arCanBuyValues.length] = arShowValues[j]; 1574 } 1575 } 1576 } 1577 else 1578 { 1579 arCanBuyValues = arShowValues; 1580 } 1581 this.updateRow(i, arFilter[strName], arShowValues, arCanBuyValues); 1582 } 1583 this.selectedValues = arFilter; 1584 this.changeInfo(); 1585 }, 1586 1587 changeInfo: function() 1588 { 1589 var i, j, 1590 index = -1, 1591 boolOneSearch = true, 1592 quantityChanged; 1593 1594 for (i = 0; i < this.offers.length; i++) 1595 { 1596 boolOneSearch = true; 1597 for (j in this.selectedValues) 1598 { 1599 if (this.selectedValues[j] !== this.offers[i].TREE[j]) 1600 { 1601 boolOneSearch = false; 1602 break; 1603 } 1604 } 1605 if (boolOneSearch) 1606 { 1607 index = i; 1608 break; 1609 } 1610 } 1611 if (index > -1) 1612 { 1613 if (this.showSkuProps && this.obSkuProps) 1614 { 1615 if (this.offers[index].DISPLAY_PROPERTIES.length) 1616 { 1617 BX.adjust(this.obSkuProps, {style: {display: ''}, html: this.offers[index].DISPLAY_PROPERTIES}); 1618 } 1619 else 1620 { 1621 BX.adjust(this.obSkuProps, {style: {display: 'none'}, html: ''}); 1622 } 1623 } 1624 1625 this.quantitySet(index); 1626 this.setPrice(); 1627 this.setCompared(this.offers[index].COMPARED); 1628 1629 this.offerNum = index; 1630 } 1631 }, 1632 1633 checkPriceRange: function(quantity) 1634 { 1635 if (typeof quantity === 'undefined'|| this.currentPriceMode != 'Q') 1636 return; 1637 1638 var range, found = false; 1639 1640 for (var i in this.currentQuantityRanges) 1641 { 1642 if (this.currentQuantityRanges.hasOwnProperty(i)) 1643 { 1644 range = this.currentQuantityRanges[i]; 1645 1646 if ( 1647 parseInt(quantity) >= parseInt(range.SORT_FROM) 1648 && ( 1649 range.SORT_TO == 'INF' 1650 || parseInt(quantity) <= parseInt(range.SORT_TO) 1651 ) 1652 ) 1653 { 1654 found = true; 1655 this.currentQuantityRangeSelected = range.HASH; 1656 break; 1657 } 1658 } 1659 } 1660 1661 if (!found && (range = this.getMinPriceRange())) 1662 { 1663 this.currentQuantityRangeSelected = range.HASH; 1664 } 1665 1666 for (var k in this.currentPrices) 1667 { 1668 if (this.currentPrices.hasOwnProperty(k)) 1669 { 1670 if (this.currentPrices[k].QUANTITY_HASH == this.currentQuantityRangeSelected) 1671 { 1672 this.currentPriceSelected = k; 1673 break; 1674 } 1675 } 1676 } 1677 }, 1678 1679 getMinPriceRange: function() 1680 { 1681 var range; 1682 1683 for (var i in this.currentQuantityRanges) 1684 { 1685 if (this.currentQuantityRanges.hasOwnProperty(i)) 1686 { 1687 if ( 1688 !range 1689 || parseInt(this.currentQuantityRanges[i].SORT_FROM) < parseInt(range.SORT_FROM) 1690 ) 1691 { 1692 range = this.currentQuantityRanges[i]; 1693 } 1694 } 1695 } 1696 1697 return range; 1698 }, 1699 1700 checkQuantityControls: function() 1701 { 1702 if (!this.obQuantity) 1703 return; 1704 1705 var reachedTopLimit = this.checkQuantity && parseFloat(this.obQuantity.value) + this.stepQuantity > this.maxQuantity, 1706 reachedBottomLimit = parseFloat(this.obQuantity.value) - this.stepQuantity < this.minQuantity; 1707 1708 if (reachedTopLimit) 1709 { 1710 BX.addClass(this.obQuantityUp, 'product-item-amount-field-btn-disabled'); 1711 } 1712 else if (BX.hasClass(this.obQuantityUp, 'product-item-amount-field-btn-disabled')) 1713 { 1714 BX.removeClass(this.obQuantityUp, 'product-item-amount-field-btn-disabled'); 1715 } 1716 1717 if (reachedBottomLimit) 1718 { 1719 BX.addClass(this.obQuantityDown, 'product-item-amount-field-btn-disabled'); 1720 } 1721 else if (BX.hasClass(this.obQuantityDown, 'product-item-amount-field-btn-disabled')) 1722 { 1723 BX.removeClass(this.obQuantityDown, 'product-item-amount-field-btn-disabled'); 1724 } 1725 1726 if (reachedTopLimit && reachedBottomLimit) 1727 { 1728 this.obQuantity.setAttribute('disabled', 'disabled'); 1729 } 1730 else 1731 { 1732 this.obQuantity.removeAttribute('disabled'); 1733 } 1734 }, 1735 1736 setPrice: function() 1737 { 1738 var obData, price; 1739 1740 if (this.obQuantity) 1741 { 1742 this.checkPriceRange(this.obQuantity.value); 1743 } 1744 1745 this.checkQuantityControls(); 1746 1747 price = this.currentPrices[this.currentPriceSelected]; 1748 1749 if (this.obPrice) 1750 { 1751 if (price) 1752 { 1753 BX.adjust(this.obPrice, {html: BX.Currency.currencyFormat(price.RATIO_PRICE, price.CURRENCY, true)}); 1754 } 1755 else 1756 { 1757 BX.adjust(this.obPrice, {html: ''}); 1758 } 1759 1760 if (this.showOldPrice && this.obPriceOld) 1761 { 1762 if (price && price.RATIO_PRICE !== price.RATIO_BASE_PRICE) 1763 { 1764 BX.adjust(this.obPriceOld, { 1765 style: {display: ''}, 1766 html: BX.Currency.currencyFormat(price.RATIO_BASE_PRICE, price.CURRENCY, true) 1767 }); 1768 } 1769 else 1770 { 1771 BX.adjust(this.obPriceOld, { 1772 style: {display: 'none'}, 1773 html: '' 1774 }); 1775 } 1776 } 1777 1778 if (this.obPriceTotal) 1779 { 1780 if (price && this.obQuantity && this.obQuantity.value != this.stepQuantity) 1781 { 1782 BX.adjust(this.obPriceTotal, { 1783 html: BX.message('PRICE_TOTAL_PREFIX') + ' <strong>' 1784 + BX.Currency.currencyFormat(price.PRICE * this.obQuantity.value, price.CURRENCY, true) 1785 + '</strong>', 1786 style: {display: ''} 1787 }); 1788 } 1789 else 1790 { 1791 BX.adjust(this.obPriceTotal, { 1792 html: '', 1793 style: {display: 'none'} 1794 }); 1795 } 1796 } 1797 1798 if (this.showPercent) 1799 {
1800 if (price && parseInt(price.PERCENT) > 0) 1801 { 1802 obData = {style: {display: ''}, html: -price.PERCENT + '%'}; 1803 } 1804 else 1805 { 1806 obData = {style: {display: 'none'}, html: ''}; 1807 } 1808 1809 if (this.obDscPerc) 1810 { 1811 BX.adjust(this.obDscPerc, obData); 1812 } 1813 1814 if (this.obSecondDscPerc) 1815 { 1816 BX.adjust(this.obSecondDscPerc, obData); 1817 } 1818 } 1819 } 1820 }, 1821 1822 compare: function(event) 1823 { 1824 var checkbox = this.obCompare.querySelector('[data-entity="compare-checkbox"]'), 1825 target = BX.getEventTarget(event), 1826 checked = true; 1827 1828 if (checkbox) 1829 { 1830 checked = target === checkbox ? checkbox.checked : !checkbox.checked; 1831 } 1832 1833 var url = checked ? this.compareData.compareUrl : this.compareData.compareDeleteUrl, 1834 compareLink; 1835 1836 if (url) 1837 { 1838 if (target !== checkbox) 1839 { 1840 BX.PreventDefault(event); 1841 this.setCompared(checked); 1842 } 1843 1844 switch (this.productType) 1845 { 1846 case 0: // no catalog 1847 case 1: // product 1848 case 2: // set 1849 compareLink = url.replace('#ID#', this.product.id.toString()); 1850 break; 1851 case 3: // sku 1852 compareLink = url.replace('#ID#', this.offers[this.offerNum].ID); 1853 break; 1854 } 1855 1856 BX.ajax({ 1857 method: 'POST', 1858 dataType: checked ? 'json' : 'html', 1859 url: compareLink + (compareLink.indexOf('?') !== -1 ? '&' : '?') + 'ajax_action=Y', 1860 onsuccess: checked 1861 ? BX.proxy(this.compareResult, this) 1862 : BX.proxy(this.compareDeleteResult, this) 1863 }); 1864 } 1865 }, 1866 1867 compareResult: function(result) 1868 { 1869 var popupContent, popupButtons; 1870 1871 if (this.obPopupWin) 1872 { 1873 this.obPopupWin.close(); 1874 } 1875 1876 if (!BX.type.isPlainObject(result)) 1877 return; 1878 1879 this.initPopupWindow(); 1880 1881 if (this.offers.length > 0) 1882 { 1883 this.offers[this.offerNum].COMPARED = result.STATUS === 'OK'; 1884 } 1885 1886 if (result.STATUS === 'OK') 1887 { 1888 BX.onCustomEvent('OnCompareChange'); 1889 1890 popupContent = '<div style="width: 100%; margin: 0; text-align: center;"><p>' 1891 + BX.message('COMPARE_MESSAGE_OK') 1892 + '</p></div>'; 1893 1894 if (this.showClosePopup) 1895 { 1896 popupButtons = [ 1897 new BasketButton({ 1898 text: BX.message('BTN_MESSAGE_COMPARE_REDIRECT'), 1899 events: { 1900 click: BX.delegate(this.compareRedirect, this) 1901 }, 1902 style: {marginRight: '10px'} 1903 }), 1904 new BasketButton({ 1905 text: BX.message('BTN_MESSAGE_CLOSE_POPUP'), 1906 events: { 1907 click: BX.delegate(this.obPopupWin.close, this.obPopupWin) 1908 } 1909 }) 1910 ]; 1911 } 1912 else 1913 { 1914 popupButtons = [ 1915 new BasketButton({ 1916 text: BX.message('BTN_MESSAGE_COMPARE_REDIRECT'), 1917 events: { 1918 click: BX.delegate(this.compareRedirect, this) 1919 } 1920 }) 1921 ]; 1922 } 1923 } 1924 else 1925 { 1926 popupContent = '<div style="width: 100%; margin: 0; text-align: center;"><p>' 1927 + (result.MESSAGE ? result.MESSAGE : BX.message('COMPARE_UNKNOWN_ERROR')) 1928 + '</p></div>'; 1929 popupButtons = [ 1930 new BasketButton({ 1931 text: BX.message('BTN_MESSAGE_CLOSE'), 1932 events: { 1933 click: BX.delegate(this.obPopupWin.close, this.obPopupWin) 1934 } 1935 }) 1936 ]; 1937 } 1938 1939 this.obPopupWin.setTitleBar(BX.message('COMPARE_TITLE')); 1940 this.obPopupWin.setContent(popupContent); 1941 this.obPopupWin.setButtons(popupButtons); 1942 this.obPopupWin.show(); 1943 }, 1944 1945 compareDeleteResult: function() 1946 { 1947 BX.onCustomEvent('OnCompareChange'); 1948 1949 if (this.offers && this.offers.length) 1950 { 1951 this.offers[this.offerNum].COMPARED = false; 1952 } 1953 }, 1954 1955 setCompared: function(state) 1956 { 1957 if (!this.obCompare) 1958 return; 1959 1960 var checkbox = this.obCompare.querySelector('[data-entity="compare-checkbox"]'); 1961 if (checkbox) 1962 { 1963 checkbox.checked = state; 1964 } 1965 }, 1966 1967 setCompareInfo: function(comparedIds) 1968 { 1969 if (!BX.type.isArray(comparedIds)) 1970 return; 1971 1972 for (var i in this.offers) 1973 { 1974 if (this.offers.hasOwnProperty(i)) 1975 { 1976 this.offers[i].COMPARED = BX.util.in_array(this.offers[i].ID, comparedIds); 1977 } 1978 } 1979 }, 1980 1981 compareRedirect: function() 1982 { 1983 if (this.compareData.comparePath) 1984 { 1985 location.href = this.compareData.comparePath; 1986 } 1987 else 1988 {
1989 this.obPopupWin.close(); 1990 } 1991 }, 1992 1993 checkDeletedCompare: function(id) 1994 { 1995 switch (this.productType) 1996 { 1997 case 0: // no catalog 1998 case 1: // product 1999 case 2: // set 2000 if (this.product.id == id) 2001 { 2002 this.setCompared(false); 2003 } 2004 2005 break; 2006 case 3: // sku 2007 var i = this.offers.length; 2008 while (i--) 2009 { 2010 if (this.offers[i].ID == id) 2011 { 2012 this.offers[i].COMPARED = false; 2013 2014 if (this.offerNum == i) 2015 { 2016 this.setCompared(false); 2017 } 2018 2019 break; 2020 } 2021 } 2022 } 2023 }, 2024 2025 initBasketUrl: function() 2026 { 2027 this.basketUrl = (this.basketMode === 'ADD' ? this.basketData.add_url : this.basketData.buy_url); 2028 switch (this.productType) 2029 { 2030 case 1: // product 2031 case 2: // set 2032 this.basketUrl = this.basketUrl.replace('#ID#', this.product.id.toString()); 2033 break; 2034 case 3: // sku 2035 this.basketUrl = this.basketUrl.replace('#ID#', this.offers[this.offerNum].ID); 2036 break; 2037 } 2038 this.basketParams = { 2039 'ajax_basket': 'Y' 2040 }; 2041 if (this.showQuantity) 2042 { 2043 this.basketParams[this.basketData.quantity] = this.obQuantity.value; 2044 } 2045 if (this.basketData.sku_props) 2046 { 2047 this.basketParams[this.basketData.sku_props_var] = this.basketData.sku_props; 2048 } 2049 }, 2050 2051 fillBasketProps: function() 2052 { 2053 if (!this.visual.BASKET_PROP_DIV) 2054 { 2055 return; 2056 } 2057 var 2058 i = 0, 2059 propCollection = null, 2060 foundValues = false, 2061 obBasketProps = null; 2062 2063 if (this.basketData.useProps && !this.basketData.emptyProps) 2064 { 2065 if (this.obPopupWin && this.obPopupWin.contentContainer) 2066 { 2067 obBasketProps = this.obPopupWin.contentContainer; 2068 } 2069 } 2070 else 2071 { 2072 obBasketProps = BX(this.visual.BASKET_PROP_DIV); 2073 } 2074 if (obBasketProps) 2075 { 2076 propCollection = obBasketProps.getElementsByTagName('select'); 2077 if (propCollection && propCollection.length) 2078 { 2079 for (i = 0; i < propCollection.length; i++) 2080 { 2081 if (!propCollection[i].disabled) 2082 { 2083 switch (propCollection[i].type.toLowerCase()) 2084 { 2085 case 'select-one': 2086 this.basketParams[propCollection[i].name] = propCollection[i].value; 2087 foundValues = true; 2088 break; 2089 default: 2090 break; 2091 } 2092 } 2093 } 2094 } 2095 propCollection = obBasketProps.getElementsByTagName('input'); 2096 if (propCollection && propCollection.length) 2097 { 2098 for (i = 0; i < propCollection.length; i++) 2099 { 2100 if (!propCollection[i].disabled) 2101 { 2102 switch (propCollection[i].type.toLowerCase()) 2103 { 2104 case 'hidden': 2105 this.basketParams[propCollection[i].name] = propCollection[i].value; 2106 foundValues = true; 2107 break; 2108 case 'radio': 2109 if (propCollection[i].checked) 2110 { 2111 this.basketParams[propCollection[i].name] = propCollection[i].value; 2112 foundValues = true; 2113 } 2114 break; 2115 default: 2116 break; 2117 } 2118 } 2119 } 2120 } 2121 } 2122 if (!foundValues) 2123 { 2124 this.basketParams[this.basketData.props] = []; 2125 this.basketParams[this.basketData.props][0] = 0; 2126 } 2127 }, 2128 2129 add2Basket: function() 2130 { 2131 this.basketMode = 'ADD'; 2132 this.basket(); 2133 }, 2134 2135 buyBasket: function() 2136 { 2137 this.basketMode = 'BUY'; 2138 this.basket(); 2139 }, 2140 2141 sendToBasket: function() 2142 { 2143 if (!this.canBuy) 2144 { 2145 return; 2146 } 2147 2148 // check recommendation 2149 if (this.product && this.product.id && this.bigData) 2150 { 2151 this.rememberProductRecommendation(); 2152 } 2153 2154 this.initBasketUrl(); 2155 this.fillBasketProps(); 2156 BX.ajax({ 2157 method: 'POST', 2158 dataType: 'json', 2159 url: this.basketUrl, 2160 data: this.basketParams, 2161 onsuccess: BX.proxy(this.basketResult, this) 2162 }); 2163 }, 2164 2165 basket: function() 2166 { 2167 var contentBasketProps = ''; 2168 if (!this.canBuy) 2169 { 2170 return; 2171 } 2172 switch (this.productType) 2173 { 2174 case 1: // product 2175 case 2: // set 2176 if (this.basketData.useProps && !this.basketData.emptyProps) 2177 { 2178 this.initPopupWindow(); 2179 this.obPopupWin.setTitleBar(BX.message('TITLE_BASKET_PROPS')); 2180 if (BX(this.visual.BASKET_PROP_DIV)) 2181 { 2182 contentBasketProps = BX(this.visual.BASKET_PROP_DIV).innerHTML; 2183 } 2184 this.obPopupWin.setContent(contentBasketProps); 2185 this.obPopupWin.setButtons([ 2186 new BasketButton({ 2187 text: BX.message('BTN_MESSAGE_SEND_PROPS'), 2188 events: { 2189 click: BX.delegate(this.sendToBasket, this) 2190 } 2191 }) 2192 ]); 2193 this.obPopupWin.show(); 2194 } 2195 else 2196 { 2197 this.sendToBasket(); 2198 } 2199 break; 2200 case 3: // sku 2201 this.sendToBasket(); 2202 break; 2203 } 2204 }, 2205 2206 basketResult: function(arResult) 2207 { 2208 var strContent = '', 2209 strPict = '', 2210 successful, 2211 buttons = []; 2212 2213 if (this.obPopupWin) 2214 this.obPopupWin.close(); 2215 2216 if (!BX.type.isPlainObject(arResult)) 2217 return; 2218 2219 successful = arResult.STATUS === 'OK'; 2220 2221 if (successful) 2222 { 2223 this.setAnalyticsDataLayer('addToCart'); 2224 } 2225 2226 if (successful && this.basketAction === 'BUY') 2227 { 2228 this.basketRedirect(); 2229 } 2230 else 2231 {
2232 this.initPopupWindow(); 2233 2234 if (successful) 2235 { 2236 BX.onCustomEvent('OnBasketChange'); 2237 2238 if (BX.findParent(this.obProduct, {className: 'bx_sale_gift_main_products'}, 10)) 2239 { 2240 BX.onCustomEvent('onAddToBasketMainProduct', [this]); 2241 } 2242 2243 switch (this.productType) 2244 { 2245 case 1: // product 2246 case 2: // set 2247 strPict = this.product.pict.SRC; 2248 break; 2249 case 3: // sku 2250 strPict = (this.offers[this.offerNum].PREVIEW_PICTURE ? 2251 this.offers[this.offerNum].PREVIEW_PICTURE.SRC : 2252 this.defaultPict.pict.SRC 2253 ); 2254 break; 2255 } 2256 2257 strContent = '<div style="width: 100%; margin: 0; text-align: center;"><img src="' 2258 + strPict + '" height="130" style="max-height:130px"><p>' + this.product.name + '</p></div>'; 2259 2260 if (this.showClosePopup) 2261 { 2262 buttons = [ 2263 new BasketButton({ 2264 text: BX.message("BTN_MESSAGE_BASKET_REDIRECT"), 2265 events: { 2266 click: BX.delegate(this.basketRedirect, this) 2267 }, 2268 style: {marginRight: '10px'} 2269 }), 2270 new BasketButton({ 2271 text: BX.message("BTN_MESSAGE_CLOSE_POPUP"), 2272 events: { 2273 click: BX.delegate(this.obPopupWin.close, this.obPopupWin) 2274 } 2275 }) 2276 ]; 2277 } 2278 else 2279 { 2280 buttons = [ 2281 new BasketButton({ 2282 text: BX.message("BTN_MESSAGE_BASKET_REDIRECT"), 2283 events: { 2284 click: BX.delegate(this.basketRedirect, this) 2285 } 2286 }) 2287 ]; 2288 } 2289 } 2290 else 2291 { 2292 strContent = '<div style="width: 100%; margin: 0; text-align: center;"><p>' 2293 + (arResult.MESSAGE ? arResult.MESSAGE : BX.message('BASKET_UNKNOWN_ERROR')) 2294 + '</p></div>'; 2295 buttons = [ 2296 new BasketButton({ 2297 text: BX.message('BTN_MESSAGE_CLOSE'), 2298 events: { 2299 click: BX.delegate(this.obPopupWin.close, this.obPopupWin) 2300 } 2301 }) 2302 ]; 2303 } 2304 this.obPopupWin.setTitleBar(successful ? BX.message('TITLE_SUCCESSFUL') : BX.message('TITLE_ERROR')); 2305 this.obPopupWin.setContent(strContent); 2306 this.obPopupWin.setButtons(buttons); 2307 this.obPopupWin.show(); 2308 } 2309 }, 2310 2311 basketRedirect: function() 2312 { 2313 location.href = (this.basketData.basketUrl ? this.basketData.basketUrl : BX.message('BASKET_URL')); 2314 }, 2315 2316 initPopupWindow: function() 2317 { 2318 if (this.obPopupWin) 2319 return; 2320 2321 this.obPopupWin = BX.PopupWindowManager.create('CatalogSectionBasket_' + this.visual.ID, null, { 2322 autoHide: true, 2323 offsetLeft: 0, 2324 offsetTop: 0, 2325 overlay : true, 2326 closeByEsc: true, 2327 titleBar: true, 2328 closeIcon: true, 2329 contentColor: 'white', 2330 className: this.templateTheme ? 'bx-' + this.templateTheme : '' 2331 }); 2332 } 2333 }; 2334})(window);
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.