PageSourceSearch

https://domrasteni.ru/local/templates/.default/components/bitrix/c…/popular/script.js?177099375963758

js domrasteni.ru collected 2026-10-05 00:04:09 UTC 63,758 bytes, 2,641 lines download raw bytes

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