PageSourceSearch

https://elamed.com/local/templates/.default/components/bitrix/catalog.item/.default/script.js

js elamed.com collected 2026-09-24 10:13:24 UTC 84,274 bytes, 2,127 lines download raw bytes

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