PageSourceSearch

https://izumclub.ru/local/templates/izum/components/bitrix/catalog.item/.default/script.js?170664284364144

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