PageSourceSearch

https://kslux.uz/bitrix/templates/alpha_s1/js/catalogitem.js?1672032128144046

js kslux.uz collected 2026-10-08 06:29:49 UTC 144,046 bytes, 4,628 lines download raw bytes

1(function (window) {
2    'use strict';
3
4    if (window.Alpha.CatalogItem)
5        return;
6
7    window.Alpha.CatalogItem = function (arParams)
8    {
9        this.productType = 0;
10        this.showQuantity = true;
11        this.showAbsent = true;
12        this.secondPict = false;
13        this.showOldPrice = false;
14        this.showMaxQuantity = 'N';
15        this.relativeQuantityFactor = 5;
16        this.showPercent = false;
17        this.showSkuProps = false;
18        this.basketAction = 'ADD';
19        this.showClosePopup = false;
20        this.useCompare = false;
21        this.showSubscription = false;
22        this.visual = {
23            ID: '',
24            QUANTITY_ID: '',
25            QUANTITY_UP_ID: '',
26            QUANTITY_DOWN_ID: '',
27            DISPLAY_PROP_DIV: '',
28            BASKET_PROP_DIV: '',
29            SUBSCRIBE_ID: '',
30            PRICE_ID: '',
31            PRICE_OLD_ID: '',
32            DSC_PERC: '',
33            SECOND_DSC_PERC: '',
34            PICT_SLIDER: '',
35            WISHLIST_ID: ''
36        };
37        this.product = {
38            checkQuantity: false,
39            maxQuantity: 0,
40            stepQuantity: 1,
41            isDblQuantity: false,
42            canBuy: true,
43            name: '',
44            id: 0,
45            addUrl: '',
46            buyUrl: '',
47            picture: ''
48        };
49
50        this.basketMode = '';
51        this.basketData = {
52            useProps: false,
53            emptyProps: false,
54            quantity: 'quantity',
55            props: 'prop',
56            basketUrl: '',
57            sku_props: '',
58            sku_props_var: 'basket_props',
59            add_url: '',
60            buy_url: '',
61            wishlist_url: '',
62            wishlist_page_url: BX.message('SITE_DIR') + 'wishlist/',
63            add_wish_to_delayed: false
64        };
65
66        this.compareData = {
67            compareUrl: '',
68            compareDeleteUrl: '',
69            comparePath: ''
70        };
71
72        this.touch = null;
73
74        this.quantityDelay = null;
75        this.quantityTimer = null;
76
77        this.checkQuantity = false;
78        this.maxQuantity = 0;
79        this.minQuantity = 0;
80        this.stepQuantity = 1;
81        this.isDblQuantity = false;
82        this.canBuy = true;
83        this.precision = 6;
84        this.precisionFactor = Math.pow(10, this.precision);
85        this.bigData = false;
86        this.fullDisplayMode = false;
87        this.viewMode = '';
88        this.isWishList = false;
89
90        this.currentPriceMode = '';
91        this.currentPrices = [];
92        this.currentPriceSelected = 0;
93        this.currentQuantityRanges = [];
94        this.currentQuantityRangeSelected = 0;
95
96
97        this.obProduct = null;
98        this.blockNodes = {};
99        this.obQuantity = null;
100        this.obQuantityUp = null;
101        this.obQuantityDown = null;
102        this.obQuantityLimit = {};
103        
104        this.obBuyBtn = null;
105        this.obBasketActions = null;
106        this.obSubscribe = null;
107        this.obWishlist = null;
108        
109        this.obCompare = null;
110        this.obPrice = null;
111        this.obDscPerc = null;
112        this.obSecondDscPerc = null;
113        this.obPopupWin = null;
114        this.basketUrl = '';
115        this.basketParams = {};
116        this.isTouchDevice = BX.hasClass(document.documentElement, 'bx-touch');
117
118        this.useEnhancedEcommerce = false;
119        this.dataLayerName = 'dataLayer';
120
121        this.errorCode = 0;
122
123        if (typeof arParams === 'object')
124        {
125            if (arParams.PRODUCT_TYPE)
126            {
127                this.productType = parseInt(arParams.PRODUCT_TYPE, 10);
128            }
129
130            this.showQuantity = arParams.SHOW_QUANTITY;
131            this.showAbsent = arParams.SHOW_ABSENT;
132            this.secondPict = arParams.SECOND_PICT;
133            this.showOldPrice = arParams.SHOW_OLD_PRICE;
134            this.showMaxQuantity = arParams.SHOW_MAX_QUANTITY;
135            this.relativeQuantityFactor = parseInt(arParams.RELATIVE_QUANTITY_FACTOR);
136            this.showPercent = arParams.SHOW_DISCOUNT_PERCENT;
137            this.showSkuProps = arParams.SHOW_SKU_PROPS;
138            this.showSubscription = arParams.USE_SUBSCRIBE;
139
140            if (arParams.ADD_TO_BASKET_ACTION)
141            {
142                this.basketAction = arParams.ADD_TO_BASKET_ACTION;
143            }
144
145            this.showClosePopup = arParams.SHOW_CLOSE_POPUP;
146            this.useCompare = arParams.DISPLAY_COMPARE;
147            this.fullDisplayMode = arParams.PRODUCT_DISPLAY_MODE === 'Y';
148            this.bigData = arParams.BIG_DATA;
149            this.viewMode = arParams.VIEW_MODE || '';
150
151            if (arParams.IS_WISHLIST === "Y")
152            {
153                this.isWishList = true;
154            }
155
156            this.templateTheme = arParams.TEMPLATE_THEME || '';
157            this.useEnhancedEcommerce = arParams.USE_ENHANCED_ECOMMERCE === 'Y';
158            this.dataLayerName = arParams.DATA_LAYER_NAME;
159
160            this.visual = arParams.VISUAL;
161
162            switch (this.productType)
163            {
164                case 0: // no catalog
165                case 1: // product
166                case 2: // set
167                case 3: // sku
168                    if (arParams.PRODUCT && typeof arParams.PRODUCT === 'object')
169                    {
170                        this.currentPriceMode = arParams.PRODUCT.ITEM_PRICE_MODE;
171                        this.currentPrices = arParams.PRODUCT.ITEM_PRICES;
172                        this.currentPriceSelected = arParams.PRODUCT.ITEM_PRICE_SELECTED;
173                        this.currentQuantityRanges = arParams.PRODUCT.ITEM_QUANTITY_RANGES;
174                        this.currentQuantityRangeSelected = arParams.PRODUCT.ITEM_QUANTITY_RANGE_SELECTED;
175                        this.product.picture = arParams.PRODUCT.PICTURE;
176
177                        if (this.showQuantity)
178                        {
179                            this.product.checkQuantity = arParams.PRODUCT.CHECK_QUANTITY;
180                            this.product.isDblQuantity = arParams.PRODUCT.QUANTITY_FLOAT;
181
182                            if (this.product.checkQuantity)
183                            {
184                                this.product.maxQuantity = (this.product.isDblQuantity ? parseFloat(arParams.PRODUCT.MAX_QUANTITY) : parseInt(arParams.PRODUCT.MAX_QUANTITY, 10));
185                            }
186
187                            this.product.stepQuantity = (this.product.isDblQuantity ? parseFloat(arParams.PRODUCT.STEP_QUANTITY) : parseInt(arParams.PRODUCT.STEP_QUANTITY, 10));
188
189                            this.checkQuantity = this.product.checkQuantity;
190                            this.isDblQuantity = this.product.isDblQuantity;
191                            this.stepQuantity = this.product.stepQuantity;
192                            this.maxQuantity = this.product.maxQuantity;
193                            this.minQuantity = this.currentPriceMode === 'Q'
194                                    ? parseFloat(this.currentPrices[this.currentPriceSelected].MIN_QUANTITY)
195                                    : this.stepQuantity;
196
197                            if (this.isDblQuantity)
198                            {
199                                this.stepQuantity = Math.round(this.stepQuantity * this.precisionFactor) / this.precisionFactor;
200                            }
201                        }
202
203                        this.product.canBuy = arParams.PRODUCT.CAN_BUY;
204
205                        if (arParams.PRODUCT.RCM_ID)
206                        {
207                            this.product.rcmId = arParams.PRODUCT.RCM_ID;
208                        }
209
210                        this.canBuy = this.product.canBuy;
211                        this.product.name = arParams.PRODUCT.NAME;
212                        this.product.id = arParams.PRODUCT.ID;
213                        this.product.DETAIL_PAGE_URL = arParams.PRODUCT.DETAIL_PAGE_URL;
214
215                        if (arParams.PRODUCT.ADD_URL)
216                        {
217                            this.product.addUrl = arParams.PRODUCT.ADD_URL;
218                        }
219
220                        if (arParams.PRODUCT.BUY_URL)
221                        {
222                            this.product.buyUrl = arParams.PRODUCT.BUY_URL;
223                        }
224
225                        if (arParams.BASKET && typeof arParams.BASKET === 'object')
226                        {
227                            this.basketData.useProps = arParams.BASKET.ADD_PROPS;
228                            this.basketData.emptyProps = arParams.BASKET.EMPTY_PROPS;
229                        }
230                    } else
231                    {
232                        this.errorCode = -1;
233                    }
234
235                    break;
236                
237                default:
238                    this.errorCode = -1;
239            }
240            
241            
242            if (arParams.BASKET && typeof arParams.BASKET === 'object')
243            {
244                if (arParams.BASKET.QUANTITY)
245                {
246                    this.basketData.quantity = arParams.BASKET.QUANTITY;
247                }
248
249                if (arParams.BASKET.PROPS)
250                {
251                    this.basketData.props = arParams.BASKET.PROPS;
252                }
253
254                if (arParams.BASKET.BASKET_URL)
255                {
256                    this.basketData.basketUrl = arParams.BASKET.BASKET_URL;
257                }
258
259
260                if (arParams.BASKET.ADD_URL_TEMPLATE)
261                {
262                    this.basketData.add_url = arParams.BASKET.ADD_URL_TEMPLATE;
263                }
264
265                if (arParams.BASKET.BUY_URL_TEMPLATE)
266                {
267                    this.basketData.buy_url = arParams.BASKET.BUY_URL_TEMPLATE;
268                }
269                
270                if (arParams.BASKET.WISHLIST_URL_TEMPLATE)
271                {
272                    this.basketData.wishlist_url = arParams.BASKET.WISHLIST_URL_TEMPLATE;
273                    if (arParams.BASKET.WISHLIST_PAGE_URL && arParams.BASKET.WISHLIST_PAGE_URL.length > 0)
274                        this.basketData.wishlist_page_url = arParams.BASKET.WISHLIST_PAGE_URL;
275                    if (arParams.BASKET.ADD_WISH_TO_DELAYED === "Y")
276                        this.basketData.add_wish_to_delayed = true;
277                }
278
279                if (this.basketData.add_url === '' && this.basketData.buy_url === '')
280                {
281                    this.errorCode = -1024;
282                }
283            }
284            
285            
286            
287
288            if (this.useCompare)
289            {
290                if (arParams.COMPARE && typeof arParams.COMPARE === 'object')
291                {
292                    if (arParams.COMPARE.COMPARE_PATH)
293                    {
294                        this.compareData.comparePath = arParams.COMPARE.COMPARE_PATH;
295                    }
296
297                    if (arParams.COMPARE.COMPARE_URL_TEMPLATE)
298                    {
299                        this.compareData.compareUrl = arParams.COMPARE.COMPARE_URL_TEMPLATE;
300                    } else
301                    {
302                        this.useCompare = false;
303                    }
304
305                    if (arParams.COMPARE.COMPARE_DELETE_URL_TEMPLATE)
306                    {
307                        this.compareData.compareDeleteUrl = arParams.COMPARE.COMPARE_DELETE_URL_TEMPLATE;
308                    } else
309                    {
310                        this.useCompare = false;
311                    }
312                } else
313                {
314                    this.useCompare = false;
315                }
316            }
317
318        }
319
320        if (this.errorCode === 0)
321        {
322            BX.ready(BX.delegate(this.init, this));
323        }
324    };
325
326    window.Alpha.CatalogItem.prototype = {
327
328        init: function ()
329        {
330            var i = 0,
331                    treeItems = null;
332
333            this.obProduct = BX(this.visual.ID);
334            if (!this.obProduct)
335            {
336                this.errorCode = -1;
337            }
338            
339            this.obPrice = BX(this.visual.PRICE_ID);
340            this.obPriceOld = BX(this.visual.PRICE_OLD_ID);
341            this.obPriceTotal = BX(this.visual.PRICE_TOTAL_ID);
342            if (!this.obPrice)
343            {
344                this.errorCode = -16;
345            }
346
347
348            if (this.showQuantity && this.visual.QUANTITY_ID && this.obProduct)
349            {
350                this.obQuantity = BX(this.visual.QUANTITY_ID);
351                this.blockNodes.quantity = this.obProduct.querySelector('[data-entity="quantity-block"]');
352
353                if (!this.isTouchDevice)
354                {
355                    BX.bind(this.obQuantity, 'focus', BX.proxy(this.onFocus, this));
356                    BX.bind(this.obQuantity, 'blur', BX.proxy(this.onBlur, this));
357                }
358
359                if (this.visual.QUANTITY_UP_ID)
360                {
361                    this.obQuantityUp = BX(this.visual.QUANTITY_UP_ID);
362                }
363
364                if (this.visual.QUANTITY_DOWN_ID)
365                {
366                    this.obQuantityDown = BX(this.visual.QUANTITY_DOWN_ID);
367                }
368            }
369
370            if (this.visual.QUANTITY_LIMIT && this.showMaxQuantity !== 'N')
371            {
372                this.obQuantityLimit.all = BX(this.visual.QUANTITY_LIMIT);
373                if (this.obQuantityLimit.all)
374                {
375                    this.obQuantityLimit.value = this.obQuantityLimit.all.querySelector('[data-entity="quantity-limit-value"]');
376                    if (!this.obQuantityLimit.value)
377                    {
378                        this.obQuantityLimit.all = null;
379                    }
380                }
381            }
382
383
384            this.obBasketActions = BX(this.visual.BASKET_ACTIONS_ID);
385            if (this.obBasketActions)
386            {
387                if (this.visual.BUY_ID)
388                {
389                    this.obBuyBtn = BX(this.visual.BUY_ID);
390                }
391            }
392
393            if (this.showSubscription)
394            {
395                this.obSubscribe = BX(this.visual.SUBSCRIBE_ID);
396            }
397            
398            if (!!this.visual.PICT_SLIDER && BX(this.visual.PICT_SLIDER))
399            {
400                var obSlier = BX(this.visual.PICT_SLIDER);
401                
402                var productGalleryThumbs = new Swiper(obSlier.querySelector('.gallery-thumbs'), {
403                    slidesPerView: 'auto',
404                    freeMode: true,
405                    watchSlidesVisibility: true,
406                    watchSlidesProgress: true,
407
408                });
409                
410                var productGalleryTop = new Swiper(obSlier.querySelector('.gallery-top'), {
411
412                    pagination: {
413                        el: '.swiper-pagination',
414                        clickable: true,
415					},
416					on: {
417						slideChangeTransitionStart: function () {
418							$(window).scroll();
419						}
420					},
421                    
422                    thumbs: {
423                        swiper: productGalleryThumbs
424                    }
425                });
426
427                $(obSlier).find('.swiper-container-thumbs').find('.swiper-slide').on('mouseover', function () {
428                    productGalleryTop.slideTo($(this).index());
429                });
430            }
431
432            if (!!this.visual.WISHLIST_ID && BX(this.visual.WISHLIST_ID))
433            {
434                this.obWishlist = BX(this.visual.WISHLIST_ID);
435            }
436            
437            if (this.obWishlist)
438            {
439                BX.bind(this.obWishlist, 'click', BX.delegate(this.wishlistChange, this));
440            }
441
442            if (this.errorCode === 0)
443            {
444                
445                if (this.bigData)
446                {
447                    var links = BX.findChildren(this.obProduct, {tag: 'a'}, true);
448                    if (links)
449                    {
450                        for (i in links)
451                        {
452                            if (links.hasOwnProperty(i))
453                            {
454                                if (links[i].getAttribute('href') == this.product.DETAIL_PAGE_URL)
455                                {
456                                    BX.bind(links[i], 'click', BX.proxy(this.rememberProductRecommendation, this));
457                                }
458                            }
459                        }
460                    }
461                }
462
463                if (this.showQuantity)
464                {
465                    var startEventName = this.isTouchDevice ? 'touchstart' : 'mousedown';
466                    var endEventName = this.isTouchDevice ? 'touchend' : 'mouseup';
467
468                    if (this.obQuantityUp)
469                    {
470                        BX.bind(this.obQuantityUp, startEventName, BX.proxy(this.startQuantityInterval, this));
471                        BX.bind(this.obQuantityUp, endEventName, BX.proxy(this.clearQuantityInterval, this));
472                        BX.bind(this.obQuantityUp, 'mouseout', BX.proxy(this.clearQuantityInterval, this));
473                        BX.bind(this.obQuantityUp, 'click', BX.delegate(this.quantityUp, this));
474                    }
475
476                    if (this.obQuantityDown)
477                    {
478                        BX.bind(this.obQuantityDown, startEventName, BX.proxy(this.startQuantityInterval, this));
479                        BX.bind(this.obQuantityDown, endEventName, BX.proxy(this.clearQuantityInterval, this));
480                        BX.bind(this.obQuantityDown, 'mouseout', BX.proxy(this.clearQuantityInterval, this));
481                        BX.bind(this.obQuantityDown, 'click', BX.delegate(this.quantityDown, this));
482                    }
483
484                    if (this.obQuantity)
485                    {
486                        BX.bind(this.obQuantity, 'change', BX.delegate(this.quantityChange, this));
487                    }
488                }
489                
490                
491
492                switch (this.productType)
493                {
494                    case 0: // no catalog
495                    case 1: // product
496                    case 2: // set
497                        
498                        this.checkQuantityControls();
499
500                        break;
501                    case 3: // sku
502                        break;
503                }
504
505                if (this.obBuyBtn)
506                {
507                    if (this.basketAction === 'ADD')
508                    {
509                        BX.bind(this.obBuyBtn, 'click', BX.proxy(this.add2Basket, this));
510                    } else
511                    {
512                        BX.bind(this.obBuyBtn, 'click', BX.proxy(this.buyBasket, this));
513                    }
514                }
515
516                if (this.useCompare)
517                {
518                    this.obCompare = BX(this.visual.COMPARE_LINK_ID);
519                    if (this.obCompare)
520                    {
521                        BX.bind(this.obCompare, 'click', BX.proxy(this.compare, this));
522                    }
523
524                    BX.addCustomEvent('onCatalogDeleteCompare', BX.proxy(this.checkDeletedCompare, this));
525                }
526            }
527        },
528
529        setAnalyticsDataLayer: function (action)
530        {
531            if (!this.useEnhancedEcommerce || !this.dataLayerName)
532                return;
533
534            var item = {},
535                    info = {},
536                    variants = [],
537                    i, k, j, propId, skuId, propValues;
538
539            item = {
540                        'id': this.product.id,
541                        'name': this.product.name,
542                        'price': this.currentPrices[this.currentPriceSelected] && this.currentPrices[this.currentPriceSelected].PRICE,
543            };
544
545            switch (action)
546            {
547                case 'addToCart':
548                    info = {
549                        'event': 'addToCart',
550                        'ecommerce': {
551                            'currencyCode': this.currentPrices[this.currentPriceSelected] && this.currentPrices[this.currentPriceSelected].CURRENCY || '',
552                            'add': {
553                                'products': [{
554                                        'name': item.name || '',
555                                        'id': item.id || '',
556                                        'price': item.price || 0,
557                                        'brand': item.brand || '',
558                                        'category': item.category || '',
559                                        'variant': item.variant || '',
560                                        'quantity': this.showQuantity && this.obQuantity ? this.obQuantity.value : 1
561                                    }]
562                            }
563                        }
564                    };
565                    break;
566            }
567
568            window[this.dataLayerName] = window[this.dataLayerName] || [];
569            window[this.dataLayerName].push(info);
570        },
571
572        getCookie: function (name)
573        {
574            var matches = document.cookie.match(new RegExp(
575                    "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
576                    ));
577
578            return matches ? decodeURIComponent(matches[1]) : null;
579        },
580
581        rememberProductRecommendation: function ()
582        {
583            // save to RCM_PRODUCT_LOG
584            var cookieName = BX.cookie_prefix + '_RCM_PRODUCT_LOG',
585                    cookie = this.getCookie(cookieName),
586                    itemFound = false;
587
588            var cItems = [],
589                    cItem;
590
591            if (cookie)
592            {
593                cItems = cookie.split('.');
594            }
595
596            var i = cItems.length;
597
598            while (i--)
599            {
600                cItem = cItems[i].split('-');
601
602                if (cItem[0] == this.product.id)
603                {
604                    // it's already in recommendations, update the date
605                    cItem = cItems[i].split('-');
606
607                    // update rcmId and date
608                    cItem[1] = this.product.rcmId;
609                    cItem[2] = BX.current_server_time;
610
611                    cItems[i] = cItem.join('-');
612                    itemFound = true;
613                } else
614                {
615                    if ((BX.current_server_time - cItem[2]) > 3600 * 24 * 30)
616                    {
617                        cItems.splice(i, 1);
618                    }
619                }
620            }
621
622            if (!itemFound)
623            {
624                // add recommendation
625                cItems.push([this.product.id, this.product.rcmId, BX.current_server_time].join('-'));
626            }
627
628            // serialize
629            var plNewCookie = cItems.join('.'),
630                    cookieDate = new Date(new Date().getTime() + 1000 * 3600 * 24 * 365 * 10).toUTCString();
631
632            document.cookie = cookieName + "=" + plNewCookie + "; path=/; expires=" + cookieDate + "; domain=" + BX.cookie_domain;
633        },
634
635        startQuantityInterval: function () // leave
636        {
637            var target = BX.proxy_context;
638            var func = target.id === this.visual.QUANTITY_DOWN_ID
639                    ? BX.proxy(this.quantityDown, this)
640                    : BX.proxy(this.quantityUp, this);
641
642            this.quantityDelay = setTimeout(
643                    BX.delegate(function () {
644                        this.quantityTimer = setInterval(func, 150);
645                    }, this),
646                    300
647                    );
648        },
649
650        clearQuantityInterval: function () // leave
651        {
652            clearTimeout(this.quantityDelay);
653            clearInterval(this.quantityTimer);
654        },
655
656        quantityUp: function () // leave
657        {
658            var curValue = 0,
659                boolSet = true;
660
661            if (this.errorCode === 0 && this.showQuantity && this.canBuy)
662            {
663                curValue = (this.isDblQuantity ? parseFloat(this.obQuantity.value) : parseInt(this.obQuantity.value, 10));
664                if (!isNaN(curValue))
665                {
666                    curValue += this.stepQuantity;
667                    if (this.checkQuantity)
668                    {
669                        if (curValue > this.maxQuantity)
670                        {
671                            boolSet = false;
672                        }
673                    }
674
675                    if (boolSet)
676                    {
677                        if (this.isDblQuantity)
678                        {
679                            curValue = Math.round(curValue * this.precisionFactor) / this.precisionFactor;
680                        }
681
682                        this.obQuantity.value = curValue;
683
684                        if (!this.obProduct.hasAttribute('data-service'))
685                        {
686                            this.setPrice();
687                        }
688                    }
689                }
690            }
691        },
692
693        quantityDown: function () // leave
694        {
695            var curValue = 0,
696                boolSet = true;
697
698            if (this.errorCode === 0 && this.showQuantity && this.canBuy)
699            {
700                curValue = (this.isDblQuantity ? parseFloat(this.obQuantity.value) : parseInt(this.obQuantity.value, 10));
701                if (!isNaN(curValue))
702                {
703                    curValue -= this.stepQuantity;
704
705                    this.checkPriceRange(curValue);
706
707                    if (curValue < this.minQuantity)
708                    {
709                        boolSet = false;
710                    }
711
712                    if (boolSet)
713                    {
714                        if (this.isDblQuantity)
715                        {
716                            curValue = Math.round(curValue * this.precisionFactor) / this.precisionFactor;
717                        }
718
719                        this.obQuantity.value = curValue;
720
721                        if (!this.obProduct.hasAttribute('data-service'))
722                        {
723                            this.setPrice();
724                        }
725                    }
726                }
727            }
728        },
729
730        quantityChange: function () // leave
731        {
732            var curValue = 0,
733                    intCount;
734
735            if (this.errorCode === 0 && this.showQuantity)
736            {
737                if (this.canBuy)
738                {
739                    curValue = this.isDblQuantity ? parseFloat(this.obQuantity.value) : Math.round(this.obQuantity.value);
740                    if (!isNaN(curValue))
741                    {
742                        if (this.checkQuantity)
743                        {
744                            if (curValue > this.maxQuantity)
745                            {
746                                curValue = this.maxQuantity;
747                            }
748                        }
749
750                        this.checkPriceRange(curValue);
751
752                        intCount = Math.floor(
753                                Math.round(curValue * this.precisionFactor / this.stepQuantity) / this.precisionFactor
754                                ) || 1;
755                        curValue = (intCount <= 1 ? this.stepQuantity : intCount * this.stepQuantity);
756                        curValue = Math.round(curValue * this.precisionFactor) / this.precisionFactor;
757
758                        if (curValue < this.minQuantity)
759                        {
760                            curValue = this.minQuantity;
761                        }
762
763                        this.obQuantity.value = curValue;
764                    } else
765                    {
766                        this.obQuantity.value = this.minQuantity;
767                    }
768                } else
769                {
770                    this.obQuantity.value = this.minQuantity;
771                }
772
773                this.setPrice();
774            }
775        },
776
777        quantitySet: function (index)
778        {
779            var resetQuantity, strLimit;
780
781            var newOffer = this.offers[index],
782                    oldOffer = this.offers[this.offerNum];
783
784            if (this.errorCode === 0)
785            {
786                this.canBuy = newOffer.CAN_BUY;
787
788                this.currentPriceMode = newOffer.ITEM_PRICE_MODE;
789                this.currentPrices = newOffer.ITEM_PRICES;
790                this.currentPriceSelected = newOffer.ITEM_PRICE_SELECTED;
791                this.currentQuantityRanges = newOffer.ITEM_QUANTITY_RANGES;
792                this.currentQuantityRangeSelected = newOffer.ITEM_QUANTITY_RANGE_SELECTED;
793
794                if (this.canBuy)
795                {
796                    if (this.blockNodes.quantity)
797                    {
798                        BX.style(this.blockNodes.quantity, 'display', '');
799                    }
800
801                    if (this.obBasketActions)
802                    {
803                        BX.style(this.obBasketActions, 'display', '');
804                    }
805
806                    if (this.obNotAvail)
807                    {
808                        BX.style(this.obNotAvail, 'display', 'none');
809                    }
810
811                    if (this.obSubscribe)
812                    {
813                        BX.style(this.obSubscribe, 'display', 'none');
814                    }
815                } else
816                {
817                    if (this.blockNodes.quantity)
818                    {
819                        BX.style(this.blockNodes.quantity, 'display', 'none');
820                    }
821
822                    if (this.obBasketActions)
823                    {
824                        BX.style(this.obBasketActions, 'display', 'none');
825                    }
826
827                    if (this.obNotAvail)
828                    {
829                        BX.style(this.obNotAvail, 'display', '');
830                    }
831
832                    if (this.obSubscribe)
833                    {
834                        if (newOffer.CATALOG_SUBSCRIBE === 'Y')
835                        {
836                            BX.style(this.obSubscribe, 'display', '');
837                            this.obSubscribe.setAttribute('data-item', newOffer.ID);
838                            BX(this.visual.SUBSCRIBE_ID + '_hidden').click();
839                        } else
840                        {
841                            BX.style(this.obSubscribe, 'display', 'none');
842                        }
843                    }
844                }
845
846                this.isDblQuantity = newOffer.QUANTITY_FLOAT;
847                this.checkQuantity = newOffer.CHECK_QUANTITY;
848
849                if (this.isDblQuantity)
850                {
851                    this.stepQuantity = Math.round(parseFloat(newOffer.STEP_QUANTITY) * this.precisionFactor) / this.precisionFactor;
852                    this.maxQuantity = parseFloat(newOffer.MAX_QUANTITY);
853                    this.minQuantity = this.currentPriceMode === 'Q' ? parseFloat(this.currentPrices[this.currentPriceSelected].MIN_QUANTITY) : this.stepQuantity;
854                } else
855                {
856                    this.stepQuantity = parseInt(newOffer.STEP_QUANTITY, 10);
857                    this.maxQuantity = parseInt(newOffer.MAX_QUANTITY, 10);
858                    this.minQuantity = this.currentPriceMode === 'Q' ? parseInt(this.currentPrices[this.currentPriceSelected].MIN_QUANTITY) : this.stepQuantity;
859                }
860
861                if (this.showQuantity)
862                {
863                    var isDifferentMinQuantity = oldOffer.ITEM_PRICES.length
864                            && oldOffer.ITEM_PRICES[oldOffer.ITEM_PRICE_SELECTED]
865                            && oldOffer.ITEM_PRICES[oldOffer.ITEM_PRICE_SELECTED].MIN_QUANTITY != this.minQuantity;
866
867                    if (this.isDblQuantity)
868                    {
869                        resetQuantity = Math.round(parseFloat(oldOffer.STEP_QUANTITY) * this.precisionFactor) / this.precisionFactor !== this.stepQuantity
870                                || isDifferentMinQuantity
871                                || oldOffer.MEASURE !== newOffer.MEASURE
872                                || (
873                                        this.checkQuantity
874                                        && parseFloat(oldOffer.MAX_QUANTITY) > this.maxQuantity
875                                        && parseFloat(this.obQuantity.value) > this.maxQuantity
876                                        );
877                    } else
878                    {
879                        resetQuantity = parseInt(oldOffer.STEP_QUANTITY, 10) !== this.stepQuantity
880                                || isDifferentMinQuantity
881                                || oldOffer.MEASURE !== newOffer.MEASURE
882                                || (
883                                        this.checkQuantity
884                                        && parseInt(oldOffer.MAX_QUANTITY, 10) > this.maxQuantity
885                                        && parseInt(this.obQuantity.value, 10) > this.maxQuantity
886                                        );
887                    }
888
889                    this.obQuantity.disabled = !this.canBuy;
890
891                    if (resetQuantity)
892                    {
893                        this.obQuantity.value = this.minQuantity;
894                    }
895
896                    if (this.obMeasure)
897                    {
898                        if (newOffer.MEASURE)
899                        {
900                            BX.adjust(this.obMeasure, {html: newOffer.MEASURE});
901                        } else
902                        {
903                            BX.adjust(this.obMeasure, {html: ''});
904                        }
905                    }
906                }
907
908                if (this.obQuantityLimit.all)
909                {
910                    if (!this.checkQuantity || this.maxQuantity == 0)
911                    {
912                        BX.adjust(this.obQuantityLimit.value, {html: ''});
913                        BX.adjust(this.obQuantityLimit.all, {style: {display: 'none'}});
914                    } else
915                    {
916                        if (this.showMaxQuantity === 'M')
917                        {
918                            strLimit = (this.maxQuantity / this.stepQuantity >= this.relativeQuantityFactor)
919 
919                                   ? BX.message('RELATIVE_QUANTITY_MANY')
920                                    : BX.message('RELATIVE_QUANTITY_FEW');
921                        } else
922                        {
923                            strLimit = this.maxQuantity;
924
925                            if (newOffer.MEASURE)
926                            {
927                                strLimit += (' ' + newOffer.MEASURE);
928                            }
929                        }
930
931                        BX.adjust(this.obQuantityLimit.value, {html: strLimit});
932                        BX.adjust(this.obQuantityLimit.all, {style: {display: ''}});
933                    }
934                }
935            }
936        },
937
938        
939        checkTouch: function (event)
940        {
941            if (!event || !event.changedTouches)
942                return false;
943
944            return event.changedTouches[0].identifier === this.touch.identifier;
945        },
946
947        touchStartEvent: function (event)
948        {
949            if (event.touches.length != 1)
950                return;
951
952            this.touch = event.changedTouches[0];
953        },
954
955        touchEndEvent: function (event)
956        {
957            if (!this.checkTouch(event))
958                return;
959
960            var deltaX = this.touch.pageX - event.changedTouches[0].pageX,
961                    deltaY = this.touch.pageY - event.changedTouches[0].pageY;
962
963            if (Math.abs(deltaX) >= Math.abs(deltaY) + 10)
964            {
965                if (deltaX > 0)
966                {
967                    this.slideNext();
968                }
969
970                if (deltaX < 0)
971                {
972                    this.slidePrev();
973                }
974            }
975        },
976
977        checkPriceRange: function (quantity) // leave
978        {
979            if (typeof quantity === 'undefined' || this.currentPriceMode != 'Q')
980                return;
981
982            var range, found = false;
983
984            for (var i in this.currentQuantityRanges)
985            {
986                if (this.currentQuantityRanges.hasOwnProperty(i))
987                {
988                    range = this.currentQuantityRanges[i];
989
990                    if (
991                            parseInt(quantity) >= parseInt(range.SORT_FROM)
992                            && (
993                                    range.SORT_TO == 'INF'
994                                    || parseInt(quantity) <= parseInt(range.SORT_TO)
995                                    )
996                            )
997                    {
998                        found = true;
999                        this.currentQuantityRangeSelected = range.HASH;
1000                        break;
1001                    }
1002                }
1003            }
1004
1005            if (!found && (range = this.getMinPriceRange()))
1006            {
1007                this.currentQuantityRangeSelected = range.HASH;
1008            }
1009
1010            for (var k in this.currentPrices)
1011            {
1012                if (this.currentPrices.hasOwnProperty(k))
1013                {
1014                    if (this.currentPrices[k].QUANTITY_HASH == this.currentQuantityRangeSelected)
1015                    {
1016                        this.currentPriceSelected = k;
1017                        break;
1018                    }
1019                }
1020            }
1021        },
1022
1023        getMinPriceRange: function () // leave
1024        {
1025            var range;
1026
1027            for (var i in this.currentQuantityRanges)
1028            {
1029                if (this.currentQuantityRanges.hasOwnProperty(i))
1030                {
1031                    if (
1032                            !range
1033                            || parseInt(this.currentQuantityRanges[i].SORT_FROM) < parseInt(range.SORT_FROM)
1034                            )
1035                    {
1036                        range = this.currentQuantityRanges[i];
1037                    }
1038                }
1039            }
1040
1041            return range;
1042        },
1043
1044        checkQuantityControls: function () // leave
1045        {
1046            if (!this.obQuantity)
1047                return;
1048
1049            var reachedTopLimit = this.checkQuantity && parseFloat(this.obQuantity.value) + this.stepQuantity > this.maxQuantity,
1050                    reachedBottomLimit = parseFloat(this.obQuantity.value) - this.stepQuantity < this.minQuantity;
1051
1052            if (reachedTopLimit)
1053            {
1054                BX.addClass(this.obQuantityUp, 'product-item-amount-field-btn-disabled');
1055            } else if (BX.hasClass(this.obQuantityUp, 'product-item-amount-field-btn-disabled'))
1056            {
1057                BX.removeClass(this.obQuantityUp, 'product-item-amount-field-btn-disabled');
1058            }
1059
1060            if (reachedBottomLimit)
1061            {
1062                BX.addClass(this.obQuantityDown, 'product-item-amount-field-btn-disabled');
1063            } else if (BX.hasClass(this.obQuantityDown, 'product-item-amount-field-btn-disabled'))
1064            {
1065                BX.removeClass(this.obQuantityDown, 'product-item-amount-field-btn-disabled');
1066            }
1067
1068            if (reachedTopLimit && reachedBottomLimit)
1069            {
1070                this.obQuantity.setAttribute('disabled', 'disabled');
1071            } else
1072            {
1073                this.obQuantity.removeAttribute('disabled');
1074            }
1075        },
1076
1077        setPrice: function () // leave
1078        {
1079            var obData, price;
1080
1081            if (this.obQuantity)
1082            {
1083                this.checkPriceRange(this.obQuantity.value);
1084            }
1085
1086            this.checkQuantityControls();
1087
1088            price = this.currentPrices[this.currentPriceSelected];
1089
1090            if (this.obPrice)
1091            {
1092                if (price)
1093                {
1094                    BX.adjust(this.obPrice, {html: BX.Currency.currencyFormat(price.RATIO_PRICE, price.CURRENCY, true)});
1095                } else
1096                {
1097                    BX.adjust(this.obPrice, {html: ''});
1098                }
1099
1100                if (this.showOldPrice && this.obPriceOld)
1101                {
1102                    if (price && price.RATIO_PRICE !== price.RATIO_BASE_PRICE)
1103                    {
1104                        BX.adjust(this.obPriceOld, {
1105                            style: {display: ''},
1106                            html: BX.Currency.currencyFormat(price.RATIO_BASE_PRICE, price.CURRENCY, true)
1107                        });
1108                    } else
1109                    {
1110                        BX.adjust(this.obPriceOld, {
1111                            style: {display: 'none'},
1112                            html: ''
1113                        });
1114                    }
1115                }
1116
1117                if (this.obPriceTotal)
1118                {
1119                    if (price && this.obQuantity && this.obQuantity.value != this.stepQuantity)
1120                    {
1121                        BX.adjust(this.obPriceTotal, {
1122                            html: BX.message('PRICE_TOTAL_PREFIX') + ' <strong>'
1123                                    + BX.Currency.currencyFormat(price.PRICE * this.obQuantity.value, price.CURRENCY, true)
1124                                    + '</strong>',
1125                            style: {display: ''}
1126                        });
1127                    } else
1128                    {
1129                        BX.adjust(this.obPriceTotal, {
1130                            html: '',
1131                            style: {display: 'none'}
1132                        });
1133                    }
1134                }
1135
1136                if (this.showPercent)
1137                {
1138                    if (price && parseInt(price.DISCOUNT) > 0)
1139                    {
1140                        obData = {style: {display: ''}, html: -price.PERCENT + '%'};
1141                    } else
1142                    {
1143                        obData = {style: {display: 'none'}, html: ''};
1144                    }
1145
1146                    if (this.obDscPerc)
1147                    {
1148                        BX.adjust(this.obDscPerc, obData);
1149                    }
1150
1151                    if (this.obSecondDscPerc)
1152                    {
1153                        BX.adjust(this.obSecondDscPerc, obData);
1154                    }
1155                }
1156            }
1157        },
1158        
1159        wishlistChange: function (event) {
1160            
1161            var target = BX.getEventTarget(event);
1162            
1163            BX.ajax({
1164                method: 'POST',
1165                dataType: 'json',
1166                url: this.basketData.wishlist_url,
1167                onsuccess: BX.proxy(function (response) {
1168                    
1169                    if (typeof(response) == 'object')
1170                    {
1171                        
1172                        if (response.result == 'ok' && response.state == "added")
1173                        {
1174                            if (!!window.Alpha.Messages && typeof (window.Alpha.Messages) == 'function')
1175                            {
1176                                new window.Alpha.Messages({
1177                                    type: 'default',
1178                                    title: BX.message('ADD_TO_WISHLIST_TITLE'),
1179                                    message: this.product.name,
1180                                    url: !this.isWishList ? this.basketData.wishlist_page_url : '',
1181                                    urlText: 'WISHLIST'
1182                                });
1183                            }
1184
1185                            BX.addClass(this.obWishlist, 'active');
1186                            if (this.isWishList && this.obProduct)
1187                            {
1188                                BX.removeClass(this.obProduct, 'disabled');
1189                                let productLink = this.obProduct.querySelector(".product-card-link");
1190                                productLink && $(productLink).css('pointer-events', 'auto');
1191                            }
1192                        }
1193                        else if (response.result == 'ok' && response.state == "deleted")
1194                        {
1195                            if (!!window.Alpha.Messages && typeof (window.Alpha.Messages) == 'function')
1196                            {
1197                                new window.Alpha.Messages({
1198                                    type: 'default',
1199                                    title: BX.message('DELETE_FROM_WISHLIST_TITLE'),
1200                                    message: this.product.name,
1201                                });
1202                            }
1203                            
1204                            BX.removeClass(this.obWishlist, 'active');
1205                            if (this.isWishList && this.obProduct)
1206                            {
1207                                BX.addClass(this.obProduct, 'disabled');
1208                                let productLink = this.obProduct.querySelector(".product-card-link");
1209                                productLink && $(productLink).css('pointer-events', 'n
1209one');
1210                            }
1211                        }
1212                        
1213                        BX.onCustomEvent('OnWishlistChange');
1214
1215                    }
1216                    else
1217                    {
1218                        console.log("error change wishlist: ", response);
1219                    }
1220                    
1221                    
1222                }, this)
1223            });
1224        },
1225        
1226        setWishlist: function (state) {
1227            
1228            state = (state) || '';
1229            
1230            if (state == "active")
1231            {
1232                BX.addClass(this.obWishlist, 'active');
1233            }
1234            else
1235            {
1236                BX.removeClass(this.obWishlist, 'active');
1237            }
1238            
1239        },
1240       
1241        compare: function (event)
1242        {
1243            if (!this.obCompare)
1244                return;
1245
1246            var isActive = this.obCompare.classList.contains('active') ? true : false;
1247            var url = !isActive ? this.compareData.compareUrl : this.compareData.compareDeleteUrl, compareLink;
1248
1249
1250            if (isActive)
1251                this.setCompared(false);
1252            else
1253                this.setCompared(true);
1254
1255            if (url)
1256            {
1257                BX.onCustomEvent('OnCompareChange');
1258
1259                compareLink = url.replace('#ID#', this.product.id.toString());
1260
1261                BX.ajax({
1262                    method: 'POST',
1263                    dataType: !isActive ? 'json' : 'html',
1264                    url: compareLink + (compareLink.indexOf('?') !== -1 ? '&' : '?') + 'ajax_action=Y',
1265                    onsuccess: !isActive
1266                        ? BX.proxy(this.compareResult, this)
1267                        : BX.proxy(this.compareDeleteResult, this)
1268                });
1269            }
1270        },
1271
1272        compareResult: function (result)
1273        {
1274            if (!BX.type.isPlainObject(result))
1275                return;
1276
1277            if (result.STATUS === 'OK')
1278            {
1279                
1280                if (!!window.Alpha.Messages && typeof (window.Alpha.Messages) == 'function')
1281                {
1282                    new window.Alpha.Messages({
1283                        type: 'default',
1284                        title: BX.message('ADD_TO_COMPARE_TITLE'),
1285                        message: this.product.name.toString(),
1286                    });
1287                }
1288
1289            }
1290            else
1291            {
1292                if (!!window.Alpha.Messages && typeof (window.Alpha.Messages) == 'function')
1293                {
1294                    new window.Alpha.Messages({
1295                        type: 'error',
1296                        title: BX.message('ADD_TO_COMPARE_ERROR'),
1297                    });
1298                }
1299
1300            }
1301
1302        },
1303
1304        compareDeleteResult: function ()
1305        {
1306            BX.onCustomEvent('OnCompareChange');
1307        },
1308
1309        setCompared: function (state)
1310        {
1311            if (!this.obCompare)
1312                return;
1313
1314            if (state == true)
1315                this.obCompare.classList.add("active");
1316            else if (state == false)
1317                this.obCompare.classList.remove("active");
1318        },
1319
1320        setCompareInfo: function (comparedIds)
1321        {
1322            if (!BX.type.isArray(comparedIds))
1323                return;
1324        },
1325
1326        compareRedirect: function ()
1327        {
1328            if (this.compareData.comparePath)
1329            {
1330                location.href = this.compareData.comparePath;
1331            } else
1332            {
1333                this.obPopupWin.close();
1334            }
1335        },
1336
1337        checkDeletedCompare: function (id)
1338        {
1339            switch (this.productType)
1340            {
1341                case 0: // no catalog
1342                case 1: // product
1343                case 2: // set
1344                    if (this.product.id == id)
1345                    {
1346                        this.setCompared(false);
1347                    }
1348
1349                    break;
1350                case 3: // sku
1351                    var i = this.offers.length;
1352                    while (i--)
1353                    {
1354                        if (this.offers[i].ID == id)
1355                        {
1356                            this.offers[i].COMPARED = false;
1357
1358                            if (this.offerNum == i)
1359                            {
1360                                this.setCompared(false);
1361                            }
1362
1363                            break;
1364                        }
1365                    }
1366            }
1367        },
1368
1369        initBasketUrl: function ()
1370        {
1371            this.basketUrl = (this.basketMode === 'ADD' ? this.basketData.add_url : this.basketData.buy_url);
1372            switch (this.productType)
1373            {
1374                case 1: // product
1375                case 2: // set
1376                    this.basketUrl = this.basketUrl.replace('#ID#', this.product.id.toString());
1377                    break;
1378                case 3: // sku
1379                    this.basketUrl = this.basketUrl.replace('#ID#', this.offers[this.offerNum].ID);
1380                    break;
1381            }
1382            this.basketParams = {
1383                'ajax_basket': 'Y'
1384            };
1385            if (this.showQuantity)
1386            {
1387                this.basketParams[this.basketData.quantity] = this.obQuantity.value;
1388            }
1389            if (this.basketData.sku_props)
1390            {
1391                this.basketParams[this.basketData.sku_props_var] = this.basketData.sku_props;
1392            }
1393        },
1394
1395        fillBasketProps: function ()
1396        {
1397            if (!this.visual.BASKET_PROP_DIV)
1398            {
1399                return;
1400            }
1401            var
1402                    i = 0,
1403                    propCollection = null,
1404                    foundValues = false,
1405                    obBasketProps = null;
1406
1407            if (this.basketData.useProps && !this.basketData.emptyProps)
1408            {
1409                if (this.obPopupWin && this.obPopupWin.contentContainer)
1410                {
1411                    obBasketProps = this.obPopupWin.contentContainer;
1412                }
1413            } else
1414            {
1415                obBasketProps = BX(this.visual.BASKET_PROP_DIV);
1416            }
1417            if (obBasketProps)
1418            {
1419                propCollection = obBasketProps.getElementsByTagName('select');
1420                if (propCollection && propCollection.length)
1421                {
1422                    for (i = 0; i < propCollection.length; i++)
1423                    {
1424                        if (!propCollection[i].disabled)
1425                        {
1426                            switch (propCollection[i].type.toLowerCase())
1427                            {
1428                                case 'select-one':
1429                                    this.basketParams[propCollection[i].name] = propCollection[i].value;
1430                                    foundValues = true;
1431                                    break;
1432                                default:
1433                                    break;
1434                            }
1435                        }
1436                    }
1437                }
1438                propCollection = obBasketProps.getElementsByTagName('input');
1439                if (propCollection && propCollection.length)
1440                {
1441                    for (i = 0; i < propCollection.length; i++)
1442                    {
1443                        if (!propCollection[i].disabled)
1444                        {
1445                            switch (propCollection[i].type.toLowerCase())
1446                            {
1447                                case 'hidden':
1448                                    this.basketParams[propCollection[i].name] = propCollection[i].value;
1449                                    foundValues = true;
1450                                    break;
1451                                case 'radio':
1452                                    if (propCollection[i].checked)
1453                                    {
1454                                        this.basketParams[propCollection[i].name] = propCollection[i].value;
1455                                        foundValues = true;
1456                                    }
1457                                    break;
1458                                default:
1459                                    break;
1460                            }
1461                        }
1462                    }
1463                }
1464            }
1465            if (!foundValues)
1466            {
1467                this.basketParams[this.basketData.props] = [];
1468                this.basketParams[this.basketData.props][0] = 0;
1469            }
1470        },
1471
1472        add2Basket: function ()
1473        {
1474            this.basketMode = 'ADD';
1475            this.basket();
1476        },
1477
1478        buyBasket: function ()
1479        {
1480            this.basketMode = 'BUY';
1481            this.basket();
1482        },
1483
1484        sendToBasket: function ()
1485        {
1486            if (!this.canBuy)
1487            {
1488                return;
1489            }
1490
1491            // check recommendation
1492            if (this.product && this.product.id && this.bigData)
1493            {
1494                this.rememberProductRecommendation();
1495            }
1496
1497            this.initBasketUrl();
1498            this.fillBasketProps();
1499            BX.ajax({
1500                method: 'POST',
1501                dataType: 'json',
1502                url: this.basketUrl,
1503                data: this.basketParams,
1504                onsuccess: BX.proxy(this.basketResult, this)
1505            });
1506        },
1507
1508        basket: function ()
1509        {
1510            var contentBasketProps = '';
1511            if (!this.canBuy)
1512            {
1513                return;
1514            }
1515            switch (this.productType)
1516            {
1517                case 1: // product
1518                case 2: // set
1519                    if (this.basketData.useProps && !this.basketData.emptyProps)
1520                    {
1521                        this.initPopupWindow();
1522                        this.obPopupWin.setTitleBar(BX.message('TITLE_BASKET_PROPS'));
1523                        if (BX(this.visual.BASKET_PROP_DIV))
1524                        {
1525                            contentBasketProps = BX(this.visual.BASKET_PROP_DIV).innerHTML;
1526                        }
1527                        this.obPopupWin.setContent(contentBasketProps);
1528                        this.obPopupWin.setButtons([
1529                            new BasketButton({
1530                                text: BX.message('BTN_MESSAGE_SEND_PROPS'),
1531                                events: {
1532                                    click: BX.delegate(this.sendToBasket, this)
1533                                }
1534                            })
1535                        ]);
1536                        this.obPopupWin.show();
1537                    } else
1538                    {
1539                        this.sendToBasket();
1540                    }
1541                    break;
1542                case 3: // sku
1543                    this.sendToBasket();
1544                    break;
1545            }
1546        },
1547
1548        basketResult: function (arResult)
1549        {
1550            var strContent = '',
1551                    strPict = '',
1552                    successful,
1553                    buttons = [];
1554
1555
1556            if (!BX.type.isPlainObject(arResult))
1557                return;
1558
1559            successful = arResult.STATUS === 'OK';
1560
1561            if (successful)
1562            {
1563                this.setAnalyticsDataLayer('addToCart');
1564            }
1565
1566            if (successful && this.basketAction === 'BUY')
1567            {
1568                this.basketRedirect();
1569            } else
1570            {
1571                
1572                if (successful)
1573                {
1574                    BX.onCustomEvent('OnBasketChange');
1575
1576                    if (BX.findParent(this.obProduct, {className: 'bx_sale_gift_main_products'}, 10))
1577                    {
1578                        BX.onCustomEvent('onAddToBasketMainProduct', [this]);
1579                    }
1580
1581                    
1582                    if (!!window.Alpha.Messages && typeof (window.Alpha.Messages) == 'function')
1583                    {
1584                        new window.Alpha.Messages({
1585                            type: 'addToBasket',
1586                            title: BX.message('TITLE_SUCCESSFUL'),
1587                            message: this.product.name,
1588                            image: this.product.picture,
1589                            url: this.basketData.basketUrl,
1590                            urlText: 'BASKET'
1591                        });
1592                    }
1593                    if (this.obBuyBtn.getAttribute('data-mobile') == 'mobile')
1594                        BX.addClass(this.obBuyBtn, 'not-empty');
1595
1596                    
1597                } else
1598                {
1599                    if (!!window.Alpha.Messages && typeof (window.Alpha.Messages) == 'function')
1600                    {
1601                        new window.Alpha.Messages({
1602                            type: 'error',
1603                            title: BX.message('TITLE_ERROR'),
1604                            message: (arResult.MESSAGE ? arResult.MESSAGE : BX.message('BASKET_UNKNOWN_ERROR')),
1605                        });
1606                    }
1607                }
1608                
1609            }
1610        },
1611
1612        basketRedirect: function ()
1613        {
1614            location.href = (this.basketData.basketUrl ? this.basketData.basketUrl : BX.message('BASKET_URL'));
1615        },
1616
1617        initPopupWindow: function ()
1618        {
1619            if (this.obPopupWin)
1620                return;
1621
1622            this.obPopupWin = BX.PopupWindowManager.create('CatalogSectionBasket_' + this.visual.ID, null, {
1623                autoHide: true,
1624                offsetLeft: 0,
1625                offsetTop: 0,
1626                overlay: true,
1627                closeByEsc: true,
1628                titleBar: true,
1629                closeIcon: true,
1630                contentColor: 'white',
1631                className: this.templateTheme ? 'bx-' + this.templateTheme : ''
1632            });
1633        }
1634
1635    };
1636    
1637    //********
1638    //** catalog.item list view mode
1639    //********
1640    
1641    if (window.Alpha.CatalogListItem)
1642		return;
1643
1644	var BasketButton = function(params)
1645	{
1646		BasketButton.superclass.constructor.apply(this, arguments);
1647		this.buttonNode = BX.create('button', {
1648			props: {className: 'btn btn-primary btn-buy btn-sm', id: this.id},
1649			style: typeof params.style === 'object' ? params.style : {},
1650			text: params.text,
1651			events: this.contextEvents
1652		});
1653
1654		if (BX.browser.IsIE())
1655		{
1656			this.buttonNode.setAttribute("hideFocus", "hidefocus");
1657		}
1658	};
1659	BX.extend(BasketButton, BX.PopupWindowButton);
1660
1661	window.Alpha.CatalogListItem = function (arParams)
1662	{
1663		this.productType = 0;
1664		this.showQuantity = true;
1665		this.showAbsent = true;
1666		this.secondPict = false;
1667		this.showOldPrice = false;
1668		this.showMaxQuantity = 'N';
1669		this.relativeQuantityFactor = 5;
1670		this.showPercent = false;
1671		this.showSkuProps = false;
1672		this.basketAction = 'ADD';
1673		this.showClosePopup = false;
1674		this.useCompare = false;
1675		this.showSubscription = false;
1676		this.visual = {
1677			ID: '',
1678			PICT_ID: '',
1679			SECOND_PICT_ID: '',
1680			PICT_SLIDER_ID: '',
1681			QUANTITY_ID: '',
1682			QUANTITY_UP_ID: '',
1683			QUANTITY_DOWN_ID: '',
1684			PRICE_ID: '',
1685			PRICE_OLD_ID: '',
1686			DSC_PERC: '',
1687			SECOND_DSC_PERC: '',
1688			DISPLAY_PROP_DIV: '',
1689			BASKET_PROP_DIV: '',
1690			SUBSCRIBE_ID: '',
1691            ITEM_CODE_ID: '',
1692            WISHLIST_ID: ''
1693		};
1694		this.product = {
1695			checkQuantity: false,
1696			maxQuantity: 0,
1697			stepQuantity: 1,
1698			isDblQuantity: false,
1699			canBuy: true,
1700			name: '',
1701			pict: {},
1702			id: 0,
1703			addUrl: '',
1704			buyUrl: ''
1705		};
1706
1707		this.basketMode = '';
1708		this.basketData = {
1709			useProps: false,
1710			emptyProps: false,
1711			quantity: 'quantity',
1712			props: 'prop',
1713			basketUrl: '',
1714			sku_props: '',
1715			sku_props_var: 'basket_props',
1716			add_url: '',
1717			buy_url: '',
1718            wishlist_url: '',
1719            wishlist_page_url: BX.message('SITE_DIR') + 'wishlist/',
1720            add_wish_to_delayed: false
1721		};
1722
1723		this.compareData = {
1724			compareUrl: '',
1725			compareDeleteUrl: '',
1726			comparePath: ''
1727		};
1728
1729		this.defaultPict = {
1730			pict: null,
1731			secondPict: null
1732		};
1733
1734		this.defaultSliderOptions = {
1735			interval: 3000,
1736			wrap: true
1737		};
1738		this.slider = {
1739			options: {},
1740			items: [],
1741			active: null,
1742			sliding: null,
1743			paused: null,
1744			interval: null,
1745			progress: null
1746		};
1747		this.touch = null;
1748
1749		this.quantityDelay = null;
1750		this.quantityTimer = null;
1751
1752		this.checkQuantity = false;
1753		this.maxQuantity = 0;
1754		this.minQuantity = 0;
1755		this.stepQuantity = 1;
1756		this.isDblQuantity = false;
1757		this.canBuy = true;
1758		this.precision = 6;
1759		this.precisionFactor = Math.pow(10, this.precision);
1760		this.bigData = false;
1761		this.fullDisplayMode = false;
1762		this.viewMode = '';
1763		this.templateTheme = '';
1764
1765		this.currentPriceMode = '';
1766		this.currentPrices = [];
1767		this.currentPriceSelected = 0;
1768		this.currentQuantityRanges = [];
1769		this.currentQuantityRangeSelected = 0;
1770
1771		this.offers = [];
1772		this.offerNum = 0;
1773		this.treeProps = [];
1774		this.selectedValues = {};
1775
1776		this.obProduct = null;
1777		this.blockNodes = {};
1778		this.obQuantity = null;
1779		this.obQuantityUp = null;
1780		this.obQuantityDown = null;
1781		this.obQuantityLimit = {};
1782		this.obPict = null;
1783		this.obSecondPict = null;
1784		this.obPictSlider = null;
1785		this.obPictSliderIndicator = null;
1786		this.obPrice = null;
1787		this.obTree = null;
1788		this.obBuyBtn = null;
1789		this.obBasketActions = null;
1790		this.obNotAvail = null;
1791		this.obSubscribe = null;
1792		this.obDscPerc = null;
1793		this.obSecondDscPerc = null;
1794		this.obSkuProps = null;
1795		this.obMeasure = null;
1796		this.obCompare = null;
1797                this.obWishlist = null;
1798
1799		this.obPopupWin = null;
1800		this.basketUrl = '';
1801		this.basketParams = {};
1802		this.isTouchDevice = BX.hasClass(document.documentElement, 'bx-touch');
1803		this.hoverTimer = null;
1804		this.hoverStateChangeForbidden = false;
1805		this.mouseX = null;
1806		this.mouseY = null;
1807
1808		this.useEnhancedEcommerce = false;
1809		this.dataLayerName = 'dataLayer';
1810		this.brandProperty = false;
1811
1812		this.errorCode = 0;
1813
1814		if (typeof arParams === 'object')
1815		{
1816			if (arParams.PRODUCT_TYPE)
1817			{
1818				this.productType = parseInt(arParams.PRODUCT_TYPE, 10);
1819			}
1820
1821			this.showQuantity = arParams.SHOW_QUANTITY;
1822			this.showAbsent = arParams.SHOW_ABSENT;
1823			this.secondPict = arParams.SECOND_PICT;
1824			this.showOldPrice = arParams.SHOW_OLD_PRICE;
1825			this.showMaxQuantity = arParams.SHOW_MAX_QUANTITY;
1826			this.relativeQuantityFactor = parseInt(arParams.RELATIVE_QUANTITY_FACTOR);
1827			this.showPercent = arParams.SHOW_DISCOUNT_PERCENT;
1828			this.showSkuProps = arParams.SHOW_SKU_PROPS;
1829			this.showSubscription = arParams.USE_SUBSCRIBE;
1830
1831			if (arParams.ADD_TO_BASKET_ACTION)
1832			{
1833				this.basketAction = arParams.ADD_TO_BASKET_ACTION;
1834			}
1835
1836			this.showClosePopup = arParams.SHOW_CLOSE_POPUP;
1837			this.useCompare = arParams.DISPLAY_COMPARE;
1838			this.fullDisplayMode = arParams.PRODUCT_DISPLAY_MODE === 'Y';
1839			this.bigData = arParams.BIG_DATA;
1840			this.viewMode = arParams.VIEW_MODE || '';
1841			this.templateTheme = arParams.TEMPLATE_THEME || '';
1842			this.useEnhancedEcommerce = arParams.USE_ENHANCED_ECOMMERCE === 'Y';
1843			this.dataLayerName = arParams.DATA_LAYER_NAME;
1844			this.brandProperty = arParams.BRAND_PROPERTY;
1845
1846			this.visual = arParams.VISUAL;
1847
1848			switch (this.productType)
1849			{
1850				case 0: // no catalog
1851				case 1: // product
1852				case 2: // set
1853					if (arParams.PRODUCT && typeof arParams.PRODUCT === 'object')
1854					{
1855						this.currentPriceMode = arParams.PRODUCT.ITEM_PRICE_MODE;
1856						this.currentPrices = arParams.PRODUCT.ITEM_PRICES;
1857						this.currentPriceSelected = arParams.PRODUCT.ITEM_PRICE_SELECTED;
1858						this.currentQuantityRanges = arParams.PRODUCT.ITEM_QUANTITY_RANGES;
1859						this.currentQuantityRangeSelected = arParams.PRODUCT.ITEM_QUANTITY_RANGE_SELECTED;
1860
1861						if (this.showQuantity)
1862						{
1863							this.product.checkQuantity = arParams.PRODUCT.CHECK_QUANTITY;
1864							this.product.isDblQuantity = arParams.PRODUCT.QUANTITY_FLOAT;
1865
1866							if (this.product.checkQuantity)
1867							{
1868								this.product.maxQuantity = (this.product.isDblQuantity ? parseFloat(arParams.PRODUCT.MAX_QUANTITY) : parseInt(arParams.PRODUCT.MAX_QUANTITY, 10));
1869							}
1870
1871							this.product.stepQuantity = (this.product.isDblQuantity ? parseFloat(arParams.PRODUCT.STEP_QUANTITY) : parseInt(arParams.PRODUCT.STEP_QUANTITY, 10));
1872
1873							this.checkQuantity = this.product.checkQuantity;
1874							this.isDblQuantity = this.product.isDblQuantity;
1875							this.stepQuantity = this.product.stepQuantity;
1876							this.maxQuantity = this.product.maxQuantity;
1877							this.minQuantity = this.currentPriceMode === 'Q'
1878								? parseFloat(this.currentPrices[this.currentPriceSelected].MIN_QUANTITY)
1879								: this.stepQuantity;
1880
1881							if (this.isDblQuantity)
1882							{
1883								this.stepQuantity = Math.round(this.stepQuantity * this.precisionFactor) / this.precisionFactor;
1884							}
1885						}
1886
1887						this.product.canBuy = arParams.PRODUCT.CAN_BUY;
1888
1889						if (arParams.PRODUCT.MORE_PHOTO_COUNT)
1890						{
1891							this.product.morePhotoCount = arParams.PRODUCT.MORE_PHOTO_COUNT;
1892							this.product.morePhoto = arParams.PRODUCT.MORE_PHOTO;
1893						}
1894
1895						if (arParams.PRODUCT.RCM_ID)
1896						{
1897							this.product.rcmId = arParams.PRODUCT.RCM_ID;
1898						}
1899
1900						this.canBuy = this.product.canBuy;
1901						this.product.name = arParams.PRODUCT.NAME;
1902						this.product.pict = arParams.PRODUCT.PICT;
1903						this.product.id = arParams.PRODUCT.ID;
1904						this.product.DETAIL_PAGE_URL = arParams.PRODUCT.DETAIL_PAGE_URL;
1905
1906						if (arParams.PRODUCT.ADD_URL)
1907						{
1908							this.product.addUrl = arParams.PRODUCT.ADD_URL;
1909						}
1910
1911						if (arParams.PRODUCT.BUY_URL)
1912						{
1913							this.product.buyUrl = arParams.PRODUCT.BUY_URL;
1914						}
1915                                                
1916						if (arParams.BASKET && typeof arParams.BASKET === 'object')
1917						{
1918							this.basketData.useProps = arParams.BASKET.ADD_PROPS;
1919							this.basketData.emptyProps = arParams.BASKET.EMPTY_PROPS;
1920						}
1921					}
1922					else
1923					{
1924						this.errorCode = -1;
1925					}
1926
1927					break;
1928				case 3: // sku
1929					if (arParams.PRODUCT && typeof arParams.PRODUCT === 'object')
1930					{
1931						this.product.name = arParams.PRODUCT.NAME;
1932						this.product.id = arParams.PRODUCT.ID;
1933						this.product.DETAIL_PAGE_URL = arParams.PRODUCT.DETAIL_PAGE_URL;
1934						this.product.morePhotoCount = arParams.PRODUCT.MORE_PHOTO_COUNT;
1935						this.product.morePhoto = arParams.PRODUCT.MORE_PHOTO;
1936
1937						if (arParams.PRODUCT.RCM_ID)
1938						{
1939							this.product.rcmId = arParams.PRODUCT.RCM_ID;
1940						}
1941					}
1942
1943					if (arParams.OFFERS && BX.type.isArray(arParams.OFFERS))
1944					{
1945						this.offers = arParams.OFFERS;
1946						this.offerNum = 0;
1947
1948						if (arParams.OFFER_SELECTED)
1949						{
1950							this.offerNum = parseInt(arParams.OFFER_SELECTED, 10);
1951						}
1952
1953						if (isNaN(this.offerNum))
1954						{
1955							this.offerNum = 0;
1956						}
1957
1958						if (arParams.TREE_PROPS)
1959						{
1960							this.treeProps = arParams.TREE_PROPS;
1961						}
1962
1963						if (arParams.DEFAULT_PICTURE)
1964						{
1965							this.defaultPict.pict = arParams.DEFAULT_PICTURE.PICTURE;
1966							this.defaultPict.secondPict = arParams.DEFAULT_PICTURE.PICTURE_SECOND;
1967						}
1968					}
1969
1970					break;
1971				default:
1972					this.errorCode = -1;
1973			}
1974                        
1975                        
1976                        
1977			if (arParams.BASKET && typeof arParams.BASKET === 'object')
1978			{
1979				if (arParams.BASKET.QUANTITY)
1980				{
1981					this.basketData.quantity = arParams.BASKET.QUANTITY;
1982				}
1983
1984				if (arParams.BASKET.PROPS)
1985				{
1986					this.basketData.props = arParams.BASKET.PROPS;
1987				}
1988
1989				if (arParams.BASKET.BASKET_URL)
1990				{
1991					this.basketData.basketUrl = arParams.BASKET.BASKET_URL;
1992				}
1993
1994				if (3 === this.productType)
1995				{
1996					if (arParams.BASKET.SKU_PROPS)
1997					{
1998						this.basketData.sku_props = arParams.BASKET.SKU_PROPS;
1999					}
2000				}
2001
2002				if (arParams.BASKET.ADD_URL_TEMPLATE)
2003				{
2004					this.basketData.add_url = arParams.BASKET.ADD_URL_TEMPLATE;
2005				}
2006
2007				if (arParams.BASKET.BUY_URL_TEMPLATE)
2008				{
2009					this.basketData.buy_url = arParams.BASKET.BUY_URL_TEMPLATE;
2010				}
2011                                
2012                if (arParams.BASKET.WISHLIST_URL_TEMPLATE)
2013                {
2014                    this.basketData.wishlist_url = arParams.BASKET.WISHLIST_URL_TEMPLATE;
2015                    if (arParams.BASKET.WISHLIST_PAGE_URL && arParams.BASKET.WISHLIST_PAGE_URL.length > 0)
2016                        this.basketData.wishlist_page_url = arParams.BASKET.WISHLIST_PAGE_URL;
2017                    if (arParams.BASKET.ADD_WISH_TO_DELAYED === "Y")
2018                        this.basketData.add_wish_to_delayed = true;
2019                }
2020
2021				if (this.basketData.add_url === '' && this.basketData.buy_url === '')
2022				{
2023					this.errorCode = -1024;
2024				}
2025			}
2026
2027			if (this.useCompare)
2028			{
2029				if (arParams.COMPARE && typeof arParams.COMPARE === 'object')
2030				{
2031					if (arParams.COMPARE.COMPARE_PATH)
2032					{
2033						this.compareData.comparePath = arParams.COMPARE.COMPARE_PATH;
2034					}
2035
2036					if (arParams.COMPARE.COMPARE_URL_TEMPLATE)
2037					{
2038						this.compareData.compareUrl = arParams.COMPARE.COMPARE_URL_TEMPLATE;
2039					}
2040					else
2041					{
2042						this.useCompare = false;
2043					}
2044
2045					if (arParams.COMPARE.COMPARE_DELETE_URL_TEMPLATE)
2046					{
2047						this.compareData.compareDeleteUrl = arParams.COMPARE.COMPARE_DELETE_URL_TEMPLATE;
2048					}
2049					else
2050					{
2051						this.useCompare = false;
2052					}
2053				}
2054				else
2055				{
2056					this.useCompare = false;
2057				}
2058			}
2059		}
2060                
2061                
2062
2063		if (this.errorCode === 0)
2064		{
2065			BX.ready(BX.delegate(this.init,this));
2066		}
2067	};
2068
2069	window.Alpha.CatalogListItem.prototype = {
2070		init: function()
2071		{
2072			var i = 0,
2073				treeItems = null;
2074
2075			this.obProduct = BX(this.visual.ID);
2076			if (!this.obProduct)
2077			{
2078				this.errorCode = -1;
2079			}
2080
2081			this.obPrice = BX(this.visual.PRICE_ID);
2082			this.obPriceOld = BX(this.visual.PRICE_OLD_ID);
2083			this.obPriceTotal = BX(this.visual.PRICE_TOTAL_ID);
2084			if (!this.obPrice)
2085			{
2086				this.errorCode = -16;
2087			}
2088                        
2089                        
2090                        
2091                        this.obPictSlider = BX(this.visual.PICT_SLIDER_ID);
2092
2093			if (this.showQuantity && this.visual.QUANTITY_ID)
2094			{
2095				this.obQuantity = BX(this.visual.QUANTITY_ID);
2096				this.blockNodes.quantity = this.obProduct.querySelector('[data-entity="quantity-block"]');
2097
2098				if (!this.isTouchDevice)
2099				{
2100					BX.bind(this.obQuantity, 'focus', BX.proxy(this.onFocus, this));
2101					BX.bind(this.obQuantity, 'blur', BX.proxy(this.onBlur, this));
2102				}
2103
2104				if (this.visual.QUANTITY_UP_ID)
2105				{
2106					this.obQuantityUp = BX(this.visual.QUANTITY_UP_ID);
2107				}
2108
2109				if (this.visual.QUANTITY_DOWN_ID)
2110				{
2111					this.obQuantityDown = BX(this.visual.QUANTITY_DOWN_ID);
2112				}
2113			}
2114
2115			if (this.visual.QUANTITY_LIMIT && this.showMaxQuantity !== 'N')
2116			{
2117				this.obQuantityLimit.all = BX(this.visual.QUANTITY_LIMIT);
2118				if (this.obQuantityLimit.all)
2119				{
2120					this.obQuantityLimit.value = this.obQuantityLimit.all.querySelector('[data-entity="quantity-limit-value"]');
2121					if (!this.obQuantityLimit.value)
2122					{
2123						this.obQuantityLimit.all = null;
2124					}
2125				}
2126			}
2127
2128			if (this.productType === 3 && this.fullDisplayMode)
2129			{
2130				if (this.visual.TREE_ID)
2131				{
2132					this.obTree = BX(this.visual.TREE_ID);
2133					if (!this.obTree)
2134					{
2135						this.errorCode = -256;
2136					}
2137				}
2138
2139				if (this.visual.QUANTITY_MEASURE)
2140				{
2141					this.obMeasure = BX(this.visual.QUANTITY_MEASURE);
2142				}
2143			}
2144
2145			this.obBasketActions = BX(this.visual.BASKET_ACTIONS_ID);
2146			if (this.obBasketActions)
2147			{
2148				if (this.visual.BUY_ID)
2149				{
2150					this.obBuyBtn = BX(this.visual.BUY_ID);
2151				}
2152			}
2153
2154			this.obNotAvail = BX(this.visual.NOT_AVAILABLE_MESS);
2155
2156			if (this.showSubscription)
2157			{
2158				this.obSubscribe = BX(this.visual.SUBSCRIBE_ID);
2159			}
2160                        
2161                        if (!!this.visual.WISHLIST_ID && BX(this.visual.WISHLIST_ID))
2162                        {
2163                            this.obWishlist = BX(this.visual.WISHLIST_ID);
2164                        }
2165                        
2166                        if (this.obWishlist)
2167                        {
2168                            BX.bind(this.obWishlist, 'click', BX.delegate(this.wishlistChange, this));
2169                        }
2170
2171			if (this.showPercent)
2172			{
2173				if (this.visual.DSC_PERC)
2174				{
2175					this.obDscPerc = BX(this.visual.DSC_PERC);
2176				}
2177				if (this.secondPict && this.visual.SECOND_DSC_PERC)
2178				{
2179					this.obSecondDscPerc = BX(this.visual.SECOND_DSC_PERC);
2180				}
2181			}
2182
2183			if (this.showSkuProps)
2184			{
2185				if (this.visual.DISPLAY_PROP_DIV)
2186				{
2187					this.obSkuProps = BX(this.visual.DISPLAY_PROP_DIV);
2188				}
2189			}
2190                        
2191			if (this.errorCode === 0)
2192			{
2193				
2194
2195				if (this.bigData)
2196				{
2197					var links = BX.findChildren(this.obProduct, {tag:'a'}, true);
2198					if (links)
2199					{
2200						for (i in links)
2201						{
2202							if (links.hasOwnProperty(i))
2203							{
2204								if (links[i].getAttribute('href') == this.product.DETAIL_PAGE_URL)
2205								{
2206									BX.bind(links[i], 'click', BX.proxy(this.rememberProductRecommendation, this));
2207								}
2208							}
2209						}
2210					}
2211				}
2212
2213				if (this.showQuantity)
2214				{
2215					var startEventName = this.isTouchDevice ? 'touchstart' : 'mousedown';
2216					var endEventName = this.isTouchDevice ? 'touchend' : 'mouseup';
2217
2218					if (this.obQuantityUp)
2219					{
2220						BX.bind(this.obQuantityUp, startEventName, BX.proxy(this.startQuantityInterval, this));
2221						BX.bind(this.obQuantityUp, endEventName, BX.proxy(this.clearQuantityInterval, this));
2222						BX.bind(this.obQuantityUp, 'mouseout', BX.proxy(this.clearQuantityInterval, this));
2223						BX.bind(this.obQuantityUp, 'click', BX.delegate(this.quantityUp, this));
2224					}
2225
2226					if (this.obQuantityDown)
2227					{
2228						BX.bind(this.obQuantityDown, startEventName, BX.proxy(this.startQuantityInterval, this));
2229						BX.bind(this.obQuantityDown, endEventName, BX.proxy(this.clearQuantityInterval, this));
2230						BX.bind(this.obQuantityDown, 'mouseout', BX.proxy(this.clearQuantityInterval, this));
2231						BX.bind(this.obQuantityDown, 'click', BX.delegate(this.quantityDown, this));
2232					}
2233
2234					if (this.obQuantity)
2235					{
2236						BX.bind(this.obQuantity, 'change', BX.delegate(this.quantityChange, this));
2237					}
2238				}
2239
2240				switch (this.productType)
2241				{
2242					case 0: // no catalog
2243					case 1: // product
2244					case 2: // set
2245						
2246                                                this.initializeSlider();
2247						this.checkQuantityControls();
2248
2249						break;
2250					case 3: // sku
2251						if (this.offers.length > 0)
2252						{
2253							treeItems = BX.findChildren(this.obTree, {tagName: 'a'}, true);
2254                                                        
2255							if (treeItems && treeItems.length)
2256							{
2257								for (i = 0; i < treeItems.length; i++)
2258								{
2259									BX.bind(treeItems[i], 'click', BX.delegate(this.selectOfferProp, this));
2260								}
2261							}
2262
2263							this.setCurrent();
2264						}
2265						else
2266						{
2267							this.initializeSlider();
2268						}
2269
2270						break;
2271				}
2272
2273				if (this.obBuyBtn)
2274				{
2275					if (this.basketAction === 'ADD')
2276					{
2277						BX.bind(this.obBuyBtn, 'click', BX.proxy(this.add2Basket, this));
2278					}
2279					else
2280					{
2281						BX.bind(this.obBuyBtn, 'click', BX.proxy(this.buyBasket, this));
2282					}
2283				}
2284
2285				if (this.useCompare)
2286				{
2287					this.obCompare = BX(this.visual.COMPARE_LINK_ID);
2288					if (this.obCompare)
2289					{
2290						BX.bind(this.obCompare, 'click', BX.proxy(this.compare, this));
2291					}
2292
2293					BX.addCustomEvent('onCatalogDeleteCompare', BX.proxy(this.checkDeletedCompare, this));
2294				}
2295			}
2296		},
2297
2298		setAnalyticsDataLayer: function(action)
2299		{
2300			if (!this.useEnhancedEcommerce || !this.dataLayerName)
2301				return;
2302
2303			var item = {},
2304				info = {},
2305				variants = [],
2306				i, k, j, propId, skuId, propValues;
2307
2308			switch (this.productType)
2309			{
2310				case 0: //no catalog
2311				case 1: //product
2312				case 2: //set
2313					item = {
2314						'id': this.product.id,
2315						'name': this.product.name,
2316						'price': this.currentPrices[this.currentPriceSelected] && this.currentPrices[this.currentPriceSelected].PRICE,
2317						'brand': BX.type.isArray(this.brandProperty) ? this.brandProperty.join('/') : this.brandProperty
2318					};
2319					break;
2320				case 3: //sku
2321					for (i in this.offers[this.offerNum].TREE)
2322					{
2323						if (this.offers[this.offerNum].TREE.hasOwnProperty(i))
2324						{
2325							propId = i.substring(5);
2326							skuId = this.offers[this.offerNum].TREE[i];
2327
2328							for (k in this.treeProps)
2329							{
2330								if (this.treeProps.hasOwnProperty(k) && this.treeProps[k].ID == propId)
2331								{
2332									for (j in this.treeProps[k].VALUES)
2333									{
2334										propValues = this.treeProps[k].VALUES[j];
2335										if (propValues.ID == skuId)
2336										{
2337											variants.push(propValues.NAME);
2338											break;
2339										}
2340									}
2341
2342								}
2343							}
2344						}
2345					}
2346
2347					item = {
2348						'id': this.offers[this.offerNum].ID,
2349						'name': this.offers[this.offerNum].NAME,
2350						'price': this.currentPrices[this.currentPriceSelected] && this.currentPrices[this.currentPriceSelected].PRICE,
2351						'brand': BX.type.isArray(this.brandProperty) ? this.brandProperty.join('/') : this.brandProperty,
2352						'variant': variants.join('/')
2353					};
2354					break;
2355			}
2356
2357			switch (action)
2358			{
2359				case 'addToCart':
2360					info = {
2361						'event': 'addToCart',
2362						'ecommerce': {
2363							'currencyCode': this.currentPrices[this.currentPriceSelected] && this.currentPrices[this.currentPriceSelected].CURRENCY || '',
2364							'add': {
2365								'products': [{
2366									'name': item.name || '',
2367									'id': item.id || '',
2368									'price': item.price || 0,
2369									'brand': item.brand || '',
2370									'category': item.category || '',
2371									'variant': item.variant || '',
2372									'quantity': this.showQuantity && this.obQuantity ? this.obQuantity.value : 1
2373								}]
2374							}
2375						}
2376					};
2377					break;
2378			}
2379
2380			window[this.dataLayerName] = window[this.dataLayerName] || [];
2381			window[this.dataLayerName].push(info);
2382		},
2383
2384		
2385		getCookie: function(name)
2386		{
2387			var matches = document.cookie.match(new RegExp(
2388				"(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
2389			));
2390
2391			return matches ? decodeURIComponent(matches[1]) : null;
2392		},
2393
2394		rememberProductRecommendation: function()
2395		{
2396			// save to RCM_PRODUCT_LOG
2397			var cookieName = BX.cookie_prefix + '_RCM_PRODUCT_LOG',
2398				cookie = this.getCookie(cookieName),
2399				itemFound = false;
2400
2401			var cItems = [],
2402				cItem;
2403
2404			if (cookie)
2405			{
2406				cItems = cookie.split('.');
2407			}
2408
2409			var i = cItems.length;
2410
2411			while (i--)
2412			{
2413				cItem = cItems[i].split('-');
2414
2415				if (cItem[0] == this.product.id)
2416				{
2417					// it's already in recommendations, update the date
2418					cItem = cItems[i].split('-');
2419
2420					// update rcmId and date
2421					cItem[1] = this.product.rcmId;
2422					cItem[2] = BX.current_server_time;
2423
2424					cItems[i] = cItem.join('-');
2425					itemFound = true;
2426				}
2427				else
2428				{
2429					if ((BX.current_server_time - cItem[2]) > 3600 * 24 * 30)
2430					{
2431						cItems.splice(i, 1);
2432					}
2433				}
2434			}
2435
2436			if (!itemFound)
2437			{
2438				// add recommendation
2439				cItems.push([this.product.id, this.product.rcmId, BX.current_server_time].join('-'));
2440			}
2441
2442			// serialize
2443			var plNewCookie = cItems.join('.'),
2444				cookieDate = new Date(new Date().getTime() + 1000 * 3600 * 24 * 365 * 10).toUTCString();
2445
2446			document.cookie = cookieName + "=" + plNewCookie + "; path=/; expires=" + cookieDate + "; domain=" + BX.cookie_domain;
2447		},
2448
2449		startQuantityInterval: function()
2450		{
2451			var target = BX.proxy_context;
2452			var func = target.id === this.visual.QUANTITY_DOWN_ID
2453				? BX.proxy(this.quantityDown, this)
2454				: BX.proxy(this.quantityUp, this);
2455
2456			this.quantityDelay = setTimeout(
2457				BX.delegate(function() {
2458					this.quantityTimer = setInterval(func, 150);
2459				}, this),
2460				300
2461			);
2462		},
2463
2464		clearQuantityInterval: function()
2465		{
2466			clearTimeout(this.quantityDelay);
2467			clearInterval(this.quantityTimer);
2468		},
2469
2470		quantityUp: function()
2471		{
2472			var curValue = 0,
2473				boolSet = true;
2474
2475			if (this.errorCode === 0 && this.showQuantity && this.canBuy)
2476			{
2477				curValue = (this.isDblQuantity ? parseFloat(this.obQuantity.value) : parseInt(this.obQuantity.value, 10));
2478				if (!isNaN(curValue))
2479				{
2480					curValue += this.stepQuantity;
2481					if (this.checkQuantity)
2482					{
2483						if (curValue > this.maxQuantity)
2484						{
2485							boolSet = false;
2486						}
2487					}
2488
2489					if (boolSet)
2490					{
2491						if (this.isDblQuantity)
2492						{
2493							curValue = Math.round(curValue * this.precisionFactor) / this.precisionFactor;
2494						}
2495
2496						this.obQuantity.value = curValue;
2497
2498						this.setPrice();
2499					}
2500				}
2501			}
2502		},
2503
2504		quantityDown: function()
2505		{
2506			var curValue = 0,
2507				boolSet = true;
2508
2509			if (this.errorCode === 0 && this.showQuantity && this.canBuy)
2510			{
2511				curValue = (this.isDblQuantity ? parseFloat(this.obQuantity.value) : parseInt(this.obQuantity.value, 10));
2512				if (!isNaN(curValue))
2513				{
2514					curValue -= this.stepQuantity;
2515
2516					this.checkPriceRange(curValue);
2517
2518					if (curValue < this.minQuantity)
2519					{
2520						boolSet = false;
2521					}
2522
2523					if (boolSet)
2524					{
2525						if (this.isDblQuantity)
2526						{
2527							curValue = Math.round(curValue * this.precisionFactor) / this.precisionFactor;
2528						}
2529
2530						this.obQuantity.value = curValue;
2531
2532						this.setPrice();
2533					}
2534				}
2535			}
2536		},
2537
2538		quantityChange: function()
2539		{
2540			var curValue = 0,
2541				intCount;
2542
2543			if (this.errorCode === 0 && this.showQuantity)
2544			{
2545				if (this.canBuy)
2546				{
2547					curValue = this.isDblQuantity ? parseFloat(this.obQuantity.value) : Math.round(this.obQuantity.value);
2548					if (!isNaN(curValue))
2549					{
2550						if (this.checkQuantity)
2551						{
2552							if (curValue > this.maxQuantity)
2553							{
2554								curValue = this.maxQuantity;
2555							}
2556						}
2557
2558						this.checkPriceRange(curValue);
2559
2560						intCount = Math.floor(
2561							Math.round(curValue * this.precisionFactor / this.stepQuantity) / this.precisionFactor
2562						) || 1;
2563						curValue = (intCount <= 1 ? this.stepQuantity : intCount * this.stepQuantity);
2564						curValue = Math.round(curValue * this.precisionFactor) / this.precisionFactor;
2565
2566						if (curValue < this.minQuantity)
2567						{
2568							curValue = this.minQuantity;
2569						}
2570
2571						this.obQuantity.value = curValue;
2572					}
2573					else
2574					{
2575						this.obQuantity.value = this.minQuantity;
2576					}
2577				}
2578				else
2579				{
2580					this.obQuantity.value = this.minQuantity;
2581				}
2582
2583				this.setPrice();
2584			}
2585		},
2586
2587		quantitySet: function(index)
2588		{
2589			var resetQuantity, strLimit;
2590
2591			var newOffer = this.offers[index],
2592				oldOffer = this.offers[this.offerNum];
2593
2594			if (this.errorCode === 0)
2595			{
2596				this.canBuy = newOffer.CAN_BUY;
2597
2598				this.currentPriceMode = newOffer.ITEM_PRICE_MODE;
2599				this.currentPrices = newOffer.ITEM_PRICES;
2600				this.currentPriceSelected = newOffer.ITEM_PRICE_SELECTED;
2601				this.currentQuantityRanges = newOffer.ITEM_QUANTITY_RANGES;
2602				this.currentQuantityRangeSelected = newOffer.ITEM_QUANTITY_RANGE_SELECTED;
2603
2604				if (this.canBuy)
2605				{
2606					if (this.blockNodes.quantity)
2607					{
2608						BX.style(this.blockNodes.quantity, 'display', '');
2609					}
2610
2611					if (this.obBasketActions)
2612					{
2613						BX.style(this.obBasketActions, 'display', '');
2614					}
2615
2616					if (this.obNotAvail)
2617					{
2618						BX.style(this.obNotAvail, 'display', 'none');
2619					}
2620
2621					if (this.obSubscribe)
2622					{
2623						BX.style(this.obSubscribe, 'display', 'none');
2624					}
2625				}
2626				else
2627				{
2628					if (this.blockNodes.quantity)
2629					{
2630						BX.style(this.blockNodes.quantity, 'display', 'none');
2631					}
2632
2633					if (this.obBasketActions)
2634					{
2635						BX.style(this.obBasketActions, 'display', 'none');
2636					}
2637
2638					if (this.obNotAvail)
2639					{
2640						BX.style(this.obNotAvail, 'display', '');
2641					}
2642
2643					if (this.obSubscribe)
2644					{
2645						if (newOffer.CATALOG_SUBSCRIBE === 'Y')
2646						{
2647							BX.style(this.obSubscribe, 'display', '');
2648							this.obSubscribe.setAttribute('data-item', newOffer.ID);
2649							BX(this.visual.SUBSCRIBE_ID + '_hidden').click();
2650						}
2651						else
2652						{
2653							BX.style(this.obSubscribe, 'display', 'none');
2654						}
2655					}
2656				}
2657
2658				this.isDblQuantity = newOffer.QUANTITY_FLOAT;
2659				this.checkQuantity = newOffer.CHECK_QUANTITY;
2660
2661				if (this.isDblQuantity)
2662				{
2663					this.stepQuantity = Math.round(parseFloat(newOffer.STEP_QUANTITY) * this.precisionFactor) / this.precisionFactor;
2664					this.maxQuantity = parseFloat(newOffer.MAX_QUANTITY);
2665					this.minQuantity = this.currentPriceMode === 'Q' ? parseFloat(this.currentPrices[this.currentPriceSelected].MIN_QUANTITY) : this.stepQuantity;
2666				}
2667				else
2668				{
2669					this.stepQuantity = parseInt(newOffer.STEP_QUANTITY, 10);
2670					this.maxQuantity = parseInt(newOffer.MAX_QUANTITY, 10);
2671					this.minQuantity = this.currentPriceMode === 'Q' ? parseInt(this.currentPrices[this.currentPriceSelected].MIN_QUANTITY) : this.stepQuantity;
2672				}
2673
2674				if (this.showQuantity)
2675				{
2676					var isDifferentMinQuantity = oldOffer.ITEM_PRICES.length
2677						&& oldOffer.ITEM_PRICES[oldOffer.ITEM_PRICE_SELECTED]
2678						&& oldOffer.ITEM_PRICES[oldOffer.ITEM_PRICE_SELECTED].MIN_QUANTITY != this.minQuantity;
2679
2680					if (this.isDblQuantity)
2681					{
2682						resetQuantity = Math.round(parseFloat(oldOffer.STEP_QUANTITY) * this.precisionFactor) / this.precisionFactor !== this.stepQuantity
2683							|| isDifferentMinQuantity
2684							|| oldOffer.MEASURE !== newOffer.MEASURE
2685							|| (
2686								this.checkQuantity
2687								&& parseFloat(oldOffer.MAX_QUANTITY) > this.maxQuantity
2688								&& parseFloat(this.obQuantity.value) > this.maxQuantity
2689							);
2690					}
2691					else
2692					{
2693						resetQuantity = parseInt(oldOffer.STEP_QUANTITY, 10) !== this.stepQuantity
2694							|| isDifferentMinQuantity
2695							|| oldOffer.MEASURE !== newOffer.MEASURE
2696							|| (
2697								this.checkQuantity
2698								&& parseInt(oldOffer.MAX_QUANTITY, 10) > this.maxQuantity
2699								&& parseInt(this.obQuantity.value, 10) > this.maxQuantity
2700							);
2701					}
2702
2703					this.obQuantity.disabled = !this.canBuy;
2704
2705					if (resetQuantity)
2706					{
2707						this.obQuantity.value = this.minQuantity;
2708					}
2709
2710					if (this.obMeasure)
2711					{
2712						if (newOffer.MEASURE)
2713						{
2714							BX.adjust(this.obMeasure, {html: newOffer.MEASURE});
2715						}
2716						else
2717						{
2718							BX.adjust(this.obMeasure, {html: ''});
2719						}
2720					}
2721				}
2722
2723				if (this.obQuantityLimit.all)
2724				{
2725					if (!this.checkQuantity || this.maxQuantity == 0)
2726					{
2727						BX.adjust(this.obQuantityLimit.value, {html: ''});
2728						BX.adjust(this.obQuantityLimit.all, {style: {display: 'none'}});
2729					}
2730					else
2731					{
2732						if (this.showMaxQuantity === 'M')
2733						{
2734							strLimit = (this.maxQuantity / this.stepQuantity >= this.relativeQuantityFactor)
2735								? BX.message('RELATIVE_QUANTITY_MANY')
2736								: BX.message('RELATIVE_QUANTITY_FEW');
2737						}
2738						else
2739						{
2740							strLimit = this.maxQuantity;
2741
2742							if (newOffer.MEASURE)
2743							{
2744								strLimit += (' ' + newOffer.MEASURE);
2745							}
2746						}
2747
2748						BX.adjust(this.obQuantityLimit.value, {html: strLimit});
2749						BX.adjust(this.obQuantityLimit.all, {style: {display: ''}});
2750					}
2751				}
2752			}
2753		},
2754
2755		initializeSlider: function()
2756		{
2757                    
2758                    if (!!this.obPictSlider)
2759                    {
2760                        var productGalleryThumbs = new Swiper(this.obPictSlider.querySelector('.gallery-thumbs'), {
2761                            slidesPerView: 'auto',
2762                            freeMode: true,
2763                            watchSlidesVisibility: true,
2764                            watchSlidesProgress: true,
2765
2766                        });
2767
2768                        var productGalleryTop = new Swiper(this.obPictSlider.querySelector('.gallery-top'), {
2769
2770                            pagination: {
2771                                el: '.swiper-pagination',
2772                                clickable: true,
2773                            },
2774
2775                            thumbs: {
2776                                swiper: productGalleryThumbs
2777                            }
2778                        });
2779
2780                        $(this.obPictSlider).find('.swiper-container-thumbs').find('.swiper-slide').on('mouseover', function () {
2781                            productGalleryTop.slideTo($(this).index());
2782                        });
2783                    }
2784		},
2785
2786		
2787
2788		eq: function(obj, i)
2789		{
2790			var len = obj.length,
2791				j = +i + (i < 0 ? len : 0);
2792
2793			return j >= 0 && j < len ? obj[j] : {};
2794		},
2795
2796		selectOfferProp: function()
2797		{
2798			var i = 0,
2799				value = '',
2800				strTreeValue = '',
2801				arTreeItem = [],
2802				rowItems = null,
2803				target = BX.proxy_context;
2804
2805			if (target && target.hasAttribute('data-treevalue'))
2806			{
2807				if (BX.hasClass(target, 'selected'))
2808					return;
2809
2810				strTreeValue = target.getAttribute('data-treevalue');
2811				arTreeItem = strTreeValue.split('_');
2812				if (this.searchOfferPropIndex(arTreeItem[0], arTreeItem[1]))
2813				{
2814					rowItems = BX.findChildren(target.parentNode, {tagName: 'a'}, false);
2815					if (rowItems && 0 < rowItems.length)
2816					{
2817						for (i = 0; i < rowItems.length; i++)
2818						{
2819							value = rowItems[i].getAttribute('data-onevalue');
2820							if (value === arTreeItem[1])
2821							{
2822								BX.addClass(rowItems[i], 'selected');
2823							}
2824							else
2825							{
2826								BX.removeClass(rowItems[i], 'selected');
2827							}
2828						}
2829					}
2830				}
2831			}
2832		},
2833
2834		searchOfferPropIndex: function(strPropID, strPropValue)
2835		{
2836			var strName = '',
2837				arShowValues = false,
2838				i, j,
2839				arCanBuyValues = [],
2840				allValues = [],
2841				index = -1,
2842				arFilter = {},
2843				tmpFilter = [];
2844
2845			for (i = 0; i < this.treeProps.length; i++)
2846			{
2847				if (this.treeProps[i].ID === strPropID)
2848				{
2849					index = i;
2850					break;
2851				}
2852			}
2853
2854			if (-1 < index)
2855			{
2856				for (i = 0; i < index; i++)
2857				{
2858					strName = 'PROP_'+this.treeProps[i].ID;
2859					arFilter[strName] = this.selectedValues[strName];
2860				}
2861				strName = 'PROP_'+this.treeProps[index].ID;
2862				arShowValues = this.getRowValues(arFilter, strName);
2863				if (!arShowValues)
2864				{
2865					return false;
2866				}
2867				if (!BX.util.in_array(strPropValue, arShowValues))
2868				{
2869					return false;
2870				}
2871				arFilter[strName] = strPropValue;
2872				for (i = index+1; i < this.treeProps.length; i++)
2873				{
2874					strName = 'PROP_'+this.treeProps[i].ID;
2875					arShowValues = this.getRowValues(arFilter, strName);
2876					if (!arShowValues)
2877					{
2878						return false;
2879					}
2880					allValues = [];
2881					if (this.showAbsent)
2882					{
2883						arCanBuyValues = [];
2884						tmpFilter = [];
2885						tmpFilter = BX.clone(arFilter, true);
2886						for (j = 0; j < arShowValues.length; j++)
2887						{
2888							tmpFilter[strName] = arShowValues[j];
2889							allValues[allValues.length] = arShowValues[j];
2890							if (this.getCanBuy(tmpFilter))
2891								arCanBuyValues[arCanBuyValues.length] = arShowValues[j];
2892						}
2893					}
2894					else
2895					{
2896						arCanBuyValues = arShowValues;
2897					}
2898					if (this.selectedValues[strName] && BX.util.in_array(this.selectedValues[strName], arCanBuyValues))
2899					{
2900						arFilter[strName] = this.selectedValues[strName];
2901					}
2902					else
2903					{
2904						if (this.showAbsent)
2905							arFilter[strName] = (arCanBuyValues.length > 0 ? arCanBuyValues[0] : allValues[0]);
2906						else
2907							arFilter[strName] = arCanBuyValues[0];
2908					}
2909					this.updateRow(i, arFilter[strName], arShowValues, arCanBuyValues);
2910				}
2911				this.selectedValues = arFilter;
2912				this.changeInfo();
2913			}
2914			return true;
2915		},
2916
2917		updateRow: function(intNumber, activeID, showID, canBuyID)
2918		{
2919			var i = 0,
2920				value = '',
2921				isCurrent = false,
2922				rowItems = null;
2923                        
2924                        
2925
2926			var lineContainer = this.obTree.querySelectorAll('[data-entity="sku-line-block"]'),
2927				listContainer;
2928
2929
2930
2931			if (intNumber > -1 && intNumber < lineContainer.length)
2932			{
2933				rowItems = lineContainer[intNumber].querySelectorAll('a');
2934				//rowItems = BX.findChildren(lineContainer, {tagName: 'a'}, true);
2935                                 
2936				if (rowItems && 0 < rowItems.length)
2937				{
2938					for (i = 0; i < rowItems.length; i++)
2939					{
2940						value = rowItems[i].getAttribute('data-onevalue');
2941						isCurrent = value === activeID;
2942                                                
2943						if (isCurrent)
2944						{
2945							BX.addClass(rowItems[i], 'selected');
2946						}
2947						else
2948						{
2949							BX.removeClass(rowItems[i], 'selected');
2950						}
2951
2952						if (BX.util.in_array(value, canBuyID))
2953						{
2954							BX.removeClass(rowItems[i], 'notallowed');
2955						}
2956						else
2957						{
2958							BX.addClass(rowItems[i], 'notallowed');
2959						}
2960
2961						rowItems[i].style.display = BX.util.in_array(value, showID) ? '' : 'none';
2962
2963						if (isCurrent)
2964						{
2965							lineContainer[intNumber].style.display = (value == 0 && canBuyID.length == 1) ? 'none' : '';
2966						}
2967					}
2968				}
2969			}
2970		},
2971
2972		getRowValues: function(arFilter, index)
2973		{
2974			var i = 0,
2975				j,
2976				arValues = [],
2977				boolSearch = false,
2978				boolOneSearch = true;
2979
2980			if (0 === arFilter.length)
2981			{
2982				for (i = 0; i < this.offers.length; i++)
2983				{
2984					if (!BX.util.in_array(this.offers[i].TREE[index], arValues))
2985					{
2986						arValues[arValues.length] = this.offers[i].TREE[index];
2987					}
2988				}
2989				boolSearch = true;
2990			}
2991			else
2992			{
2993				for (i = 0; i < this.offers.length; i++)
2994				{
2995					boolOneSearch = true;
2996					for (j in arFilter)
2997					{
2998						if (arFilter[j] !== this.offers[i].TREE[j])
2999						{
3000							boolOneSearch = false;
3001							break;
3002						}
3003					}
3004					if (boolOneSearch)
3005					{
3006						if (!BX.util.in_array(this.offers[i].TREE[index], arValues))
3007						{
3008							arValues[arValues.length] = this.offers[i].TREE[index];
3009						}
3010						boolSearch = true;
3011					}
3012				}
3013			}
3014			return (boolSearch ? arValues : false);
3015		},
3016
3017		getCanBuy: function(arFilter)
3018		{
3019			var i, j,
3020				boolSearch = false,
3021				boolOneSearch = true;
3022
3023			for (i = 0; i < this.offers.length; i++)
3024			{
3025				boolOneSearch = true;
3026				for (j in arFilter)
3027				{
3028					if (arFilter[j] !== this.offers[i].TREE[j])
3029					{
3030						boolOneSearch = false;
3031						break;
3032					}
3033				}
3034				if (boolOneSearch)
3035				{
3036					if (this.offers[i].CAN_BUY)
3037					{
3038						boolSearch = true;
3039						break;
3040					}
3041				}
3042			}
3043
3044			return boolSearch;
3045		},
3046
3047		setCurrent: function()
3048		{
3049			var i,
3050				j = 0,
3051				arCanBuyValues = [],
3052				strName = '',
3053				arShowValues = false,
3054				arFilter = {},
3055				tmpFilter = [],
3056				current = this.offers[this.offerNum].TREE;
3057                        
3058			for (i = 0; i < this.treeProps.length; i++)
3059			{
3060				strName = 'PROP_'+this.treeProps[i].ID;
3061				arShowValues = this.getRowValues(arFilter, strName);
3062                                
3063				if (!arShowValues)
3064				{
3065					break;
3066				}
3067				if (BX.util.in_array(current[strName], arShowValues))
3068				{
3069					arFilter[strName] = current[strName];
3070				}
3071				else
3072				{
3073					arFilter[strName] = arShowValues[0];
3074					this.offerNum = 0;
3075				}
3076				if (this.showAbsent)
3077				{
3078					arCanBuyValues = [];
3079					tmpFilter = [];
3080					tmpFilter = BX.clone(arFilter, true);
3081					for (j = 0; j < arShowValues.length; j++)
3082					{
3083						tmpFilter[strName] = arShowValues[j];
3084						if (this.getCanBuy(tmpFilter))
3085						{
3086							arCanBuyValues[arCanBuyValues.length] = arShowValues[j];
3087						}
3088					}
3089				}
3090				else
3091				{
3092					arCanBuyValues = arShowValues;
3093				}
3094                                
3095                                
3096				this.updateRow(i, arFilter[strName], arShowValues, arCanBuyValues);
3097			}
3098			this.selectedValues = arFilter;
3099			this.changeInfo();
3100		},
3101
3102		changeInfo: function()
3103		{
3104			var i, j,
3105				index = -1,
3106				boolOneSearch = true,
3107				quantityChanged;
3108
3109			for (i = 0; i < this.offers.length; i++)
3110			{
3111				boolOneSearch = true;
3112				for (j in this.selectedValues)
3113				{
3114					if (this.selectedValues[j] !== this.offers[i].TREE[j])
3115					{
3116						boolOneSearch = false;
3117						break;
3118					}
3119				}
3120				if (boolOneSearch)
3121				{
3122					index = i;
3123					break;
3124				}
3125			}
3126			if (index > -1)
3127			{
3128                                BX.cleanNode(this.obPictSlider);
3129                                
3130                                if (!!this.offers[index].PREVIEW_PICTURE && !!this.offers[index].PREVIEW_PICTURE.SRC)
3131                                {
3132                                    
3133                                    if (this.offers[index].MORE_PHOTO.length > 0)
3134                                    {
3135                                        var innerHtml = '<div class="swiper-container gallery-top"><div class="swiper-wrapper">', innerThumbs = '<div class="swiper-container gallery-thumbs"><div class="swiper-wrapper">';
3136                                        innerHtml += '<div class="swiper-slide"><img class="product-image" data-src="'+this.offers[index].PREVIEW_PICTURE.SRC+'"></div>';
3137                                        innerThumbs += '<div class="swiper-slide"></div>';
3138                                        
3139                                        for (i in this.offers[index].MORE_PHOTO)
3140					{
3141                                            if (this.offers[index].MORE_PHOTO.hasOwnProperty(i))
3142                                            {
3143                                                innerHtml += '<div class="swiper-slide"><img class="product-image" data-src="'+this.offers[index].MORE_PHOTO[i].SRC+'"></div>';
3144                                                innerThumbs += '<div class="swiper-slide"></div>';
3145                                            }
3146                                        }
3147                                        innerThumbs += '</div><div class="swiper-pagination"></div></div>';
3148                                        innerHtml += '</div><div class="swiper-pagination"></div></div>';
3149                                        
3150                                        BX.adjust(this.obPictSlider, {
3151                                            html: innerHtml + innerThumbs
3152                                        });
3153                                        
3154                                        this.initializeSlider();
3155                                    }
3156                                    else
3157                                    {
3158                                        
3159                                        BX.adjust(this.obPictSlider, {
3160                                            html: '<img class="product-image" data-src="'+this.offers[index].PREVIEW_PICTURE.SRC+'">'
3161                                        });
3162                                    }
3163                                    
3164                                }
3165                                else if (!!this.defaultPict && !!this.defaultPict.pict && !!this.defaultPict.pict.SRC)
3166                                {
3167                                    if (this.offers[index].MORE_PHOTO.length > 0)
3168                                    {
3169                                        var innerHtml = '<div class="swiper-container gallery-top"><div class="swiper-wrapper">', innerThumbs = '<div class="swiper-container gallery-thumbs"><div class="swiper-wrapper">';
3170                                        innerHtml += '<div class="swiper-slide"><img class="product-image" data-src="'+this.defaultPict.pict.SRC+'"></div>';
3171                                        innerThumbs += '<div class="swiper-slide"></div>';
3172                                        
3173                                        for (i in this.offers[index].MORE_PHOTO)
3174					{
3175                                            if (this.offers[index].MORE_PHOTO.hasOwnProperty(i))
3176                                            {
3177                                                innerHtml += '<div class="swiper-slide"><img class="product-image" data-src="'+this.offers[index].MORE_PHOTO[i].SRC+'"></div>';
3178                                                innerThumbs += '<div class="swiper-slide"></div>';
3179                                            }
3180                                        }
3181                                        innerThumbs += '</div><div class="swiper-pagination"></div></div>';
3182                                        innerHtml += '</div><div class="swiper-pagination"></div></div>';
3183                                        
3184                                        BX.adjust(this.obPictSlider, {
3185                                            html: innerHtml + innerThumbs
3186                                        });
3187                                        
3188                                        this.initializeSlider();
3189                                    }
3190                                    else
3191                                    {
3192                                        
3193                                        BX.adjust(this.obPictSlider, {
3194                                            html: '<img class="product-image" data-src="'+this.defaultPict.pict.SRC + '">'
3195                                        });
3196                                    }
3197                                }
3198                                
3199                                $(this.obPictSlider).find('.product-image').Lazy({
3200                                    effect: "fadeIn",
3201                                    effectTime: 250,
3202                                    threshold: 0
3203                                });
3204                                
3205                               
3206                                if (!!this.visual.ITEM_CODE_ID)
3207                                {
3208                                    var obItemCode = BX(this.visual.ITEM_CODE_ID),
3209                                        obItemCodeValue = obItemCode.querySelector('[data-entity="item-code-value"]');
3210                                    
3211                                    if (!!this.offers[index].ITEM_CODE && this.offers[index].ITEM_CODE.length > 0)
3212                                    {
3213                                        BX.adjust(obItemCodeValue, {
3214                                            html: this.offers[index].ITEM_CODE
3215                                        });
3216                                        
3217                                        BX.adjust(obItemCode, {
3218                                            style: {display: 'inline-flex'}
3219                                        });
3220                                    }
3221                                    else
3222                                    {
3223                                        BX.adjust(obItemCode, {
3224                                            style: {display: 'none'}
3225                                        });
3226                                    }
3227                                }
3228                                
3229
3230				if (this.showSkuProps && this.obSkuProps)
3231				{
3232					if (this.offers[index].DISPLAY_PROPERTIES.length)
3233					{
3234						BX.adjust(this.obSkuProps, {style: {display: ''}, html: this.offers[index].DISPLAY_PROPERTIES});
3235					}
3236					else
3237					{
3238						BX.adjust(this.obSkuProps, {style: {display: 'none'}, html: ''});
3239					}
3240				}
3241
3242				this.quantitySet(index);
3243				this.setPrice();
3244				this.setCompared(this.offers[index].COMPARED);
3245
3246				this.offerNum = index;
3247			}
3248		},
3249
3250		checkPriceRange: function(quantity)
3251		{
3252			if (typeof quantity === 'undefined'|| this.currentPriceMode != 'Q')
3253				return;
3254
3255			var range, found = false;
3256
3257			for (var i in this.currentQuantityRanges)
3258			{
3259				if (this.currentQuantityRanges.hasOwnProperty(i))
3260				{
3261					range = this.currentQuantityRanges[i];
3262
3263					if (
3264						parseInt(quantity) >= parseInt(range.SORT_FROM)
3265						&& (
3266							range.SORT_TO == 'INF'
3267							|| parseInt(quantity) <= parseInt(range.SORT_TO)
3268						)
3269					)
3270					{
3271						found = true;
3272						this.currentQuantityRangeSelected = range.HASH;
3273						break;
3274					}
3275				}
3276			}
3277
3278			if (!found && (range = this.getMinPriceRange()))
3279			{
3280				this.currentQuantityRangeSelected = range.HASH;
3281			}
3282
3283			for (var k in this.currentPrices)
3284			{
3285				if (this.currentPrices.hasOwnProperty(k))
3286				{
3287					if (this.currentPrices[k].QUANTITY_HASH == this.currentQuantityRangeSelected)
3288					{
3289						this.currentPriceSelected = k;
3290						break;
3291					}
3292				}
3293			}
3294		},
3295
3296		getMinPriceRange: function()
3297		{
3298			var range;
3299
3300			for (var i in this.currentQuantityRanges)
3301			{
3302				if (this.currentQuantityRanges.hasOwnProperty(i))
3303				{
3304					if (
3305						!range
3306						|| parseInt(this.currentQuantityRanges[i].SORT_FROM) < parseInt(range.SORT_FROM)
3307					)
3308					{
3309						range = this.currentQuantityRanges[i];
3310					}
3311				}
3312			}
3313
3314			return range;
3315		},
3316
3317		checkQuantityControls: function()
3318		{
3319			if (!this.obQuantity)
3320				return;
3321
3322			var reachedTopLimit = this.checkQuantity && parseFloat(this.obQuantity.value) + this.stepQuantity > this.maxQuantity,
3323				reachedBottomLimit = parseFloat(this.obQuantity.value) - this.stepQuantity < this.minQuantity;
3324
3325			if (reachedTopLimit)
3326			{
3327				BX.addClass(this.obQuantityUp, 'product-item-amount-field-btn-disabled');
3328			}
3329			else if (BX.hasClass(this.obQuantityUp, 'product-item-amount-field-btn-disabled'))
3330			{
3331				BX.removeClass(this.obQuantityUp, 'product-item-amount-field-btn-disabled');
3332			}
3333
3334			if (reachedBottomLimit)
3335			{
3336				BX.addClass(this.obQuantityDown, 'product-item-amount-field-btn-disabled');
3337			}
3338			else if (BX.hasClass(this.obQuantityDown, 'product-item-amount-field-btn-disabled'))
3339			{
3340				BX.removeClass(this.obQuantityDown, 'product-item-amount-field-btn-disabled');
3341			}
3342
3343			if (reachedTopLimit && reachedBottomLimit)
3344			{
3345				this.obQuantity.setAttribute('disabled', 'disabled');
3346			}
3347			else
3348			{
3349				this.obQuantity.removeAttribute('disabled');
3350			}
3351		},
3352
3353		setPrice: function()
3354		{
3355			var obData, price;
3356
3357			if (this.obQuantity)
3358			{
3359				this.checkPriceRange(this.obQuantity.value);
3360			}
3361
3362			this.checkQuantityControls();
3363
3364			price = this.currentPrices[this.currentPriceSelected];
3365                        
3366			if (this.obPrice)
3367			{
3368				if (price)
3369				{
3370					BX.adjust(this.obPrice, {html: BX.Currency.currencyFormat(price.RATIO_PRICE, price.CURRENCY, true)});
3371				}
3372				else
3373				{
3374					BX.adjust(this.obPrice, {html: ''});
3375				}
3376
3377				if (this.showOldPrice && this.obPriceOld)
3378				{
3379					if (price && price.RATIO_PRICE !== price.RATIO_BASE_PRICE)
3380					{
3381						BX.adjust(this.obPriceOld, {
3382							style: {display: ''},
3383							html: BX.Currency.currencyFormat(price.RATIO_BASE_PRICE, price.CURRENCY, true)
3384						});
3385					}
3386					else
3387					{
3388						BX.adjust(this.obPriceOld, {
3389							style: {display: 'none'},
3390							html: ''
3391						});
3392					}
3393				}
3394
3395				if (this.obPriceTotal)
3396				{
3397					if (price && this.obQuantity && this.obQuantity.value != this.stepQuantity)
3398					{
3399						BX.adjust(this.obPriceTotal, {
3400							html: BX.message('PRICE_TOTAL_PREFIX') + ' <strong>'
3401							+ BX.Currency.currencyFormat(price.PRICE * this.obQuantity.value, price.CURRENCY, true)
3402							+ '</strong>',
3403							style: {display: ''}
3404						});
3405					}
3406					else
3407					{
3408						BX.adjust(this.obPriceTotal, {
3409							html: '',
3410							style: {display: 'none'}
3411						});
3412					}
3413				}
3414
3415				if (this.showPercent)
3416				{
3417					if (price && parseInt(price.DISCOUNT) > 0)
3418					{
3419						obData = {style: {display: ''}, html: -price.PERCENT + '%'};
3420					}
3421					else
3422					{
3423						obData = {style: {display: 'none'}, html: ''};
3424					}
3425
3426					if (this.obDscPerc)
3427					{
3428						BX.adjust(this.obDscPerc, obData);
3429					}
3430
3431					if (this.obSecondDscPerc)
3432					{
3433						BX.adjust(this.obSecondDscPerc, obData);
3434					}
3435				}
3436			}
3437		},
3438                
3439        wishlistChange: function (event) {
3440
3441            var target = BX.getEventTarget(event),
3442                changeUrl = this.basketData.wishlist_url;
3443
3444            if (changeUrl == '' || changeUrl.indexOf('#ID#') == -1)
3445                return false;
3446
3447            if (this.basketData.add_wish_to_delayed)
3448            {
3449                switch (this.productType)
3450                {
3451                    case 0: // no catalog
3452                    case 1: // product
3453                    case 2: // set
3454                        changeUrl = changeUrl.replace('#ID#', this.product.id.toString());
3455                        break;
3456                    case 3: // sku
3457                        changeUrl = changeUrl.replace('#ID#', this.offers[this.offerNum].ID);
3458                        break;
3459                }
3460            }
3461            else
3462                changeUrl = changeUrl.replace('#ID#', this.product.id.toString());
3463
3464            BX.ajax({
3465                method: 'POST',
3466                dataType: 'json',
3467                url: changeUrl,
3468                onsuccess: BX.proxy(function (response) {
3469
3470                    if (typeof(response) == 'object')
3471                    {
3472
3473                        if (response.result == 'ok' && response.state == "added")
3474                        {
3475                            if (!!window.Alpha.Messages && typeof (window.Alpha.Messages) == 'function')
3476                            {
3477                                new window.Alpha.Messages({
3478                                    type: 'default',
3479                                    title: BX.message('ADD_TO_WISHLIST_TITLE'),
3480                                    message: this.product.name.toString(),
3481                                    url: !this.isWishList ? this.basketData.wishlist_page_url : '',
3482                                    urlText: 'WISHLIST'
3483                                });
3484                            }
3485
3486                            BX.addClass(this.obWishlist, 'active');
3487                        }
3488                        else if (response.result == 'ok' && response.state == "deleted")
3489                        {
3490                            if (!!window.Alpha.Messages && typeof (window.Alpha.Messages) == 'function')
3491                            {
3492                                new window.Alpha.Messages({
3493                                    type: 'default',
3494                                    title: BX.message('DELETE_FROM_WISHLIST_TITLE'),
3495                                    message: this.product.name.toString()
3496                                });
3497                            }
3498
3499                            BX.removeClass(this.obWishlist, 'active');
3500                        }
3501
3502                        BX.onCustomEvent('OnWishlistChange');
3503
3504                    }
3505                    else
3506                    {
3507                        console.log("error change wishlist: ", response);
3508                    }
3509
3510
3511                }, this)
3512            });
3513        },
3514
3515        setWishlist: function (state) {
3516
3517            state = (state) || '';
3518
3519            if (state == "active")
3520            {
3521                BX.addClass(this.obWishlist, 'active');
3522            }
3523            else
3524            {
3525                BX.removeClass(this.obWishlist, 'active');
3526            }
3527
3528        },
3529
3530        compare: function (event)
3531        {
3532            if (!this.obCompare)
3533                return;
3534
3535            var isActive = this.obCompare.classList.contains('active') ? true : false;
3536            var url = !isActive ? this.compareData.compareUrl : this.compareData.compareDeleteUrl, compareLink;
3537
3538
3539            if (isActive)
3540                this.setCompared(false);
3541            else
3542                this.setCompared(true);
3543
3544            if (url)
3545            {
3546                switch (this.productType)
3547                {
3548                    case 0: // no catalog
3549                    case 1: // product
3550                    case 2: // set
3551                        compareLink = url.replace('#ID#', this.product.id.toString());
3552                        break;
3553                    case 3: // sku
3554                        compareLink = url.replace('#ID#', this.offers[this.offerNum].ID);
3555                        break;
3556                }
3557
3558                BX.ajax({
3559                    method: 'POST',
3560                    dataType: 'json',
3561                    url: compareLink + (compareLink.indexOf('?') !== -1 ? '&' : '?') + 'ajax_action=Y',
3562                    onsuccess: !isActive
3563                        ? BX.proxy(this.compareResult, this)
3564                        : BX.proxy(this.compareDeleteResult, this)
3565                });
3566            }
3567        },
3568
3569		compareResult: function(result)
3570		{
3571		
3572			if (!BX.type.isPlainObject(result))
3573				return;
3574            
3575			if (this.offers.length > 0)
3576			{
3577				this.offers[this.offerNum].COMPARED = result.STATUS === 'OK';
3578			}
3579
3580			if (result.STATUS === 'OK')
3581			{
3582				BX.onCustomEvent('OnCompareChange');
3583                                
3584                if (!!window.Alpha.Messages && typeof(window.Alpha.Messages) == 'function')
3585                {
3586                    new window.Alpha.Messages({
3587                        type: 'default',
3588                        title: BX.message('ADD_TO_COMPARE_TITLE'),
3589                        message: this.product.name.toString(),
3590                    });
3591                }
3592			}
3593			else
3594			{
3595                if (!!window.Alpha.Messages && typeof(window.Alpha.Messages) == 'function')
3596                {
3597                    new window.Alpha.Messages({
3598                        type: 'error',
3599                        title: BX.message('ADD_TO_COMPARE_ERROR'),
3600                    });
3601                }
3602			}
3603		},
3604
3605		compareDeleteResult: function()
3606		{
3607			BX.onCustomEvent('OnCompareChange');
3608
3609			if (this.offers && this.offers.length)
3610			{
3611				this.offers[this.offerNum].COMPARED = false;
3612			}
3613		},
3614
3615        setCompared: function (state)
3616        {
3617            if (!this.obCompare)
3618                return;
3619
3620            if (state == true)
3621                this.obCompare.classList.add("active");
3622            else if (state == false)
3623                this.obCompare.classList.remove("active");
3624        },
3625
3626		setCompareInfo: function(comparedIds)
3627		{
3628			if (!BX.type.isArray(comparedIds))
3629				return;
3630
3631			for (var i in this.offers)
3632			{
3633				if (this.offers.hasOwnProperty(i))
3634				{
3635					this.offers[i].COMPARED = BX.util.in_array(this.offers[i].ID, comparedIds);
3636				}
3637			}
3638		},
3639
3640		compareRedirect: function()
3641		{
3642			if (this.compareData.comparePath)
3643			{
3644				location.href = this.compareData.comparePath;
3645			}
3646			else
3647			{
3648				this.obPopupWin.close();
3649			}
3650		},
3651
3652		checkDeletedCompare: function(id)
3653		{
3654			switch (this.productType)
3655			{
3656				case 0: // no catalog
3657				case 1: // product
3658				case 2: // set
3659					if (this.product.id == id)
3660					{
3661						this.setCompared(false);
3662					}
3663
3664					break;
3665				case 3: // sku
3666					var i = this.offers.length;
3667					while (i--)
3668					{
3669						if (this.offers[i].ID == id)
3670						{
3671							this.offers[i].COMPARED = false;
3672
3673							if (this.offerNum == i)
3674							{
3675								this.setCompared(false);
3676							}
3677
3678							break;
3679						}
3680					}
3681			}
3682		},
3683
3684		initBasketUrl: function()
3685		{
3686			this.basketUrl = (this.basketMode === 'ADD' ? this.basketData.add_url : this.basketData.buy_url);
3687			switch (this.productType)
3688			{
3689				case 1: // product
3690				case 2: // set
3691					this.basketUrl = this.basketUrl.replace('#ID#', this.product.id.toString());
3692					break;
3693				case 3: // sku
3694					this.basketUrl = this.basketUrl.replace('#ID#', this.offers[this.offerNum].ID);
3695					break;
3696			}
3697			this.basketParams = {
3698				'ajax_basket': 'Y'
3699			};
3700			if (this.showQuantity)
3701			{
3702				this.basketParams[this.basketData.quantity] = this.obQuantity.value;
3703			}
3704			if (this.basketData.sku_props)
3705			{
3706				this.basketParams[this.basketData.sku_props_var] = this.basketData.sku_props;
3707			}
3708		},
3709
3710		fillBasketProps: function()
3711		{
3712			if (!this.visual.BASKET_PROP_DIV)
3713			{
3714				return;
3715			}
3716			var
3717				i = 0,
3718				propCollection = null,
3719				foundValues = false,
3720				obBasketProps = null;
3721
3722			if (this.basketData.useProps && !this.basketData.emptyProps)
3723			{
3724				if (this.obPopupWin && this.obPopupWin.contentContainer)
3725				{
3726					obBasketProps = this.obPopupWin.contentContainer;
3727				}
3728			}
3729			else
3730			{
3731				obBasketProps = BX(this.visual.BASKET_PROP_DIV);
3732			}
3733			if (obBasketProps)
3734			{
3735				propCollection = obBasketProps.getElementsByTagName('select');
3736				if (propCollection && propCollection.length)
3737				{
3738					for (i = 0; i < propCollection.length; i++)
3739					{
3740						if (!propCollection[i].disabled)
3741						{
3742							switch (propCollection[i].type.toLowerCase())
3743							{
3744								case 'select-one':
3745									this.basketParams[propCollection[i].name] = propCollection[i].value;
3746									foundValues = true;
3747									break;
3748								default:
3749									break;
3750							}
3751						}
3752					}
3753				}
3754				propCollection = obBasketProps.getElementsByTagName('input');
3755				if (propCollection && propCollection.length)
3756				{
3757					for (i = 0; i < propCollection.length; i++)
3758					{
3759						if (!propCollection[i].disabled)
3760						{
3761							switch (propCollection[i].type.toLowerCase())
3762							{
3763								case 'hidden':
3764									this.basketParams[propCollection[i].name] = propCollection[i].value;
3765									foundValues = true;
3766									break;
3767								case 'radio':
3768									if (propCollection[i].checked)
3769									{
3770										this.basketParams[propCollection[i].name] = propCollection[i].value;
3771										foundValues = true;
3772									}
3773									break;
3774								default:
3775									break;
3776							}
3777						}
3778					}
3779				}
3780			}
3781			if (!foundValues)
3782			{
3783				this.basketParams[this.basketData.props] = [];
3784				this.basketParams[this.basketData.props][0] = 0;
3785			}
3786		},
3787
3788		add2Basket: function()
3789		{
3790			this.basketMode = 'ADD';
3791			this.basket();
3792		},
3793
3794		buyBasket: function()
3795		{
3796			this.basketMode = 'BUY';
3797			this.basket();
3798		},
3799
3800		sendToBasket: function()
3801		{
3802			if (!this.canBuy)
3803			{
3804				return;
3805			}
3806
3807			// check recommendation
3808			if (this.product && this.product.id && this.bigData)
3809			{
3810				this.rememberProductRecommendation();
3811			}
3812
3813			this.initBasketUrl();
3814			this.fillBasketProps();
3815			BX.ajax({
3816				method: 'POST',
3817				dataType: 'json',
3818				url: this.basketUrl,
3819				data: this.basketParams,
3820				onsuccess: BX.proxy(this.basketResult, this)
3821			});
3822		},
3823
3824		basket: function()
3825		{
3826			var contentBasketProps = '';
3827			if (!this.canBuy)
3828			{
3829				return;
3830			}
3831			switch (this.productType)
3832			{
3833				case 1: // product
3834				case 2: // set
3835					if (this.basketData.useProps && !this.basketData.emptyProps)
3836					{
3837						this.initPopupWindow();
3838						this.obPopupWin.setTitleBar(BX.message('TITLE_BASKET_PROPS'));
3839						if (BX(this.visual.BASKET_PROP_DIV))
3840						{
3841							contentBasketProps = BX(this.visual.BASKET_PROP_DIV).innerHTML;
3842						}
3843						this.obPopupWin.setContent(contentBasketProps);
3844						this.obPopupWin.setButtons([
3845							new BasketButton({
3846								text: BX.message('BTN_MESSAGE_SEND_PROPS'),
3847								events: {
3848									click: BX.delegate(this.sendToBasket, this)
3849								}
3850							})
3851						]);
3852						this.obPopupWin.show();
3853					}
3854					else
3855					{
3856						this.sendToBasket();
3857					}
3858					break;
3859				case 3: // sku
3860					this.sendToBasket();
3861					break;
3862			}
3863		},
3864
3865		basketResult: function(arResult)
3866		{
3867			var strContent = '',
3868				strPict = '',
3869				successful,
3870				buttons = [];
3871
3872
3873			if (!BX.type.isPlainObject(arResult))
3874				return;
3875
3876			successful = arResult.STATUS === 'OK';
3877
3878			if (successful)
3879			{
3880				this.setAnalyticsDataLayer('addToCart');
3881			}
3882
3883			if (successful && this.basketAction === 'BUY')
3884			{
3885				this.basketRedirect();
3886			}
3887			else
3888			{
3889
3890				if (successful)
3891				{
3892					BX.onCustomEvent('OnBasketChange');
3893
3894					if  (BX.findParent(this.obProduct, {className: 'bx_sale_gift_main_products'}, 10))
3895					{
3896						BX.onCustomEvent('onAddToBasketMainProduct', [this]);
3897					}
3898
3899					switch (this.productType)
3900					{
3901						case 1: // product
3902						case 2: // set
3903							strPict = this.product.pict.SRC;
3904							break;
3905						case 3: // sku
3906							strPict = (this.offers[this.offerNum].PREVIEW_PICTURE ?
3907									this.offers[this.offerNum].PREVIEW_PICTURE.SRC :
3908									this.defaultPict.pict.SRC
3909							);
3910							break;
3911					}
3912
3913                    if (!!window.Alpha.Messages && typeof(window.Alpha.Messages) == 'function')
3914                    {
3915                        new window.Alpha.Messages({
3916                            type: 'addToBasket',
3917                            title: BX.message('TITLE_SUCCESSFUL'),
3918                            message: this.product.name,
3919                            image: strPict,
3920                            url: this.basketData.basketUrl,
3921                            urlText: 'BASKET'
3922                        });
3923                    }
3924
3925                    }
3926                    else
3927                    {
3928                        if (!!window.Alpha.Messages && typeof(window.Alpha.Messages) == 'fu
3928nction')
3929                        {
3930                            new window.Alpha.Messages({
3931                                type: 'error',
3932                                title: BX.message('TITLE_ERROR'),
3933                                message: (arResult.MESSAGE ? arResult.MESSAGE : BX.message('BASKET_UNKNOWN_ERROR')),
3934                            });
3935                        }
3936				    }
3937
3938			}
3939		},
3940
3941		basketRedirect: function()
3942		{
3943			location.href = (this.basketData.basketUrl ? this.basketData.basketUrl : BX.message('BASKET_URL'));
3944		},
3945
3946		initPopupWindow: function()
3947		{
3948			if (this.obPopupWin)
3949				return;
3950
3951			this.obPopupWin = BX.PopupWindowManager.create('CatalogSectionBasket_' + this.visual.ID, null, {
3952				autoHide: true,
3953				offsetLeft: 0,
3954				offsetTop: 0,
3955				overlay : true,
3956				closeByEsc: true,
3957				titleBar: true,
3958				closeIcon: true,
3959				contentColor: 'white',
3960				className: this.templateTheme ? 'bx-' + this.templateTheme : ''
3961			});
3962		}
3963	};
3964        
3965        
3966        
3967        //*******************
3968        //**** catalog.product.subscribe
3969        //*******************
3970        
3971        if (!!window.Alpha.CatalogProductSubscribe)
3972	{
3973		return;
3974	}
3975
3976	var subscribeButton = function(params)
3977	{
3978		subscribeButton.superclass.constructor.apply(this, arguments);
3979		this.nameNode = BX.create('span', {
3980			props : { id : this.id },
3981			style: typeof(params.style) === 'object' ? params.style : {},
3982			text: params.text
3983		});
3984		this.buttonNode = BX.create('span', {
3985			attrs: { className: params.className },
3986			style: { marginBottom: '0', borderBottom: '0 none transparent' },
3987			children: [this.nameNode],
3988			events : this.contextEvents
3989		});
3990		if (BX.browser.IsIE())
3991		{
3992			this.buttonNode.setAttribute("hideFocus", "hidefocus");
3993		}
3994	};
3995	BX.extend(subscribeButton, BX.PopupWindowButton);
3996
3997	window.Alpha.CatalogProductSubscribe = function(params)
3998	{
3999		this.buttonId = params.buttonId;
4000		this.buttonClass = params.buttonClass;
4001		this.jsObject = params.jsObject;
4002		this.ajaxUrl = '/bitrix/components/bitrix/catalog.product.subscribe/ajax.php';
4003		this.alreadySubscribed = params.alreadySubscribed;
4004		this.listIdAlreadySubscribed = params.listIdAlreadySubscribed;
4005		this.urlListSubscriptions = params.urlListSubscriptions;
4006		this.listOldItemId = {};
4007		this.landingId = params.landingId;
4008
4009		this.elemButtonSubscribe = null;
4010		this.elemPopupWin = null;
4011		this.defaultButtonClass = 'bx-catalog-subscribe-button';
4012
4013		this._elemButtonSubscribeClickHandler = BX.delegate(this.subscribe, this);
4014		this._elemHiddenClickHandler = BX.delegate(this.checkSubscribe, this);
4015
4016		BX.ready(BX.delegate(this.init,this));
4017	};
4018
4019	window.Alpha.CatalogProductSubscribe.prototype.init = function()
4020	{
4021		if (!!this.buttonId)
4022		{
4023			this.elemButtonSubscribe = BX(this.buttonId);
4024			this.elemHiddenSubscribe = BX(this.buttonId+'_hidden');
4025		}
4026
4027		if (!!this.elemButtonSubscribe)
4028		{
4029			BX.bind(this.elemButtonSubscribe, 'click', this._elemButtonSubscribeClickHandler);
4030		}
4031
4032		if (!!this.elemHiddenSubscribe)
4033		{
4034			BX.bind(this.elemHiddenSubscribe, 'click', this._elemHiddenClickHandler);
4035		}
4036
4037		this.setButton(this.alreadySubscribed);
4038		this.setIdAlreadySubscribed(this.listIdAlreadySubscribed);
4039	};
4040
4041	window.Alpha.CatalogProductSubscribe.prototype.checkSubscribe = function()
4042	{
4043		if(!this.elemHiddenSubscribe || !this.elemButtonSubscribe) return;
4044
4045		if(this.listOldItemId.hasOwnProperty(this.elemButtonSubscribe.dataset.item))
4046		{
4047			this.setButton(true);
4048		}
4049		else
4050		{
4051			BX.ajax({
4052				method: 'POST',
4053				dataType: 'json',
4054				url: this.ajaxUrl,
4055				data: {
4056					sessid: BX.bitrix_sessid(),
4057					checkSubscribe: 'Y',
4058					itemId: this.elemButtonSubscribe.dataset.item
4059				},
4060				onsuccess: BX.delegate(function (result) {
4061					if(result.subscribe)
4062					{
4063						this.setButton(true);
4064						this.listOldItemId[this.elemButtonSubscribe.dataset.item] = true;
4065					}
4066					else
4067					{
4068						this.setButton(false);
4069					}
4070				}, this)
4071			});
4072		}
4073	};
4074
4075	window.Alpha.CatalogProductSubscribe.prototype.subscribe = function()
4076	{
4077		this.elemButtonSubscribe = BX.proxy_context;
4078		if(!this.elemButtonSubscribe) return false;
4079
4080		BX.ajax({
4081			method: 'POST',
4082			dataType: 'json',
4083			url: this.ajaxUrl,
4084			data: {
4085				sessid: BX.bitrix_sessid(),
4086				subscribe: 'Y',
4087				itemId: this.elemButtonSubscribe.dataset.item,
4088				siteId: BX.message('SITE_ID'),
4089				landingId: this.landingId
4090			},
4091			onsuccess: BX.delegate(function (result) {
4092				if(result.success)
4093				{
4094					this.createSuccessPopup(result);
4095					this.setButton(true);
4096					this.listOldItemId[this.elemButtonSubscribe.dataset.item] = true;
4097				}
4098				else if(result.contactFormSubmit)
4099				{
4100                    this.initPopupWindow();
4101					this.elemPopupWin.setTitleBar(BX.message('CPST_SUBSCRIBE_POPUP_TITLE'));
4102					var form = this.createContentForPopup(result);
4103					this.elemPopupWin.setContent(form);
4104					this.elemPopupWin.setButtons([
4105						new subscribeButton({
4106							text: BX.message('CPST_SUBSCRIBE_BUTTON_NAME'),
4107							className : 'btn btn-primary',
4108							events: {
4109								click : BX.delegate(function() {
4110									if(!this.validateContactField(result.contactTypeData))
4111									{
4112										return false;
4113									}
4114									BX.ajax.submitAjax(form, {
4115										method : 'POST',
4116										url: this.ajaxUrl,
4117										processData : true,
4118										onsuccess: BX.delegate(function (resultForm) {
4119											resultForm = BX.parseJSON(resultForm, {});
4120											if(resultForm.success)
4121											{
4122												this.createSuccessPopup(resultForm);
4123												this.setButton(true);
4124												this.listOldItemId[this.elemButtonSubscribe.dataset.item] = true;
4125											}
4126											else if(resultForm.error)
4127											{
4128												if(resultForm.hasOwnProperty('setButton'))
4129												{
4130													this.listOldItemId[this.elemButtonSubscribe.dataset.item] = true;
4131													this.setButton(true);
4132												}
4133												var errorMessage = resultForm.message;
4134												if(resultForm.hasOwnProperty('typeName'))
4135												{
4136													errorMessage = resultForm.message.replace('USER_CONTACT',
4137														resultForm.typeName);
4138												}
4139												BX('bx-catalog-subscribe-form-notify').style.color = 'red';
4140												BX('bx-catalog-subscribe-form-notify').innerHTML = errorMessage;
4141											}
4142										}, this)
4143									});
4144								}, this)
4145							}
4146						}),
4147					]);
4148					this.elemPopupWin.show();
4149				}
4150				else if(result.error)
4151				{
4152					if(result.hasOwnProperty('setButton'))
4153					{
4154						this.listOldItemId[this.elemButtonSubscribe.dataset.item] = true;
4155						this.setButton(true);
4156					}
4157					this.showWindowWithAnswer({status: 'error', message: result.message});
4158				}
4159			}, this)
4160		});
4161	};
4162
4163	window.Alpha.CatalogProductSubscribe.prototype.validateContactField = function(contactTypeData)
4164	{
4165		var inputFields = BX.findChildren(BX('bx-catalog-subscribe-form'),
4166			{'tag': 'input', 'attribute': {id: 'userContact'}}, true);
4167		if(!inputFields.length || typeof contactTypeData !== 'object')
4168		{
4169			BX('bx-catalog-subscribe-form-notify').style.color = 'red';
4170			BX('bx-catalog-subscribe-form-notify').innerHTML = BX.message('CPST_SUBSCRIBE_VALIDATE_UNKNOW_ERROR');
4171			return false;
4172		}
4173
4174		var contactTypeId, contactValue, useContact, errors = [], useContactErrors = [];
4175		for(var k = 0; k < inputFields.length; k++)
4176		{
4177			contactTypeId = inputFields[k].getAttribute('data-id');
4178			contactValue = inputFields[k].value;
4179			useContact = BX('bx-contact-use-'+contactTypeId);
4180			if(useContact && useContact.value == 'N')
4181			{
4182				useContactErrors.push(true);
4183				continue;
4184			}
4185			if(!contactValue.length)
4186			{
4187				errors.push(BX.message('CPST_SUBSCRIBE_VALIDATE_ERROR_EMPTY_FIELD').replace(
4188					'#FIELD#', contactTypeData[contactTypeId].contactLable));
4189			}
4190		}
4191
4192		if(inputFields.length == useContactErrors.length)
4193		{
4194			BX('bx-catalog-subscribe-form-notify').style.color = 'red';
4195			BX('bx-catalog-subscribe-form-notify').innerHTML = BX.message('CPST_SUBSCRIBE_VALIDATE_ERROR');
4196			return false;
4197		}
4198
4199		if(errors.length)
4200		{
4201			BX('bx-catalog-subscribe-form-notify').style.color = 'red';
4202			for(var i = 0; i < errors.length; i++)
4203			{
4204				BX('bx-catalog-subscribe-form-notify').innerHTML = errors[i];
4205			}
4206			return false;
4207		}
4208
4209		return true;
4210	};
4211
4212	window.Alpha.CatalogProductSubscribe.prototype.reloadCaptcha = function()
4213	{
4214		BX.ajax.get(this.ajaxUrl+'?reloadCaptcha=Y', '', function(captchaCode) {
4215			BX('captcha_sid').value = captchaCode;
4216			BX('captcha_img').src = '/bitrix/tools/captcha.php?captcha_sid='+captchaCode+'';
4217		});
4218	};
4219
4220	window.Alpha.CatalogProductSubscribe.prototype.createContentForPopup = function(responseData)
4221	{
4222		if(!responseData.hasOwnProperty('contactTypeData'))
4223		{
4224			return null;
4225		}
4226
4227		var contactTypeData = responseData.contactTypeData, contactCount = Object.keys(contactTypeData).length,
4228			styleInputForm = '', manyContact = 'N', content = document.createDocumentFragment();
4229
4230		if(contactCount > 1)
4231		{
4232			manyContact = 'Y';
4233			styleInputForm = 'display:none;';
4234			content.appendChild(BX.create('p', {
4235				text: BX.message('CPST_SUBSCRIBE_MANY_CONTACT_NOTIFY')
4236			}));
4237		}
4238
4239		content.appendChild(BX.create('p', {
4240			props: {id: 'bx-catalog-subscribe-form-notify'}
4241		}));
4242
4243		for(var k in contactTypeData)
4244		{
4245			if(contactCount > 1)
4246			{
4247				content.appendChild(BX.create('div', {
4248					props: {
4249						className: 'bx-catalog-subscribe-form-container'
4250					},
4251					children: [
4252						BX.create('div', {
4253							props: {
4254								className: 'checkbox'
4255							},
4256							children: [
4257								BX.create('lable', {
4258									props: {
4259										className: 'bx-filter-param-label'
4260									},
4261									attrs: {
4262										onclick: this.jsObject+'.selectContactType('+k+', event);'
4263									},
4264									children: [
4265										BX.create('input', {
4266											props: {
4267												type: 'hidden',
4268												id: 'bx-contact-use-'+k,
4269												name: 'contact['+k+'][use]',
4270												value: 'N'
4271											}
4272										}),
4273										BX.create('input', {
4274											props: {
4275												id: 'bx-contact-checkbox-'+k,
4276												type: 'checkbox'
4277											}
4278										}),
4279										BX.create('span', {
4280											props: {
4281												className: 'bx-filter-param-text'
4282											},
4283											text: contactTypeData[k].contactLable
4284										})
4285									]
4286								})
4287							]
4288						})
4289					]
4290				}));
4291			}
4292			content.appendChild(BX.create('div', {
4293				props: {
4294					id: 'bx-catalog-subscribe-form-container-'+k,
4295					className: 'bx-catalog-subscribe-form-container',
4296					style: styleInputForm
4297				},
4298				children: [
4299					BX.create('div', {
4300						props: {
4301							className: 'bx-catalog-subscribe-form-container-label'
4302						},
4303						text: BX.message('CPST_SUBSCRIBE_LABLE_CONTACT_INPUT').replace(
4304							'#CONTACT#', contactTypeData[k].contactLable)
4305					}),
4306					BX.create('div', {
4307						props: {
4308							className: 'bx-catalog-subscribe-form-container-input'
4309						},
4310						children: [
4311							BX.create('input', {
4312								props: {
4313									id: 'userContact',
4314									className: '',
4315									type: 'text',
4316									name: 'contact['+k+'][user]'
4317								},
4318								attrs: {'data-id': k}
4319							})
4320						]
4321					})
4322				]
4323			}));
4324		}
4325		if(responseData.hasOwnProperty('captchaCode'))
4326		{
4327			content.appendChild(BX.create('div', {
4328				props: {
4329					className: 'bx-catalog-subscribe-form-container'
4330				},
4331				children: [
4332					BX.create('span', {props: {className: 'bx-catalog-subscribe-form-star-required'}, text: '*'}),
4333					BX.message('CPST_ENTER_WORD_PICTURE'),
4334					BX.create('div', {
4335						props: {className: 'bx-captcha'},
4336						children: [
4337							BX.create('input', {
4338								props: {
4339									type: 'hidden',
4340									id: 'captcha_sid',
4341									name: 'captcha_sid',
4342									value: responseData.captchaCode
4343								}
4344							}),
4345							BX.create('img', {
4346								props: {
4347									id: 'captcha_img',
4348									src: '/bitrix/tools/captcha.php?captcha_sid='+responseData.captchaCode+''
4349								},
4350								attrs: {
4351									width: '180',
4352									height: '40',
4353									alt: 'captcha',
4354									onclick: this.jsObject+'.reloadCaptcha();'
4355								}
4356							})
4357						]
4358					}),
4359					BX.create('div', {
4360						props: {className: 'bx-catalog-subscribe-form-container-input'},
4361						children: [
4362							BX.create('input', {
4363								props: {
4364									id: 'captcha_word',
4365									className: '',
4366									type: 'text',
4367									name: 'captcha_word'
4368								},
4369								attrs: {maxlength: '50'}
4370							})
4371						]
4372					})
4373				]
4374			}));
4375		}
4376		var form = BX.create('form', {
4377			props: {
4378				id: 'bx-catalog-subscribe-form'
4379			},
4380			children: [
4381				BX.create('input', {
4382					props: {
4383						type: 'hidden',
4384						name: 'manyContact',
4385						value: manyContact
4386					}
4387				}),
4388				BX.create('input', {
4389					props: {
4390						type: 'hidden',
4391						name: 'sessid',
4392						value: BX.bitrix_sessid()
4393					}
4394				}),
4395				BX.create('input', {
4396					props: {
4397						type: 'hidden',
4398						name: 'itemId',
4399						value: this.elemButtonSubscribe.dataset.item
4400					}
4401				}),
4402				BX.create('input', {
4403					props: {
4404						type: 'hidden',
4405						name: 'landingId',
4406						value: this.landingId
4407					}
4408				}),
4409				BX.create('input', {
4410					props: {
4411						type: 'hidden',
4412						name: 'siteId',
4413						value: BX.message('SITE_ID')
4414					}
4415				}),
4416				BX.create('input', {
4417					props: {
4418						type: 'hidden',
4419						name: 'contactFormSubmit',
4420						value: 'Y'
4421					}
4422				})
4423			]
4424		});
4425
4426		form.appendChild(content);
4427
4428		return form;
4429	};
4430
4431	window.Alpha.CatalogProductSubscribe.prototype.selectContactType = function(contactTypeId, event)
4432	{
4433		var contactInput = BX('bx-catalog-subscribe-form-container-'+contactTypeId), visibility = '',
4434			checkboxInput = BX('bx-contact-checkbox-'+contactTypeId);
4435		if(!contactInput)
4436		{
4437			return false;
4438		}
4439
4440		if(checkboxInput != event.target)
4441		{
4442			if(checkboxInput.checked)
4443			{
4444				checkboxInput.checked = false;
4445			}
4446			else
4447			{
4448				checkboxInput.checked = true;
4449			}
4450		}
4451
4452		if (contactInput.currentStyle)
4453		{
4454			visibility = contactInput.currentStyle.display;
4455		}
4456		else if (window.getComputedStyle)
4457		{
4458			var computedStyle = window.getComputedStyle(contactInput, null);
4459			visibility = computedStyle.getPropertyValue('display');
4460		}
4461
4462		if(visibility === 'none')
4463		{
4464			BX('bx-contact-use-'+contactTypeId).value = 'Y';
4465			BX.style(contactInput, 'display', '');
4466		}
4467		else
4468		{
4469			BX('bx-contact-use-'+contactTypeId).value = 'N';
4470			BX.style(contactInput, 'display', 'none');
4471		}
4472	};
4473
4474	window.Alpha.CatalogProductSubscribe.prototype.createSuccessPopup = function(result)
4475	{
4476		this.initPopupWindow();
4477		this.elemPopupWin.setTitleBar(BX.message('CPST_SUBSCRIBE_POPUP_TITLE'));
4478		var content = BX.create('div', {
4479			props:{
4480				className: 'bx-catalog-popup-content'
4481			},
4482			children: [
4483				BX.create('p', {
4484					props: {
4485						className: 'bx-catalog-popup-message'
4486					},
4487					text: result.message
4488				})
4489			]
4490		});
4491		this.elemPopupWin.setContent(content);
4492		this.elemPopupWin.setButtons([
4493			new subscribeButton({
4494				text : BX.message('CPST_SUBSCRIBE_BUTTON_CLOSE'),
4495				className : 'btn btn-primary',
4496				events : {
4497					click : BX.delegate(function() {
4498						this.elemPopupWin.destroy();
4499                        BX.removeClass(document.body, 'modal-open');
4500                        $('body').trigger('modalClose');
4501					}, this)
4502				}
4503			})
4504		]);
4505		this.elemPopupWin.show();
4506	};
4507
4508	window.Alpha.CatalogProductSubscribe.prototype.initPopupWindow = function()
4509	{
4510		this.elemPopupWin = BX.PopupWindowManager.create('CatalogSubscribe_'+this.buttonId, null, {
4511			autoHide: true,
4512			offsetLeft: 0,
4513			offsetTop: 0,
4514			overlay : true,
4515			closeByEsc: true,
4516			titleBar: true,
4517			closeIcon: true,
4518			contentColor: 'white',
4519            events: {
4520                onPopupShow: function() {
4521                    $('body').trigger('modalOpen');
4522                    BX.addClass(document.body, 'modal-open');
4523                },
4524                onPopupClose: function() {
4525                    BX.removeClass(document.body, 'modal-open');
4526                    $('body').trigger('modalClose');
4527                }
4528            }
4529		});
4530	};
4531
4532	window.Alpha.CatalogProductSubscribe.prototype.setButton = function(statusSubscription)
4533	{
4534		this.alreadySubscribed = Boolean(statusSubscription);
4535		if(this.alreadySubscribed)
4536		{
4537			this.elemButtonSubscribe.className = this.buttonClass + ' ' + this.defaultButtonClass + ' disabled';
4538			this.elemButtonSubscribe.innerHTML = '<span>' + BX.message('CPST_TITLE_ALREADY_SUBSCRIBED') + '</span>';
4539			BX.unbind(this.elemButtonSubscribe, 'click', this._elemButtonSubscribeClickHandler);
4540		}
4541		else
4542		{
4543			this.elemButtonSubscribe.className = this.buttonClass + ' ' + this.defaultButtonClass;
4544			this.elemButtonSubscribe.innerHTML = '<span>' + BX.message('CPST_SUBSCRIBE_BUTTON_NAME') + '</span>';
4545			BX.bind(this.elemButtonSubscribe, 'click', this._elemButtonSubscribeClickHandler);
4546		}
4547	};
4548
4549	window.Alpha.CatalogProductSubscribe.prototype.setIdAlreadySubscribed = function(listIdAlreadySubscribed)
4550	{
4551		if (BX.type.isPlainObject(listIdAlreadySubscribed))
4552		{
4553			this.listOldItemId = listIdAlreadySubscribed;
4554		}
4555	};
4556
4557	window.Alpha.CatalogProductSubscribe.prototype.showWindowWithAnswer = function(answer)
4558	{
4559		answer = answer || {};
4560		if (!answer.message) {
4561			if (answer.status == 'success') {
4562				answer.message = BX.message('CPST_STATUS_SUCCESS');
4563			} else {
4564				answer.message = BX.message('CPST_STATUS_ERROR');
4565			}
4566		}
4567		var messageBox = BX.create('div', {
4568			props: {
4569				className: 'bx-catalog-subscribe-alert'
4570			},
4571			children: [
4572				BX.create('span', {
4573					props: {
4574						className: 'bx-catalog-subscribe-aligner'
4575					}
4576				}),
4577				BX.create('span', {
4578					props: {
4579						className: 'bx-catalog-subscribe-alert-text'
4580					},
4581					text: answer.message
4582				}),
4583				BX.create('div', {
4584					props: {
4585						className: 'bx-catalog-subscribe-alert-footer'
4586					}
4587				})
4588			]
4589		});
4590		var currentPopup = BX.PopupWindowManager.getCurrentPopup();
4591		if(currentPopup) {
4592			currentPopup.destroy();
4593		}
4594		var idTimeout = setTimeout(function () {
4595			var w = BX.PopupWindowManager.getCurrentPopup();
4596			if (!w || w.uniquePopupId != 'bx-catalog-subscribe-status-action') {
4597				return;
4598			}
4599			w.close();
4600			w.destroy();
4601		}, 3500);
4602		var popupConfirm = BX.PopupWindowManager.create('bx-catalog-subscribe-status-action', null, {
4603			content: messageBox,
4604			onPopupClose: function () {
4605				this.destroy();
4606				clearTimeout(idTimeout);
4607			},
4608			autoHide: true,
4609			zIndex: 2000,
4610			className: 'bx-catalog-subscribe-alert-popup'
4611		});
4612		popupConfirm.show();
4613		BX('bx-catalog-subscribe-status-action').onmouseover = function (e) {
4614			clearTimeout(idTimeout);
4615		};
4616		BX('bx-catalog-subscribe-status-action').onmouseout = function (e) {
4617			idTimeout = setTimeout(function () {
4618				var w = BX.PopupWindowManager.getCurrentPopup();
4619				if (!w || w.uniquePopupId != 'bx-catalog-subscribe-status-action') {
4620					return;
4621				}
4622				w.close();
4623				w.destroy();
4624			}, 3500);
4625		};
4626	};
4627
4628})(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.