PageSourceSearch

https://fabrika38.ru/bitrix/cache/js/s1/fabrika38/page_d5cb90fe59b…2d05965986025b689fae_v1.js?1791356260230288

js fabrika38.ru collected 2026-10-07 20:05:06 UTC 230,288 bytes, 8,943 lines download raw bytes

1
2; /* Start:"a:4:{s:4:"full";s:99:"/local/templates/fabrika38/components/bitrix/sale.basket.basket/basket_38/script.js?176337996838809";s:6:"source";s:83:"/local/templates/fabrika38/components/bitrix/sale.basket.basket/basket_38/script.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
3
4BasketPoolQuantity = function()
5{
6	this.processing = false;
7	this.poolQuantity = {};
8	this.updateTimer = null;
9	this.currentQuantity = {};
10	this.lastStableQuantities = {};
11
12	this.updateQuantity();
13
14};
15
16
17BasketPoolQuantity.prototype.updateQuantity = function() {
18	var items = BX('basket_items');
19
20	if (typeof basketJSParams !== 'undefined' && basketJSParams['USE_ENHANCED_ECOMMERCE'] === 'Y'){
21		checkAnalytics(this.lastStableQuantities, items);
22	}
23
24	if (!!items && items.rows.length > 0)
25	{
26		for (var i = 1; items.rows.length > i; i++)
27		{
28			var itemId = items.rows[i].id;
29			this.currentQuantity[itemId] = BX('QUANTITY_' + itemId).value;
30		}
31	}
32	this.lastStableQuantities = BX.clone(this.currentQuantity, true);
33};
34
35
36BasketPoolQuantity.prototype.changeQuantity = function(itemId)
37{
38
39	var quantity = BX('QUANTITY_' + itemId).value;
40	var isPoolEmpty = this.isPoolEmpty();
41
42	if (this.currentQuantity[itemId] && this.currentQuantity[itemId] != quantity)
43	{
44		this.poolQuantity[itemId] = this.currentQuantity[itemId] = quantity;
45	}
46
47	if (!isPoolEmpty)
48	{
49		this.enableTimer(true);
50	}
51	else
52	{
53		this.trySendPool();
54	}
55};
56
57
58BasketPoolQuantity.prototype.trySendPool = function()
59{
60	if (!this.isPoolEmpty() && !this.isProcessing())
61	{
62		this.enableTimer(false);
63		recalcBasketAjax({});
64	}
65};
66
67BasketPoolQuantity.prototype.isPoolEmpty = function()
68{
69	return ( Object.keys(this.poolQuantity).length == 0 );
70};
71
72BasketPoolQuantity.prototype.clearPool = function()
73{
74	this.poolQuantity = {};
75};
76
77BasketPoolQuantity.prototype.isProcessing = function()
78{
79	return (this.processing === true);
80};
81
82BasketPoolQuantity.prototype.setProcessing = function(value)
83{
84	this.processing = (value === true);
85};
86
87BasketPoolQuantity.prototype.enableTimer = function(value)
88{
89	clearTimeout(this.updateTimer);
90	if (value === false)
91		return;
92
93	this.updateTimer = setTimeout(function(){ basketPoolQuantity.trySendPool(); }, 1500);
94};
95
96/**
97 * @param basketItemId
98 * @param {{BASKET_ID : string, BASKET_DATA : { GRID : { ROWS : {} }}, COLUMNS: {}, PARAMS: {}, DELETE_ORIGINAL : string }} res
99 */
100function updateBasketTable(basketItemId, res)
101{
102	var table = BX("basket_items"),
103		rows,
104		newBasketItemId,
105		arItem,
106		lastRow,
107		newRow,
108		arColumns,
109		bShowDeleteColumn = false,
110		bShowDelayColumn = false,
111		bShowPropsColumn = false,
112		bShowPriceType = false,
113		bUseFloatQuantity,
114		origBasketItem,
115		oCellMargin,
116		i,
117		oCellName,
118		imageURL,
119		cellNameHTML,
120		oCellItem,
121		cellItemHTML,
122		bSkip,
123		j,
124		val,
125		propId,
126		arProp,
127		bIsImageProperty,
128		countValues,
129		full,
130		fullWidth,
131		itemWidth,
132		arVal,
133		valId,
134		arSkuValue,
135		selected,
136		valueId,
137		k,
138		arItemProp,
139		oCellQuantity,
140		oCellQuantityHTML,
141		ratio,
142		isUpdateQuantity,
143		oldQuantity,
144		oCellPrice,
145		fullPrice,
146		id,
147		oCellDiscount,
148		oCellWeight,
149		oCellCustom,
150		customColumnVal,
151		propsMap,
152		selectedIndex,
153		counter,
154		marginLeft,
155		createNewItem;
156
157	if (!table || typeof res !== 'object')
158	{
159		return;
160	}
161
162	rows = table.rows;
163	lastRow = rows[rows.length - 1];
164	bUseFloatQuantity = (res.PARAMS.QUANTITY_FLOAT === 'Y');
165
166	// insert new row instead of original basket item row
167	if (basketItemId !== null && !!res.BASKET_DATA)
168	{
169		origBasketItem = BX(basketItemId);
170
171		newBasketItemId = res.BASKET_ID;
172		createNewItem = BX.type.isPlainObject(res.BASKET_DATA.GRID.ROWS[newBasketItemId]);
173		if (createNewItem)
174		{
175			arItem = res.BASKET_DATA.GRID.ROWS[newBasketItemId];
176			newRow = document.createElement('tr');
177
178			newRow.setAttribute('id', res.BASKET_ID);
179			newRow.setAttribute('data-item-name', arItem['NAME']);
180			newRow.setAttribute('data-item-brand', arItem[basketJSParams['BRAND_PROPERTY'] + '_VALUE']);
181			newRow.setAttribute('data-item-price', arItem['PRICE']);
182			newRow.setAttribute('data-item-currency', arItem['CURRENCY']);
183
184			lastRow.parentNode.insertBefore(newRow, origBasketItem.nextSibling);
185		}
186
187		if (res.DELETE_ORIGINAL === 'Y')
188		{
189			origBasketItem.parentNode.removeChild(origBasketItem);
190		}
191
192		if (createNewItem)
193		{
194			// fill row with fields' values
195			oCellMargin = newRow.insertCell(-1);
196			oCellMargin.setAttribute('class', 'margin');
197
198			arColumns = res.COLUMNS.split(',');
199
200			for (i = 0; i < arColumns.length; i++)
201			{
202				if (arColumns[i] === 'DELETE')
203				{
204					bShowDeleteColumn = true;
205				}
206				else if (arColumns[i] === 'DELAY')
207				{
208					bShowDelayColumn = true;
209				}
210				else if (arColumns[i] === 'PROPS')
211				{
212					bShowPropsColumn = true;
213				}
214				else if (arColumns[i] === 'TYPE')
215				{
216					bShowPriceType = true;
217				}
218			}
219
220			for (i = 0; i < arColumns.length; i++)
221			{
222				switch (arColumns[i])
223				{
224					case 'PROPS':
225					case 'DELAY':
226					case 'DELETE':
227					case 'TYPE':
228						break;
229					case 'NAME':
230						// first <td> - image and brand
231						oCellName = newRow.insertCell(-1);
232						imageURL = '';
233						cellNameHTML = '';
234
235						oCellName.setAttribute('class', 'itemphoto');
236
237						if (arItem.PREVIEW_PICTURE_SRC.length > 0)
238						{
239							imageURL = arItem.PREVIEW_PICTURE_SRC;
240						}
241						else if (arItem.DETAIL_PICTURE_SRC.length > 0)
242						{
243							imageURL = arItem.DETAIL_PICTURE_SRC;
244						}
245						else
246						{
247							imageURL = basketJSParams.TEMPLATE_FOLDER + '/images/no_photo.png';
248						}
249
250						if (arItem.DETAIL_PAGE_URL.length > 0)
251						{
252							cellNameHTML = '<div class="bx_ordercart_photo_container">\
253							<a href="' + arItem.DETAIL_PAGE_URL + '">\
254								<div class="bx_ordercart_photo" style="background-image:url(\'' + imageURL + '\')"></div>\
255							</a>\
256						</div>';
257						}
258						else
259						{
260							cellNameHTML = '<div class="bx_ordercart_photo_container">\
261							<div class="bx_ordercart_photo" style="background-image:url(\'' + imageURL + '\')"></div>\
262						</div>';
263						}
264
265						if (arItem.BRAND && arItem.BRAND.length > 0)
266						{
267							cellNameHTML += '<div class="bx_ordercart_brand">\
268							<img alt="" src="' + arItem.BRAND + '"/>\
269						</div>';
270						}
271
272						oCellName.innerHTML = cellNameHTML;
273
274						// second <td> - name, basket props, sku props
275						oCellItem = newRow.insertCell(-1);
276						cellItemHTML = '';
277						oCellItem.setAttribute('class', 'item');
278
279						if (arItem['DETAIL_PAGE_URL'].length > 0)
280							cellItemHTML += '<h2 class="bx_ordercart_itemtitle"><a href="' + arItem['DETAIL_PAGE_URL'] + '">' + arItem['NAME'] + '</a></h2>';
281						else
282							cellItemHTML += '<h2 class="bx_ordercart_itemtitle">' + arItem['NAME'] + '</h2>';
283
284						cellItemHTML += '<div class="bx_ordercart_itemart">';
285
286						if (bShowPropsColumn)
287						{
288							for (j = 0; j < arItem['PROPS'].length; j++)
289							{
290								val = arItem['PROPS'][j];
291
292								if (arItem.SKU_DATA)
293								{
294									bSkip = false;
295									for (propId in arItem.SKU_DATA)
296									{
297										if (arItem.SKU_DATA.hasOwnProperty(propId))
298										{
299											arProp = arItem.SKU_DATA[propId];
300
301											if (arProp['CODE'] === val['CODE'])
302											{
303												bSkip = true;
304												break;
305											}
306										}
307									}
308									if (bSkip)
309										continue;
310								}
311
312								cellItemHTML += BX.util.htmlspecialchars(val['NAME']) + ':&nbsp;<span>' + val['VALUE'] + '</span><br/>';
313							}
314						}
315						cellItemHTML += '</div>';
316
317						if (arItem.SKU_DATA)
318						{
319							propsMap = {};
320							for (k = 0; k < arItem['PROPS'].length; k++)
321							{
322								arItemProp = arItem['PROPS'][k];
323								propsMap[arItemProp['CODE']] = (BX.type.isNotEmptyString(arItemProp['~VALUE']) ? arItemProp['~VALUE'] : arItemProp['VALUE']);
324							}
325							for (propId in arItem.SKU_DATA)
326							{
327								if (arItem.SKU_DATA.hasOwnProperty(propId))
328								{
329									selectedIndex = 0;
330									arProp = arItem.SKU_DATA[propId];
331									bIsImageProperty = false;
332									countValues = BX.util.array_keys(arProp['VALUES']).length;
333									if (countValues > 5)
334									{
335										full = 'full';
336										fullWidth = (countValues*20) + '%';
337										itemWidth = (100/countValues) + '%';
338									}
339									else
340									{
341										full = '';
342										fullWidth = '100%';
343										itemWidth = '20%';
344									}
345
346									counter = 0;
347									for (valId in arProp['VALUES'])
348									{
349										counter++;
350										arVal = arProp['VALUES'][valId];
351										if (BX.type.isNotEmptyString(propsMap[arProp['CODE']]))
352										{
353											if (propsMap[arProp['CODE']] == arVal['NAME'] || propsMap[arProp['CODE']] == arVal['XML_ID'])
354												selectedIndex = counter;
355										}
356										if (!!arVal && typeof arVal === 'object' && !!arVal['PICT'])
357										{
358											bIsImageProperty = true;
359										}
360									}
361
362									marginLeft = '0';
363									if (full !== '' && selectedIndex > 5)
364										marginLeft = ((5 - selectedIndex) * 20) + '%';
365
366									// sku property can contain list of images or values
367									if (bIsImageProperty)
368									{
369										cellItemHTML += '<div class="bx_item_detail_scu_small_noadaptive ' + full + '">';
370										cellItemHTML += '<span class="bx_item_section_name_gray">' + BX.util.htmlspecialchars(arProp['NAME']) + '</span>';
371										cellItemHTML += '<div class="bx_scu_scroller_container">';
372										cellItemHTML += '<div class="bx_scu">';
373
374										cellItemHTML += '<ul id="prop_' + arProp['CODE'] + '_' + arItem['ID'] + '" style="width: ' + fullWidth + '; margin-left: ' + marginLeft + ';" class="sku_prop_list">';
375
376										counter = 0;
377										for (valueId in arProp['VALUES'])
378										{
379											counter++;
380											arSkuValue = arProp['VALUES'][valueId];
381											selected = (selectedIndex == counter ? ' bx_active' : '');
382
383											cellItemHTML += '<li style="width: ' + itemWidth + '; padding-top: ' + itemWidth + ';"\
384															class="sku_prop' + selected + '" \
385															data-sku-selector="Y" \
386															data-value-id="' + arSkuValue['XML_ID'] + '" \
387															data-sku-name="' + BX.util.htmlspecialchars(arSkuValue['NAME']) + '" \
388															data-element="' + arItem['ID'] + '" \
389															data-property="' + arProp['CODE'] + '"\
390															>\
391															<a href="javascript:void(0)" class="cnt"><span class="cnt_item" style="background-image:url(' + arSkuValue['PICT']['SRC'] + '"></span></a>\
392														</li>';
393										}
394
395										cellItemHTML += '</ul>';
396										cellItemHTML += '</div>';
397
398										cellItemHTML += '<div class="bx_slide_left" onclick="leftScroll(\'' + arProp['CODE'] + '\', ' + arItem['ID'] + ', ' + BX.util.array_keys(arProp['VALUES']).length + ');"></div>';
399										cellItemHTML += '<div class="bx_slide_right" onclick="rightScroll(\'' + arProp['CODE'] + '\', ' + arItem['ID'] + ', ' + BX.util.array_keys(arProp['VALUES']).length + ');"></div>';
400
401										cellItemHTML += '</div>';
402										cellItemHTML += '</div>';
403									}
404									else // not image
405									{
406										cellItemHTML += '<div class="bx_item_detail_size_small_noadaptive ' + full + '">';
407										cellItemHTML += '<span class="bx_item_section_name_gray">' + BX.util.htmlspecialchars(arProp['NAME']) + '</span>';
408										cellItemHTML += '<div class="bx_size_scroller_container">';
409										cellItemHTML += '<div class="bx_size">';
410
411										cellItemHTML += '<ul id="prop_' + arProp['CODE'] + '_' + arItem['ID'] + '" style="width: ' + fullWidth + '; margin-left: ' + marginLeft + ';" class="sku_prop_list">';
412
413										counter = 0;
414										for (valueId in arProp['VALUES'])
415										{
416											counter++;
417											arSkuValue = arProp['VALUES'][valueId];
418											selected = (selectedIndex == counter ? ' bx_active' : '');
419
420											cellItemHTML += '<li style="width: ' + itemWidth + ';"\
421															class="sku_prop ' + selected + '" \
422															data-sku-selector="Y" \
423															data-value-id="' + (arProp['TYPE'] === 'S' && arProp['USER_TYPE'] === 'directory' ? arSkuValue['XML_ID'] : BX.util.htmlspecialchars(arSkuValue['NAME'])) + '" \
424															data-sku-name="' + BX.util.htmlspecialchars(arSkuValue['NAME']) + '" \
425															data-element="' + arItem['ID'] + '" \
426															data-property="' + arProp['CODE'] + '" \
427															>\
428															<a href="javascript:void(0)" class="cnt">' + BX.util.htmlspecialchars(arSkuValue['NAME']) + '</a>\
429														</li>';
430										}
431
432										cellItemHTML += '</ul>';
433										cellItemHTML += '</div>';
434
435										cellItemHTML += '<div class="bx_slide_left" onclick="leftScroll(\'' + arProp['CODE'] + '\', ' + arItem['ID'] + ', ' + BX.util.array_keys(arProp['VALUES']).length + ');"></div>';
436										cellItemHTML += '<div class="bx_slide_right" onclick="rightScroll(\'' + arProp['CODE'] + '\', ' + arItem['ID'] + ', ' + BX.util.array_keys(arProp['VALUES']).length + ');"></div>';
437
438										cellItemHTML += '</div>';
439										cellItemHTML += '</div>';
440									}
441								}
442							}
443						}
444
445						oCellItem.innerHTML = cellItemHTML;
446						break;
447					case 'QUANTITY':
448						oCellQuantity = newRow.insertCell(-1);
449						oCellQuantityHTML = '';
450						ratio = (parseFloat(arItem['MEASURE_RATIO']) > 0) ? arItem['MEASURE_RATIO'] : 1;
451
452						isUpdateQuantity = false;
453
454						if (ratio != 0 && ratio != '')
455						{
456							oldQuantity = arItem['QUANTITY'];
457							arItem['QUANTITY'] = getCorrectRatioQuantity(arItem['QUANTITY'], ratio, bUseFloatQuantity);
458
459							if (oldQuantity != arItem['QUANTITY'])
460							{
461								isUpdateQuantity = true;
462							}
463						}
464
465						oCellQuantity.setAttribute('class', 'custom');
466						oCellQuantityHTML += '<span>' + getColumnName(res, arColumns[i]) + ':</span>';
467
468						oCellQuantityHTML += '<div class="centered">';
469						oCellQuantityHTML += '<table cellspacing="0" cellpadding="0" class="counter">';
470						oCellQuantityHTML += '<tr>';
471						oCellQuantityHTML += '<td>';
472
473						oCellQuantityHTML += '<input type="text" size="3" id="QUANTITY_INPUT_' + arItem['ID'] + '"\
474											name="QUANTITY_INPUT_' + arItem['ID'] + '"\
475											style="max-width: 50px"\
476											value="' + arItem['QUANTITY'] + '"\
477											onchange="updateQuantity(\'QUANTITY_INPUT_' + arItem['ID'] + '\',\'' + arItem['ID'] + '\', ' + ratio + ',' + bUseFloatQuantity + ')"\
478						>';
479
480						oCellQuantityHTML += '</td>';
481
482						if (ratio != 0
483							&& ratio != ''
484						) // if not Set parent, show quantity control
485						{
486							oCellQuantityHTML += '<td id="basket_quantity_control">\
487							<div class="basket_quantity_control">\
488								<a href="javascript:void(0);" class="plus" onclick="setQuantity(' + arItem['ID'] + ', ' + ratio + ', \'up\', ' + bUseFloatQuantity + ');"></a>\
489								<a href="javascript:void(0);" class="minus" onclick="setQuantity(' + arItem['ID'] + ', ' + ratio + ', \'down\', ' + bUseFloatQuantity + ');"></a>\
490							</div>\
491						</td>';
492						}
493
494						if (arItem.hasOwnProperty('MEASURE_TEXT') && arItem['MEASURE_TEXT'].length > 0)
495							oCellQuantityHTML += '<td style="text-align: left">' + BX.util.htmlspecialchars(arItem['MEASURE_TEXT']) + '</td>';
496
497						oCellQuantityHTML += '</tr>';
498						oCellQuantityHTML += '</table>';
499						oCellQuantityHTML += '</div>';
500
501						oCellQuantityHTML += '<input type="hidden" id="QUANTITY_' + arItem['ID'] + '" name="QUANTITY_' + arItem['ID'] + '" value="' + arItem['QUANTITY'] + '" />';
502
503						oCellQuantity.innerHTML = oCellQuantityHTML;
504
505						if (isUpdateQuantity)
506						{
507							updateQuantity('QUANTITY_INPUT_' + arItem['ID'], arItem['ID'], ratio, bUseFloatQuantity);
508						}
509						break;
510					case 'PRICE':
511
512						oCellPrice = newRow.insertCell(-1);
513						fullPrice = (arItem['DISCOUNT_PRICE_PERCENT'] > 0) ? arItem['FULL_PRICE_FORMATED'] : '';
514
515						oCellPrice.setAttribute('class', 'price');
516						oCellPrice.innerHTML = '<div class="current_price" id="current_price_' + arItem['ID'] + '">' + arItem['PRICE_FORMATED'] + '</div>' +
517							'<div class="old_price" id="old_price_' + arItem['ID'] + '">' + fullPrice + '</div>';
518
519						if (bShowPriceType && arItem['NOTES'].length > 0)
520						{
521							oCellPrice.innerHTML += '<div class="type_price">' + basketJSParams['SALE_TYPE'] + '</div>';
522							oCellPrice.innerHTML += '<div class="type_price_value">' + arItem['NOTES'] + '</div>';
523						}
524						break;
525					case 'DISCOUNT':
526						oCellDiscount = newRow.insertCell(-1);
527						oCellDiscount.setAttribute('class', 'custom');
528						oCellDiscount.innerHTML = '<span>' + getColumnName(res, arColumns[i]) + ':</span>';
529						oCellDiscount.innerHTML += '<div id="discount_value_' + arItem['ID'] + '">' + arItem['DISCOUNT_PRICE_PERCENT_FORMATED'] + '</div>';
530						break;
531					case 'WEIGHT':
532						oCellWeight = newRow.insertCell(-1);
533						oCellWeight.setAttribute('class', 'custom');
534						oCellWeight.innerHTML = '<span>' + getColumnName(res, arColumns[i]) + ':</span>';
535						oCellWeight.innerHTML += arItem['WEIGHT_FORMATED'];
536						break;
537					default:
538						oCellCustom = newRow.insertCell(-1);
539						customColumnVal = '';
540
541						oCellCustom.setAttribute('class', 'custom');
542						oCellCustom.innerHTML = '<span>' + getColumnName(res, arColumns[i]) + ':</span>';
543
544						if (arColumns[i] == 'SUM')
545							customColumnVal += '<div id="sum_' + arItem['ID'] + '">';
546
547						if (typeof(arItem[arColumns[i]]) != 'undefined')
548						{
549							customColumnVal += arItem[arColumns[i]];
550						}
551
552						if (arColumns[i] == 'SUM')
553							customColumnVal += '</div>';
554
555						oCellCustom.innerHTML += customColumnVal;
556						break;
557				}
558			}
559
560			if (bShowDeleteColumn || bShowDelayColumn)
561			{
562				var oCellControl = newRow.insertCell(-1);
563				oCellControl.setAttribute('class', 'control');
564
565				if (bShowDeleteColumn)
566					oCellControl.innerHTML = '<a href="' + basketJSParams['DELET
566E_URL'].replace('#ID#', arItem['ID']) + '">' + basketJSParams['SALE_DELETE'] + '</a><br />';
567
568				if (bShowDelayColumn)
569					oCellControl.innerHTML += '<a href="' + basketJSParams['DELAY_URL'].replace('#ID#', arItem['ID']) + '">' + basketJSParams['SALE_DELAY'] + '</a>';
570			}
571
572			var oCellMargin2 = newRow.insertCell(-1);
573			oCellMargin2.setAttribute('class', 'margin');
574		}
575	}
576
577	// update product params after recalculation
578	if (!!res.BASKET_DATA)
579	{
580		for (id in res.BASKET_DATA.GRID.ROWS)
581		{
582			if (res.BASKET_DATA.GRID.ROWS.hasOwnProperty(id))
583			{
584				var item = res.BASKET_DATA.GRID.ROWS[id];
585
586				if (BX('discount_value_' + id))
587					BX('discount_value_' + id).innerHTML = item.DISCOUNT_PRICE_PERCENT_FORMATED;
588
589				if (BX('current_price_' + id))
590					BX('current_price_' + id).innerHTML = item.PRICE_FORMATED;
591
592				if (BX('old_price_' + id))
593					BX('old_price_' + id).innerHTML = (item.DISCOUNT_PRICE_PERCENT > 0) ? item.FULL_PRICE_FORMATED : '';
594
595				if (BX('sum_' + id))
596					BX('sum_' + id).innerHTML = item.SUM;
597
598				// if the quantity was set by user to 0 or was too much, we need to show corrected quantity value from ajax response
599				if (BX('QUANTITY_' + id))
600				{
601					BX('QUANTITY_INPUT_' + id).value = item.QUANTITY;
602					BX('QUANTITY_INPUT_' + id).defaultValue = item.QUANTITY;
603
604					BX('QUANTITY_' + id).value = item.QUANTITY;
605				}
606
607			}
608		}
609	}
610
611	// update coupon info
612	if (!!res.BASKET_DATA)
613		couponListUpdate(res.BASKET_DATA);
614
615	// update warnings if any
616	if (res.hasOwnProperty('WARNING_MESSAGE'))
617	{
618		var warningText = '';
619
620		for (i = res['WARNING_MESSAGE'].length - 1; i >= 0; i--)
621			warningText += res['WARNING_MESSAGE'][i] + '<br/>';
622
623		BX('warning_message').innerHTML = warningText;
624	}
625
626	// update total basket values
627	if (!!res.BASKET_DATA)
628	{
629		if (BX('allWeight_FORMATED'))
630			BX('allWeight_FORMATED').innerHTML = res['BASKET_DATA']['allWeight_FORMATED'].replace(/\s/g, '&nbsp;');
631
632		if (BX('allSum_wVAT_FORMATED'))
633			BX('allSum_wVAT_FORMATED').innerHTML = res['BASKET_DATA']['allSum_wVAT_FORMATED'].replace(/\s/g, '&nbsp;');
634
635		if (BX('allVATSum_FORMATED'))
636			BX('allVATSum_FORMATED').innerHTML = res['BASKET_DATA']['allVATSum_FORMATED'].replace(/\s/g, '&nbsp;');
637
638		if (BX('allSum_FORMATED'))
639			BX('allSum_FORMATED').innerHTML = res['BASKET_DATA']['allSum_FORMATED'].replace(/\s/g, '&nbsp;');
640
641		if (BX('PRICE_WITHOUT_DISCOUNT'))
642		{
643			var showPriceWithoutDiscount = (res['BASKET_DATA']['PRICE_WITHOUT_DISCOUNT'] != res['BASKET_DATA']['allSum_FORMATED']);
644			BX('PRICE_WITHOUT_DISCOUNT').innerHTML = showPriceWithoutDiscount ? res['BASKET_DATA']['PRICE_WITHOUT_DISCOUNT'].replace(/\s/g, '&nbsp;') : '';
645			BX.style(BX('PRICE_WITHOUT_DISCOUNT').parentNode, 'display', (showPriceWithoutDiscount ? 'table-row' : 'none'));
646		}
647
648		BX.onCustomEvent('OnBasketChange');
649	}
650}
651/**
652 * @param couponBlock
653 * @param {COUPON: string, JS_STATUS: string} oneCoupon - new coupon.
654 */
655function couponCreate(couponBlock, oneCoupon)
656{
657	var couponClass = 'disabled';
658
659	if (!BX.type.isElementNode(couponBlock))
660		return;
661	if (oneCoupon.JS_STATUS === 'BAD')
662		couponClass = 'bad';
663	else if (oneCoupon.JS_STATUS === 'APPLYED')
664		couponClass = 'good';
665
666	couponBlock.appendChild(BX.create(
667		'div',
668		{
669			props: {
670				className: 'bx_ordercart_coupon'
671			},
672			children: [
673				BX.create(
674					'input',
675					{
676						props: {
677							className: couponClass,
678							type: 'text',
679							value: oneCoupon.COUPON,
680							name: 'OLD_COUPON[]'
681						},
682						attrs: {
683							disabled: true,
684							readonly: true
685						}
686					}
687				),
688				BX.create(
689					'span',
690					{
691						props: {
692							className: couponClass
693						},
694						attrs: {
695							'data-coupon': oneCoupon.COUPON
696						}
697					}
698				),
699				BX.create(
700					'div',
701					{
702						props: {
703							className: 'bx_ordercart_coupon_notes'
704						},
705						html: oneCoupon.JS_CHECK_CODE
706					}
707				)
708			]
709		}
710	));
711}
712
713/**
714 * @param {COUPON_LIST : []} res
715 */
716function couponListUpdate(res)
717{
718	var couponBlock,
719		couponClass,
720		fieldCoupon,
721		couponsCollection,
722		couponFound,
723		i,
724		j,
725		key;
726
727	if (!!res && typeof res !== 'object')
728	{
729		return;
730	}
731
732	couponBlock = BX('coupons_block');
733	if (!!couponBlock)
734	{
735		if (!!res.COUPON_LIST && BX.type.isArray(res.COUPON_LIST))
736		{
737			fieldCoupon = BX('coupon');
738			if (!!fieldCoupon)
739			{
740				fieldCoupon.value = '';
741			}
742			couponsCollection = BX.findChildren(couponBlock, { tagName: 'input', property: { name: 'OLD_COUPON[]' } }, true);
743
744			if (!!couponsCollection)
745			{
746				if (BX.type.isElementNode(couponsCollection))
747				{
748					couponsCollection = [couponsCollection];
749				}
750				for (i = 0; i < res.COUPON_LIST.length; i++)
751				{
752					couponFound = false;
753					key = -1;
754					for (j = 0; j < couponsCollection.length; j++)
755					{
756						if (couponsCollection[j].value === res.COUPON_LIST[i].COUPON)
757						{
758							couponFound = true;
759							key = j;
760							couponsCollection[j].couponUpdate = true;
761							break;
762						}
763					}
764					if (couponFound)
765					{
766						couponClass = 'disabled';
767						if (res.COUPON_LIST[i].JS_STATUS === 'BAD')
768							couponClass = 'bad';
769						else if (res.COUPON_LIST[i].JS_STATUS === 'APPLYED')
770							couponClass = 'good';
771
772						BX.adjust(couponsCollection[key], {props: {className: couponClass}});
773						BX.adjust(couponsCollection[key].nextSibling, {props: {className: couponClass}});
774						BX.adjust(couponsCollection[key].nextSibling.nextSibling, {html: res.COUPON_LIST[i].JS_CHECK_CODE});
775					}
776					else
777					{
778						couponCreate(couponBlock, res.COUPON_LIST[i]);
779					}
780				}
781				for (j = 0; j < couponsCollection.length; j++)
782				{
783					if (typeof (couponsCollection[j].couponUpdate) === 'undefined' || !couponsCollection[j].couponUpdate)
784					{
785						BX.remove(couponsCollection[j].parentNode);
786						couponsCollection[j] = null;
787					}
788					else
789					{
790						couponsCollection[j].couponUpdate = null;
791					}
792				}
793			}
794			else
795			{
796				for (i = 0; i < res.COUPON_LIST.length; i++)
797				{
798					couponCreate(couponBlock, res.COUPON_LIST[i]);
799				}
800			}
801		}
802	}
803	couponBlock = null;
804}
805
806function skuPropClickHandler()
807{
808	var target = this,
809		basketItemId,
810		property,
811		property_values = {},
812		postData = {},
813		action_var,
814		all_sku_props,
815		i,
816		sku_prop_value,
817		m;
818
819	if (!!target && target.hasAttribute('data-value-id'))
820	{
821		BX.showWait();
822
823		basketItemId = target.getAttribute('data-element');
824		property = target.getAttribute('data-property');
825		action_var = BX('action_var').value;
826
827		property_values[property] = BX.util.htmlspecialcharsback(target.getAttribute('data-value-id'));
828
829		// if already selected element is clicked
830		if (BX.hasClass(target, 'bx_active'))
831		{
832			BX.closeWait();
833			return;
834		}
835
836		// get other basket item props to get full unique set of props of the new product
837		all_sku_props = BX.findChildren(BX(basketItemId), {tagName: 'ul', className: 'sku_prop_list'}, true);
838		if (!!all_sku_props && all_sku_props.length > 0)
839		{
840			for (i = 0; all_sku_props.length > i; i++)
841			{
842				if (all_sku_props[i].id !== 'prop_' + property + '_' + basketItemId)
843				{
844					sku_prop_value = BX.findChildren(BX(all_sku_props[i].id), {tagName: 'li', className: 'bx_active'}, true);
845					if (!!sku_prop_value && sku_prop_value.length > 0)
846					{
847						for (m = 0; sku_prop_value.length > m; m++)
848						{
849							if (sku_prop_value[m].hasAttribute('data-value-id'))
850							{
851								property_values[sku_prop_value[m].getAttribute('data-property')] = BX.util.htmlspecialcharsback(sku_prop_value[m].getAttribute('data-value-id'));
852							}
853						}
854					}
855				}
856			}
857		}
858
859		postData = {
860			'basketItemId': basketItemId,
861			'sessid': BX.bitrix_sessid(),
862			'site_id': BX.message('SITE_ID'),
863			'props': property_values,
864			'action_var': action_var,
865			'select_props': BX('column_headers').value,
866			'offers_props': BX('offers_props').value,
867			'quantity_float': BX('quantity_float').value,
868			'price_vat_show_value': BX('price_vat_show_value').value,
869			'hide_coupon': BX('hide_coupon').value,
870			'use_prepayment': BX('use_prepayment').value
871		};
872
873		postData[action_var] = 'select_item';
874
875		BX.ajax({
876			url: '/bitrix/components/bitrix/sale.basket.basket/ajax.php',
877			method: 'POST',
878			data: postData,
879			dataType: 'json',
880			onsuccess: function(result)
881			{
882				BX.closeWait();
883				updateBasketTable(basketItemId, result);
884			}
885		});
886	}
887}
888
889function getColumnName(result, columnCode)
890{
891	if (BX('col_' + columnCode))
892	{
893		return BX.util.trim(BX('col_' + columnCode).innerHTML);
894	}
895	else
896	{
897		return '';
898	}
899}
900
901function leftScroll(prop, id, count)
902{
903	count = parseInt(count, 10);
904	var el = BX('prop_' + prop + '_' + id);
905
906	if (el)
907	{
908		var curVal = parseInt(el.style.marginLeft, 10);
909		if (curVal <= -20)
910			el.style.marginLeft = curVal + 20 + '%';
911	}
912}
913
914function rightScroll(prop, id, count)
915{
916	count = parseInt(count, 10);
917
918	var el = BX('prop_' + prop + '_' + id);
919
920	if (el)
921	{
922		var curVal = parseInt(el.style.marginLeft, 10);
923		if (curVal > (5 - count)*20)
924			el.style.marginLeft = curVal - 20 + '%';
925	}
926}
927
928function checkOut()
929{
930	if (!!BX('coupon'))
931		BX('coupon').disabled = true;
932	BX("basket_form").submit();
933	return true;
934}
935
936function updateBasket()
937{
938    deleteNotChosen();
939	recalcBasketAjax({});
940}
941
942function enterCoupon()
943{
944	var newCoupon = BX('coupon');
945	if (!!newCoupon && !!newCoupon.value)
946		recalcBasketAjax({'coupon' : newCoupon.value});
947}
948function deleteNotChosen () {
949    if (document.querySelector('.basket-item-scu-item'))    {
950        document.querySelectorAll('.basket-item-scu-item').forEach(item => {
951            if (item.getAttribute('data-sku-name').trim() == 'Не выбрано') {
952                item.remove();
953            }
954        })
955    }
956}
957deleteNotChosen();
958setInterval(() => {
959    deleteNotChosen();
960}, 500)
961// check if quantity is valid
962// and update values of both controls (text input field for PC and mobile quantity select) simultaneously
963function updateQuantity(controlId, basketId, ratio, bUseFloatQuantity)
964{
965	var oldVal = BX(controlId).defaultValue,
966		newVal = parseFloat(BX(controlId).value) || 0,
967		bIsCorrectQuantityForRatio = false,
968		autoCalculate = ((BX("auto_calculation") && BX("auto_calculation").value == "Y") || !BX("auto_calculation"));
969
970	if (ratio === 0 || ratio == 1)
971	{
972		bIsCorrectQuantityForRatio = true;
973	}
974	else
975	{
976
977		var newValInt = newVal * 10000,
978			ratioInt = ratio * 10000,
979			reminder = newValInt % ratioInt,
980			newValRound = parseInt(newVal);
981
982		if (reminder === 0)
983		{
984			bIsCorrectQuantityForRatio = true;
985		}
986	}
987
988	var bIsQuantityFloat = false;
989
990	if (parseInt(newVal) != parseFloat(newVal))
991	{
992		bIsQuantityFloat = true;
993	}
994
995	newVal = (bUseFloatQuantity === false && bIsQuantityFloat === false) ? parseInt(newVal) : parseFloat(newVal).toFixed(4);
996	newVal = correctQuantity(newVal);
997
998	if (bIsCorrectQuantityForRatio)
999	{
1000		BX(controlId).defaultValue = newVal;
1001
1002		BX("QUANTITY_INPUT_" + basketId).value = newVal;
1003
1004		// set hidden real quantity value (will be used in actual calculation)
1005		BX("QUANTITY_" + basketId).value = newVal;
1006
1007		if (autoCalculate)
1008		{
1009			basketPoolQuantity.changeQuantity(basketId);
1010		}
1011	}
1012	else
1013	{
1014		newVal = getCorrectRatioQuantity(newVal, ratio, bUseFloatQuantity);
1015		newVal = correctQuantity(newVal);
1016
1017		if (newVal != oldVal)
1018		{
1019			BX("QUANTITY_INPUT_" + basketId).value = newVal;
1020			BX("QUANTITY_" + basketId).value = newVal;
1021
1022			if (autoCalculate)
1023			{
1024				basketPoolQuantity.changeQuantity(basketId);
1025			}
1026		}else
1027		{
1028			BX(controlId).value = oldVal;
1029		}
1030	}
1031    deleteNotChosen();
1032}
1033
1034// used when quantity is changed by clicking on arrows
1035function setQuantity(basketId, ratio, sign, bUseFloatQuantity)
1036{
1037	var curVal = parseFloat(BX("QUANTITY_INPUT_" + basketId).value),
1038		newVal;
1039
1040	newVal = (sign == 'up') ? curVal + ratio : curVal - ratio;
1041
1042	if (newVal < 0)
1043		newVal = 0;
1044
1045	if (bUseFloatQuantity)
1046	{
1047		newVal = parseFloat(newVal).toFixed(4);
1048	}
1049	newVal = correctQuantity(newVal);
1050
1051	if (ratio > 0 && newVal < ratio)
1052	{
1053		newVal = ratio;
1054	}
1055
1056	if (!bUseFloatQuantity && newVal != newVal.toFixed(4))
1057	{
1058		newVal = parseFloat(newVal).toFixed(4);
1059	}
1060
1061	newVal = getCorrectRatioQuantity(newVal, ratio, bUseFloatQuantity);
1062	newVal = correctQuantity(newVal);
1063
1064	BX("QUANTITY_INPUT_" + basketId).value = newVal;
1065	BX("QUANTITY_INPUT_" + basketId).defaultValue = newVal;
1066
1067	updateQuantity('QUANTITY_INPUT_' + basketId, basketId, ratio, bUseFloatQuantity);
1068    deleteNotChosen();
1069}
1070
1071function getCorrectRatioQuantity(quantity, ratio, bUseFloatQuantity)
1072{
1073	var newValInt = quantity * 10000,
1074		ratioInt = ratio * 10000,
1075		reminder = (quantity / ratio - ((quantity / ratio).toFixed(0))).toFixed(6),
1076		result = quantity,
1077		bIsQuantityFloat = false,
1078		i;
1079	ratio = parseFloat(ratio);
1080
1081	if (reminder == 0)
1082	{
1083		return result;
1084	}
1085
1086	if (ratio !== 0 && ratio != 1)
1087	{
1088		for (i = ratio, max = parseFloat(quantity) + parseFloat(ratio); i <= max; i = parseFloat(parseFloat(i) + parseFloat(ratio)).toFixed(4))
1089		{
1090			result = i;
1091		}
1092
1093	}else if (ratio === 1)
1094	{
1095		result = quantity | 0;
1096	}
1097
1098	if (parseInt(result, 10) != parseFloat(result))
1099	{
1100		bIsQuantityFloat = true;
1101	}
1102
1103	result = (bUseFloatQuantity === false && bIsQuantityFloat === false) ? parseInt(result, 10) : parseFloat(result).toFixed(4);
1104	result = correctQuantity(result);
1105	return result;
1106}
1107
1108function correctQuantity(quantity)
1109{
1110	return parseFloat((quantity * 1).toString());
1111}
1112
1113
1114/**
1115 *
1116 * @param {} params
1117 */
1118function recalcBasketAjax(params)
1119{
1120	if (basketPoolQuantity.isProcessing())
1121	{
1122		return false;
1123	}
1124
1125	BX.showWait();
1126
1127	var property_values = {},
1128		action_var = BX('action_var').value,
1129		items = BX('basket_items'),
1130		delayedItems = BX('delayed_items'),
1131		postData,
1132		i;
1133
1134	postData = {
1135		'sessid': BX.bitrix_sessid(),
1136		'site_id': BX.message('SITE_ID'),
1137		'props': property_values,
1138		'action_var': action_var,
1139		'select_props': BX('column_headers').value,
1140		'offers_props': BX('offers_props').value,
1141		'quantity_float': BX('quantity_float').value,
1142		'price_vat_show_value': BX('price_vat_show_value').value,
1143		'hide_coupon': BX('hide_coupon').value,
1144		'use_prepayment': BX('use_prepayment').value
1145	};
1146	postData[action_var] = 'recalculate';
1147	if (!!params && typeof params === 'object')
1148	{
1149		for (i in params)
1150		{
1151			if (params.hasOwnProperty(i))
1152				postData[i] = params[i];
1153		}
1154	}
1155
1156	if (!!items && items.rows.length > 0)
1157	{
1158		for (i = 1; items.rows.length > i; i++)
1159			postData['QUANTITY_' + items.rows[i].id] = BX('QUANTITY_' + items.rows[i].id).value;
1160	}
1161
1162	if (!!delayedItems && delayedItems.rows.length > 0)
1163	{
1164		for (i = 1; delayedItems.rows.length > i; i++)
1165			postData['DELAY_' + delayedItems.rows[i].id] = 'Y';
1166	}
1167
1168	basketPoolQuantity.setProcessing(true);
1169	basketPoolQuantity.clearPool();
1170
1171	BX.ajax({
1172		url: '/bitrix/components/bitrix/sale.basket.basket/ajax.php',
1173		method: 'POST',
1174		data: postData,
1175		dataType: 'json',
1176		onsuccess: function(result)
1177		{
1178			BX.closeWait();
1179			basketPoolQuantity.setProcessing(false);
1180
1181			if(params.coupon)
1182			{
1183				//hello, gifts!
1184				if(!!result && !!result.BASKET_DATA && !!result.BASKET_DATA.NEED_TO_RELOAD_FOR_GETTING_GIFT
1184S)
1185				{
1186					BX.reload();
1187				}
1188			}
1189
1190			if (basketPoolQuantity.isPoolEmpty())
1191			{
1192				updateBasketTable(null, result);
1193				basketPoolQuantity.updateQuantity();
1194			}
1195			else
1196			{
1197				basketPoolQuantity.enableTimer(true);
1198			}
1199		}
1200	});
1201}
1202
1203function showBasketItemsList(val)
1204{
1205	BX.removeClass(BX("basket_toolbar_button"), "current");
1206	BX.removeClass(BX("basket_toolbar_button_delayed"), "current");
1207	BX.removeClass(BX("basket_toolbar_button_subscribed"), "current");
1208	BX.removeClass(BX("basket_toolbar_button_not_available"), "current");
1209
1210	BX("normal_count").style.display = 'inline-block';
1211	BX("delay_count").style.display = 'inline-block';
1212	BX("subscribe_count").style.display = 'inline-block';
1213	BX("not_available_count").style.display = 'inline-block';
1214
1215	if (val == 2)
1216	{
1217		if (BX("basket_items_list"))
1218			BX("basket_items_list").style.display = 'none';
1219		if (BX("basket_items_delayed"))
1220		{
1221			BX("basket_items_delayed").style.display = 'block';
1222			BX.addClass(BX("basket_toolbar_button_delayed"), "current");
1223			BX("delay_count").style.display = 'none';
1224		}
1225		if (BX("basket_items_subscribed"))
1226			BX("basket_items_subscribed").style.display = 'none';
1227		if (BX("basket_items_not_available"))
1228			BX("basket_items_not_available").style.display = 'none';
1229	}
1230	else if(val == 3)
1231	{
1232		if (BX("basket_items_list"))
1233			BX("basket_items_list").style.display = 'none';
1234		if (BX("basket_items_delayed"))
1235			BX("basket_items_delayed").style.display = 'none';
1236		if (BX("basket_items_subscribed"))
1237		{
1238			BX("basket_items_subscribed").style.display = 'block';
1239			BX.addClass(BX("basket_toolbar_button_subscribed"), "current");
1240			BX("subscribe_count").style.display = 'none';
1241		}
1242		if (BX("basket_items_not_available"))
1243			BX("basket_items_not_available").style.display = 'none';
1244	}
1245	else if (val == 4)
1246	{
1247		if (BX("basket_items_list"))
1248			BX("basket_items_list").style.display = 'none';
1249		if (BX("basket_items_delayed"))
1250			BX("basket_items_delayed").style.display = 'none';
1251		if (BX("basket_items_subscribed"))
1252			BX("basket_items_subscribed").style.display = 'none';
1253		if (BX("basket_items_not_available"))
1254		{
1255			BX("basket_items_not_available").style.display = 'block';
1256			BX.addClass(BX("basket_toolbar_button_not_available"), "current");
1257			BX("not_available_count").style.display = 'none';
1258		}
1259	}
1260	else
1261	{
1262		if (BX("basket_items_list"))
1263		{
1264			BX("basket_items_list").style.display = 'block';
1265			BX.addClass(BX("basket_toolbar_button"), "current");
1266			BX("normal_count").style.display = 'none';
1267		}
1268		if (BX("basket_items_delayed"))
1269			BX("basket_items_delayed").style.display = 'none';
1270		if (BX("basket_items_subscribed"))
1271			BX("basket_items_subscribed").style.display = 'none';
1272		if (BX("basket_items_not_available"))
1273			BX("basket_items_not_available").style.display = 'none';
1274	}
1275}
1276
1277function deleteCoupon()
1278{
1279	var target = this,
1280		value;
1281
1282	if (BX.type.isElementNode(target) && target.hasAttribute('data-coupon'))
1283	{
1284		value = target.getAttribute('data-coupon');
1285		if (BX.type.isNotEmptyString(value))
1286		{
1287			recalcBasketAjax({'delete_coupon' : value});
1288		}
1289	}
1290}
1291
1292function deleteProductRow(target)
1293{
1294	var targetRow = BX.findParent(target, {tagName: 'TR'}),
1295		quantityNode,
1296		delItem;
1297
1298	if (targetRow)
1299	{
1300		quantityNode = BX('QUANTITY_' + targetRow.id);
1301		if (quantityNode)
1302		{
1303			delItem = getCurrentItemAnalyticsInfo(targetRow, quantityNode.value);
1304		}
1305	}
1306
1307	setAnalyticsDataLayer([], [delItem]);
1308
1309	document.location.href = target.href;
1310
1311	return false;
1312}
1313
1314function checkAnalytics(currentQuantity, newItems)
1315{
1316	if (!currentQuantity || !newItems || BX.util.array_values(currentQuantity).length === 0)
1317		return;
1318
1319	var itemId, diff,
1320		current = {}, addItems = [], delItems = [],
1321		i;
1322
1323	if (!!newItems && newItems.rows.length)
1324	{
1325		for (i = 1; newItems.rows.length > i; i++)
1326		{
1327			itemId = newItems.rows[i].id;
1328			diff = BX('QUANTITY_' + itemId).value - currentQuantity[itemId];
1329
1330			if (diff != 0)
1331			{
1332				current = getCurrentItemAnalyticsInfo(newItems.rows[i], diff);
1333
1334				if (diff > 0)
1335				{
1336					addItems.push(current);
1337				}
1338				else
1339				{
1340					delItems.push(current);
1341				}
1342			}
1343		}
1344	}
1345
1346	if (addItems.length || delItems.length)
1347	{
1348		setAnalyticsDataLayer(addItems, delItems);
1349	}
1350}
1351
1352function getCurrentItemAnalyticsInfo(row, diff)
1353{
1354	if (!row)
1355		return;
1356
1357	var temp, k, variants = [];
1358
1359	var current = {
1360		'name': row.getAttribute('data-item-name') || '',
1361		'id': row.id,
1362		'price': row.getAttribute('data-item-price') || 0,
1363		'brand': (row.getAttribute('data-item-brand') || '').split(',  ').join('/'),
1364		'variant': '',
1365		'quantity': Math.abs(diff)
1366	};
1367
1368	temp = row.querySelectorAll('.bx_active[data-sku-name]');
1369	for (k = 0; k < temp.length; k++)
1370	{
1371		variants.push(temp[k].getAttribute('data-sku-name'));
1372	}
1373
1374	current.variant = variants.join('/');
1375
1376	return current;
1377}
1378
1379function setAnalyticsDataLayer(addItems, delItems)
1380{
1381	window[basketJSParams['DATA_LAYER_NAME']] = window[basketJSParams['DATA_LAYER_NAME']] || [];
1382
1383	if (addItems && addItems.length)
1384	{
1385		window[basketJSParams['DATA_LAYER_NAME']].push({
1386			'event': 'addToCart',
1387			'ecommerce': {
1388				'currencyCode': getCurrencyCode(),
1389				'add': {
1390					'products': addItems
1391				}
1392			}
1393		});
1394	}
1395
1396	if (delItems && delItems.length)
1397	{
1398		window[basketJSParams['DATA_LAYER_NAME']].push({
1399			'event': 'removeFromCart',
1400			'ecommerce': {
1401				'currencyCode': getCurrencyCode(),
1402				'remove': {
1403					'products': delItems
1404				}
1405			}
1406		});
1407	}
1408}
1409
1410function getCurrencyCode()
1411{
1412	var root = BX('basket_items'),
1413		node,
1414		currency = '';
1415
1416	if (root)
1417	{
1418		node = root.querySelector('[data-item-currency');
1419		node && (currency = node.getAttribute('data-item-currency'));
1420	}
1421
1422	return currency;
1423
1424
1425}
1426
1427BX.ready(function() {
1428
1429	if (typeof basketJSParams === 'undefined') return;
1430
1431	basketPoolQuantity = new BasketPoolQuantity();
1432	var couponBlock = BX('coupons_block'),
1433		basketItems = BX('basket_items');
1434
1435	if (BX.type.isElementNode(couponBlock))
1436		BX.bindDelegate(couponBlock, 'click', { 'attribute': 'data-coupon' }, deleteCoupon);
1437
1438	if (BX.type.isElementNode(basketItems))
1439		BX.bindDelegate(basketItems, 'click', {tagName: 'li', 'attr': { 'data-sku-selector': 'Y' }}, skuPropClickHandler);
1440
1441	if (basketJSParams && BX.type.isNotEmptyString(basketJSParams['EVENT_ONCHANGE_ON_START']) && basketJSParams['EVENT_ONCHANGE_ON_START'] == "Y")
1442		BX.onCustomEvent('OnBasketChange');
1443});
1444
1445/* End */
1446;
1447; /* Start:"a:4:{s:4:"full";s:104:"/local/templates/fabrika38/components/bitrix/sale.basket.basket/basket_38/js/mustache.js?175439056419670";s:6:"source";s:88:"/local/templates/fabrika38/components/bitrix/sale.basket.basket/basket_38/js/mustache.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
1448/*!
1449 * mustache.js - Logic-less {{mustache}} templates with JavaScript
1450 * http://github.com/janl/mustache.js
1451 *
1452 * Copyright (c) 2009 Chris Wanstrath (Ruby)
1453 * Copyright (c) 2010-2014 Jan Lehnardt (JavaScript)
1454 * Copyright (c) 2010-2015 The mustache.js community
1455 *
1456 * Licensed under MIT (https://github.com/janl/mustache.js/blob/master/LICENSE)
1457 */
1458
vendor: 10,901 bytes, lines 1459-1833
1459/*global define: false Mustache: true*/
1460
1461(function defineMustache (global, factory) {
1462  if (typeof exports === 'object' && exports && typeof exports.nodeName !== 'string') {
1463    factory(exports); // CommonJS
1464  } else if (typeof define === 'function' && define.amd) {
1465    define(['exports'], factory); // AMD
1466  } else {
1467    global.Mustache = {};
1468    factory(global.Mustache); // script, wsh, asp
1469  }
1470}(this, function mustacheFactory (mustache) {
1471
1472  var objectToString = Object.prototype.toString;
1473  var isArray = Array.isArray || function isArrayPolyfill (object) {
1474    return objectToString.call(object) === '[object Array]';
1475  };
1476
1477  function isFunction (object) {
1478    return typeof object === 'function';
1479  }
1480
1481  /**
1482   * More correct typeof string handling array
1483   * which normally returns typeof 'object'
1484   */
1485  function typeStr (obj) {
1486    return isArray(obj) ? 'array' : typeof obj;
1487  }
1488
1489  function escapeRegExp (string) {
1490    return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&');
1491  }
1492
1493  /**
1494   * Null safe way of checking whether or not an object,
1495   * including its prototype, has a given property
1496   */
1497  function hasProperty (obj, propName) {
1498    return obj != null && typeof obj === 'object' && (propName in obj);
1499  }
1500
1501  // Workaround for https://issues.apache.org/jira/browse/COUCHDB-577
1502  // See https://github.com/janl/mustache.js/issues/189
1503  var regExpTest = RegExp.prototype.test;
1504  function testRegExp (re, string) {
1505    return regExpTest.call(re, string);
1506  }
1507
1508  var nonSpaceRe = /\S/;
1509  function isWhitespace (string) {
1510    return !testRegExp(nonSpaceRe, string);
1511  }
1512
1513  var entityMap = {
1514    '&': '&amp;',
1515    '<': '&lt;',
1516    '>': '&gt;',
1517    '"': '&quot;',
1518    "'": '&#39;',
1519    '/': '&#x2F;',
1520    '`': '&#x60;',
1521    '=': '&#x3D;'
1522  };
1523
1524  function escapeHtml (string) {
1525    return String(string).replace(/[&<>"'`=\/]/g, function fromEntityMap (s) {
1526      return entityMap[s];
1527    });
1528  }
1529
1530  var whiteRe = /\s*/;
1531  var spaceRe = /\s+/;
1532  var equalsRe = /\s*=/;
1533  var curlyRe = /\s*\}/;
1534  var tagRe = /#|\^|\/|>|\{|&|=|!/;
1535
1536  /**
1537   * Breaks up the given `template` string into a tree of tokens. If the `tags`
1538   * argument is given here it must be an array with two string values: the
1539   * opening and closing tags used in the template (e.g. [ "<%", "%>" ]). Of
1540   * course, the default is to use mustaches (i.e. mustache.tags).
1541   *
1542   * A token is an array with at least 4 elements. The first element is the
1543   * mustache symbol that was used inside the tag, e.g. "#" or "&". If the tag
1544   * did not contain a symbol (i.e. {{myValue}}) this element is "name". For
1545   * all text that appears outside a symbol this element is "text".
1546   *
1547   * The second element of a token is its "value". For mustache tags this is
1548   * whatever else was inside the tag besides the opening symbol. For text tokens
1549   * this is the text itself.
1550   *
1551   * The third and fourth elements of the token are the start and end indices,
1552   * respectively, of the token in the original template.
1553   *
1554   * Tokens that are the root node of a subtree contain two more elements: 1) an
1555   * array of tokens in the subtree and 2) the index in the original template at
1556   * which the closing tag for that section begins.
1557   */
1558  function parseTemplate (template, tags) {
1559    if (!template)
1560      return [];
1561
1562    var sections = [];     // Stack to hold section tokens
1563    var tokens = [];       // Buffer to hold the tokens
1564    var spaces = [];       // Indices of whitespace tokens on the current line
1565    var hasTag = false;    // Is there a {{tag}} on the current line?
1566    var nonSpace = false;  // Is there a non-space char on the current line?
1567
1568    // Strips all whitespace tokens array for the current line
1569    // if there was a {{#tag}} on it and otherwise only space.
1570    function stripSpace () {
1571      if (hasTag && !nonSpace) {
1572        while (spaces.length)
1573          delete tokens[spaces.pop()];
1574      } else {
1575        spaces = [];
1576      }
1577
1578      hasTag = false;
1579      nonSpace = false;
1580    }
1581
1582    var openingTagRe, closingTagRe, closingCurlyRe;
1583    function compileTags (tagsToCompile) {
1584      if (typeof tagsToCompile === 'string')
1585        tagsToCompile = tagsToCompile.split(spaceRe, 2);
1586
1587      if (!isArray(tagsToCompile) || tagsToCompile.length !== 2)
1588        throw new Error('Invalid tags: ' + tagsToCompile);
1589
1590      openingTagRe = new RegExp(escapeRegExp(tagsToCompile[0]) + '\\s*');
1591      closingTagRe = new RegExp('\\s*' + escapeRegExp(tagsToCompile[1]));
1592      closingCurlyRe = new RegExp('\\s*' + escapeRegExp('}' + tagsToCompile[1]));
1593    }
1594
1595    compileTags(tags || mustache.tags);
1596
1597    var scanner = new Scanner(template);
1598
1599    var start, type, value, chr, token, openSection;
1600    while (!scanner.eos()) {
1601      start = scanner.pos;
1602
1603      // Match any text between tags.
1604      value = scanner.scanUntil(openingTagRe);
1605
1606      if (value) {
1607        for (var i = 0, valueLength = value.length; i < valueLength; ++i) {
1608          chr = value.charAt(i);
1609
1610          if (isWhitespace(chr)) {
1611            spaces.push(tokens.length);
1612          } else {
1613            nonSpace = true;
1614          }
1615
1616          tokens.push([ 'text', chr, start, start + 1 ]);
1617          start += 1;
1618
1619          // Check for whitespace on the current line.
1620          if (chr === '\n')
1621            stripSpace();
1622        }
1623      }
1624
1625      // Match the opening tag.
1626      if (!scanner.scan(openingTagRe))
1627        break;
1628
1629      hasTag = true;
1630
1631      // Get the tag type.
1632      type = scanner.scan(tagRe) || 'name';
1633      scanner.scan(whiteRe);
1634
1635      // Get the tag value.
1636      if (type === '=') {
1637        value = scanner.scanUntil(equalsRe);
1638        scanner.scan(equalsRe);
1639        scanner.scanUntil(closingTagRe);
1640      } else if (type === '{') {
1641        value = scanner.scanUntil(closingCurlyRe);
1642        scanner.scan(curlyRe);
1643        scanner.scanUntil(closingTagRe);
1644        type = '&';
1645      } else {
1646        value = scanner.scanUntil(closingTagRe);
1647      }
1648
1649      // Match the closing tag.
1650      if (!scanner.scan(closingTagRe))
1651        throw new Error('Unclosed tag at ' + scanner.pos);
1652
1653      token = [ type, value, start, scanner.pos ];
1654      tokens.push(token);
1655
1656      if (type === '#' || type === '^') {
1657        sections.push(token);
1658      } else if (type === '/') {
1659        // Check section nesting.
1660        openSection = sections.pop();
1661
1662        if (!openSection)
1663          throw new Error('Unopened section "' + value + '" at ' + start);
1664
1665        if (openSection[1] !== value)
1666          throw new Error('Unclosed section "' + openSection[1] + '" at ' + start);
1667      } else if (type === 'name' || type === '{' || type === '&') {
1668        nonSpace = true;
1669      } else if (type === '=') {
1670        // Set the tags for the next time around.
1671        compileTags(value);
1672      }
1673    }
1674
1675    // Make sure there are no open sections when we're done.
1676    openSection = sections.pop();
1677
1678    if (openSection)
1679      throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos);
1680
1681    return nestTokens(squashTokens(tokens));
1682  }
1683
1684  /**
1685   * Combines the values of consecutive text tokens in the given `tokens` array
1686   * to a single token.
1687   */
1688  function squashTokens (tokens) {
1689    var squashedTokens = [];
1690
1691    var token, lastToken;
1692    for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
1693      token = tokens[i];
1694
1695      if (token) {
1696        if (token[0] === 'text' && lastToken && lastToken[0] === 'text') {
1697          lastToken[1] += token[1];
1698          lastToken[3] = token[3];
1699        } else {
1700          squashedTokens.push(token);
1701          lastToken = token;
1702        }
1703      }
1704    }
1705
1706    return squashedTokens;
1707  }
1708
1709  /**
1710   * Forms the given array of `tokens` into a nested tree structure where
1711   * tokens that represent a section have two additional items: 1) an array of
1712   * all tokens that appear in that section and 2) the index in the original
1713   * template that represents the end of that section.
1714   */
1715  function nestTokens (tokens) {
1716    var nestedTokens = [];
1717    var collector = nestedTokens;
1718    var sections = [];
1719
1720    var token, section;
1721    for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
1722      token = tokens[i];
1723
1724      switch (token[0]) {
1725        case '#':
1726        case '^':
1727          collector.push(token);
1728          sections.push(token);
1729          collector = token[4] = [];
1730          break;
1731        case '/':
1732          section = sections.pop();
1733          section[5] = token[2];
1734          collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens;
1735          break;
1736        default:
1737          collector.push(token);
1738      }
1739    }
1740
1741    return nestedTokens;
1742  }
1743
1744  /**
1745   * A simple string scanner that is used by the template parser to find
1746   * tokens in template strings.
1747   */
1748  function Scanner (string) {
1749    this.string = string;
1750    this.tail = string;
1751    this.pos = 0;
1752  }
1753
1754  /**
1755   * Returns `true` if the tail is empty (end of string).
1756   */
1757  Scanner.prototype.eos = function eos () {
1758    return this.tail === '';
1759  };
1760
1761  /**
1762   * Tries to match the given regular expression at the current position.
1763   * Returns the matched text if it can match, the empty string otherwise.
1764   */
1765  Scanner.prototype.scan = function scan (re) {
1766    var match = this.tail.match(re);
1767
1768    if (!match || match.index !== 0)
1769      return '';
1770
1771    var string = match[0];
1772
1773    this.tail = this.tail.substring(string.length);
1774    this.pos += string.length;
1775
1776    return string;
1777  };
1778
1779  /**
1780   * Skips all text until the given regular expression can be matched. Returns
1781   * the skipped string, which is the entire tail if no match can be made.
1782   */
1783  Scanner.prototype.scanUntil = function scanUntil (re) {
1784    var index = this.tail.search(re), match;
1785
1786    switch (index) {
1787      case -1:
1788        match = this.tail;
1789        this.tail = '';
1790        break;
1791      case 0:
1792        match = '';
1793        break;
1794      default:
1795        match = this.tail.substring(0, index);
1796        this.tail = this.tail.substring(index);
1797    }
1798
1799    this.pos += match.length;
1800
1801    return match;
1802  };
1803
1804  /**
1805   * Represents a rendering context by wrapping a view object and
1806   * maintaining a reference to the parent context.
1807   */
1808  function Context (view, parentContext) {
1809    this.view = view;
1810    this.cache = { '.': this.view };
1811    this.parent = parentContext;
1812  }
1813
1814  /**
1815   * Creates a new context using the given view with this context
1816   * as the parent.
1817   */
1818  Context.prototype.push = function push (view) {
1819    return new Context(view, this);
1820  };
1821
1822  /**
1823   * Returns the value of the given name in this context, traversing
1824   * up the context hierarchy if the value is absent in this context's view.
1825   */
1826  Context.prototype.lookup = function lookup (name) {
1827    var cache = this.cache;
1828
1829    var value;
1830    if (cache.hasOwnProperty(name)) {
1831      value = cache[name];
1832    } else {
1833      var context = this, names, index, lookupHit = false;
1834
1835      while (context) {
1836        if (name.indexOf('.') > 0) {
1837          value = context.view;
1838          names = name.split('.');
1839          index = 0;
1840
1841          /**
1842           * Using the dot notion path in `name`, we descend through the
1843           * nested objects.
1844           *
1845           * To be certain that the lookup has been successful, we have to
1846           * check if the last object in the path actually has the property
1847           * we are looking for. We store the result in `lookupHit`.
1848           *
1849           * This is specially necessary for when the value has been set to
1850           * `undefined` and we want to avoid looking up parent contexts.
1851           **/
1852          while (value != null && index < names.length) {
1853            if (index === names.length - 1)
1854              lookupHit = hasProperty(value, names[index]);
1855
1856            value = value[names[index++]];
1857          }
1858        } else {
1859          value = context.view[name];
1860          lookupHit = hasProperty(context.view, name);
1861        }
1862
1863        if (lookupHit)
1864          break;
1865
1866        context = context.parent;
1867      }
1868
1869      cache[name] = value;
1870    }
1871
1872    if (isFunction(value))
1873      value = value.call(this.view);
1874
1875    return value;
1876  };
1877
1878  /**
1879   * A Writer knows how to take a stream of tokens and render them to a
1880   * string, given a context. It also maintains a cache of templates to
1881   * avoid the need to parse the same template twice.
1882   */
1883  function Writer () {
1884    this.cache = {};
1885  }
1886
1887  /**
1888   * Clears all cached templates in this writer.
1889   */
1890  Writer.prototype.clearCache = function clearCache () {
1891    this.cache = {};
1892  };
1893
1894  /**
1895   * Parses and caches the given `template` and returns the array of tokens
1896   * that is generated from the parse.
1897   */
1898  Writer.prototype.parse = function parse (template, tags) {
1899    var cache = this.cache;
1900    var tokens = cache[template];
1901
1902    if (tokens == null)
1903      tokens = cache[template + ':' + (tags || mustache.tags).join(':')] = parseTemplate(template, tags);
1904
1905    return tokens;
1906  };
1907
1908  /**
1909   * High-level method that is used to render the given `template` with
1910   * the given `view`.
1911   *
1912   * The optional `partials` argument may be an object that contains the
1913   * names and templates of partials that are used in the template. It may
1914   * also be a function that is used to load partial templates on the fly
1915   * that takes a single argument: the name of the partial.
1916   */
1917  Writer.prototype.render = function render (template, view, partials) {
1918    var tokens = this.parse(template);
1919    var context = (view instanceof Context) ? view : new Context(view);
1920    return this.renderTokens(tokens, context, partials, template);
1921  };
1922
1923  /**
1924   * Low-level method that renders the given array of `tokens` using
1925   * the given `context` and `partials`.
1926   *
1927   * Note: The `originalTemplate` is only ever used to extract the portion
1928   * of the original template that was contained in a higher-order section.
1929   * If the template doesn't use higher-order sections, this argument may
1930   * be omitted.
1931   */
1932  Writer.prototype.renderTokens = function renderTokens (tokens, context, partials, originalTemplate) {
1933    var buffer = '';
1934
1935    var token, symbol, value;
1936    for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
1937      value = undefined;
1938      token = tokens[i];
1939      symbol = token[0];
1940
1941      if (symbol === '#') value = this.renderSection(token, context, partials, originalTemplate);
1942      else if (symbol === '^') value = this.renderInverted(token, context, partials, originalTemplate);
1943      else if (symbol === '>') value = this.renderPartial(token, context, partials, originalTemplate);
1944      else if (symbol === '&') value = this.unescapedValue(token, context);
1945      else if (symbol === 'name') value = this.escapedValue(token, context);
1946      else if (symbol === 'text') value = this.rawValue(token);
1947
1948      if (value !== undefined)
1949        buffer += value;
1950    }
1951
1952    return buffer;
1953  };
1954
vendor: 4,948 bytes, lines 1955-2097
1955  Writer.prototype.renderSection = function renderSection (token, context, partials, originalTemplate) {
1956    var self = this;
1957    var buffer = '';
1958    var value = context.lookup(token[1]);
1959
1960    // This function is used to render an arbitrary template
1961    // in the current context by higher-order sections.
1962    function subRender (template) {
1963      return self.render(template, context, partials);
1964    }
1965
1966    if (!value) return;
1967
1968    if (isArray(value)) {
1969      for (var j = 0, valueLength = value.length; j < valueLength; ++j) {
1970        buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate);
1971      }
1972    } else if (typeof value === 'object' || typeof value === 'string' || typeof value === 'number') {
1973      buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate);
1974    } else if (isFunction(value)) {
1975      if (typeof originalTemplate !== 'string')
1976        throw new Error('Cannot use higher-order sections without the original template');
1977
1978      // Extract the portion of the original template that the section contains.
1979      value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender);
1980
1981      if (value != null)
1982        buffer += value;
1983    } else {
1984      buffer += this.renderTokens(token[4], context, partials, originalTemplate);
1985    }
1986    return buffer;
1987  };
1988
1989  Writer.prototype.renderInverted = function renderInverted (token, context, partials, originalTemplate) {
1990    var value = context.lookup(token[1]);
1991
1992    // Use JavaScript's definition of falsy. Include empty arrays.
1993    // See https://github.com/janl/mustache.js/issues/186
1994    if (!value || (isArray(value) && value.length === 0))
1995      return this.renderTokens(token[4], context, partials, originalTemplate);
1996  };
1997
1998  Writer.prototype.renderPartial = function renderPartial (token, context, partials) {
1999    if (!partials) return;
2000
2001    var value = isFunction(partials) ? partials(token[1]) : partials[token[1]];
2002    if (value != null)
2003      return this.renderTokens(this.parse(value), context, partials, value);
2004  };
2005
2006  Writer.prototype.unescapedValue = function unescapedValue (token, context) {
2007    var value = context.lookup(token[1]);
2008    if (value != null)
2009      return value;
2010  };
2011
2012  Writer.prototype.escapedValue = function escapedValue (token, context) {
2013    var value = context.lookup(token[1]);
2014    if (value != null)
2015      return mustache.escape(value);
2016  };
2017
2018  Writer.prototype.rawValue = function rawValue (token) {
2019    return token[1];
2020  };
2021
2022  mustache.name = 'mustache.js';
2023  mustache.version = '2.3.0';
2024  mustache.tags = [ '{{', '}}' ];
2025
2026  // All high-level mustache.* functions use this writer.
2027  var defaultWriter = new Writer();
2028
2029  /**
2030   * Clears all cached templates in the default writer.
2031   */
2032  mustache.clearCache = function clearCache () {
2033    return defaultWriter.clearCache();
2034  };
2035
2036  /**
2037   * Parses and caches the given template in the default writer and returns the
2038   * array of tokens it contains. Doing this ahead of time avoids the need to
2039   * parse templates on the fly as they are rendered.
2040   */
2041  mustache.parse = function parse (template, tags) {
2042    return defaultWriter.parse(template, tags);
2043  };
2044
2045  /**
2046   * Renders the `template` with the given `view` and `partials` using the
2047   * default writer.
2048   */
2049  mustache.render = function render (template, view, partials) {
2050    if (typeof template !== 'string') {
2051      throw new TypeError('Invalid template! Template should be a "string" ' +
2052                          'but "' + typeStr(template) + '" was given as the first ' +
2053                          'argument for mustache#render(template, view, partials)');
2054    }
2055
2056    return defaultWriter.render(template, view, partials);
2057  };
2058
2059  // This is here for backwards compatibility with 0.4.x.,
2060  /*eslint-disable */ // eslint wants camel cased function name
2061  mustache.to_html = function to_html (template, view, partials, send) {
2062    /*eslint-enable*/
2063
2064    var result = mustache.render(template, view, partials);
2065
2066    if (isFunction(send)) {
2067      send(result);
2068    } else {
2069      return result;
2070    }
2071  };
2072
2073  // Export the escaping function so that the user may override it.
2074  // See https://github.com/janl/mustache.js/issues/244
2075  mustache.escape = escapeHtml;
2076
2077  // Export these mainly for testing, but also for advanced usage.
2078  mustache.Scanner = Scanner;
2079  mustache.Context = Context;
2080  mustache.Writer = Writer;
2081
2082  return mustache;
2083}));
2084
2085/* End */
2086;
2087; /* Start:"a:4:{s:4:"full";s:106:"/local/templates/fabrika38/components/bitrix/sale.basket.basket/basket_38/js/action-pool.js?17543905645918";s:6:"source";s:91:"/local/templates/fabrika38/components/bitrix/sale.basket.basket/basket_38/js/action-pool.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
2088;(function(){
2089	'use strict';
2090
2091	BX.namespace('BX.Sale.BasketActionPool');
2092
2093	BX.Sale.BasketActionPool = function(component)
2094	{
2095		this.component = component;
2096
2097		this.requestProcessing = false;
2098		this.updateTimer = null;
2099
2100		this.isBasketRefreshed = this.component.params.DEFERRED_REFRESH !== 'Y';
2101		this.needFullRecalculation = this.component.params.DEFERRED_REFRESH === 'Y';
2102
2103		this.pool = {};
2104		this.lastActualPool = {};
2105
2106		this.approvedAction = ['QUANTITY', 'DELETE', 'RESTORE', 'DELAY', 'OFFER', 'MERGE_OFFER'];
2107
2108		this.switchTimer();
2109	};
2110
2111	BX.Sale.BasketActionPool.prototype.setRefreshStatus = function(status)
2112	{
2113		this.isBasketRefreshed = !!status;
2114	};
2115
2116	BX.Sale.BasketActionPool.prototype.getRefreshStatus = function()
2117	{
2118		return this.isBasketRefreshed;
2119	};
2120
2121	BX.Sale.BasketActionPool.prototype.isItemInPool = function(itemId)
2122	{
2123		return !!this.pool[itemId];
2124	};
2125
2126	BX.Sale.BasketActionPool.prototype.clearLastActualQuantityPool = function(itemId)
2127	{
2128		this.lastActualPool[itemId] && delete this.lastActualPool[itemId].QUANTITY;
2129	};
2130
2131	BX.Sale.BasketActionPool.prototype.checkItemPoolBefore = function(itemId)
2132	{
2133		if (!itemId)
2134			return;
2135
2136		this.pool[itemId] = this.pool[itemId] || {};
2137	};
2138
2139	BX.Sale.BasketActionPool.prototype.checkItemPoolAfter = function(itemId)
2140	{
2141		if (!itemId || !this.pool[itemId])
2142			return;
2143
2144		if (Object.keys(this.pool[itemId]).length === 0)
2145		{
2146			delete this.pool[itemId];
2147		}
2148	};
2149
2150	BX.Sale.BasketActionPool.prototype.addCoupon = function(coupon)
2151	{
2152		this.pool.COUPON = coupon;
2153
2154		this.switchTimer();
2155	};
2156
2157	BX.Sale.BasketActionPool.prototype.removeCoupon = function(coupon)
2158	{
2159		this.checkItemPoolBefore('REMOVE_COUPON');
2160
2161		this.pool.REMOVE_COUPON[coupon] = coupon;
2162
2163		this.switchTimer();
2164	};
2165
2166	BX.Sale.BasketActionPool.prototype.changeQuantity = function(itemId, quantity, oldQuantity)
2167	{
2168		this.checkItemPoolBefore(itemId);
2169
2170		if (
2171			(this.lastActualPool[itemId] && this.lastActualPool[itemId].QUANTITY !== quantity)
2172			|| (!this.lastActualPool[itemId] && quantity !== oldQuantity)
2173		)
2174		{
2175			this.pool[itemId].QUANTITY = quantity;
2176		}
2177		else
2178		{
2179			this.pool[itemId] && delete this.pool[itemId].QUANTITY;
2180		}
2181
2182		this.checkItemPoolAfter(itemId);
2183		this.switchTimer();
2184	};
2185
2186	BX.Sale.BasketActionPool.prototype.deleteItem = function(itemId)
2187	{
2188		this.checkItemPoolBefore(itemId);
2189
2190		if (this.pool[itemId].RESTORE)
2191		{
2192			delete this.pool[itemId].RESTORE;
2193		}
2194		else
2195		{
2196			this.pool[itemId].DELETE = 'Y';
2197		}
2198
2199		this.checkItemPoolAfter(itemId);
2200		this.switchTimer();
2201	};
2202
2203	BX.Sale.BasketActionPool.prototype.restoreItem = function(itemId, itemData)
2204	{
2205		this.checkItemPoolBefore(itemId);
2206
2207		if (this.pool[itemId].DELETE === 'Y')
2208		{
2209			delete this.pool[itemId].DELETE;
2210		}
2211		else
2212		{
2213			this.pool[itemId].RESTORE = itemData;
2214		}
2215
2216		this.checkItemPoolAfter(itemId);
2217		this.switchTimer();
2218	};
2219
2220	BX.Sale.BasketActionPool.prototype.addDelayed = function(itemId)
2221	{
2222		this.checkItemPoolBefore(itemId);
2223
2224		this.pool[itemId].DELAY = 'Y';
2225
2226		this.checkItemPoolAfter(itemId);
2227		this.switchTimer();
2228	};
2229
2230	BX.Sale.BasketActionPool.prototype.removeDelayed = function(itemId)
2231	{
2232		this.checkItemPoolBefore(itemId);
2233
2234		this.pool[itemId].DELAY = 'N';
2235
2236		this.checkItemPoolAfter(itemId);
2237		this.switchTimer();
2238	};
2239
2240	BX.Sale.BasketActionPool.prototype.changeSku = function(itemId, props, oldProps)
2241	{
2242		if (JSON.stringify(props) !== JSON.stringify(oldProps))
2243		{
2244			this.checkItemPoolBefore(itemId);
2245			this.pool[itemId].OFFER = props;
2246		}
2247		else
2248		{
2249			this.pool[itemId] && delete this.pool[itemId].OFFER;
2250			this.checkItemPoolAfter(itemId);
2251		}
2252
2253		this.switchTimer();
2254	};
2255
2256	BX.Sale.BasketActionPool.prototype.mergeSku = function(itemId)
2257	{
2258		this.checkItemPoolBefore(itemId);
2259		this.pool[itemId].MERGE_OFFER = 'Y';
2260
2261		this.switchTimer();
2262	};
2263
2264	BX.Sale.BasketActionPool.prototype.switchTimer = function()
2265	{
2266		clearTimeout(this.updateTimer);
2267
2268		if (this.isProcessing())
2269		{
2270			return;
2271		}
2272
2273		if (this.isPoolEmpty())
2274		{
2275			this.component.editPostponedBasketItems();
2276			this.component.fireCustomEvents();
2277		}
2278
2279		if (!this.isPoolEmpty())
2280		{
2281			this.updateTimer = setTimeout(BX.proxy(this.trySendPool, this), 300);
2282		}
2283		else if (!this.getRefreshStatus())
2284		{
2285			this.trySendPool();
2286		}
2287	};
2288
2289	BX.Sale.BasketActionPool.prototype.trySendPool = function()
2290	{
2291		if (this.isPoolEmpty() && this.getRefreshStatus())
2292		{
2293			return;
2294		}
2295
2296		this.doProcessing(true);
2297
2298		if (!this.isPoolEmpty())
2299		{
2300			this.component.sendRequest('recalculateAjax', {
2301				basket: this.getPoolData()
2302			});
2303
2304			this.lastActualPool = this.pool;
2305			this.pool = {};
2306		}
2307		else if (!this.getRefreshStatus())
2308		{
2309			this.component.sendRequest('refreshAjax', {
2310				fullRecalculation: this.needFullRecalculation ? 'Y' : 'N'
2311			});
2312			this.needFullRecalculation = false;
2313		}
2314	};
2315
2316	BX.Sale.BasketActionPool.prototype.getPoolData = function()
2317	{
2318		var poolData = {},
2319			currentPool = this.pool;
2320
2321		if (currentPool.COUPON)
2322		{
2323			poolData.coupon = currentPool.COUPON;
2324			delete currentPool.COUPON;
2325		}
2326
2327		if (currentPool.REMOVE_COUPON)
2328		{
2329			poolData.delete_coupon = currentPool.REMOVE_COUPON;
2330			delete currentPool.REMOVE_COUPON;
2331		}
2332
2333		for (var id in currentPool)
2334		{
2335			if (currentPool.hasOwnProperty(id))
2336			{
2337				for (var action in currentPool[id])
2338				{
2339					if (currentPool[id].hasOwnProperty(action) && BX.util.in_array(action, this.approvedAction))
2340					{
2341						poolData[action + '_' + id] = currentPool[id][action];
2342					}
2343				}
2344			}
2345		}
2346
2347		return poolData;
2348	};
2349
2350	BX.Sale.BasketActionPool.prototype.isPoolEmpty = function()
2351	{
2352		return Object.keys(this.pool).length === 0;
2353	};
2354
2355	BX.Sale.BasketActionPool.prototype.doProcessing = function(state)
2356	{
2357		this.requestProcessing = state === true;
2358
2359		if (this.requestProcessing)
2360		{
2361			this.component.startLoader();
2362		}
2363		else
2364		{
2365			this.component.endLoader();
2366		}
2367	};
2368
2369	BX.Sale.BasketActionPool.prototype.isProcessing = function()
2370	{
2371		return this.requestProcessing === true;
2372	};
2373})();
2374/* End */
2375;
2376; /* Start:"a:4:{s:4:"full";s:102:"/local/templates/fabrika38/components/bitrix/sale.basket.basket/basket_38/js/filter.js?175439056414092";s:6:"source";s:86:"/local/templates/fabrika38/components/bitrix/sale.basket.basket/basket_38/js/filter.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
2377;(function(){
2378	'use strict';
2379
2380	BX.namespace('BX.Sale.BasketFilter');
2381
2382	BX.Sale.BasketFilter = function(component)
2383	{
2384		this.component = component;
2385
2386		this.activeFilterMode = false;
2387		this.filterTimer = null;
2388		this.mouseOverClearFilter = false;
2389
2390		this.realShownItems = [];
2391		this.realSortedItems = [];
2392		this.realScrollTop = 0;
2393
2394		this.lastShownItemsHash = '';
2395		this.currentFilter = {
2396			query: '',
2397			similarHash: '',
2398			warning: false,
2399			notAvailable: false,
2400			delayed: false
2401		};
2402
2403		if (this.component.useItemsFilter)
2404		{
2405			this.bindEvents();
2406		}
2407	};
2408
2409	BX.Sale.BasketFilter.prototype.bindEvents = function()
2410	{
2411		var entity;
2412		var filterNode = this.component.getEntity(
2413			this.component.getCacheNode(this.component.ids.itemListWrapper),
2414			'basket-filter'
2415		);
2416
2417		entity = this.component.getEntity(filterNode, 'basket-filter-input');
2418		if (BX.type.isDomNode(entity))
2419		{
2420			BX.bind(entity, 'focus', function() {
2421				filterNode.style.flex = 3;
2422			});
2423			BX.bind(entity, 'blur', BX.delegate(function() {
2424				if (!this.mouseOverClearFilter)
2425				{
2426					filterNode.style.flex = '';
2427				}
2428			}, this));
2429
2430			BX.bind(entity, 'keyup', BX.proxy(this.onFilterInput, this));
2431			BX.bind(entity, 'cut', BX.proxy(this.onFilterInput, this));
2432			BX.bind(entity, 'paste', BX.proxy(this.onFilterInput, this));
2433		}
2434
2435		entity = this.component.getEntity(filterNode, 'basket-filter-clear-btn');
2436		if (BX.type.isDomNode(entity))
2437		{
2438			BX.bind(entity, 'mouseenter', BX.delegate(function() {
2439				this.mouseOverClearFilter = true;
2440			}, this));
2441			BX.bind(entity, 'mouseout', BX.delegate(function() {
2442				this.mouseOverClearFilter = false;
2443			}, this));
2444			BX.bind(entity, 'click', BX.delegate(function() {
2445				if (!this.filterInputEmpty())
2446				{
2447					this.clearFilterInput();
2448					this.onFilterChange();
2449				}
2450
2451				filterNode.style.flex = '';
2452			}, this));
2453		}
2454	};
2455
2456	BX.Sale.BasketFilter.prototype.isActive = function()
2457	{
2458		return this.activeFilterMode;
2459	};
2460
2461	BX.Sale.BasketFilter.prototype.showFilterByName = function(name)
2462	{
2463		if (!name)
2464			return;
2465
2466		switch (name)
2467		{
2468			case 'not-available':
2469				this.showNotAvailableItemsFilter();
2470				break;
2471			case 'delayed':
2472				this.showDelayItemsFilter();
2473				break;
2474			case 'warning':
2475				this.showWarningItemsFilter();
2476				break;
2477			case 'similar':
2478				this.showSimilarItemsFilter();
2479				break;
2480			case 'all':
2481			default:
2482				this.clearAllFiltersExcept([]);
2483				this.onFilterChange();
2484		}
2485	};
2486
2487	BX.Sale.BasketFilter.prototype.onFilterInput = function()
2488	{
2489		var value = BX.type.isDomNode(BX.proxy_context) ? BX.util.trim(BX.proxy_context.value).toLowerCase() : '';
2490
2491		if (this.currentFilter.query !== value)
2492		{
2493			this.currentFilter.query = value;
2494
2495			this.onFilterChange();
2496		}
2497	};
2498
2499	BX.Sale.BasketFilter.prototype.clearAllFiltersExcept = function(names)
2500	{
2501		if (!names || !BX.type.isArray(names))
2502			return;
2503
2504		!BX.util.in_array('input', names) && this.clearFilterInput();
2505		!BX.util.in_array('warning', names) && this.clearWarningItemsFilter();
2506		!BX.util.in_array('delayed', names) && this.clearDelayItemsFilter();
2507		!BX.util.in_array('not-available', names) && this.clearNotAvailableItemsFilter();
2508
2509		if (!BX.util.in_array('similar', names))
2510		{
2511			this.clearSimilarItemsFilter();
2512			this.component.showSimilarCount(false);
2513		}
2514	};
2515
2516	BX.Sale.BasketFilter.prototype.filterInputEmpty = function()
2517	{
2518		return this.currentFilter.query.length === 0;
2519	};
2520
2521	BX.Sale.BasketFilter.prototype.clearFilterInput = function()
2522	{
2523		this.currentFilter.query = '';
2524
2525		var input = this.component.getEntity(
2526			this.component.getCacheNode(this.component.ids.itemListWrapper),
2527			'basket-filter-input'
2528		);
2529		if (BX.type.isDomNode(input))
2530		{
2531			input.value = '';
2532		}
2533	};
2534
2535	BX.Sale.BasketFilter.prototype.addWarningItemsFilter = function()
2536	{
2537		this.currentFilter.warning = true;
2538	};
2539
2540	BX.Sale.BasketFilter.prototype.clearWarningItemsFilter = function()
2541	{
2542		this.currentFilter.warning = false;
2543	};
2544
2545	BX.Sale.BasketFilter.prototype.showWarningItemsFilter = function()
2546	{
2547		if (!this.currentFilter.warning)
2548		{
2549			this.clearAllFiltersExcept(['warning']);
2550			this.addWarningItemsFilter();
2551			this.onFilterChange();
2552		}
2553	};
2554
2555	BX.Sale.BasketFilter.prototype.addDelayItemsFilter = function()
2556	{
2557		this.currentFilter.delayed = true;
2558	};
2559
2560	BX.Sale.BasketFilter.prototype.clearDelayItemsFilter = function()
2561	{
2562		this.currentFilter.delayed = false;
2563	};
2564
2565	BX.Sale.BasketFilter.prototype.showDelayItemsFilter = function()
2566	{
2567		if (!this.currentFilter.delayed)
2568		{
2569			this.clearAllFiltersExcept(['delayed']);
2570			this.addDelayItemsFilter();
2571			this.onFilterChange();
2572		}
2573	};
2574
2575	BX.Sale.BasketFilter.prototype.addNotAvailableItemsFilter = function()
2576	{
2577		this.currentFilter.notAvailable = true;
2578	};
2579
2580	BX.Sale.BasketFilter.prototype.clearNotAvailableItemsFilter = function()
2581	{
2582		this.currentFilter.notAvailable = false;
2583	};
2584
2585	BX.Sale.BasketFilter.prototype.showNotAvailableItemsFilter = function()
2586	{
2587		if (!this.currentFilter.notAvailable)
2588		{
2589			this.clearAllFiltersExcept(['not-available']);
2590			this.addNotAvailableItemsFilter();
2591			this.onFilterChange();
2592		}
2593	};
2594
2595	BX.Sale.BasketFilter.prototype.addSimilarItemsFilter = function(item)
2596	{
2597		this.currentFilter.similarHash = item.HASH;
2598	};
2599
2600	BX.Sale.BasketFilter.prototype.clearSimilarItemsFilter = function()
2601	{
2602		this.currentFilter.similarHash = '';
2603	};
2604
2605	BX.Sale.BasketFilter.prototype.showSimilarItemsFilter = function()
2606	{
2607		var item = this.component.getItemDataByTarget(BX.proxy_context);
2608
2609		if (this.currentFilter.similarHash !== item.HASH)
2610		{
2611			this.clearAllFiltersExcept(['similar']);
2612			this.addSimilarItemsFilter(item);
2613			this.onFilterChange();
2614		}
2615	};
2616
2617	BX.Sale.BasketFilter.prototype.getTimeoutDuration = function()
2618	{
2619		return this.component.duration.filterTimer;
2620	};
2621
2622	BX.Sale.BasketFilter.prototype.onFilterChange = function()
2623	{
2624		this.component.showItemsOverlay();
2625
2626		if (
2627			this.currentFilter.query.length
2628			|| this.currentFilter.similarHash.length
2629			|| this.currentFilter.warning
2630			|| this.currentFilter.notAvailable
2631			|| this.currentFilter.delayed
2632		)
2633		{
2634			clearTimeout(this.filterTimer);
2635			this.filterTimer = setTimeout(BX.proxy(this.enableFilterMode, this), this.getTimeoutDuration());
2636		}
2637		else
2638		{
2639			this.disableFilterMode();
2640		}
2641	};
2642
2643	BX.Sale.BasketFilter.prototype.enableFilterMode = function()
2644	{
2645		var foundItemsHash;
2646
2647		if (!this.activeFilterMode)
2648		{
2649			this.activeFilterMode = true;
2650			this.realShownItems = BX.util.array_values(this.component.shownItems);
2651			this.realSortedItems = BX.util.array_values(this.component.sortedItems);
2652			this.realScrollTop = this.component.getDocumentScrollTop();
2653		}
2654
2655		this.component.scrollToFirstItem();
2656
2657		this.component.sortedItems = this.searchItems();
2658
2659		foundItemsHash = JSON.stringify(this.component.sortedItems);
2660
2661		if (this.lastShownItemsHash !== foundItemsHash)
2662		{
2663			this.lastShownItemsHash = foundItemsHash;
2664
2665			this.component.deleteBasketItems(BX.util.array_values(this.component.shownItems), false);
2666
2667			if (this.component.sortedItems.length)
2668			{
2669				this.component.initializeBasketItems();
2670				this.hideEmptyFilterResult();
2671			}
2672			else
2673			{
2674				this.showEmptyFilterResult();
2675			}
2676
2677			if (this.currentFilter.similarHash.length)
2678			{
2679				this.component.showSimilarCount(true);
2680			}
2681		}
2682		else
2683		{
2684			this.highlightFoundItems();
2685		}
2686
2687		this.component.hideItemsOverlay();
2688	};
2689
2690	BX.Sale.BasketFilter.prototype.disableFilterMode = function()
2691	{
2692		clearTimeout(this.filterTimer);
2693		this.lastShownItemsHash = '';
2694
2695		if (this.activeFilterMode)
2696		{
2697			this.activeFilterMode = false;
2698			this.component.sortedItems = BX.util.array_values(this.realSortedItems);
2699
2700			this.component.deleteBasketItems(BX.util.array_values(this.component.shownItems), false);
2701			this.hideEmptyFilterResult();
2702
2703			this.component.editBasketItems(BX.util.array_values(this.realShownItems));
2704			window.scrollTo(0, this.realScrollTop);
2705		}
2706
2707		this.component.hideItemsOverlay();
2708	};
2709
2710	BX.Sale.BasketFilter.prototype.searchItems = function()
2711	{
2712		var items = [];
2713
2714		for (var i = 0; i < this.realSortedItems.length; i++)
2715		{
2716			var item = this.component.items[this.realSortedItems[i]];
2717
2718			if (item && this.searchItemMatch(item))
2719			{
2720				items.push(item.ID);
2721			}
2722		}
2723
2724		return items;
2725	};
2726
2727	BX.Sale.BasketFilter.prototype.highlightFoundItems = function()
2728	{
2729		if (!this.activeFilterMode)
2730			return;
2731
2732		for (var i in this.component.shownItems)
2733		{
2734			if (this.component.shownItems.hasOwnProperty(i))
2735			{
2736				this.highlightSearchMatch(this.component.items[this.component.shownItems[i]]);
2737			}
2738		}
2739	};
2740
2741	BX.Sale.BasketFilter.prototype.searchItemMatch = function(item)
2742	{
2743		var match = false,
2744			found = false;
2745
2746		if (this.currentFilter.notAvailable)
2747		{
2748			found = !!item.NOT_AVAILABLE;
2749			if (!found)
2750			{
2751				return match;
2752			}
2753		}
2754		else if (this.currentFilter.delayed)
2755		{
2756			found = !!item.DELAYED;
2757			if (!found)
2758			{
2759				return match;
2760			}
2761		}
2762		else if (this.currentFilter.warning)
2763		{
2764			found = BX.util.in_array(item.ID, this.component.warningItems);
2765			if (!found)
2766			{
2767				return match;
2768			}
2769		}
2770		else if (BX.type.isNotEmptyString(this.currentFilter.similarHash))
2771		{
2772			found = this.currentFilter.similarHash === item.HASH;
2773			if (!found)
2774			{
2775				return match;
2776			}
2777		}
2778
2779		if (BX.type.isNotEmptyString(this.currentFilter.query))
2780		{
2781			if (item.NAME.toLowerCase().indexOf(this.currentFilter.query) !== -1)
2782			{
2783				match = 'NAME';
2784			}
2785
2786			if (!match)
2787			{
2788				var floatValue = parseFloat(this.currentFilter.query);
2789				if (!isNaN(floatValue))
2790				{
2791					if (parseFloat(item.PRICE) === floatValue)
2792					{
2793						match = 'PRICE';
2794					}
2795					else if (parseFloat(item.SUM_PRICE) === floatValue)
2796					{
2797						match = 'SUM_PRICE';
2798					}
2799				}
2800			}
2801
2802			if (!match && this.currentFilter.query.length >= 3)
2803			{
2804				if (item.PRICE_FORMATED.toLowerCase().indexOf(this.currentFilter.query) !== -1)
2805				{
2806					match = 'PRICE';
2807				}
2808				else if (item.SUM_PRICE_FORMATED.toLowerCase().indexOf(this.currentFilter.query) !== -1)
2809				{
2810					match = 'SUM_PRICE';
2811				}
2812			}
2813
2814			var k, lcValue;
2815
2816			if (!match && item.PROPS.length)
2817			{
2818				for (k in item.PROPS)
2819				{
2820					if (item.PROPS.hasOwnProperty(k) && BX.type.isNotEmptyString(item.PROPS[k].VALUE))
2821					{
2822						lcValue = item.PROPS[k].VALUE.toLowerCase();
2823
2824						if (
2825							lcValue === this.currentFilter.query
2826							|| (this.currentFilter.query.length >= 3 && lcValue.indexOf(this.currentFilter.query) !== -1)
2827						)
2828						{
2829							match = 'PROPS';
2830							break;
2831						}
2832					}
2833				}
2834			}
2835
2836			if (!match && item.COLUMN_LIST.length)
2837			{
2838				for (k in item.COLUMN_LIST)
2839				{
2840					if (item.COLUMN_LIST.hasOwnProperty(k) && BX.type.isNotEmptyString(item.COLUMN_LIST[k].VALUE))
2841					{
2842						lcValue = item.COLUMN_LIST[k].VALUE.toLowerCase();
2843
2844						if (
2845							lcValue === this.currentFilter.query
2846							|| (this.currentFilter.query.length >= 3 && lcValue.indexOf(this.currentFilter.query) !== -1)
2847						)
2848						{
2849							match = 'COLUMNS';
2850							break;
2851						}
2852					}
2853				}
2854			}
2855		}
2856		else if (found)
2857		{
2858			match = true;
2859		}
2860
2861		return match;
2862	};
2863
2864	BX.Sale.BasketFilter.prototype.highlightSearchMatch = function(itemData)
2865	{
2866		var searchMatch = this.searchItemMatch(itemData);
2867
2868		if (searchMatch)
2869		{
2870			var entity, i, k, code;
2871
2872			switch (searchMatch)
2873			{
2874				case 'NAME':
2875					entity = this.component.getEntity(BX(this.component.ids.item + itemData.ID), 'basket-item-name');
2876					if (BX.type.isDomNode(entity))
2877					{
2878						entity.innerHTML = itemData.NAME.replace(
2879							new RegExp('(.*)(' + this.currentFilter.query.replace(/[.*+?^${}
2879()|[\]\\]/g, "\\$&") + ')(.*)', 'gi'),
2880							function (full, match1 , match2, match3)
2881							{
2882								return BX.util.htmlspecialchars(match1)
2883									+ '<span class="basket-item-highlighted">'
2884									+ BX.util.htmlspecialchars(match2)
2885									+ '</span>' + BX.util.htmlspecialchars(match3);
2886							}
2887						);
2888					}
2889					break;
2890				case 'PRICE':
2891					entity = BX(this.component.ids.price + itemData.ID);
2892					BX.addClass(entity, 'basket-item-highlighted');
2893					break;
2894				case 'SUM_PRICE':
2895					entity = BX(this.component.ids.sumPrice + itemData.ID);
2896					BX.addClass(entity, 'basket-item-highlighted');
2897					break;
2898				case 'PROPS':
2899					entity = this.component.getEntities(BX(this.component.ids.item + itemData.ID), 'basket-item-property-value');
2900
2901					for (i = 0; i < entity.length; i++)
2902					{
2903						code = entity[i].getAttribute('data-property-code');
2904
2905						for (k in itemData.PROPS)
2906						{
2907							if (itemData.PROPS.hasOwnProperty(k) && itemData.PROPS[k].CODE === code)
2908							{
2909								entity[i].innerHTML = itemData.PROPS[k].VALUE.replace(
2910									new RegExp('(' + this.currentFilter.query + ')', 'gi'),
2911									'<span class="basket-item-highlighted">$1</span>'
2912								);
2913							}
2914						}
2915					}
2916					break;
2917				case 'COLUMNS':
2918					entity = this.component.getEntities(BX(this.component.ids.item + itemData.ID), 'basket-item-property-column-value');
2919
2920					for (i = 0; i < entity.length; i++)
2921					{
2922						code = entity[i].getAttribute('data-column-property-code');
2923
2924						for (k in itemData.COLUMN_LIST)
2925						{
2926							if (itemData.COLUMN_LIST.hasOwnProperty(k) && itemData.COLUMN_LIST[k].CODE === code)
2927							{
2928								entity[i].innerHTML = itemData.COLUMN_LIST[k].VALUE.replace(
2929									new RegExp('(' + this.currentFilter.query + ')', 'gi'),
2930									'<span class="basket-item-highlighted">$1</span>'
2931								);
2932							}
2933						}
2934					}
2935					break;
2936			}
2937		}
2938	};
2939
2940	BX.Sale.BasketFilter.prototype.showEmptyFilterResult = function()
2941	{
2942		var itemListNode = this.component.getCacheNode(this.component.ids.itemList);
2943
2944		if (BX.type.isDomNode(itemListNode) && itemListNode.clientHeight >= 500)
2945		{
2946			var emptyResultNode = this.component.getCacheNode(this.component.ids.itemListEmptyResult);
2947
2948			if (BX.type.isDomNode(emptyResultNode))
2949			{
2950				emptyResultNode.style.display = '';
2951			}
2952		}
2953	};
2954
2955	BX.Sale.BasketFilter.prototype.hideEmptyFilterResult = function()
2956	{
2957		var emptyResultNode = this.component.getCacheNode(this.component.ids.itemListEmptyResult);
2958
2959		if (BX.type.isDomNode(emptyResultNode))
2960		{
2961			emptyResultNode.style.display = 'none';
2962		}
2963	};
2964})();
2965/* End */
2966;
2967; /* Start:"a:4:{s:4:"full";s:105:"/local/templates/fabrika38/components/bitrix/sale.basket.basket/basket_38/js/component.js?175439056462461";s:6:"source";s:89:"/local/templates/fabrika38/components/bitrix/sale.basket.basket/basket_38/js/component.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
2968;(function() {
2969	'use strict';
2970
2971	BX.namespace('BX.Sale.BasketComponent');
2972
2973	BX.Sale.BasketComponent = {
2974		isMobile: BX.browser.IsMobile(),
2975		isTouch: BX.hasClass(document.documentElement, 'bx-touch'),
2976		lastAction: 'initialLoad',
2977		maxItemsShowCount: 30,
2978
2979		precisionFactor: Math.pow(10, 6),
2980
2981		quantityDelay: null,
2982		quantityTimer: null,
2983
2984		stickyHeaderOffset: 0,
2985
2986		duration: {
2987			priceAnimation: 300,
2988			filterTimer: 300
2989		},
2990
2991		imagePopup: null,
2992		loadingScreen: null,
2993
2994		templates: {},
2995		nodes: {},
2996
2997		/** Object of all basket items (itemId => itemArray) */
2998		items: {},
2999
3000		/** Array of all basket items to show sorted by field SORT */
3001		sortedItems: [],
3002
3003		/** Array of basket items showed on screen */
3004		shownItems: [],
3005
3006		/** Array of basket items changed since last request */
3007		changedItems: [],
3008
3009		/** Array of basket items postponed by pool to edit */
3010		postponedItems: [],
3011
3012		/** Array of basket items with warnings */
3013		warningItems: [],
3014
3015		ids: {
3016			item: 'basket-item-',
3017			quantity: 'basket-item-quantity-',
3018			price: 'basket-item-price-',
3019			sumPrice: 'basket-item-sum-price-',
3020			sumPriceOld: 'basket-item-sum-price-old-',
3021			sumPriceDiff: 'basket-item-sum-price-difference-',
3022			itemHeightAligner: 'basket-item-height-aligner-',
3023			total: 'basket-total-price',
3024			basketRoot: 'basket-root',
3025			itemListWrapper: 'basket-items-list-wrapper',
3026			itemListContainer: 'basket-items-list-container',
3027			itemList: 'basket-item-list',
3028			itemListTable: 'basket-item-table',
3029			itemListEmptyResult: 'basket-item-list-empty-result',
3030			itemListOverlay: 'basket-items-list-overlay',
3031			warning: 'basket-warning'
3032		},
3033
3034		init: function(parameters)
3035		{
3036			this.params = parameters.params || {};
3037			this.template = parameters.template || '';
3038			this.signedParamsString = parameters.signedParamsString || '';
3039			this.siteId = parameters.siteId || '';
3040			this.ajaxUrl = this.params.AJAX_PATH || '';
3041			this.templateFolder = parameters.templateFolder || '';
3042
3043			this.useDynamicScroll = this.params.USE_DYNAMIC_SCROLL === 'Y';
3044			this.useItemsFilter = this.params.SHOW_FILTER === 'Y' && !this.isMobile;
3045
3046			this.initializeFilter();
3047			this.applyBasketResult(parameters.result);
3048			this.initializeActionPool();
3049
3050			if (this.useItemsFilter)
3051			{
3052				this.checkHeaderDisplay();
3053				this.bindHeaderEvents();
3054			}
3055
3056			this.initializeBasketItems();
3057			this.editTotal();
3058			this.editWarnings();
3059
3060			this.adjustBasketWrapperHeight();
3061			this.getCacheNode(this.ids.basketRoot).style.opacity = 1;
3062
3063			this.bindInitialEvents();
3064		},
3065
3066		getTemplate: function(templateName)
3067		{
3068			if (!this.templates.hasOwnProperty(templateName))
3069			{
3070				var template = BX(templateName);
3071				this.templates[templateName] = BX.type.isDomNode(template) ? template.innerHTML : '';
3072			}
3073
3074			return this.templates[templateName];
3075		},
3076
3077		getCacheNode: function(id)
3078		{
3079			if (!this.nodes.hasOwnProperty(id))
3080			{
3081				this.nodes[id] = BX(id);
3082			}
3083
3084			return this.nodes[id];
3085		},
3086
3087		getEntity: function(parent, entity, additionalFilter)
3088		{
3089			if (!parent || !entity)
3090				return null;
3091
3092			additionalFilter = additionalFilter || '';
3093
3094			return parent.querySelector(additionalFilter + '[data-entity="' + entity + '"]');
3095		},
3096
3097		getEntities: function(parent, entity, additionalFilter)
3098		{
3099			if (!parent || !entity)
3100				return {length: 0};
3101
3102			additionalFilter = additionalFilter || '';
3103
3104			return parent.querySelectorAll(additionalFilter + '[data-entity="' + entity + '"]');
3105		},
3106
3107		bindInitialEvents: function()
3108		{
3109			this.bindWarningEvents();
3110
3111			BX.bind(window, 'scroll', BX.proxy(this.checkStickyHeaders, this));
3112			BX.bind(window, 'scroll', BX.proxy(this.lazyLoad, this));
3113
3114			BX.bind(window, 'resize', BX.throttle(this.checkStickyHeaders, 20, this));
3115			BX.bind(window, 'resize', BX.throttle(this.adjustBasketWrapperHeight, 20, this));
3116		},
3117
3118		bindWarningEvents: function()
3119		{
3120			var showItemsNode = this.getEntity(BX(this.ids.warning), 'basket-items-warning-count');
3121
3122			if (BX.type.isDomNode(showItemsNode))
3123			{
3124				showItemsNode.style.display = '';
3125				BX.bind(showItemsNode, 'click', BX.delegate(function() {this.toggleFilter('warning');}, this));
3126			}
3127
3128			BX.bind(
3129				this.getEntity(BX(this.ids.warning), 'basket-items-warning-notification-close'),
3130				'click',
3131				BX.proxy(this.removeAllWarnings, this)
3132			);
3133		},
3134
3135		toggleFilter: function(event)
3136		{
3137			var target = BX.type.isNotEmptyString(event) ?
3138				this.getEntity(
3139					this.getCacheNode(this.ids.itemListWrapper),
3140					'basket-items-count',
3141					'[data-filter="' + event + '"]'
3142				)
3143				: BX.getEventTarget(event);
3144
3145			if (!BX.type.isDomNode(target) || BX.hasClass(target, 'active'))
3146				return;
3147
3148			var entityName = target.getAttribute('data-filter');
3149			var entities = target.parentNode.querySelectorAll('[data-filter]');
3150
3151			for (var i = 0; i < entities.length; i++)
3152			{
3153				if (entities[i].getAttribute('data-filter') === entityName)
3154				{
3155					BX.addClass(entities[i], 'active');
3156				}
3157				else if (BX.hasClass(entities[i], 'active'))
3158				{
3159					BX.removeClass(entities[i], 'active');
3160				}
3161			}
3162
3163			this.filter.showFilterByName(entityName);
3164		},
3165
3166		scrollToFirstItem: function()
3167		{
3168			var headerNode = this.getEntity(this.getCacheNode(this.ids.itemListWrapper), 'basket-items-list-header');
3169
3170			if (BX.type.isDomNode(headerNode))
3171			{
3172				var itemListTopPosition = BX.pos(this.getCacheNode(this.ids.itemListContainer)).top;
3173				var headerBottomPosition = BX.pos(headerNode).bottom;
3174
3175				if (itemListTopPosition < headerBottomPosition)
3176				{
3177					window.scrollTo(0, itemListTopPosition - this.stickyHeaderOffset);
3178				}
3179			}
3180		},
3181
3182		showItemsOverlay: function()
3183		{
3184			var overlay = this.getCacheNode(this.ids.itemListOverlay);
3185
3186			if (BX.type.isDomNode(overlay))
3187			{
3188				overlay.style.display = '';
3189			}
3190		},
3191
3192		hideItemsOverlay: function()
3193		{
3194			var overlay = this.getCacheNode(this.ids.itemListOverlay);
3195
3196			if (BX.type.isDomNode(overlay))
3197			{
3198				overlay.style.display = 'none';
3199			}
3200		},
3201
3202		checkHeaderDisplay: function()
3203		{
3204			var header = this.getCacheNode(this.ids.itemListWrapper);
3205
3206			if (BX.type.isDomNode(header))
3207			{
3208				BX.removeClass(header, 'basket-items-list-wrapper-light');
3209			}
3210		},
3211
3212		bindHeaderEvents: function()
3213		{
3214			var entities = this.getEntities(this.getCacheNode(this.ids.itemListWrapper), 'basket-items-count');
3215
3216			for (var i = 0; i < entities.length; i++)
3217			{
3218				BX.bind(entities[i], 'click', BX.proxy(this.toggleFilter, this));
3219			}
3220		},
3221
3222		checkStickyHeaders: function()
3223		{
3224			if (this.isMobile)
3225				return;
3226
3227			var node, position;
3228			var border = 2, offset = 0;
3229			var scrollTop = this.getDocumentScrollTop();
3230			var basketPosition = BX.pos(this.getCacheNode(this.ids.basketRoot));
3231			var basketScrolledToEnd = scrollTop + 200 >= basketPosition.bottom;
3232
3233			if (BX.util.in_array('top', this.params.TOTAL_BLOCK_DISPLAY))
3234			{
3235				var totalBlockNode = this.getEntity(this.getCacheNode(this.ids.basketRoot), 'basket-total-block');
3236				if (BX.type.isDomNode(totalBlockNode))
3237				{
3238					node = this.getEntity(totalBlockNode, 'basket-checkout-aligner');
3239					if (BX.type.isDomNode(node))
3240					{
3241						position = BX.pos(totalBlockNode);
3242
3243						if (scrollTop >= position.top)
3244						{
3245							offset += node.clientHeight;
3246
3247							if (!BX.hasClass(node, 'basket-checkout-container-fixed'))
3248							{
3249								totalBlockNode.style.height = position.height + 'px';
3250
3251								node.style.width = node.clientWidth + border + 'px';
3252								BX.addClass(node, 'basket-checkout-container-fixed');
3253							}
3254						}
3255						else if (BX.hasClass(node, 'basket-checkout-container-fixed'))
3256						{
3257							totalBlockNode.style.height = '';
3258
3259							node.style.width = '';
3260							BX.removeClass(node, 'basket-checkout-container-fixed');
3261						}
3262
3263						if (basketScrolledToEnd)
3264						{
3265							if (!BX.hasClass(node, 'basket-checkout-container-fixed-hide'))
3266							{
3267								BX.addClass(node, 'basket-checkout-container-fixed-hide');
3268							}
3269						}
3270						else if (BX.hasClass(node, 'basket-checkout-container-fixed-hide'))
3271						{
3272							BX.removeClass(node, 'basket-checkout-container-fixed-hide');
3273						}
3274					}
3275				}
3276			}
3277
3278			if (this.useItemsFilter)
3279			{
3280				var itemWrapperNode = this.getCacheNode(this.ids.itemListWrapper);
3281
3282				node = this.getEntity(itemWrapperNode, 'basket-items-list-header');
3283				if (BX.type.isDomNode(node))
3284				{
3285					position = BX.pos(itemWrapperNode);
3286
3287					if ((scrollTop + offset >= position.top) && !basketScrolledToEnd)
3288					{
3289						if (!BX.hasClass(node, 'basket-items-list-header-fixed'))
3290						{
3291							node.style.width = node.clientWidth + border + 'px';
3292
3293							itemWrapperNode.style.paddingTop = node.clientHeight + 'px';
3294
3295							BX.addClass(node, 'basket-items-list-header-fixed');
3296						}
3297
3298						if (offset)
3299						{
3300							node.style.top = offset + 'px';
3301						}
3302
3303						offset += node.clientHeight;
3304					}
3305					else if (BX.hasClass(node, 'basket-items-list-header-fixed'))
3306					{
3307						itemWrapperNode.style.paddingTop = '';
3308
3309						node.style.width = '';
3310						node.style.top = '';
3311
3312						BX.removeClass(node, 'basket-items-list-header-fixed');
3313					}
3314				}
3315			}
3316
3317			var offsetChanged = this.stickyHeaderOffset === offset;
3318
3319			this.stickyHeaderOffset = offset;
3320
3321			if (offsetChanged && !basketScrolledToEnd)
3322			{
3323				this.adjustBasketWrapperHeight();
3324			}
3325		},
3326
3327		getDocumentScrollTop: function()
3328		{
3329			return window.scrollY
3330				|| window.pageYOffset
3331				|| document.body.scrollTop + (document.documentElement && document.documentElement.scrollTop || 0);
3332		},
3333
3334		lazyLoad: function()
3335		{
3336			var itemsNodePosition = BX.pos(this.getCacheNode(this.ids.itemListContainer));
3337
3338			if (this.getDocumentScrollTop() + window.innerHeight >= itemsNodePosition.bottom - 400)
3339			{
3340				var itemIds = this.getItemsAfter();
3341				if (itemIds.length)
3342				{
3343					this.editBasketItems(itemIds);
3344				}
3345			}
3346		},
3347
3348		fireCustomEvents: function()
3349		{
3350			if (this.result.EVENT_ONCHANGE_ON_START === 'Y')
3351			{
3352				BX.onCustomEvent('OnBasketChange');
3353			}
3354		},
3355
3356		adjustBasketWrapperHeight: function()
3357		{
3358			var itemListContainer = this.getCacheNode(this.ids.itemListContainer),
3359				itemList = this.getCacheNode(this.ids.itemList);
3360
3361			if (BX.type.isDomNode(itemListContainer) && BX.type.isDomNode(itemList))
3362			{
3363				if (itemListContainer.clientHeight + this.stickyHeaderOffset > window.innerHeight)
3364				{
3365					itemListContainer.style.minHeight = 'calc(100vh - 15px - ' + this.stickyHeaderOffset + 'px)';
3366					itemList.style.minHeight = 'calc(100vh - 15px - ' + this.stickyHeaderOffset + 'px)';
3367				}
3368				else
3369				{
3370					itemListContainer.style.minHeight = itemListContainer.clientHeight + 'px';
3371					itemList.style.minHeight = itemListContainer.clientHeight + 'px';
3372				}
3373			}
3374		},
3375
3376		editTotal: function()
3377		{
3378			this.fillTotalBlocks();
3379			this.showItemsCount();
3380			this.showWarningItemsCount();
3381			this.showNotAvailableItemsCount();
3382			this.showDelayedItemsCount();
3383		},
3384
3385		fillTotalBlocks: function()
3386		{
3387			var totalNodes = this.getEntities(this.getCacheNode(this.ids.basketRoot), 'basket-total-block');
3388
3389			if (totalNodes && totalNodes.length)
3390			{
3391				var totalTemplate = this.getTemplate('basket-total-template');
3392				if (totalTemplate)
3393				{
3394					var totalRender = this.render(totalTemplate, this.result.TOTAL_RENDER_DATA);
3395
3396					for (var i in totalNodes)
3397					{
3398						if (totalNodes.hasOwnProperty(i) && BX.type.isDomNode(totalNodes[i])
3398)
3399						{
3400							totalNodes[i].innerHTML = totalRender;
3401
3402							this.bindTotalEvents(totalNodes[i]);
3403						}
3404					}
3405				}
3406			}
3407
3408			this.checkStickyHeaders();
3409		},
3410
3411		showItemsCount: function()
3412		{
3413			var itemCountNode = this.getEntity(
3414				this.getCacheNode(this.ids.itemListWrapper),
3415				'basket-items-count',
3416				'[data-filter="all"]'
3417			);
3418
3419			if (BX.type.isDomNode(itemCountNode))
3420			{
3421				itemCountNode.innerHTML = BX.message('SBB_IN_BASKET') + ' ' + this.result.BASKET_ITEMS_COUNT + ' ' + this.getGoodsMessage(this.result.BASKET_ITEMS_COUNT);
3422				itemCountNode.style.display = '';
3423			}
3424		},
3425
3426		showSimilarCount: function(state)
3427		{
3428			var itemCountNode = this.getEntity(
3429				this.getCacheNode(this.ids.itemListWrapper),
3430				'basket-items-count',
3431				'[data-filter="similar"]'
3432			);
3433
3434			if (BX.type.isDomNode(itemCountNode))
3435			{
3436				if (state)
3437				{
3438					itemCountNode.innerHTML = this.sortedItems.length + ' '
3439						+ this.getGoodsMessage(this.result.BASKET_ITEMS_COUNT, 'SBB_SIMILAR_ITEM');
3440					itemCountNode.style.display = '';
3441				}
3442				else
3443				{
3444					itemCountNode.style.display = 'none';
3445				}
3446			}
3447		},
3448
3449		showWarningItemsCount: function()
3450		{
3451			var itemCountNode = this.getEntity(
3452				this.getCacheNode(this.ids.itemListWrapper),
3453				'basket-items-count',
3454				'[data-filter="warning"]'
3455			);
3456
3457			if (BX.type.isDomNode(itemCountNode))
3458			{
3459				if (this.warningItems.length)
3460				{
3461					itemCountNode.innerHTML = this.warningItems.length + ' ' + BX.message('SBB_BASKET_ITEMS_WARNING');
3462					itemCountNode.style.display = '';
3463				}
3464				else
3465				{
3466					itemCountNode.style.display = 'none';
3467				}
3468			}
3469		},
3470
3471		showNotAvailableItemsCount: function()
3472		{
3473			var itemCountNode = this.getEntity(
3474				this.getCacheNode(this.ids.itemListWrapper),
3475				'basket-items-count',
3476				'[data-filter="not-available"]'
3477			);
3478
3479			if (BX.type.isDomNode(itemCountNode))
3480			{
3481				if (parseInt(this.result.NOT_AVAILABLE_BASKET_ITEMS_COUNT))
3482				{
3483					itemCountNode.innerHTML = this.result.NOT_AVAILABLE_BASKET_ITEMS_COUNT + ' '
3484						+ this.getGoodsMessage(this.result.NOT_AVAILABLE_BASKET_ITEMS_COUNT, 'SBB_NOT_AVAILABLE_ITEM');
3485					itemCountNode.style.display = '';
3486				}
3487				else
3488				{
3489					itemCountNode.style.display = 'none';
3490				}
3491			}
3492		},
3493
3494		showDelayedItemsCount: function()
3495		{
3496			var itemCountNode = this.getEntity(
3497				this.getCacheNode(this.ids.itemListWrapper),
3498				'basket-items-count',
3499				'[data-filter="delayed"]'
3500			);
3501
3502			if (BX.type.isDomNode(itemCountNode))
3503			{
3504				if (parseInt(this.result.DELAYED_BASKET_ITEMS_COUNT))
3505				{
3506					itemCountNode.innerHTML = this.result.DELAYED_BASKET_ITEMS_COUNT + ' '
3507						+ this.getGoodsMessage(this.result.DELAYED_BASKET_ITEMS_COUNT, 'SBB_DELAYED_ITEM');
3508					itemCountNode.style.display = '';
3509				}
3510				else
3511				{
3512					itemCountNode.style.display = 'none';
3513				}
3514			}
3515		},
3516
3517		getGoodsMessage: function(count, customMessage)
3518		{
3519			var mesCode;
3520			var countReminder = (count > 10 && count < 20) ? 0 : count % 10;
3521
3522			if (countReminder === 1)
3523			{
3524				mesCode = customMessage || 'SBB_GOOD';
3525			}
3526			else if (countReminder >= 2 && countReminder <= 4)
3527			{
3528				mesCode = customMessage ? customMessage + '_2' : 'SBB_GOOD_2';
3529			}
3530			else
3531			{
3532				mesCode = customMessage ? customMessage + 'S' : 'SBB_GOODS';
3533			}
3534
3535			return BX.message(mesCode);
3536		},
3537
3538		bindTotalEvents: function(node)
3539		{
3540			if (!this.result.TOTAL_RENDER_DATA.DISABLE_CHECKOUT)
3541			{
3542				BX.bind(this.getEntity(node, 'basket-checkout-button'), 'click', BX.proxy(this.checkOutAction, this));
3543			}
3544
3545			BX.bind(this.getEntity(node, 'basket-coupon-input'), 'change', BX.proxy(this.addCouponAction, this));
3546			BX.bind(this.getEntity(node, 'basket-coupon-input'), 'paste', BX.proxy(this.pasteCouponAction, this));
3547
3548			var couponNodes = this.getEntities(node, 'basket-coupon-delete');
3549			for (var i = 0, l = couponNodes.length; i < l; i++)
3550			{
3551				BX.bind(couponNodes[i], 'click', BX.proxy(this.removeCouponAction, this));
3552			}
3553
3554		},
3555
3556		checkOutAction: function()
3557		{
3558			document.location.href = this.params.PATH_TO_ORDER;
3559		},
3560
3561		addCouponAction: function(event)
3562		{
3563			var target = BX.getEventTarget(event);
3564			if (target && target.value)
3565			{
3566				this.actionPool.addCoupon(target.value);
3567				target.disabled = true;
3568			}
3569		},
3570
3571		pasteCouponAction: function(event)
3572		{
3573			setTimeout(BX.delegate(function() {
3574				this.addCouponAction(event);
3575			}, this), 10);
3576		},
3577
3578		removeCouponAction: function()
3579		{
3580			var value = BX.proxy_context && BX.util.trim(BX.proxy_context.getAttribute('data-coupon'));
3581			if (value)
3582			{
3583				this.actionPool.removeCoupon(value);
3584			}
3585		},
3586
3587		initializeActionPool: function()
3588		{
3589			this.actionPool = new BX.Sale.BasketActionPool(this);
3590		},
3591
3592		initializeFilter: function()
3593		{
3594			this.filter = new BX.Sale.BasketFilter(this);
3595		},
3596
3597		/**
3598		 * Send ajax request with basket data and executes callback by action
3599		 */
3600		sendRequest: function(action, data)
3601		{
3602			this.lastAction = action;
3603
3604			if (this.lastAction === 'recalculateAjax')
3605			{
3606				// we use it to reload all items if applied discounts changed
3607				data.lastAppliedDiscounts = BX.util.array_keys(this.result.FULL_DISCOUNT_LIST).join(',');
3608
3609				if (this.params.USE_ENHANCED_ECOMMERCE === 'Y')
3610				{
3611					this.checkAnalytics(data);
3612				}
3613			}
3614
3615			BX.ajax({
3616				method: 'POST',
3617				dataType: 'json',
3618				url: this.ajaxUrl,
3619				data: this.getData(data),
3620				onsuccess: BX.delegate(function(result) {
3621					this.actionPool.doProcessing(false);
3622
3623					if (!BX.type.isPlainObject(result))
3624						return;
3625
3626					this.actionPool.setRefreshStatus(result.BASKET_REFRESHED);
3627
3628					if (result.RESTORED_BASKET_ITEMS)
3629					{
3630						this.restoreBasketItems(result.RESTORED_BASKET_ITEMS);
3631					}
3632
3633					if (result.DELETED_BASKET_ITEMS)
3634					{
3635						this.deleteBasketItems(result.DELETED_BASKET_ITEMS, this.params.SHOW_RESTORE === 'Y');
3636					}
3637
3638					if (result.MERGED_BASKET_ITEMS)
3639					{
3640						this.deleteBasketItems(result.MERGED_BASKET_ITEMS, false, true);
3641					}
3642
3643					this.applyBasketResult(result.BASKET_DATA);
3644					this.editBasketItems(this.getItemsToEdit());
3645					this.editTotal();
3646
3647					this.adjustBasketWrapperHeight();
3648					this.applyPriceAnimation();
3649					this.editWarnings();
3650
3651					this.actionPool.switchTimer();
3652
3653					if (this.isBasketIntegrated() && this.isBasketChanged())
3654					{
3655						BX.Sale.OrderAjaxComponent.sendRequest();
3656					}
3657				}, this),
3658				onfailure: BX.delegate(function() {
3659					this.actionPool.doProcessing(false);
3660				}, this)
3661			});
3662		},
3663
3664		isBasketIntegrated: function()
3665		{
3666			return this.params.BASKET_WITH_ORDER_INTEGRATION === 'Y';
3667		},
3668
3669		isBasketChanged: function()
3670		{
3671			return this.changedItems.length;
3672		},
3673
3674		addPriceAnimationData: function(nodeId, start, finish, currency)
3675		{
3676			if (!BX.type.isPlainObject(this.priceAnimationData))
3677			{
3678				this.clearPriceAnimationData();
3679			}
3680
3681			this.priceAnimationData.start[nodeId] = parseFloat(start);
3682			this.priceAnimationData.finish[nodeId] = parseFloat(finish);
3683			this.priceAnimationData.currency[nodeId] = currency;
3684			this.priceAnimationData.int[nodeId] = (parseFloat(start) === parseInt(start)) && (parseFloat(finish) === parseInt(finish));
3685		},
3686
3687		clearPriceAnimationData: function()
3688		{
3689			this.priceAnimationData = {
3690				start: {},
3691				finish: {},
3692				currency: {},
3693				int: {}
3694			};
3695		},
3696
3697		applyBasketResult: function(result)
3698		{
3699			this.changedItems = [];
3700			this.clearPriceAnimationData();
3701
3702			if (!BX.type.isPlainObject(result))
3703			{
3704				return;
3705			}
3706
3707			if (result.BASKET_ITEM_RENDER_DATA)
3708			{
3709				var i, newData;
3710
3711				for (i in result.BASKET_ITEM_RENDER_DATA)
3712				{
3713					if (result.BASKET_ITEM_RENDER_DATA.hasOwnProperty(i))
3714					{
3715						newData = result.BASKET_ITEM_RENDER_DATA[i];
3716						newData.WARNINGS = this.checkBasketItemWarnings(newData, result.WARNING_MESSAGE_WITH_CODE);
3717
3718						if (this.items[newData.ID])
3719						{
3720							if (JSON.stringify(this.items[newData.ID]) === JSON.stringify(newData))
3721							{
3722								continue;
3723							}
3724						}
3725						else
3726						{
3727							this.addSortedItem(newData.ID, true);
3728						}
3729
3730						this.changedItems.push(newData.ID);
3731
3732						newData = this.checkBasketItemsAnimation(newData);
3733						this.items[newData.ID] = newData;
3734					}
3735				}
3736
3737				this.changedItems = BX.util.array_unique(this.changedItems.concat(this.getChangedSimilarOffers()));
3738
3739				if (this.isBasketChanged())
3740				{
3741					this.sortSortedItems(true);
3742				}
3743			}
3744
3745			if (result.TOTAL_RENDER_DATA)
3746			{
3747				result.TOTAL_RENDER_DATA = this.checkTotalAnimation(result.TOTAL_RENDER_DATA);
3748			}
3749
3750			this.result = result;
3751		},
3752
3753		itemSortFunction: function(a, b)
3754		{
3755			if (!this.items.hasOwnProperty(a) || !this.items.hasOwnProperty(b))
3756			{
3757				return 0;
3758			}
3759
3760			return parseFloat(this.items[a].SORT) - parseFloat(this.items[b].SORT);
3761		},
3762
3763		getChangedSimilarOffers: function()
3764		{
3765			var changedSimilarOffers = [];
3766
3767			var otherSimilarItemsQuantity, totalSimilarItemsQuantity;
3768			var hashMap = this.getHashMap();
3769
3770			for (var hash in hashMap)
3771			{
3772				if (hashMap.hasOwnProperty(hash))
3773				{
3774					if (hashMap[hash].length > 1)
3775					{
3776						for (var i = 0; i < hashMap[hash].length; i++)
3777						{
3778							otherSimilarItemsQuantity = 0;
3779							totalSimilarItemsQuantity = 0;
3780
3781							for (var k = 0; k < hashMap[hash].length; k ++)
3782							{
3783								if (hashMap[hash][k] != hashMap[hash][i])
3784								{
3785									otherSimilarItemsQuantity += parseFloat(this.items[hashMap[hash][k]].QUANTITY);
3786								}
3787
3788								totalSimilarItemsQuantity += parseFloat(this.items[hashMap[hash][k]].QUANTITY);
3789							}
3790
3791							if (
3792								!this.items[hashMap[hash][i]].HAS_SIMILAR_ITEMS
3793								|| this.items[hashMap[hash][i]].SIMILAR_ITEMS_QUANTITY != otherSimilarItemsQuantity
3794								|| this.items[hashMap[hash][i]].TOTAL_SIMILAR_ITEMS_QUANTITY != totalSimilarItemsQuantity
3795							)
3796							{
3797								changedSimilarOffers.push(hashMap[hash][i]);
3798
3799								this.items[hashMap[hash][i]].HAS_SIMILAR_ITEMS = true;
3800								this.items[hashMap[hash][i]].SIMILAR_ITEMS_QUANTITY = otherSimilarItemsQuantity;
3801								this.items[hashMap[hash][i]].TOTAL_SIMILAR_ITEMS_QUANTITY = totalSimilarItemsQuantity;
3802
3803								this.items[hashMap[hash][i]].ALL_AVAILABLE_QUANTITY = this.items[hashMap[hash][i]].AVAILABLE_QUANTITY;
3804								this.items[hashMap[hash][i]].AVAILABLE_QUANTITY = this.items[hashMap[hash][i]].ALL_AVAILABLE_QUANTITY - otherSimilarItemsQuantity;
3805							}
3806						}
3807					}
3808					else if (hashMap[hash][0] && this.items[hashMap[hash][0]].HAS_SIMILAR_ITEMS)
3809					{
3810						changedSimilarOffers.push(hashMap[hash][0]);
3811
3812						delete this.items[hashMap[hash][0]].HAS_SIMILAR_ITEMS;
3813						delete this.items[hashMap[hash][0]].SIMILAR_ITEMS_QUANTITY;
3814						delete this.items[hashMap[hash][0]].TOTAL_SIMILAR_ITEMS_QUANTITY;
3815
3816						this.items[hashMap[hash][0]].AVAILABLE_QUANTITY = this.items[hashMap[hash][0]].ALL_AVAILABLE_QUANTITY;
3817						delete this.items[hashMap[hash][0]].ALL_AVAILABLE_QUANTITY;
3818					}
3819				}
3820			}
3821
3822			return changedSimilarOffers;
3823		},
3824
3825		getHashMap: function()
3826		{
3827			var hashMap = {};
3828
3829			for (var id in this.items)
3830			{
3831				if (this.items.hasOwnProperty(id) && this.isItemAvailable(id))
3832				{
3833					if (!hashMap.hasOwnProperty(this.items[id].HASH))
3834					{
3835						hashMap[this.items[id].HASH] = [];
3836					}
3837
3838					hashMap[this.items[id].HASH].push(id);
3839				}
3840			}
3841
3842			return hashMap;
3843		},
3844
3845		isItemAvailable: function(itemId)
3846		{
3847			var sortedItems = this.filter.isActive() ? this.filter.realSortedItems : this.sortedItems;
3848
3849			return !this.items[itemId].NOT_AVAILABLE
3850				&& !this.items[itemId].SHOW_RESTORE
3851				&& BX.util.in_array(itemId, sortedItems);
3852		},
3853
3854		checkTotalAnimation: function(totalData)
3855		{
3856			if (this.result && this.result.TOTAL_RENDER_DATA && parseFloat(this.result.TOTAL_RENDER_DATA.PRICE) > parseFloat(totalData.PRICE))
3857			{
3858				totalData.PRICE_NEW = totalData.PRICE;
3859				totalData.PRICE = this.result.TOTAL_RENDER_DATA.PRICE;
3860
3861				totalData.PRICE_FORMATED_NEW = totalData.PRICE_FORMATED;
3862				totalData.PRICE_FORMATED = this.result.TOTAL_RENDER_DATA.PRICE_FORMATED;
3863
3864				this.addPriceAnimationData(this.ids.total, totalData.PRICE, totalData.PRICE_NEW, totalData.CURRENCY);
3865			}
3866
3867			return totalData;
3868		},
3869
3870		checkBasketItemsAnimation: function(itemData)
3871		{
3872			var itemId = itemData.ID;
3873
3874			if (this.items[itemId])
3875			{
3876				var quantityNode = BX(this.ids.quantity + itemId);
3877				if (
3878					BX.type.isDomNode(quantityNode)
3879					&& !this.actionPool.isItemInPool(itemId)
3880					&& parseFloat(quantityNode.value) !== parseFloat(itemData.QUANTITY)
3881				)
3882				{
3883					itemData.QUANTITY_ANIMATION = true;
3884					this.actionPool.clearLastActualQuantityPool(itemId);
3885				}
3886
3887				if (parseFloat(this.items[itemId].PRICE) > parseFloat(itemData.PRICE))
3888				{
3889					itemData.PRICE_NEW = itemData.PRICE;
3890					itemData.PRICE = this.items[itemId].PRICE;
3891
3892					itemData.PRICE_FORMATED_NEW = itemData.PRICE_FORMATED;
3893					itemData.PRICE_FORMATED = this.items[itemId].PRICE_FORMATED;
3894
3895					this.addPriceAnimationData(this.ids.price + itemId, itemData.PRICE, itemData.PRICE_NEW, itemData.CURRENCY);
3896				}
3897
3898				if (
3899					BX.util.in_array('SUM', this.params.COLUMNS_LIST)
3900					&& parseFloat(this.items[itemId].SUM_PRICE) > parseFloat(itemData.SUM_PRICE)
3901					&& parseFloat(this.items[itemId].QUANTITY) === parseFloat(itemData.QUANTITY)
3902				)
3903				{
3904					itemData.SUM_PRICE_NEW = itemData.SUM_PRICE;
3905					itemData.SUM_PRICE = this.items[itemId].SUM_PRICE;
3906
3907					itemData.SUM_PRICE_FORMATED_NEW = itemData.SUM_PRICE_FORMATED;
3908					itemData.SUM_PRICE_FORMATED = this.items[itemId].SUM_PRICE_FORMATED;
3909
3910					this.addPriceAnimationData(this.ids.sumPrice + itemId, itemData.SUM_PRICE, itemData.SUM_PRICE_NEW, itemData.CURRENCY);
3911				}
3912			}
3913
3914			return itemData;
3915		},
3916
3917		getData: function(data)
3918		{
3919			data = data || {};
3920
3921			data[this.params.ACTION_VARIABLE] = this.lastAction;
3922			data.via_ajax = 'Y';
3923			data.site_id = this.siteId;
3924			data.sessid = BX.bitrix_sessid();
3925			data.template = this.template;
3926			data.signedParamsString = this.signedParamsString;
3927
3928			return data;
3929		},
3930
3931		startLoader: function()
3932		{
3933			// if (!this.loadingScreen)
3934			// {
3935			// 	this.loadingScreen = new BX.PopupWindow('loading_screen', null, {
3936			// 		events: {
3937			// 			onAfterPopupShow: BX.delegate(function() {
3938			// 				BX.cleanNode(this.loadingScreen.popupContainer);
3939			// 				BX.removeClass(this.loadingScreen.popupContainer, 'popup-window');
3940			// 				this.loadingScreen.popupContainer.appendChild(
3941			// 					BX.create('IMG', {props: {src: this.templateFolder + '/images/loader.gif'}})
3942			// 				);
3943			// 				this.loadingScreen.popupContainer.removeAttribute('style');
3944			// 				this.loadingScreen.popupContainer.style.display = 'block';
3945			// 			}, this)
3946			// 		}
3947			// 	});
3948			// 	BX.addClass(this.loadingScreen.popupContainer, 'bx-step-opacity');
3949			// }
3950			//
3951			// this.loadingScreen.show();
3952		},
3953
3954		/**
3955		 * Hiding loader image with overlay.
3956		 */
3957		endLoader: function()
3958		{
3959			// if (this.loadingScreen && this.loadingScreen.isShown())
3960			// {
3961			// 	this.loadingScreen.close();
3962			// }
3963		},
3964
3965		editWarnings: function()
3966		{
3967			this.editGeneralWarnings();
3968			this.editBasketItemWarnings();
3969			this.toggleWarningBlock();
3970			this.showWarningItemsCount();
3971		},
3972
3973		editGeneralWarnings: function()
3974		{
3975			var warningsNode = this.getEntity(this.getCacheNode(this.ids.warning), 'basket-general-warnings');
3976
3977			if (BX.type.isDomNode(warningsNode))
3978			{
3979				var generalWarningText = warningsNode.innerHTML;
3980
3981				if (this.result.WARNING_MESSAGE_WITH_CODE)
3982				{
3983					for (var code in this.result.WARNING_MESSAGE_WITH_CODE)
3984					{
3985						if (this.result.WARNING_MESSAGE_WITH_CODE.hasOwnProperty(code))
3986						{
3987							if (
3988								!this.items[code]
3989								&& generalWarningText.indexOf(this.result.WARNING_MESSAGE_WITH_CODE[code]) === -1
3990							)
3991							{
3992								generalWarningText += this.result.WARNING_MESSAGE_WITH_CODE[code] + '<br/>';
3993							}
3994						}
3995					}
3996				}
3997
3998				if (generalWarningText)
3999				{
4000					warningsNode.innerHTML = generalWarningText;
4001					warningsNode.style.display = '';
4002				}
4003				else
4004				{
4005					warningsNode.style.display = 'none';
4006					warningsNode.innerHTML = '';
4007				}
4008			}
4009		},
4010
4011		editBasketItemWarnings: function()
4012		{
4013			var itemsWarningsNode = this.getEntity(this.getCacheNode(this.ids.warning), 'basket-item-warnings');
4014
4015			if (BX.type.isDomNode(itemsWarningsNode))
4016			{
4017				if (this.warningItems.length)
4018				{
4019					var warningCount = this.getEntity(itemsWarningsNode, 'basket-items-warning-count');
4020					if (BX.type.isDomNode(warningCount))
4021					{
4022						warningCount.innerHTML = this.warningItems.length + ' ' + this.getGoodsMessage(this.warningItems.length);
4023					}
4024
4025					itemsWarningsNode.style.display = '';
4026				}
4027				else if (itemsWarningsNode.style.display !== 'none')
4028				{
4029					itemsWarningsNode.style.display = 'none';
4030
4031					if (this.filter.isActive())
4032					{
4033						this.toggleFilter('all');
4034					}
4035				}
4036			}
4037		},
4038
4039		toggleWarningBlock: function()
4040		{
4041			var warningNode = this.getCacheNode(this.ids.warning);
4042
4043			if (BX.type.isDomNode(warningNode))
4044			{
4045				var generalWarningNode = this.getEntity(warningNode, 'basket-general-warnings');
4046				var itemsWarningsNode = this.getEntity(warningNode, 'basket-item-warnings');
4047
4048				if (
4049					(!BX.type.isDomNode(generalWarningNode) || generalWarningNode.style.display === 'none')
4050					&& (!BX.type.isDomNode(itemsWarningsNode) || itemsWarningsNode.style.display === 'none')
4051				)
4052				{
4053					warningNode.style.display = 'none';
4054				}
4055				else
4056				{
4057					warningNode.style.display = '';
4058				}
4059			}
4060		},
4061
4062		checkBasketItemWarnings: function(itemData, warnings)
4063		{
4064			if (!itemData)
4065				return;
4066
4067			var itemWarnings;
4068
4069			if (this.items[itemData.ID] && this.lastAction === 'refreshAjax')
4070			{
4071				itemWarnings = this.items[itemData.ID].WARNINGS;
4072			}
4073			else
4074			{
4075				itemWarnings = [];
4076			}
4077
4078			if (BX.type.isArray(warnings[itemData.ID]) && warnings[itemData.ID].length)
4079			{
4080				for (var i in warnings[itemData.ID])
4081				{
4082					if (warnings[itemData.ID].hasOwnProperty(i) && !BX.util.in_array(warnings[itemData.ID][i], itemWarnings))
4083					{
4084						itemWarnings.push(warnings[itemData.ID][i]);
4085					}
4086				}
4087			}
4088
4089			if (itemWarnings.length)
4090			{
4091				if (!BX.util.in_array(itemData.ID, this.warningItems))
4092				{
4093					this.warningItems.push(itemData.ID);
4094				}
4095			}
4096			else if (BX.util.in_array(itemData.ID, this.warningItems))
4097			{
4098				this.warningItems.splice(BX.util.array_search(itemData.ID, this.warningItems), 1);
4099			}
4100
4101			return itemWarnings;
4102		},
4103
4104		removeAllWarnings: function(event)
4105		{
4106			this.clearGeneralWarnings();
4107			this.clearBasketItemsWarnings();
4108
4109			this.editWarnings();
4110
4111			event && event.preventDefault();
4112		},
4113
4114		clearGeneralWarnings: function()
4115		{
4116			this.result.WARNING_MESSAGE_WITH_CODE = {};
4117
4118			var generalWarningNode = this.getEntity(this.getCacheNode(this.ids.warning), 'basket-general-warnings');
4119
4120			if (BX.type.isDomNode(generalWarningNode))
4121			{
4122				generalWarningNode.innerHTML = '';
4123			}
4124		},
4125
4126		clearBasketItemsWarnings: function()
4127		{
4128			var itemsToEdit = [];
4129
4130			for (var i in this.warningItems)
4131			{
4132				if (this.warningItems.hasOwnProperty(i))
4133				{
4134					this.items[this.warningItems[i]].WARNINGS = [];
4135
4136					if (this.isItemShown(this.warningItems[i]))
4137					{
4138						itemsToEdit.push(this.warningItems[i]);
4139					}
4140				}
4141			}
4142
4143			this.warningItems = [];
4144			this.editBasketItems(itemsToEdit);
4145		},
4146
4147		isItemShown: function(itemId)
4148		{
4149			return BX.util.in_array(itemId, this.shownItems);
4150		},
4151
4152		initializeBasketItems: function()
4153		{
4154			if (Object.keys(this.items).length === 0)
4155				return;
4156
4157			for (var i = 0; i < this.sortedItems.length; i++)
4158			{
4159				if (this.useDynamicScroll && this.shownItems.length >= this.maxItemsShowCount)
4160				{
4161					break;
4162				}
4163
4164				this.createBasketItem(this.sortedItems[i]);
4165			}
4166		},
4167
4168		createBasketItem: function(itemId)
4169		{
4170			if (!this.items[itemId])
4171			{
4172				return;
4173			}
4174
4175			var basketItemTemplate = this.getTemplate('basket-item-template');
4176			if (basketItemTemplate)
4177			{
4178				var basketItemHtml = this.renderBasketItem(basketItemTemplate, this.items[itemId]);
4179				var sortIndex = BX.util.array_search(itemId, this.sortedItems);
4180
4181				if (this.shownItems.length && sortIndex >= 0)
4182				{
4183					if (sortIndex < BX.util.array_search(this.shownItems[0], this.sortedItems))
4184					{
4185						// insert before
4186						BX(this.ids.item + this.shownItems[0]).insertAdjacentHTML('beforebegin', basketItemHtml);
4187						this.shownItems.unshift(itemId);
4188					}
4189					else if (sortIndex > BX.util.array_search(this.shownItems[this.shownItems.length - 1], this.sortedItems))
4190					{
4191						// insert after
4192						BX(this.ids.item + this.shownItems[this.shownItems.length - 1]).insertAdjacentHTML('afterend', basketItemHtml);
4193						this.shownItems.push(itemId);
4194					}
4195					else
4196					{
4197						// insert between
4198						BX(this.ids.item + this.sortedItems[sortIndex + 1]).insertAdjacentHTML('beforebegin', basketItemHtml);
4199						this.shownItems.splice(sortIndex + 1, 0, itemId);
4200					}
4201				}
4202				else
4203				{
4204					this.getCacheNode(this.ids.itemListTable).insertAdjacentHTML('beforeend', basketItemHtml);
4205					this.shownItems.push(itemId);
4206				}
4207
4208				this.bindBasketItemEvents(this.items[itemId]);
4209
4210				if (this.filter.isActive())
4211				{
4212					this.filter.highlightSearchMatch(this.items[itemId]);
4213				}
4214			}
4215		},
4216
4217		getItemsToEdit: function()
4218		{
4219			var itemIds = [];
4220
4221			if (this.isBasketChanged())
4222			{
4223				for (var i in this.changedItems)
4224				{
4225					if (this.changedItems.hasOwnProperty(i) && this.isItemShown(this.changedItems[i]))
4226					{
4227						itemIds.push(this.changedItems[i]);
4228					}
4229				}
4230			}
4231
4232			return itemIds;
4233		},
4234
4235		getItemsAfter: function()
4236		{
4237			var itemIdsAfter = [];
4238
4239			if (this.useDynamicScroll)
4240			{
4241				var lastShownItemId = this.shownItems[this.shownItems.length - 1] || false;
4242
4243				if (lastShownItemId)
4244				{
4245					var i = 0;
4246					var index = BX.util.array_search(lastShownItemId, this.sortedItems);
4247
4248					while (this.sortedItems[++index] && i++ < this.maxItemsShowCount)
4249					{
4250						itemIdsAfter.push(this.sortedItems[index]);
4251					}
4252				}
4253			}
4254
4255			return itemIdsAfter;
4256		},
4257
4258		editBasketItems: function(itemIds)
4259		{
4260			if (!itemIds || itemIds.length === 0)
4261			{
4262				return;
4263			}
4264
4265			var i, item;
4266
4267			for (i in itemIds)
4268			{
4269				if (!itemIds.hasOwnProperty(i) || !BX.type.isPlainObject(this.items[itemIds[i]]))
4270				{
4271					continue;
4272				}
4273
4274				item = this.items[itemIds[i]];
4275
4276				if (this.actionPool.isItemInPool(item.ID))
4277				{
4278					if (!BX.util.in_array(item.ID, this.postponedItems))
4279					{
4280						this.postponedItems.push(item.ID);
4281					}
4282
4283					continue;
4284				}
4285
4286				if (BX.type.isDomNode(BX(this.ids.item + item.ID)))
4287				{
4288					this.redrawBasketItemNode(item.ID);
4289					this.applyQuantityAnimation(item.ID);
4290				}
4291				else
4292				{
4293					this.createBasketItem(item.ID);
4294				}
4295			}
4296		},
4297
4298		editPostponedBasketItems: function()
4299		{
4300			if (!this.postponedItems.length)
4301				return;
4302
4303			var itemsToEdit = [];
4304
4305			for (var i in this.postponedItems)
4306			{
4307				if (this.postponedItems.hasOwnProperty(i) && this.isItemShown(this.postponedItems[i]))
4308				{
4309					itemsToEdit.push(this.postponedItems[i]);
4310				}
4311			}
4312
4313			this.postponedItems = [];
4314			this.editBasketItems(itemsToEdit);
4315		},
4316
4317		applyQuantityAnimation: function(itemId)
4318		{
4319			var basketItemNode = BX(this.ids.item + itemId);
4320
4321			if (BX.type.isDomNode(basketItemNode) && this.items[itemId])
4322			{
4323				if (this.items[itemId].QUANTITY_ANIMATION)
4324				{
4325					BX.addClass(BX(this.ids.quantity + itemId), 'basket-updated');
4326				}
4327			}
4328		},
4329
4330		applyPriceAnimation: function()
4331		{
4332			if (!this.priceAnimationData || Object.keys(this.priceAnimationData.start).length === 0)
4333				return;
4334
4335			var animationData = this.priceAnimationData,
4336				nodeCache = {};
4337
4338			new BX.easing({
4339				duration: this.params.USE_PRICE_ANIMATION === 'Y' ? this.duration.priceAnimation : 1,
4340				start: animationData.start,
4341				finish: animationData.finish,
4342				transition: BX.easing.makeEaseOut(BX.easing.transitions.quad),
4343				step: BX.delegate(function(state){
4344					for (var nodeId in animationData.start)
4345					{
4346						if (animationData.start.hasOwnProperty(nodeId))
4347						{
4348							if (!nodeCache[nodeId])
4349							{
4350								if (nodeId === this.ids.total)
4351								{
4352									nodeCache[nodeId] = this.getEntities(this.getCacheNode(this.ids.basketRoot), this.ids.total);
4353								}
4354								else
4355								{
4356									var node = BX(nodeId);
4357									nodeCache[nodeId] = node ? [node] : [];
4358								}
4359							}
4360
4361							if (!animationData.int[nodeId])
4362							{
4363								// fix price blinking
4364								state[nodeId] = (state[nodeId] + (state[nodeId] % 1000) / 1000).toFixed(5);
4365							}
4366
4367							for (var i = 0; i < nodeCache[nodeId].length; i++)
4368							{
4369								nodeCache[nodeId][i].innerHTML = this.getFormatPrice(state[nodeId], animationData.currency[nodeId]);
4370							}
4371						}
4372					}
4373				}, this),
4374				complete: BX.delegate(function() {
4375					var nodeId, formattedPrice, itemId, type;
4376
4377					for (nodeId in animationData.start)
4378					{
4379						if (animationData.start.hasOwnProperty(nodeId))
4380						{
4381							formattedPrice = this.getFormatPrice(animationData.finish[nodeId], animationData.currency[nodeId]);
4382
4383							for (var i = 0; i < nodeCache[nodeId].length; i++)
4384							{
4385								nodeCache[nodeId][i].innerHTML = formattedPrice;
4386							}
4387
4388							if (nodeId.indexOf(this.ids.sumPrice) !== -1)
4389							{
4390								type = 'SUM_PRICE';
4391								itemId = nodeId.substr(this.ids.sumPrice.length);
4392							}
4393							else if (nodeId.indexOf(this.ids.price) !== -1)
4394							{
4395								type = 'PRICE';
4396								itemId = nodeId.substr(this.ids.price.length);
4397							}
4398							else if (nodeId.indexOf(this.ids.total) !== -1)
4399							{
4400								type = 'TOTAL';
4401								itemId = '';
4402							}
4403							else
4404							{
4405								itemId = '';
4406								type = '';
4407							}
4408
4409							if (BX.type.isNotEmptyString(type))
4410							{
4411								if (itemId)
4412								{
4413									this.items[itemId][type] = animationData.finish[nodeId];
4414									delete this.items[itemId][type + '_NEW'];
4415									this.items[itemId][type + '_FORMATED'] = formattedPrice;
4416									delete this.items[itemId][type + '_FORMATED_NEW'];
4417								}
4418								else if (type === 'TOTAL')
4419								{
4420									this.result.TOTAL_RENDER_DATA.PRICE = animationData.finish[nodeId];
4421									delete this.result.TOTAL_RENDER_DATA.PRICE_NEW;
4422									this.result.TOTAL_RENDER_DATA.PRICE_FORMATED = formattedPrice;
4423									delete this.result.TOTAL_RENDER_DATA.PRICE_FORMATED_NEW;
4424								}
4425							}
4426						}
4427					}
4428
4429					this.filter.highlightFoundItems();
4430				}, this)
4431			}).animate();
4432		},
4433
4434		getFormatPrice: function(price, currency)
4435		{
4436			return BX.Currency.currencyFormat(price, currency, true);
4437		},
4438
4439		deleteBasketItems: function(items, restore, final)
4440		{
4441			if (!items || !items.length)
4442			{
4443				return;
4444			}
4445
4446			for (var i in items)
4447			{
4448				if (items.hasOwnProperty(i))
4449				{
4450					this.deleteBasketItem(items[i], restore, final);
4451				}
4452			}
4453		},
4454
4455		deleteBasketItem: function(itemId, restore, final)
4456		{
4457			// delete not available item with no chance to restore
4458			if (this.items[itemId].NOT_AVAILABLE && restore)
4459			{
4460				restore = false;
4461				final = true;
4462			}
4463
4464			if (restore)
4465			{
4466				this.items[itemId].SHOW_RESTORE = true;
4467				this.items[itemId].SHOW_LOADING = false;
4468				this.redrawBasketItemNode(itemId);
4469			}
4470			else
4471			{
4472				this.changeShownItem(itemId);
4473				BX.remove(BX(this.ids.item + itemId));
4474			}
4475
4476			if (final)
4477			{
4478				this.changeSortedItem(itemId, false, true);
4479				this.changeShownItem(itemId, false, true);
4480			}
4481		},
4482
4483		addSortedItem: function(itemId, all)
4484		{
4485			this.sortedItems.push(itemId.toString());
4486
4487			if (all && this.filter.isActive())
4488			{
4489				this.filter.realSortedItems.push(itemId.toString());
4490			}
4491		},
4492
4493		changeSortedItem: function(itemId, newItemId, all)
4494		{
4495			var index = BX.util.array_search(itemId, this.sortedItems);
4496
4497			if (index >= 0)
4498			{
4499				if (newItemId)
4500				{
4501					this.sortedItems.splice(index, 1, newItemId.toString());
4502				}
4503				else
4504				{
4505					this.sortedItems.splice(index, 1);
4506				}
4507			}
4508
4509			if (all && this.filter.isActive())
4510			{
4511				index = BX.util.array_search(itemId, this.filter.realSortedItems);
4512
4513				if (index >= 0)
4514				{
4515					if (newItemId)
4516					{
4517						this.filter.realSortedItems.splice(index, 1, newItemId.toString());
4518					}
4519					else
4520					{
4521						this.filter.realSortedItems.splice(index, 1);
4522					}
4523				}
4524			}
4525		},
4526
4527		sortSortedItems: function(all)
4528		{
4529			this.sortedItems.sort(BX.proxy(this.itemSortFunction, this));
4530
4531			if (all && this.filter.isActive())
4532			{
4533				this.filter.realSortedItems.sort(BX.proxy(this.itemSortFunction, this));
4534			}
4535		},
4536
4537		changeShownItem: function(itemId, newItemId, all)
4538		{
4539			var index = BX.util.array_search(itemId, this.shownItems);
4540
4541			if (index >= 0)
4542			{
4543				if (newItemId)
4544				{
4545					this.shownItems.splice(index, 1, newItemId.toString());
4546				}
4547				else
4548				{
4549					this.shownItems.splice(index, 1);
4550				}
4551			}
4552
4553			if (all && this.filter.isActive())
4554			{
4555				index = BX.util.array_search(itemId, this.filter.realShownItems);
4556
4557				if (index >= 0)
4558				{
4559					if (newItemId)
4560					{
4561						this.filter.realShownItems.splice(index, 1, newItemId.toString());
4562					}
4563					else
4564					{
4565						this.filter.realShownItems.splice(index, 1);
4566					}
4567				}
4568			}
4569		},
4570
4571		redrawBasketItemNode: function(itemId)
4572		{
4573			var basketItemNode = BX(this.ids.item + itemId);
4574
4575			if (!this.items[itemId] || !BX.type.isDomNode(basketItemNode))
4576				return;
4577
4578			var basketItemTemplate = this.getTemplate('basket-item-template');
4579			if (basketItemTemplate)
4580			{
4581				var nodeAligner = BX(this.ids.itemHeightAligner + itemId),
4582					oldHeight;
4583
4584				if (BX.type.isDomNode(nodeAligner))
4585				{
4586					oldHeight = nodeAligner.clientHeight;
4587				}
4588
4589				var basketItemHtml = this.renderBasketItem(basketItemTemplate, this.items[itemId]);
4590				basketItemNode.insertAdjacentHTML('beforebegin', basketItemHtml);
4591				BX.remove(basketItemNode);
4592
4593				if (oldHeight)
4594				{
4595					nodeAligner = BX(this.ids.itemHeightAligner + itemId);
4596
4597					if (BX.type.isDomNode(nodeAligner) && nodeAligner.clientHeight < oldHeight)
4598					{
4599						nodeAligner.style.minHeight = oldHeight + 'px';
4600						setTimeout(function(){nodeAligner.style.minHeight = '0px';}, 1);
4601					}
4602				}
4603
4604				this.bindBasketItemEvents(this.items[itemId]);
4605
4606				if (this.filter.isActive())
4607				{
4608					this.filter.highlightSearchMatch(this.items[itemId]);
4609				}
4610			}
4611		},
4612
4613		restoreBasketItems: function(items)
4614		{
4615			if (!items || Object.keys(items).length === 0)
4616			{
4617				return;
4618			}
4619
4620			var oldItemId, newItemId, basketItemNode;
4621
4622			for (oldItemId in items)
4623			{
4624				if (items.hasOwnProperty(oldItemId))
4625				{
4626					newItemId = items[oldItemId];
4627
4628					if (this.isItemShown(oldItemId))
4629					{
4630						this.changeShownItem(oldItemId, newItemId, true);
4631
4632						basketItemNode = BX(this.ids.item + oldItemId);
4633						if (BX.type.isDomNode(basketItemNode))
4634						{
4635							basketItemNode.id = this.ids.item + newItemId;
4636							basketItemNode.setAttribute('data-id', newItemId);
4637						}
4638					}
4639
4640					this.changeSortedItem(oldItemId, false, true);
4641				}
4642			}
4643		},
4644
4645		bindBasketItemEvents: function(itemData)
4646		{
4647			if (!itemData)
4648				return;
4649
4650			var itemNode = BX(this.ids.item + itemData.ID);
4651			if (BX.type.isDomNode(itemNode))
4652			{
4653				this.bindQuantityEvents(itemNode, itemData);
4654				this.bindSkuEvents(itemNode, itemData);
4655				this.bindImageEvents(itemNode, itemData);
4656				this.bindActionEvents(itemNode, itemData);
4657				this.bindRestoreAction(itemNode, itemData);
4658				this.bindItemWarningEvents(itemNode, itemData);
4659			}
4660		},
4661
4662		bindQuantityEvents: function(node, data)
4663		{
4664			if (!node || !data || !this.isItemAvailable(data.ID))
4665				return;
4666
4667			//var entityminus, entityplus, entityinput;
4668
4669			var block = this.getEntity(node, 'basket-item-quantity-block');
4670			if (block)
4671			{
4672				var startEventName = this.isTouch ? 'touchstart' : 'mousedown';
4673				var endEventName = this.isTouch ? 'touchend' : 'mouseup';
4674
4675				let entityminus = this.getEntity(block, 'basket-item-quantity-minus');
4676				BX.bind(entityminus, startEventName, BX.proxy(this.startQuantityInterval, this));
4677				BX.bind(entityminus, endEventName, BX.proxy(this.clearQuantityInterval, this));
4678				BX.bind(entityminus, 'mouseout', BX.proxy(this.clearQuantityInterval, this));
4679				BX.bind(entityminus, 'click', BX.proxy(this.quantityMinus, this));
4680
4681				let entityplus = this.getEntity(block, 'basket-item-quantity-plus');
4682				BX.bind(entityplus, startEventName, BX.proxy(this.startQuantityInterval, this));
4683				BX.bind(entityplus, endEventName, BX.proxy(this.clearQuantityInterval, this));
4684				BX.bind(entityplus, 'mouseout', BX.proxy(this.clearQuantityInterval, this));
4685				BX.bind(entityplus, 'click', BX.proxy(this.quantityPlus, this));
4686
4687				let entityinput = this.getEntity(block, 'basket-item-quantity-field');
4688				BX.bind(entityinput, 'change', BX.proxy(this.quantityChange, this));
4689
4690			}
4691		},
4692
4693		startQuantityInterval: function()
4694		{
4695
4696			var target = BX.proxy_context;
4697			var func = target.getAttribute('data-entity') === 'basket-item-quantity-minus'
4698				? BX.proxy(this.quantityMinus, this)
4699				: BX.proxy(this.quantityPlus, this);
4700
4701			this.quantityDelay = setTimeout(
4702				BX.delegate(function() {
4703					this.quantityTimer = setInterval(function(){func(target);}, 150);
4704				}, this),
4705				300
4706			);
4707		},
4708
4709		clearQuantityInterval: function()
4710		{
4711			clearTimeout(this.quantityDelay);
4712			clearInterval(this.quantityTimer);
4713		},
4714
4715		quantityPlus: function(target)
4716		{
4717
4718			if (!BX.type.isDomNode(target))
4719			{
4720				target = BX.proxy_context;
4721				this.clearQuantityInterval();
4722			}
4723
4724			var itemData = this.getItemDataByTarget(target);
4725			if (itemData)
4726			{
4727				var quantityField = BX(this.ids.quantity + itemData.ID);
4728				var isQuantityFloat = this.isQuantityFloat(itemData);
4729
4730				var currentQuantity = isQuantityFloat ? parseFloat(quantityField.value) : Math.round(quantityField.value);
4731				var measureRatio = isQuantityFloat ? parseFloat(itemData.MEASURE_RATIO) : parseInt(itemData.MEASURE_RATIO);
4732
4733				var quantity = parseFloat((currentQuantity + measureRatio).toFixed(5));
4734				quantity = this.getCorrectQuantity(itemData, quantity);
4735
4736				this.setQuantity(itemData, quantity);
4737			}
4738		},
4739
4740		quantityMinus: function(target)
4741		{
4742
4743			if (!BX.type.isDomNode(target))
4744			{
4745				target = BX.proxy_context;
4746				this.clearQuantityInterval();
4747			}
4748			//target = BX.type.isDomNode(target) ? target : BX.proxy_context;
4749
4750			var itemData = this.getItemDataByTarget(target);
4751			if (itemData)
4752			{
4753				var quantityField = BX(this.ids.quantity + itemData.ID);
4754				var isQuantityFloat = this.isQuantityFloat(itemData);
4755
4756				var currentQuantity = isQuantityFloat ? parseFloat(quantityField.value) : Math.round(quantityField.value);
4757				var measureRatio = isQuantityFloat ? parseFloat(itemData.MEASURE_RATIO) : parseInt(itemData.MEASURE_RATIO);
4758
4759				var quantity = parseFloat((currentQuantity - measureRatio).toFixed(5));
4760				quantity = this.getCorrectQuantity(itemData, quantity);
4761
4762				this.setQuantity(itemData, quantity);
4763			}
4764		},
4765
4766		quantityChange: function()
4767		{
4768			var itemData = this.getItemDataByTarget(BX.proxy_context);
4769			if (itemData)
4770			{
4771				var quantityField, quantity;
4772
4773				quantityField = BX(this.ids.quantity + itemData.ID);
4774				quantity = this.getCorrectQuantity(itemData, quantityField.value);
4775
4776				this.setQuantity(itemData, quantity);
4777			}
4778		},
4779
4780		isQuantityFloat: function(item)
4781		{
4782			return this.params.QUANTITY_FLOAT === 'Y' || (parseInt(item.MEASURE_RATIO) !== parseFloat(item.MEASURE_RATIO));
4783		},
4784
4785		getCorrectQuantity: function(itemData, quantity)
4786		{
4787
4788			var isQuantityFloat = this.isQuantityFloat(itemData),
4789				measureRatio = isQuantityFloat ? parseFloat(itemData.MEASURE_RATIO) : parseInt(itemData.MEASURE_RATIO),
4790				availableQuantity = 0;
4791
4792			quantity = (isQuantityFloat ? parseFloat(quantity) : parseInt(quantity, 10)) || 0;
4793			if (quantity < 0)
4794			{
4795				quantity = 0;
4796			}
4797
4798			if (measureRatio > 0 && quantity < measureRatio)
4799			{
4800				quantity = measureRatio;
4801			}
4802
4803			if (itemData.CHECK_MAX_QUANTITY === 'Y')
4804			{
4805				availableQuantity = isQuantityFloat ? parseFloat(itemData.AVAILABLE_QUANTITY) : parseInt(itemData.AVAILABLE_QUANTITY);
4806				if (availableQuantity > 0 && quantity > availableQuantity)
4807				{
4808					quantity = availableQuantity;
4809				}
4810			}
4811
4812			var reminder = (quantity / measureRatio - ((quantity / measureRatio).toFixed(0))).toFixed(5),
4813				remain;
4814
4815			if (parseFloat(reminder) === 0)
4816			{
4817				return quantity;
4818			}
4819
4820			if (measureRatio !== 0 && measureRatio !== 1)
4821			{
4822				remain = (quantity * this.precisionFactor) % (measureRatio * this.precisionFactor) / this.precisionFactor;
4823
4824				if (measureRatio > 0 && remain > 0)
4825				{
4826					if (
4827						remain >= measureRatio / 2
4828						&& (
4829							availableQuantity === 0
4830							|| (quantity + measureRatio - remain) <= availableQuantity
4831						)
4832					)
4833					{
4834						quantity += (measureRatio - remain);
4835					}
4836					else
4837					{
4838						quantity -= remain;
4839					}
4840				}
4841			}
4842
4843			quantity = isQuantityFloat ? parseFloat(quantity) : parseInt(quantity, 10);
4844
4845			return quantity;
4846		},
4847
4848		setQuantity: function(itemData, quantity)
4849		{
4850
4851			var quantityField = BX(this.ids.quantity + itemData.ID),
4852				currentQuantity;
4853
4854			if (quantityField)
4855			{
4856				quantity = parseFloat(quantity);
4857				currentQuantity = parseFloat(quantityField.getAttribute('data-value'));
4858
4859				quantityField.value = quantity;
4860
4861				if (parseFloat(itemData.QUANTITY) !== parseFloat(quantity))
4862				{
4863					this.animatePriceByQuantity(itemData, quantity);
4864					this.actionPool.changeQuantity(itemData.ID, quantity, currentQuantity);
4865				}
4866			}
4867		},
4868
4869		animatePriceByQuantity: function(itemData, quantity)
4870		{
4871
4872			var priceNode = BX(this.ids.sumPrice + itemData.ID);
4873			if (!BX.type.isDomNode(priceNode))
4874				return;
4875
4876			var quantityMultiplier = quantity / parseFloat(itemData.MEASURE_RATIO);
4877
4878			var startPrice = parseFloat(itemData.SUM_PRICE),
4879				finalPrice = parseFloat(itemData.PRICE) * quantityMultiplier,
4880				isInt = parseInt(startPrice) === parseFloat(startPrice)
4881					&& parseInt(finalPrice) === parseFloat(finalPrice);
4882
4883			if (startPrice !== finalPrice)
4884			{
4885				this.items[itemData.ID].QUANTITY = quantity;
4886				this.items[itemData.ID].SUM_PRICE = finalPrice;
4887
4888				new BX.easing({
4889					duration: this.params.USE_PRICE_ANIMATION === 'Y' ? this.duration.priceAnimation : 1,
4890					start: {price: startPrice},
4891					finish: {price: finalPrice},
4892					transition: BX.easing.makeEaseOut(BX.easing.transitions.quad),
4893					step: BX.delegate(function(state){
4894						if (!isInt)
4895						{
4896							// fix price blinking
4897							state.price = (state.price + (state.price % 1000) / 1000).toFixed(5);
4898						}
4899
4900						priceNode.innerHTML = this.getFormatPrice(state.price, itemData.CURRENCY);
4901					}, this),
4902					complete: BX.delegate(function() {
4903						var node, price;
4904
4905						priceNode.innerHTML = this.getFormatPrice(finalPrice, itemData.CURRENCY);
4906
4907						node = BX(this.ids.sumPriceOld + itemData.ID);
4908						if (BX.type.isDomNode(node))
4909						{
4910							price = parseFloat(itemData.FULL_PRICE) * quantityMultiplier;
4911							node.innerHTML = this.getFormatPrice(price, itemData.CURRENCY);
4912						}
4913
4914						node = BX(this.ids.sumPriceDiff + itemData.ID);
4915						if (BX.type.isDomNode(node))
4916						{
4917							price = parseFloat(itemData.DISCOUNT_PRICE) * quantityMultiplier;
4918							node.innerHTML = this.getFormatPrice(price, itemData.CURRENCY);
4919						}
4920					}, this)
4921				}).animate();
4922			}
4923		},
4924
4925		getItemDataByTarget: function(target)
4926		{
4927			var data = false;
4928			var id;
4929
4930			var itemNode = BX.findParent(target, {attrs: {'data-entity': 'basket-item'}});
4931			if (itemNode)
4932			{
4933				id = itemNode.getAttribute('data-id');
4934				data = this.items[id];
4935			}
4936
4937			return data;
4938		},
4939
4940		bindSkuEvents: function(node, data)
4941		{
4942			if (!node || !data)
4943				return;
4944
4945			var blocks = this.getEntities(node, 'basket-item-sku-block');
4946			var blockEntities, i, l, ii, ll;
4947
4948			for (i = 0, l = blocks.length; i < l; i++)
4949			{
4950				blockEntities = this.getEntities(blocks[i], 'basket-item-sku-field');
4951
4952				for (ii = 0, ll = blockEntities.length; ii < ll; ii++)
4953				{
4954					BX.bind(blockEntities[ii], 'click', BX.proxy(this.changeSku, this));
4955				}
4956			}
4957		},
4958
4959		changeSku: function()
4960		{
4961			var i, l;
4962
4963			var target = BX.proxy_context;
4964
4965			if (BX.hasClass(target, 'selected'))
4966				return;
4967
4968			var itemData = this.getItemDataByTarget(target);
4969			if (itemData)
4970			{
4971				var basketItemNode = BX(this.ids.item + itemData.ID);
4972				if (basketItemNode)
4973				{
4974					var currentSkuListNodes = this.getEntities(target.parentNode, 'basket-item-sku-field');
4975					for (i = 0, l = currentSkuListNodes.length; i < l; i++)
4976					{
4977						if (currentSkuListNodes[i].isEqualNode(target))
4978						{
4979							BX.addClass(currentSkuListNodes[i], 'selected');
4980						}
4981						else
4982						{
4983							BX.removeClass(currentSkuListNodes[i], 'selected');
4984						}
4985					}
4986
4987					this.actionPool.changeSku(
4988						itemData.ID,
4989						this.getSkuPropertyValues(basketItemNode),
4990						this.getInitialSkuPropertyValues(basketItemNode)
4991					);
4992				}
4993			}
4994		},
4995
4996		getSkuPropertyValues: function(basketItemNode)
4997		{
4998			var propertyValues = {};
4999
5000			var propNodes = this.getEntities(basketItemNode, 'basket-item-sku-field', '.selected');
5001			for (var i = 0, l = propNodes.length; i < l; i++)
5002			{
5003				propertyValues[propNodes[i].getAttribute('data-property')] = BX.util.htmlspecialcharsback(propNodes[i].getAttribute('data-value-id'));
5004			}
5005
5006			return propertyValues;
5007		},
5008
5009		getInitialSkuPropertyValues: function(basketItemNode)
5010		{
5011			var propertyValues = {};
5012
5013			var propNodes = this.getEntities(basketItemNode, 'basket-item-sku-field', '[data-initial="true"]');
5014			for (var i = 0, l = propNodes.length; i < l; i++)
5015			{
5016				propertyValues[propNodes[i].getAttribute('data-property')] = BX.util.htmlspecialcharsback(propNodes[i].getAttribute('data-value-id'));
5017			}
5018
5019			return propertyValues;
5020		},
5021
5022		bindImageEvents: function(node, data)
5023		{
5024			if (!node || !data)
5025				return;
5026
5027			var images = node.querySelectorAll('.basket-item-custom-block-photo-item');
5028			for (var i = 0, l = images.length; i < l; i++)
5029			{
5030				BX.bind(images[i], 'click', BX.proxy(this.showPropertyImagePopup, this));
5031			}
5032		},
5033
5034		showPropertyImagePopup: function()
5035		{
5036			var target, propertyCode, imageIndex, item, imageSrc, i;
5037
5038			target = BX.proxy_context;
5039			item = this.getItemDataByTarget(target);
5040
5041			propertyCode = target.getAttribute('data-column-property-code');
5042			imageIndex = target.getAttribute('data-image-index');
5043
5044			if (item && item.COLUMN_LIST)
5045			{
5046				for (i in item.COLUMN_LIST)
5047				{
5048					if (
5049						item.COLUMN_LIST.hasOwnProperty(i)
5050						&& item.COLUMN_LIST[i].CODE === propertyCode
5051						&& item.COLUMN_LIST[i].VALUE[imageIndex]
5052					)
5053					{
5054						imageSrc = item.COLUMN_LIST[i].VALUE[imageIndex].IMAGE_SRC_ORIGINAL;
5055						break;
5056					}
5057				}
5058			}
5059
5060			if (!imageSrc)
5061			{
5062				return;
5063			}
5064
5065			if (this.imagePopup)
5066			{
5067				this.imagePopup.destroy();
5068			}
5069
5070			var imageId = 'bx-soa-image-popup-content';
5071			var that = this;
5072
5073			this.imagePopup = new BX.PopupWindow('bx-soa-image-popup', null, {
5074				lightShadow: true,
5075				offsetTop: 0,
5076				offsetLeft: 0,
5077				closeIcon: {top: '3px', right: '10px'},
5078				autoHide: true,
5079				bindOptions: {position: 'bottom'},
5080				closeByEsc: true,
5081				zIndex: 100,
5082				events: {
5083					onPopupShow: function() {
5084						BX.create('IMG', {
5085							props: {src: imageSrc},
5086							events: {
5087								load: function() {
5088									var content = BX(imageId);
5089									if (content)
5090									{
5091										var windowSize = BX.GetWindowInnerSize(),
5092											ratio = that.isMobile ? 0.5 : 0.9,
5093											contentHeight, contentWidth;
5094
5095										BX.cleanNode(content);
5096										content.appendChild(this);
5097
5098										contentHeight = content.offsetHeight;
5099										contentWidth = content.offsetWidth;
5100
5101										if (contentHeight >
5101 windowSize.innerHeight * ratio)
5102										{
5103											content.style.height = windowSize.innerHeight * ratio + 'px';
5104											content.style.width = contentWidth * (windowSize.innerHeight * ratio / contentHeight) + 'px';
5105											contentHeight = content.offsetHeight;
5106											contentWidth = content.offsetWidth;
5107										}
5108
5109										if (contentWidth > windowSize.innerWidth * ratio)
5110										{
5111											content.style.width = windowSize.innerWidth * ratio + 'px';
5112											content.style.height = contentHeight * (windowSize.innerWidth * ratio / contentWidth) + 'px';
5113										}
5114
5115										content.style.height = content.offsetHeight + 'px';
5116										content.style.width = content.offsetWidth + 'px';
5117
5118										that.imagePopup.adjustPosition();
5119									}
5120								}
5121							}
5122						});
5123					},
5124					onPopupClose: function() {
5125						this.destroy();
5126					}
5127				},
5128				content: BX.create('DIV', {props: {id: imageId}})
5129			});
5130			this.imagePopup.show();
5131		},
5132
5133		bindActionEvents: function(node, data)
5134		{
5135			if (!node || !data)
5136				return;
5137
5138			var entity;
5139
5140			if (BX.util.in_array('DELETE', this.params.COLUMNS_LIST))
5141			{
5142				entity = this.getEntities(node, 'basket-item-delete');
5143				for (var i = 0, l = entity.length; i < l; i++)
5144				{
5145					BX.bind(entity[i], 'click', BX.proxy(this.deleteAction, this));
5146				}
5147			}
5148
5149			if (BX.util.in_array('DELAY', this.params.COLUMNS_LIST))
5150			{
5151				entity = this.getEntity(node, 'basket-item-add-delayed');
5152				BX.bind(entity, 'click', BX.proxy(this.addDelayedAction, this));
5153			}
5154
5155			entity = this.getEntity(node, 'basket-item-remove-delayed');
5156			BX.bind(entity, 'click', BX.proxy(this.removeDelayedAction, this));
5157
5158			entity = this.getEntity(node, 'basket-item-merge-sku-link');
5159			BX.bind(entity, 'click', BX.proxy(this.mergeAction, this));
5160
5161			entity = this.getEntity(node, 'basket-item-show-similar-link');
5162			BX.bind(entity, 'click', BX.delegate(function() {this.toggleFilter('similar');}, this));
5163		},
5164
5165		deleteAction: function()
5166		{
5167			var itemData = this.getItemDataByTarget(BX.proxy_context);
5168			if (itemData)
5169			{
5170				this.actionPool.deleteItem(itemData.ID);
5171
5172				this.items[itemData.ID].SHOW_LOADING = true;
5173
5174				if (this.params.SHOW_RESTORE === 'Y' && this.isItemAvailable(itemData.ID))
5175				{
5176					this.items[itemData.ID].SHOW_RESTORE = true;
5177				}
5178
5179				this.redrawBasketItemNode(itemData.ID);
5180			}
5181		},
5182
5183		addDelayedAction: function()
5184		{
5185			var itemData = this.getItemDataByTarget(BX.proxy_context);
5186			if (itemData)
5187			{
5188				this.actionPool.addDelayed(itemData.ID);
5189
5190				this.items[itemData.ID].SHOW_LOADING = true;
5191				this.redrawBasketItemNode(itemData.ID);
5192			}
5193		},
5194
5195		removeDelayedAction: function()
5196		{
5197			var itemData = this.getItemDataByTarget(BX.proxy_context);
5198			if (itemData)
5199			{
5200				this.actionPool.removeDelayed(itemData.ID);
5201
5202				this.items[itemData.ID].SHOW_LOADING = true;
5203				this.redrawBasketItemNode(itemData.ID);
5204			}
5205		},
5206
5207		mergeAction: function()
5208		{
5209			var itemData = this.getItemDataByTarget(BX.proxy_context);
5210			if (itemData)
5211			{
5212				this.actionPool.mergeSku(itemData.ID);
5213			}
5214		},
5215
5216		bindRestoreAction: function(node, itemData)
5217		{
5218			if (!node || !itemData || this.params.SHOW_RESTORE !== 'Y')
5219				return;
5220
5221			BX.bind(
5222				this.getEntity(node, 'basket-item-restore-button'),
5223				'click',
5224				BX.delegate(function() {
5225					this.actionPool.restoreItem(itemData.ID, {
5226						PRODUCT_ID: itemData.PRODUCT_ID,
5227						QUANTITY: itemData.QUANTITY,
5228						PROPS: itemData.PROPS_ALL,
5229						SORT: itemData.SORT,
5230						MODULE: itemData.MODULE,
5231						PRODUCT_PROVIDER_CLASS: itemData.PRODUCT_PROVIDER_CLASS
5232					});
5233
5234					this.items[itemData.ID].SHOW_RESTORE = false;
5235					this.items[itemData.ID].SHOW_LOADING = true;
5236					this.redrawBasketItemNode(itemData.ID);
5237				}, this)
5238			);
5239			BX.bind(
5240				this.getEntity(node, 'basket-item-close-restore-button'),
5241				'click',
5242				BX.delegate(function() {
5243					this.deleteBasketItem(itemData.ID, false, true);
5244				}, this)
5245			);
5246		},
5247
5248		bindItemWarningEvents: function(node, data)
5249		{
5250			if (!node || !data)
5251				return;
5252
5253			BX.bind(
5254				this.getEntity(BX(this.ids.item + data.ID), 'basket-item-warning-close'),
5255				'click',
5256				BX.proxy(this.closeItemWarnings, this)
5257			);
5258		},
5259
5260		closeItemWarnings: function()
5261		{
5262			var target = BX.proxy_context;
5263
5264			if (BX.type.isDomNode(target))
5265			{
5266				var itemData = this.getItemDataByTarget(target);
5267
5268				this.items[itemData.ID].WARNINGS = [];
5269				this.warningItems.splice(BX.util.array_search(itemData.ID, this.warningItems), 1);
5270
5271				this.redrawBasketItemNode(itemData.ID);
5272				this.editWarnings();
5273			}
5274		},
5275
5276		renderBasketItem: function(template, data)
5277		{
5278			var clonedData = BX.clone(data);
5279
5280			if (BX.type.isPlainObject(clonedData))
5281			{
5282				clonedData.USE_FILTER = this.useItemsFilter
5283					&& !this.filter.currentFilter.similarHash.length;
5284			}
5285
5286			return Mustache.render(template, clonedData);
5287		},
5288
5289		render: function(template, data)
5290		{
5291			return Mustache.render(template, data);
5292		},
5293
5294		checkAnalytics: function(data)
5295		{
5296			if (!data || !data.basket)
5297				return;
5298
5299			var itemId, itemsDiff = {};
5300
5301			for (var i in data.basket)
5302			{
5303				if (data.basket.hasOwnProperty(i))
5304				{
5305					if (i.indexOf('QUANTITY_') >= 0)
5306					{
5307						itemId = i.substr(9);
5308
5309						if (this.items[itemId])
5310						{
5311							itemsDiff[itemId] = parseFloat(data.basket[i]) - parseFloat(BX(this.ids.quantity + itemId).getAttribute('data-value'));
5312						}
5313					}
5314					else if (i.indexOf('DELETE_') >= 0)
5315					{
5316						itemId = i.substr(7);
5317
5318						if (this.items[itemId])
5319						{
5320							itemsDiff[itemId] = -parseFloat(this.items[itemId].QUANTITY);
5321						}
5322					}
5323					else if (i.indexOf('RESTORE_') >= 0)
5324					{
5325						itemId = i.substr(8);
5326
5327						if (this.items[itemId])
5328						{
5329							itemsDiff[itemId] = parseFloat(this.items[itemId].QUANTITY);
5330						}
5331					}
5332				}
5333			}
5334
5335			this.setAnalyticsDataLayer(itemsDiff);
5336		},
5337
5338		setAnalyticsDataLayer: function(itemsDiff)
5339		{
5340			if (!itemsDiff || Object.keys(itemsDiff).length === 0)
5341				return;
5342
5343			window[this.params.DATA_LAYER_NAME] = window[this.params.DATA_LAYER_NAME] || [];
5344
5345			var plus = [], minus = [];
5346
5347			for (var itemId in itemsDiff)
5348			{
5349				if (itemsDiff.hasOwnProperty(itemId))
5350				{
5351					if (itemsDiff[itemId] > 0)
5352					{
5353						plus.push(this.getItemAnalyticsInfo(itemId, itemsDiff[itemId]));
5354					}
5355					else if (itemsDiff[itemId] < 0)
5356					{
5357						minus.push(this.getItemAnalyticsInfo(itemId, itemsDiff[itemId]));
5358					}
5359				}
5360			}
5361
5362			if (plus.length)
5363			{
5364				window[this.params.DATA_LAYER_NAME].push({
5365					event: 'addToCart',
5366					ecommerce: {
5367						currencyCode: this.items[itemId].CURRENCY || '',
5368						add: {
5369							products: plus
5370						}
5371					}
5372				});
5373			}
5374
5375			if (minus.length)
5376			{
5377				window[this.params.DATA_LAYER_NAME].push({
5378					event: 'removeFromCart',
5379					ecommerce: {
5380						currencyCode: this.items[itemId].CURRENCY || '',
5381						remove: {
5382							products: minus
5383						}
5384					}
5385				});
5386			}
5387		},
5388
5389		getItemAnalyticsInfo: function(itemId, diff)
5390		{
5391			if (!this.items[itemId])
5392				return {};
5393
5394			var brand = (this.items[itemId].BRAND || '').split(',  ').join('/');
5395			var variants = [];
5396
5397			var selectedSku = this.getEntities(BX(this.ids.item + itemId), 'basket-item-sku-field', '.selected');
5398			for (var i = 0, l = selectedSku.length; i < l; i++)
5399			{
5400				variants.push(selectedSku[i].getAttribute('data-sku-name'));
5401			}
5402
5403			return {
5404				'name': this.items[itemId].NAME || '',
5405				'id': this.items[itemId].PRODUCT_ID || '',
5406				'price': this.items[itemId].PRICE || 0,
5407				'brand': brand,
5408				'variant': variants.join('/'),
5409				'quantity': Math.abs(diff)
5410			};
5411		}
5412	};
5413})();
5414/* End */
5415;
5416; /* Start:"a:4:{s:4:"full";s:96:"/local/templates/fabrika38/components/bitrix/catalog.item/parrots_item/script.js?179135599363328";s:6:"source";s:80:"/local/templates/fabrika38/components/bitrix/catalog.item/parrots_item/script.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
5417(function (window){
5418	'use strict';
5419
5420	if (window.JCCatalogItem)
5421		return;
5422
5423	var BasketButton = function(params)
5424	{
5425		BasketButton.superclass.constructor.apply(this, arguments);
5426		this.buttonNode = BX.create('span', {
5427			props: {className: 'btn btn-buy btn-sm green', id: this.id},
5428			style: typeof params.style === 'object' ? params.style : {},
5429			text: params.text,
5430			events: this.contextEvents
5431		});
5432
5433		if (BX.browser.IsIE())
5434		{
5435			this.buttonNode.setAttribute("hideFocus", "hidefocus");
5436		}
5437	};
5438	BX.extend(BasketButton, BX.PopupWindowButton);
5439
5440	window.JCCatalogItem = function (arParams)
5441	{
5442		this.productType = 0;
5443		this.showQuantity = true;
5444		this.showAbsent = true;
5445		this.secondPict = false;
5446		this.showOldPrice = false;
5447		this.showMaxQuantity = 'N';
5448		this.relativeQuantityFactor = 5;
5449		this.showPercent = false;
5450		this.showSkuProps = false;
5451		this.basketAction = 'ADD';
5452		this.showClosePopup = false;
5453		this.useCompare = false;
5454		this.showSubscription = false;
5455		this.visual = {
5456			ID: '',
5457			PICT_ID: '',
5458			SECOND_PICT_ID: '',
5459			PICT_SLIDER_ID: '',
5460			QUANTITY_ID: '',
5461			QUANTITY_UP_ID: '',
5462			QUANTITY_DOWN_ID: '',
5463			PRICE_ID: '',
5464			PRICE_OLD_ID: '',
5465			DSC_PERC: '',
5466			SECOND_DSC_PERC: '',
5467			DISPLAY_PROP_DIV: '',
5468			BASKET_PROP_DIV: '',
5469			SUBSCRIBE_ID: ''
5470		};
5471		this.product = {
5472			checkQuantity: false,
5473			maxQuantity: 0,
5474			stepQuantity: 1,
5475			isDblQuantity: false,
5476			canBuy: true,
5477			name: '',
5478			pict: {},
5479			id: 0,
5480			addUrl: '',
5481			buyUrl: ''
5482		};
5483
5484		this.basketMode = '';
5485		this.basketData = {
5486			useProps: false,
5487			emptyProps: false,
5488			quantity: 'quantity',
5489			props: 'prop',
5490			basketUrl: '',
5491			sku_props: '',
5492			sku_props_var: 'basket_props',
5493			add_url: '',
5494			buy_url: ''
5495		};
5496
5497		this.compareData = {
5498			compareUrl: '',
5499			compareDeleteUrl: '',
5500			comparePath: ''
5501		};
5502
5503		this.defaultPict = {
5504			pict: null,
5505			secondPict: null
5506		};
5507
5508		this.defaultSliderOptions = {
5509			interval: 3000,
5510			wrap: true
5511		};
5512		this.slider = {
5513			options: {},
5514			items: [],
5515			active: null,
5516			sliding: null,
5517			paused: null,
5518			interval: null,
5519			progress: null
5520		};
5521		this.touch = null;
5522
5523		this.quantityDelay = null;
5524		this.quantityTimer = null;
5525
5526		this.checkQuantity = false;
5527		this.maxQuantity = 0;
5528		this.minQuantity = 0;
5529		this.stepQuantity = 1;
5530		this.isDblQuantity = false;
5531		this.canBuy = true;
5532		this.precision = 6;
5533		this.precisionFactor = Math.pow(10, this.precision);
5534		this.bigData = false;
5535		this.fullDisplayMode = false;
5536		this.viewMode = '';
5537		this.templateTheme = '';
5538
5539		this.currentPriceMode = '';
5540		this.currentPrices = [];
5541		this.currentPriceSelected = 0;
5542		this.currentQuantityRanges = [];
5543		this.currentQuantityRangeSelected = 0;
5544
5545		this.offers = [];
5546		this.offerNum = 0;
5547		this.treeProps = [];
5548		this.selectedValues = {};
5549
5550		this.obProduct = null;
5551		this.blockNodes = {};
5552		this.obQuantity = null;
5553		this.obQuantityUp = null;
5554		this.obQuantityDown = null;
5555		this.obQuantityLimit = {};
5556		this.obPict = null;
5557		this.obSecondPict = null;
5558		this.obPictSlider = null;
5559		this.obPictSliderIndicator = null;
5560		this.obPrice = null;
5561		this.obTree = null;
5562		this.obBuyBtn = null;
5563		this.obBasketActions = null;
5564		this.obNotAvail = null;
5565		this.obSubscribe = null;
5566		this.obDscPerc = null;
5567		this.obSecondDscPerc = null;
5568		this.obSkuProps = null;
5569		this.obMeasure = null;
5570		this.obCompare = null;
5571
5572		this.obPopupWin = null;
5573		this.basketUrl = '';
5574		this.basketParams = {};
5575		this.isTouchDevice = BX.hasClass(document.documentElement, 'bx-touch');
5576		this.hoverTimer = null;
5577		this.hoverStateChangeForbidden = false;
5578		this.mouseX = null;
5579		this.mouseY = null;
5580
5581		this.useEnhancedEcommerce = false;
5582		this.dataLayerName = 'dataLayer';
5583		this.brandProperty = false;
5584
5585		this.errorCode = 0;
5586
5587		if (typeof arParams === 'object')
5588		{
5589			if (arParams.PRODUCT_TYPE)
5590			{
5591				this.productType = parseInt(arParams.PRODUCT_TYPE, 10);
5592			}
5593
5594			this.showQuantity = arParams.SHOW_QUANTITY;
5595			this.showAbsent = arParams.SHOW_ABSENT;
5596			this.secondPict = arParams.SECOND_PICT;
5597			this.showOldPrice = arParams.SHOW_OLD_PRICE;
5598			this.showMaxQuantity = arParams.SHOW_MAX_QUANTITY;
5599			this.relativeQuantityFactor = parseInt(arParams.RELATIVE_QUANTITY_FACTOR);
5600			this.showPercent = arParams.SHOW_DISCOUNT_PERCENT;
5601			this.showSkuProps = arParams.SHOW_SKU_PROPS;
5602			this.showSubscription = arParams.USE_SUBSCRIBE;
5603
5604			if (arParams.ADD_TO_BASKET_ACTION)
5605			{
5606				this.basketAction = arParams.ADD_TO_BASKET_ACTION;
5607			}
5608
5609			this.showClosePopup = arParams.SHOW_CLOSE_POPUP;
5610			this.useCompare = arParams.DISPLAY_COMPARE;
5611			this.fullDisplayMode = arParams.PRODUCT_DISPLAY_MODE === 'Y';
5612			this.bigData = arParams.BIG_DATA;
5613			this.viewMode = arParams.VIEW_MODE || '';
5614			this.templateTheme = arParams.TEMPLATE_THEME || '';
5615			this.useEnhancedEcommerce = arParams.USE_ENHANCED_ECOMMERCE === 'Y';
5616			this.dataLayerName = arParams.DATA_LAYER_NAME;
5617			this.brandProperty = arParams.BRAND_PROPERTY;
5618
5619			this.visual = arParams.VISUAL;
5620
5621			switch (this.productType)
5622			{
5623				case 0: // no catalog
5624				case 1: // product
5625				case 2: // set
5626					if (arParams.PRODUCT && typeof arParams.PRODUCT === 'object')
5627					{
5628						this.currentPriceMode = arParams.PRODUCT.ITEM_PRICE_MODE;
5629						this.currentPrices = arParams.PRODUCT.ITEM_PRICES;
5630						this.currentPriceSelected = arParams.PRODUCT.ITEM_PRICE_SELECTED;
5631						this.currentQuantityRanges = arParams.PRODUCT.ITEM_QUANTITY_RANGES;
5632						this.currentQuantityRangeSelected = arParams.PRODUCT.ITEM_QUANTITY_RANGE_SELECTED;
5633
5634						if (this.showQuantity)
5635						{
5636							this.product.checkQuantity = arParams.PRODUCT.CHECK_QUANTITY;
5637							this.product.isDblQuantity = arParams.PRODUCT.QUANTITY_FLOAT;
5638
5639							if (this.product.checkQuantity)
5640							{
5641								this.product.maxQuantity = (this.product.isDblQuantity ? parseFloat(arParams.PRODUCT.MAX_QUANTITY) : parseInt(arParams.PRODUCT.MAX_QUANTITY, 10));
5642							}
5643
5644							this.product.stepQuantity = (this.product.isDblQuantity ? parseFloat(arParams.PRODUCT.STEP_QUANTITY) : parseInt(arParams.PRODUCT.STEP_QUANTITY, 10));
5645
5646							this.checkQuantity = this.product.checkQuantity;
5647							this.isDblQuantity = this.product.isDblQuantity;
5648							this.stepQuantity = this.product.stepQuantity;
5649							this.maxQuantity = this.product.maxQuantity;
5650							this.minQuantity = this.currentPriceMode === 'Q'
5651								? parseFloat(this.currentPrices[this.currentPriceSelected].MIN_QUANTITY)
5652								: this.stepQuantity;
5653
5654							if (this.isDblQuantity)
5655							{
5656								this.stepQuantity = Math.round(this.stepQuantity * this.precisionFactor) / this.precisionFactor;
5657							}
5658						}
5659
5660						this.product.canBuy = arParams.PRODUCT.CAN_BUY;
5661
5662						if (arParams.PRODUCT.MORE_PHOTO_COUNT)
5663						{
5664							this.product.morePhotoCount = arParams.PRODUCT.MORE_PHOTO_COUNT;
5665							this.product.morePhoto = arParams.PRODUCT.MORE_PHOTO;
5666						}
5667
5668						if (arParams.PRODUCT.RCM_ID)
5669						{
5670							this.product.rcmId = arParams.PRODUCT.RCM_ID;
5671						}
5672
5673						this.canBuy = this.product.canBuy;
5674						this.product.name = arParams.PRODUCT.NAME;
5675						this.product.pict = arParams.PRODUCT.PICT;
5676						this.product.id = arParams.PRODUCT.ID;
5677						this.product.DETAIL_PAGE_URL = arParams.PRODUCT.DETAIL_PAGE_URL;
5678
5679						if (arParams.PRODUCT.ADD_URL)
5680						{
5681							this.product.addUrl = arParams.PRODUCT.ADD_URL;
5682						}
5683
5684						if (arParams.PRODUCT.BUY_URL)
5685						{
5686							this.product.buyUrl = arParams.PRODUCT.BUY_URL;
5687						}
5688
5689						if (arParams.BASKET && typeof arParams.BASKET === 'object')
5690						{
5691							this.basketData.useProps = arParams.BASKET.ADD_PROPS;
5692							this.basketData.emptyProps = arParams.BASKET.EMPTY_PROPS;
5693						}
5694					}
5695					else
5696					{
5697						this.errorCode = -1;
5698					}
5699
5700					break;
5701				case 3: // sku
5702					if (arParams.PRODUCT && typeof arParams.PRODUCT === 'object')
5703					{
5704						this.product.name = arParams.PRODUCT.NAME;
5705						this.product.id = arParams.PRODUCT.ID;
5706						this.product.DETAIL_PAGE_URL = arParams.PRODUCT.DETAIL_PAGE_URL;
5707						this.product.morePhotoCount = arParams.PRODUCT.MORE_PHOTO_COUNT;
5708						this.product.morePhoto = arParams.PRODUCT.MORE_PHOTO;
5709
5710						if (arParams.PRODUCT.RCM_ID)
5711						{
5712							this.product.rcmId = arParams.PRODUCT.RCM_ID;
5713						}
5714					}
5715
5716					if (arParams.OFFERS && BX.type.isArray(arParams.OFFERS))
5717					{
5718						this.offers = arParams.OFFERS;
5719						this.offerNum = 0;
5720
5721						if (arParams.OFFER_SELECTED)
5722						{
5723							this.offerNum = parseInt(arParams.OFFER_SELECTED, 10);
5724						}
5725
5726						if (isNaN(this.offerNum))
5727						{
5728							this.offerNum = 0;
5729						}
5730
5731						if (arParams.TREE_PROPS)
5732						{
5733							this.treeProps = arParams.TREE_PROPS;
5734						}
5735
5736						if (arParams.DEFAULT_PICTURE)
5737						{
5738							this.defaultPict.pict = arParams.DEFAULT_PICTURE.PICTURE;
5739							this.defaultPict.secondPict = arParams.DEFAULT_PICTURE.PICTURE_SECOND;
5740						}
5741					}
5742
5743					break;
5744				default:
5745					this.errorCode = -1;
5746			}
5747			if (arParams.BASKET && typeof arParams.BASKET === 'object')
5748			{
5749				if (arParams.BASKET.QUANTITY)
5750				{
5751					this.basketData.quantity = arParams.BASKET.QUANTITY;
5752				}
5753
5754				if (arParams.BASKET.PROPS)
5755				{
5756					this.basketData.props = arParams.BASKET.PROPS;
5757				}
5758
5759				if (arParams.BASKET.BASKET_URL)
5760				{
5761					this.basketData.basketUrl = arParams.BASKET.BASKET_URL;
5762				}
5763
5764				if (3 === this.productType)
5765				{
5766					if (arParams.BASKET.SKU_PROPS)
5767					{
5768						this.basketData.sku_props = arParams.BASKET.SKU_PROPS;
5769					}
5770				}
5771
5772				if (arParams.BASKET.ADD_URL_TEMPLATE)
5773				{
5774					this.basketData.add_url = arParams.BASKET.ADD_URL_TEMPLATE;
5775				}
5776
5777				if (arParams.BASKET.BUY_URL_TEMPLATE)
5778				{
5779					this.basketData.buy_url = arParams.BASKET.BUY_URL_TEMPLATE;
5780				}
5781
5782				if (this.basketData.add_url === '' && this.basketData.buy_url === '')
5783				{
5784					this.errorCode = -1024;
5785				}
5786			}
5787
5788			if (this.useCompare)
5789			{
5790				if (arParams.COMPARE && typeof arParams.COMPARE === 'object')
5791				{
5792					if (arParams.COMPARE.COMPARE_PATH)
5793					{
5794						this.compareData.comparePath = arParams.COMPARE.COMPARE_PATH;
5795					}
5796
5797					if (arParams.COMPARE.COMPARE_URL_TEMPLATE)
5798					{
5799						this.compareData.compareUrl = arParams.COMPARE.COMPARE_URL_TEMPLATE;
5800					}
5801					else
5802					{
5803						this.useCompare = false;
5804					}
5805
5806					if (arParams.COMPARE.COMPARE_DELETE_URL_TEMPLATE)
5807					{
5808						this.compareData.compareDeleteUrl = arParams.COMPARE.COMPARE_DELETE_URL_TEMPLATE;
5809					}
5810					else
5811					{
5812						this.useCompare = false;
5813					}
5814				}
5815				else
5816				{
5817					this.useCompare = false;
5818				}
5819			}
5820		}
5821
5822		if (this.errorCode === 0)
5823		{
5824			BX.ready(BX.delegate(this.init,this));
5825		}
5826	};
5827
5828	window.JCCatalogItem.prototype = {
5829		init: function()
5830		{
5831			var i = 0,
5832				treeItems = null;
5833
5834			this.obProduct = BX(this.visual.ID);
5835			if (!this.obProduct)
5836			{
5837				this.errorCode = -1;
5838			}
5839
5840			this.obPict = BX(this.visual.PICT_ID);
5841			if (!this.obPict)
5842			{
5843				this.errorCode = -2;
5844			}
5845
5846			if (this.secondPict && this.visual.SECOND_PICT_ID)
5847			{
5848				this.obSecondPict = BX(this.visual.SECOND_PICT_ID);
5849			}
5850
5851			this.obPictSlider = BX(this.visual.PICT_SLIDER_ID);
5852			this.obPictSliderIndicator = BX(this.visual.PICT_SLIDER_ID + '_indicator');
5853			this.obPictSliderProgressBar = BX(this.visual.PICT_SLIDER_ID + '_progress_bar');
5854			if (!this.obPictSlider)
5855			{
5856				this.errorCode = -4;
5857			}
5858
5859			this.obPrice = BX(this.visual.PRICE_ID);
5860			this.obPriceOld = BX(this.visual.PRICE_OLD_ID);
5861			this.obPriceTotal = BX(this.visual.PRICE_TOTAL_ID);
5862			if (!this.obPrice)
5863			{
5864				this.errorCode = -16;
5865			}
5866
5867			if (this.showQuantity && this.visual.QUANTITY_ID)
5868			{
5869				this.obQuantity = BX(this.visual.QUANTITY_ID);
5870				this.blockNodes.quantity = this.obProduct.querySelector('[data-entity="quantity-block"]');
5871
5872				if (!this.isTouchDevice)
5873				{
5874					BX.bind(this.obQuantity, 'focus', BX.proxy(this.onFocus, this));
5875					BX.bind(this.obQuantity, 'blur', BX.proxy(this.onBlur, this));
5876				}
5877
5878				if (this.visual.QUANTITY_UP_ID)
5879				{
5880					this.obQuantityUp = BX(this.visual.QUANTITY_UP_ID);
5881				}
5882
5883				if (this.visual.QUANTITY_DOWN_ID)
5884				{
5885					this.obQuantityDown = BX(this.visual.QUANTITY_DOWN_ID);
5886				}
5887			}
5888
5889			if (this.visual.QUANTITY_LIMIT && this.showMaxQuantity !== 'N')
5890			{
5891				this.obQuantityLimit.all = BX(this.visual.QUANTITY_LIMIT);
5892				if (this.obQuantityLimit.all)
5893				{
5894					this.obQuantityLimit.value = this.obQuantityLimit.all.querySelector('[data-entity="quantity-limit-value"]');
5895					if (!this.obQuantityLimit.value)
5896					{
5897						this.obQuantityLimit.all = null;
5898					}
5899				}
5900			}
5901
5902			if (this.productType === 3 && this.fullDisplayMode)
5903			{
5904				if (this.visual.TREE_ID)
5905				{
5906					this.obTree = BX(this.visual.TREE_ID);
5907					if (!this.obTree)
5908					{
5909						this.errorCode = -256;
5910					}
5911				}
5912
5913				if (this.visual.QUANTITY_MEASURE)
5914				{
5915					this.obMeasure = BX(this.visual.QUANTITY_MEASURE);
5916				}
5917			}
5918
5919			this.obBasketActions = BX(this.visual.BASKET_ACTIONS_ID);
5920			if (this.obBasketActions)
5921			{
5922				if (this.visual.BUY_ID)
5923				{
5924					this.obBuyBtn = BX(this.visual.BUY_ID);
5925				}
5926			}
5927
5928			this.obNotAvail = BX(this.visual.NOT_AVAILABLE_MESS);
5929
5930			if (this.showSubscription)
5931			{
5932				this.obSubscribe = BX(this.visual.SUBSCRIBE_ID);
5933			}
5934
5935			if (this.showPercent)
5936			{
5937				if (this.visual.DSC_PERC)
5938				{
5939					this.obDscPerc = BX(this.visual.DSC_PERC);
5940				}
5941				if (this.secondPict && this.visual.SECOND_DSC_PERC)
5942				{
5943					this.obSecondDscPerc = BX(this.visual.SECOND_DSC_PERC);
5944				}
5945			}
5946
5947			if (this.showSkuProps)
5948			{
5949				if (this.visual.DISPLAY_PROP_DIV)
5950				{
5951					this.obSkuProps = BX(this.visual.DISPLAY_PROP_DIV);
5952				}
5953			}
5954
5955			if (this.errorCode === 0)
5956			{
5957				// product slider events
5958				if (this.isTouchDevice)
5959				{
5960					BX.bind(this.obPictSlider, 'touchstart', BX.proxy(this.touchStartEvent, this));
5961					BX.bind(this.obPictSlider, 'touchend', BX.proxy(this.touchEndEvent, this));
5962					BX.bind(this.obPictSlider, 'touchcancel', BX.proxy(this.touchEndEvent, this));
5963				}
5964				else
5965				{
5966					if (this.viewMode === 'CARD')
5967					{
5968						// product hover events
5969						// BX.bind(this.obProduct, 'mouseenter', BX.proxy(this.hoverOn, this));
5970						// BX.bind(this.obProduct, 'mouseleave', BX.proxy(this.hoverOff, this));
5971					}
5972
5973					// product slider events
5974					BX.bind(this.obProduct, 'mouseenter', BX.proxy(this.cycleSlider, this));
5975					BX.bind(this.obProduct, 'mouseleave', BX.proxy(this.stopSlider, this));
5976				}
5977
5978				if (this.bigData)
5979				{
5980					var links = BX.findChildren(this.obProduct, {tag:'a'}, true);
5981					if (links)
5982					{
5983						for (i in links)
5984						{
5985							if (links.hasOwnProperty(i))
5986							{
5987								if (links[i].getAttribute('href') == this.product.DETAIL_PAGE_URL)
5988								{
5989									BX.bind(links[i], 'click', BX.proxy(this.rememberProductRecommendation, this));
5990								}
5991							}
5992						}
5993					}
5994				}
5995
5996				if (this.showQuantity)
5997				{
5998					var startEventName = this.isTouchDevice ? 'touchstart' : 'mousedown';
5999					var endEventName = this.isTouchDevice ? 'touchend' : 'mouseup';
6000
6001					if (this.obQuantityUp)
6002					{
6003						BX.bind(this.obQuantityUp, startEventName, BX.proxy(this.startQuantityInterval, this));
6004						BX.bind(this.obQuantityUp, endEventName, BX.proxy(this.clearQuantityInterval, this));
6005						BX.bind(this.obQuantityUp, 'mouseout', BX.proxy(this.clearQuantityInterval, this));
6006						BX.bind(this.obQuantityUp, 'click', BX.delegate(this.quantityUp, this));
6007					}
6008
6009					if (this.obQuantityDown)
6010					{
6011						BX.bind(this.obQuantityDown, startEventName, BX.proxy(this.startQuantityInterval, this));
6012						BX.bind(this.obQuantityDown, endEventName, BX.proxy(this.clearQuantityInterval, this));
6013						BX.bind(this.obQuantityDown, 'mouseout', BX.proxy(this.clearQuantityInterval, this));
6014						BX.bind(this.obQuantityDown, 'click', BX.delegate(this.quantityDown, this));
6015					}
6016
6017					if (this.obQuantity)
6018					{
6019						BX.bind(this.obQuantity, 'change', BX.delegate(this.quantityChange, this));
6020					}
6021				}
6022
6023				switch (this.productType)
6024				{
6025					case 0: // no catalog
6026					case 1: // product
6027					case 2: // set
6028						if (parseInt(this.product.morePhotoCount) > 1 && this.obPictSlider)
6029						{
6030							this.initializeSlider();
6031						}
6032
6033						this.checkQuantityControls();
6034
6035						break;
6036					case 3: // sku
6037						if (this.offers.length > 0)
6038						{
6039							treeItems = BX.findChildren(this.obTree, {tagName: 'li'}, true);
6040
6041							if (treeItems && treeItems.length)
6042							{
6043								for (i = 0; i < treeItems.length; i++)
6044								{
6045									BX.bind(treeItems[i], 'click', BX.delegate(this.selectOfferProp, this));
6046								}
6047							}
6048
6049							this.setCurrent();
6050						}
6051						else if (parseInt(this.product.morePhotoCount) > 1 && this.obPictSlider)
6052						{
6053							this.initializeSlider();
6054						}
6055
6056						break;
6057				}
6058
6059				if (this.obBuyBtn)
6060				{
6061					if (this.basketAction === 'ADD')
6062					{
6063						BX.bind(this.obBuyBtn, 'click', BX.proxy(this.add2Basket, this));
6064					}
6065					else
6066					{
6067						BX.bind(this.obBuyBtn, 'click', BX.proxy(this.buyBasket, this));
6068					}
6069				}
6070
6071				if (this.useCompare)
6072				{
6073					this.obCompare = BX(this.visual.COMPARE_LINK_ID);
6074					if (this.obCompare)
6075					{
6076						BX.bind(this.obCompare, 'click', BX.proxy(this.compare, this));
6077					}
6078
6079					BX.addCustomEvent('onCatalogDeleteCompare', BX.proxy(this.checkDeletedCompare, this));
6080				}
6081			}
6082		},
6083
6084		setAnalyticsDataLayer: function(action)
6085		{
6086			if (!this.useEnhancedEcommerce || !this.dataLayerName)
6087				return;
6088
6089			var item = {},
6090				info = {},
6091				variants = [],
6092				i, k, j, propId, skuId, propValues;
6093
6094			switch (this.productType)
6095			{
6096				case 0: //no catalog
6097				case 1: //product
6098				case 2: //set
6099					item = {
6100						'id': this.product.id,
6101						'name': this.product.name,
6102						'price': this.currentPrices[this.currentPriceSelected] && this.currentPrices[this.currentPriceSelected].PRICE,
6103						'brand': BX.type.isArray(this.brandProperty) ? this.brandProperty.join('/') : this.brandProperty
6104					};
6105					break;
6106				case 3: //sku
6107					for (i in this.offers[this.offerNum].TREE)
6108					{
6109						if (this.offers[this.offerNum].TREE.hasOwnProperty(i))
6110						{
6111							propId = i.substring(5);
6112							skuId = this.offers[this.offerNum].TREE[i];
6113
6114							for (k in this.treeProps)
6115							{
6116								if (this.treeProps.hasOwnProperty(k) && this.treeProps[k].ID == propId)
6117								{
6118									for (j in this.treeProps[k].VALUES)
6119									{
6120										propValues = this.treeProps[k].VALUES[j];
6121										if (propValues.ID == skuId)
6122										{
6123											variants.push(propValues.NAME);
6124											break;
6125										}
6126									}
6127
6128								}
6129							}
6130						}
6131					}
6132
6133					item = {
6134						'id': this.offers[this.offerNum].ID,
6135						'name': this.offers[this.offerNum].NAME,
6136						'price': this.currentPrices[this.currentPriceSelected] && this.currentPrices[this.currentPriceSelected].PRICE,
6137						'brand': BX.type.isArray(this.brandProperty) ? this.brandProperty.join('/') : this.brandProperty,
6138						'variant': variants.join('/')
6139					};
6140					break;
6141			}
6142
6143			switch (action)
6144			{
6145				case 'addToCart':
6146					info = {
6147						'event': 'addToCart',
6148						'ecommerce': {
6149							'currencyCode': this.currentPrices[this.currentPriceSelected] && this.currentPrices[this.currentPriceSelected].CURRENCY || '',
6150							'add': {
6151								'products': [{
6152									'name': item.name || '',
6153									'id': item.id || '',
6154									'price': item.price || 0,
6155									'brand': item.brand || '',
6156									'category': item.category || '',
6157									'variant': item.variant || '',
6158									'quantity': this.showQuantity && this.obQuantity ? this.obQuantity.value : 1
6159								}]
6160							}
6161						}
6162					};
6163					break;
6164			}
6165
6166			window[this.dataLayerName] = window[this.dataLayerName] || [];
6167			window[this.dataLayerName].push(info);
6168		},
6169
6170		hoverOn: function(event)
6171		{
6172			// clearTimeout(this.hoverTimer);
6173			// this.obProduct.style.height = getComputedStyle(this.obProduct).height;
6174
6175
6176			// BX.addClass(this.obProduct, 'hover');
6177
6178			BX.PreventDefault(event);
6179		},
6180
6181		hoverOff: function(event)
6182		{
6183			if (this.hoverStateChangeForbidden)
6184				return;
6185
6186			BX.removeClass(this.obProduct, 'hover');
6187			this.hoverTimer = setTimeout(
6188				BX.delegate(function(){
6189					this.obProduct.style.height = 'auto';
6190				}, this),
6191				300
6192			);
6193
6194			BX.PreventDefault(event);
6195		},
6196
6197		onFocus: function()
6198		{
6199			this.hoverStateChangeForbidden = true;
6200			BX.bind(document, 'mousemove', BX.proxy(this.captureMousePosition, this));
6201		},
6202
6203		onBlur: function()
6204		{
6205			this.hoverStateChangeForbidden = false;
6206			BX.unbind(document, 'mousemove', BX.proxy(this.captureMousePosition, this));
6207
6208			var cursorElement = document.elementFromPoint(this.mouseX, this.mouseY);
6209			if (!cursorElement || !this.obProduct.contains(cursorElement))
6210			{
6211				this.hoverOff();
6212			}
6213		},
6214
6215		captureMousePosition: function(event)
6216		{
6217			this.mouseX = event.clientX;
6218			this.mouseY = event.clientY;
6219		},
6220
6221		getCookie: function(name)
6222		{
6223			var matches = document.cookie.match(new RegExp(
6224				"(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
6225			));
6226
6227			return matches ? decodeURIComponent(matches[1]) : null;
6228		},
6229
6230		rememberProductRecommendation: function()
6231		{
6232			// save to RCM_PRODUCT_LOG
6233			var cookieName = BX.cookie_prefix + '_RCM_PRODUCT_LOG',
6234				cookie = this.getCookie(cookieName),
6235				itemFound = false;
6236
6237			var cItems = [],
6238				cItem;
6239
6240			if (cookie)
6241			{
6242				cItems = cookie.split('.');
6243			}
6244
6245			var i = cItems.length;
6246
6247			while (i--)
6248			{
6249				cItem = cItems[i].split('-');
6250
6251				if (cItem[0] == this.product.id)
6252				{
6253					// it's already in recommendations, update the date
6254					cItem = cItems[i].split('-');
6255
6256					// update rcmId and date
6257					cItem[1] = this.product.rcmId;
6258					cItem[2] = BX.current_server_time;
6259
6260					cItems[i] = cItem.join('-');
6261					itemFound = true;
6262				}
6263				else
6264				{
6265					if ((BX.current_server_time - cItem[2]) > 3600 * 24 * 30)
6266					{
6267						cItems.splice(i, 1);
6268					}
6269				}
6270			}
6271
6272			if (!itemFound)
6273			{
6274				// add recommendation
6275				cItems.push([this.product.id, this.product.rcmId, BX.current_server_time].join('-'));
6276			}
6277
6278			// serialize
6279			var plNewCookie = cItems.join('.'),
6280				cookieDate = new Date(new Date().getTime() + 1000 * 3600 * 24 * 365 * 10).toUTCString();
6281
6282			document.cookie = cookieName + "=" + plNewCookie + "; path=/; expires=" + cookieDate + "; domain=" + BX.cookie_domain;
6283		},
6284
6285		startQuantityInterval: function()
6286		{
6287			var target = BX.proxy_context;
6288			var func = target.id === this.visual.QUANTITY_DOWN_ID
6289				? BX.proxy(this.quantityDown, this)
6290				: BX.proxy(this.quantityUp, this);
6291
6292			this.quantityDelay = setTimeout(
6293				BX.delegate(function() {
6294					this.quantityTimer = setInterval(func, 150);
6295				}, this),
6296				300
6297			);
6298		},
6299
6300		clearQuantityInterval: function()
6301		{
6302			clearTimeout(this.quantityDelay);
6303			clearInterval(this.quantityTimer);
6304		},
6305
6306		quantityUp: function()
6307		{
6308			var curValue = 0,
6309				boolSet = true;
6310
6311			if (this.errorCode === 0 && this.showQuantity && this.canBuy)
6312			{
6313				curValue = (this.isDblQuantity ? parseFloat(this.obQuantity.value) : parseInt(this.obQuantity.value, 10));
6314				if (!isNaN(curValue))
6315				{
6316					curValue += this.stepQuantity;
6317					if (this.checkQuantity)
6318					{
6319						if (curValue > this.maxQuantity)
6320						{
6321							boolSet = false;
6322						}
6323					}
6324
6325					if (boolSet)
6326					{
6327						if (this.isDblQuantity)
6328						{
6329							curValue = Math.round(curValue * this.precisionFactor) / this.precisionFactor;
6330						}
6331
6332						this.obQuantity.value = curValue;
6333
6334						this.setPrice();
6335					}
6336				}
6337			}
6338		},
6339
6340		quantityDown: function()
6341		{
6342			var curValue = 0,
6343				boolSet = true;
6344
6345			if (this.errorCode === 0 && this.showQuantity && this.canBuy)
6346			{
6347				curValue = (this.isDblQuantity ? parseFloat(this.obQuantity.value) : parseInt(this.obQuantity.value, 10));
6348				if (!isNaN(curValue))
6349				{
6350					curValue -= this.stepQuantity;
6351
6352					this.checkPriceRange(curValue);
6353
6354					if (curValue < this.minQuantity)
6355					{
6356						boolSet = false;
6357					}
6358
6359					if (boolSet)
6360					{
6361						if (this.isDblQuantity)
6362						{
6363							curValue = Math.round(curValue * this.precisionFactor) / this.precisionFactor;
6364						}
6365
6366						this.obQuantity.value = curValue;
6367
6368						this.setPrice();
6369					}
6370				}
6371			}
6372		},
6373
6374		quantityChange: function()
6375		{
6376			var curValue = 0,
6377				intCount;
6378
6379			if (this.errorCode === 0 && this.showQuantity)
6380			{
6381				if (this.canBuy)
6382				{
6383					curValue = this.isDblQuantity ? parseFloat(this.obQuantity.value) : Math.round(this.obQuantity.value);
6384					if (!isNaN(curValue))
6385					{
6386						if (this.checkQuantity)
6387						{
6388							if (curValue > this.maxQuantity)
6389							{
6390								curValue = this.maxQuantity;
6391							}
6392						}
6393
6394						this.checkPriceRange(curValue);
6395
6396						intCount = Math.floor(
6397							Math.round(curValue * this.precisionFactor / this.stepQuantity) / this.precisionFactor
6398						) || 1;
6399						curValue = (intCount <= 1 ? this.stepQuantity : intCount * this.stepQuantity);
6400						curValue = Math.round(curValue * this.precisionFactor) / this.precisionFactor;
6401
6402						if (curValue < this.minQuantity)
6403						{
6404							curValue = this.minQuantity;
6405						}
6406
6407						this.obQuantity.value = curValue;
6408					}
6409					else
6410					{
6411						this.obQuantity.value = this.minQuantity;
6412					}
6413				}
6414				else
6415				{
6416					this.obQuantity.value = this.minQuantity;
6417				}
6418
6419				this.setPrice();
6420			}
6421		},
6422
6423		quantitySet: function(index)
6424		{
6425			var resetQuantity, strLimit;
6426
6427			var newOffer = this.offers[index],
6428				oldOffer = this.offers[this.offerNum];
6429
6430			if (this.errorCode === 0)
6431			{
6432				this.canBuy = newOffer.CAN_BUY;
6433
6434				this.currentPriceMode = newOffer.ITEM_PRICE_MODE;
6435				this.currentPrices = newOffer.ITEM_PRICES;
6436				this.currentPriceSelected = newOffer.ITEM_PRICE_SELECTED;
6437				this.currentQuantityRanges = newOffer.ITEM_QUANTITY_RANGES;
6438				this.currentQuantityRangeSelected = newOffer.ITEM_QUANTITY_RANGE_SELECTED;
6439
6440				if (this.canBuy)
6441				{
6442					if (this.blockNodes.quantity)
6443					{
6444						BX.style(this.blockNodes.quantity, 'display', '');
6445					}
6446
6447					if (this.obBasketActions)
6448					{
6449						BX.style(this.obBasketActions, 'display', '');
6450					}
6451
6452					if (this.obNotAvail)
6453					{
6454						BX.style(this.obNotAvail, 'display', 'none');
6455					}
6456
6457					if (this.obSubscribe)
6458					{
6459						BX.style(this.obSubscribe, 'display', 'none');
6460					}
6461				}
6462				else
6463				{
6464					if (this.blockNodes.quantity)
6465					{
6466						BX.style(this.blockNodes.quantity, 'display', 'none');
6467					}
6468
6469					if (this.obBasketActions)
6470					{
6471						BX.style(this.obBasketActions, 'display', 'none');
6472					}
6473
6474					if (this.obNotAvail)
6475					{
6476						BX.style(this.obNotAvail, 'display', '');
6477					}
6478
6479					if (this.obSubscribe)
6480					{
6481						if (newOffer.CATALOG_SUBSCRIBE === 'Y')
6482						{
6483							BX.style(this.obSubscribe, 'display', '');
6484							this.obSubscribe.setAttribute('data-item', newOffer.ID);
6485							BX(this.visual.SUBSCRIBE_ID + '_hidden').click();
6486						}
6487						else
6488						{
6489							BX.style(this.obSubscribe, 'display', 'none');
6490						}
6491					}
6492				}
6493
6494				this.isDblQuantity = newOffer.QUANTITY_FLOAT;
6495				this.checkQuantity = newOffer.CHECK_QUANTITY;
6496
6497				if (this.isDblQuantity)
6498				{
6499					this.stepQuantity = Math.round(parseFloat(newOffer.STEP_QUANTITY) * this.precisionFactor) / this.precisionFactor;
6500					this.maxQuantity = parseFloat(newOffer.MAX_QUANTITY);
6501					this.minQuantity = this.currentPriceMode === 'Q' ? parseFloat(this.currentPrices[this.currentPriceSelected].MIN_QUANTITY) : this.stepQuantity;
6502				}
6503				else
6504				{
6505					this.stepQuantity = parseInt(newOffer.STEP_QUANTITY, 10);
6506					this.maxQuantity = parseInt(newOffer.MAX_QUANTITY, 10);
6507					this.minQuantity = this.currentPriceMode === 'Q' ? parseInt(this.currentPrices[this.currentPriceSelected].MIN_QUANTITY) : this.stepQuantity;
6508				}
6509
6510				if (this.showQuantity)
6511				{
6512					var isDifferentMinQuantity = oldOffer.ITEM_PRICES.length
6513						&& oldOffer.ITEM_PRICES[oldOffer.ITEM_PRICE_SELECTED]
6514						&& oldOffer.ITEM_PRICES[oldOffer.ITEM_PRICE_SELECTED].MIN_QUANTITY != this.minQuantity;
6515
6516					if (this.isDblQuantity)
6517					{
6518						resetQuantity = Math.round(parseFloat(oldOffer.STEP_QUANTITY) * this.precisionFactor) / this.precisionFactor !== this.stepQuantity
6519							|| isDifferentMinQuantity
6520							|| oldOffer.MEASURE !== newOffer.MEASURE
6521							|| (
6522								this.checkQuantity
6523								&& parseFloat(oldOffer.MAX_QUANTITY) > this.maxQuantity
6524								&& parseFloat(this.obQuantity.value) > this.maxQuantity
6525							);
6526					}
6527					else
6528					{
6529						resetQuantity = parseInt(oldOffer.STEP_QUANTITY, 10) !== this.stepQuantity
6530							|| isDifferentMinQuantity
6531							|| oldOffer.MEASURE !== newOffer.MEASURE
6532							|| (
6533								this.checkQuantity
6534								&& parseInt(oldOffer.MAX_QUANTITY, 10) > this.maxQuantity
6535								&& parseInt(this.obQuantity.value, 10) > this.maxQuantity
6536							);
6537					}
6538
6539					this.obQuantity.disabled = !this.canBuy;
6540
6541					if (resetQuantity)
6542					{
6543						this.obQuantity.value = this.minQuantity;
6544					}
6545
6546					if (this.obMeasure)
6547					{
6548						if (newOffer.MEASURE)
6549						{
6550							BX.adjust(this.obMeasure, {html: newOffer.MEASURE});
6551						}
6552						else
6553						{
6554							BX.adjust(this.obMeasure, {html: ''});
6555						}
6556					}
6557				}
6558
6559				if (this.obQuantityLimit.all)
6560				{
6561					if (!this.checkQuantity || this.maxQuantity == 0)
6562					{
6563						BX.adjust(this.obQuantityLimit.value, {html: ''});
6564						BX.adjust(this.obQuantityLimit.all, {style: {display: 'none'}});
6565					}
6566					else
6567					{
6568						if (this.showMaxQuantity === 'M')
6569						{
6570							strLimit = (this.maxQuantity / this.stepQuantity >= this.relativeQuantityFactor)
6571								? BX.message('RELATIVE_QUANTITY_MANY')
6572								: BX.message('RELATIVE_QUANTITY_FEW');
6573						}
6574						else
6575						{
6576							strLimit = this.maxQuantity;
6577
6578							if (newOffer.MEASURE)
6579							{
6580								strLimit += (' ' + newOffer.MEASURE);
6581							}
6582						}
6583
6584						BX.adjust(this.obQuantityLimit.value, {html: strLimit});
6585						BX.adjust(this.obQuantityLimit.all, {style: {display: ''}});
6586					}
6587				}
6588			}
6589		},
6590
6591		initializeSlider: function()
6592		{
6593			var wrap = this.obPictSlider.getAttribute('data-slider-wrap');
6594			if (wrap)
6595			{
6596				this.slider.options.wrap = wrap === 'true';
6597			}
6598			else
6599			{
6600				this.slider.options.wrap = this.defaultSliderOptions.wrap;
6601			}
6602
6603			if (this.isTouchDevice)
6604			{
6605				this.slider.options.interval = false;
6606			}
6607			else
6608			{
6609				this.slider.options.interval = parseInt(this.obPictSlider.getAttribute('data-slider-interval')) || this.defaultSliderOptions.interval;
6610				// slider interval must be more than 700ms because of css transitions
6611				if (this.slider.options.interval < 700)
6612				{
6613					this.slider.options.interval = 700;
6614				}
6615
6616				if (this.obPictSliderIndicator)
6617				{
6618					var controls = this.obPictSliderIndicator.querySelectorAll('[data-go-to]');
6619					for (var i in controls)
6620					{
6621						if (controls.hasOwnProperty(i))
6622						{
6623							BX.bind(controls[i], 'click', BX.proxy(this.sliderClickHandler, this));
6624						}
6625					}
6626				}
6627
6628				if (this.obPictSliderProgressBar)
6629				{
6630					if (this.slider.progress)
6631					{
6632						this.resetProgress();
6633						this.cycleSlider();
6634					}
6635					else
6636					{
6637						this.slider.progress = new BX.easing({
6638							transition: BX.easing.transitions.linear,
6639							step: BX.delegate(function(state){
6640								this.obPictSliderProgressBar.style.width = state.width / 10 + '%';
6641							}, this)
6642						});
6643					}
6644				}
6645			}
6646		},
6647
6648		checkTouch: function(event)
6649		{
6650			if (!event || !event.changedTouches)
6651				return false;
6652
6653			return event.changedTouches[0].identifier === this.touch.identifier;
6654		},
6655
6656		touchStartEvent: function(event)
6657		{
6658			if (event.touches.length != 1)
6659				return;
6660
6661			this.touch = event.changedTouches[0];
6662		},
6663
6664		touchEndEvent: function(event)
6665		{
6666			if (!this.checkTouch(event))
6667				return;
6668
6669			var deltaX = this.touch.pageX - event.changedTouches[0].pageX,
6670				deltaY = this.touch.pageY - event.changedTouches[0].pageY;
6671
6672			if (Math.abs(deltaX) >= Math.abs(deltaY) + 10)
6673			{
6674				if (deltaX > 0)
6675				{
6676					this.slideNext();
6677				}
6678
6679				if (deltaX < 0)
6680				{
6681					this.slidePrev();
6682				}
6683			}
6684		},
6685
6686		sliderClickHandler: function(event)
6687		{
6688			var target = BX.getEventTarget(event),
6689				slideIndex = target.getAttribute('data-go-to');
6690
6691			if (slideIndex)
6692			{
6693				this.slideTo(slideIndex)
6694			}
6695
6696			BX.PreventDefault(event);
6697		},
6698
6699		slideNext: function()
6700		{
6701			if (this.slider.sliding)
6702				return;
6703
6704			return this.slide('next');
6705		},
6706
6707		slidePrev: function()
6708		{
6709			if (this.slider.sliding)
6710				return;
6711
6712			return this.slide('prev');
6713		},
6714
6715		slideTo: function(pos)
6716		{
6717			this.slider.active = BX.findChild(this.obPictSlider, {className: 'item active'}, true, false);
6718			this.slider.progress && (this.slider.interval = true);
6719
6720			var activeIndex = this.getItemIndex(this.slider.active);
6721
6722			if (pos > (this.slider.items.length - 1) || pos < 0)
6723				return;
6724
6725			if (this.slider.sliding)
6726				return false;
6727
6728			if (activeIndex == pos)
6729			{
6730				this.stopSlider();
6731				this.cycleSlider();
6732				return;
6733			}
6734
6735			return this.slide(pos > activeIndex ? 'next' : 'prev', this.eq(this.slider.items, pos));
6736		},
6737
6738		slide: function(type, next)
6739		{
6740			var active = BX.findChild(this.obPictSlider, {className: 'item active'}, true, false),
6741				isCycling = this.slider.interval,
6742				direction = type === 'next' ? 'left' : 'right';
6743
6744			next = next || this.getItemForDirection(type, active);
6745
6746			if (BX.hasClass(next, 'active'))
6747			{
6748				return (this.slider.sliding = false);
6749			}
6750
6751			this.slider.sliding = true;
6752
6753			isCycling && this.stopSlider();
6754
6755			if (this.obPictSliderIndicator)
6756			{
6757				BX.removeClass(this.obPictSliderIndicator.querySelector('.active'), 'active');
6758				var nextIndicator = this.obPictSliderIndicator.querySelectorAll('[data-go-to]')[this.getItemIndex(next)];
6759				nextIndicator && BX.addClass(nextIndicator, 'active');
6760			}
6761
6762			if (BX.hasClass(this.obPictSlider, 'slide') && !BX.browser.IsIE())
6763			{
6764				var self = this;
6765				BX.addClass(next, type);
6766				next.offsetWidth; // force reflow
6767				BX.addClass(active, direction);
6768				BX.addClass(next, direction);
6769				setTimeout(function() {
6770					BX.addClass(next, 'active');
6771					BX.removeClass(active, 'active');
6772					BX.removeClass(active, direction);
6773					BX.removeClass(next, type);
6774					BX.removeClass(next, direction);
6775					self.slider.sliding = false;
6776				}, 700);
6777			}
6778			else
6779			{
6780				BX.addClass(next, 'active');
6781				this.slider.sliding = false;
6782			}
6783
6784			this.obPictSliderProgressBar && this.resetProgress();
6785			isCycling && this.cycleSlider();
6786		},
6787
6788		stopSlider: function(event)
6789		{
6790			event || (this.slider.paused = true);
6791
6792			this.slider.interval && clearInterval(this.slider.interval);
6793
6794			if (this.slider.progress)
6795			{
6796				this.slider.progress.stop();
6797
6798				var width = parseInt(this.obPictSliderProgressBar.style.width);
6799
6800				this.slider.progress.options.duration = this.slider.options.interval * width / 200;
6801				this.slider.progress.options.start = {width: width * 10};
6802				this.slider.progress.options.finish = {width: 0};
6803				this.slider.progress.options.complete = null;
6804				this.slider.progress.animate();
6805			}
6806		},
6807
6808		cycleSlider: function(event)
6809		{
6810			event || (this.slider.paused = false);
6811
6812			this.slider.interval && clearInterval(this.slider.interval);
6813
6814			if (this.slider.options.interval && !this.slider.paused)
6815			{
6816				if (this.slider.progress)
6817				{
6818					this.slider.progress.stop();
6819
6820					var width = parseInt(this.obPictSliderProgressBar.style.width);
6821
6822					this.slider.progress.options.duration = this.slider.options.interval * (100 - width) / 100;
6823					this.slider.progress.options.start = {width: width * 10};
6824					this.slider.progress.options.finish = {width: 1000};
6825					this.slider.progress.options.complete = BX.delegate(function(){
6826						this.slider.interval = true;
6827						this.slideNext();
6828					}, this);
6829					this.slider.progress.animate();
6830				}
6831				else
6832				{
6833					this.slider.interval = setInterval(BX.proxy(this.slideNext, this), this.slider.options.interval);
6834				}
6835			}
6836		},
6837
6838		resetProgress: function()
6839		{
6840			this.slider.progress && this.slider.progress.stop();
6841			this.obPictSliderProgressBar.style.width = 0;
6842		},
6843
6844		getItemForDirection: function(direction, active)
6845		{
6846			var activeIndex = this.getItemIndex(active),
6847				willWrap = direction === 'prev' && activeIndex === 0
6848					|| direction === 'next' && activeIndex == (this.slider.items.length - 1);
6849
6850			if (willWrap && !this.slider.options.wrap)
6851				return active;
6852
6853			var delta = direction === 'prev' ? -1 : 1,
6854				itemIndex = (activeIndex + delta) % this.slider.items.length;
6855
6856			return this.eq(this.slider.items, itemIndex);
6857		},
6858
6859		getItemIndex: function(item)
6860		{
6861			this.slider.items = BX.findChildren(item.parentNode, {className: 'item'}, true);
6862
6863			return this.slider.items.indexOf(item || this.slider.active);
6864		},
6865
6866		eq: function(obj, i)
6867		{
6868			var len = obj.length,
6869				j = +i + (i < 0 ? len : 0);
6870
6871			return j >= 0 && j < len ? obj[j] : {};
6872		},
6873
6874		selectOfferProp: function()
6875		{
6876			var i = 0,
6877				value = '',
6878				strTreeValue = '',
6879				arTreeItem = [],
6880				rowItems = null,
6881				target = BX.proxy_context;
6882
6883			if (target && target.hasAttribute('data-treevalue'))
6884			{
6885				if (BX.hasClass(target, 'selected'))
6886					return;
6887
6888				strTreeValue = target.getAttribute('data-treevalue');
6889				arTreeItem = strTreeValue.split('_');
6890				if (this.searchOfferPropIndex(arTreeItem[0], arTreeItem[1]))
6891				{
6892					rowItems = BX.findChildren(target.parentNode, {tagName: 'li'}, false);
6893					if (rowItems && 0 < rowItems.length)
6894					{
6895						for (i = 0; i < rowItems.length; i++)
6896						{
6897							value = rowItems[i].getAttribute('data-onevalue');
6898							if (value === arTreeItem[1])
6899							{
6900								BX.addClass(rowItems[i], 'selected');
6901							}
6902							else
6903							{
6904								BX.removeClass(rowItems[i], 'selected');
6905							}
6906						}
6907					}
6908				}
6909			}
6910		},
6911
6912		searchOfferPropIndex: function(strPropID, strPropValue)
6913		{
6914			var strName = '',
6915				arShowValues = false,
6916				i, j,
6917				arCanBuyValues = [],
6918				allValues = [],
6919				index = -1,
6920				arFilter = {},
6921				tmpFilter = [];
6922
6923			for (i = 0; i < this.treeProps.length; i++)
6924			{
6925				if (this.treeProps[i].ID === strPropID)
6926				{
6927					index = i;
6928					break;
6929				}
6930			}
6931
6932			if (-1 < index)
6933			{
6934				for (i = 0; i < index; i++)
6935				{
6936					strName = 'PROP_'+this.treeProps[i].ID;
6937					arFilter[strName] = this.selectedValues[strName];
6938				}
6939				strName = 'PROP_'+this.treeProps[index].ID;
6940				arShowValues = this.getRowValues(arFilter, strName);
6941				if (!arShowValues)
6942				{
6943					return false;
6944				}
6945				if (!BX.util.in_array(strPropValue, arShowValues))
6946				{
6947					return false;
6948				}
6949				arFilter[strName] = strPropValue;
6950				for (i = index+1; i < this.treeProps.length; i++)
6951				{
6952					strName = 'PROP_'+this.treeProps[i].ID;
6953					arShowValues = this.getRowValues(arFilter, strName);
6954					if (!arShowValues)
6955					{
6956						return false;
6957					}
6958					allValues = [];
6959					if (this.showAbsent)
6960					{
6961						arCanBuyValues = [];
6962						tmpFilter = [];
6963						tmpFilter = BX.clone(arFilter, true);
6964						for (j = 0; j < arShowValues.length; j++)
6965						{
6966							tmpFilter[strName] = arShowValues[j];
6967							allValues[allValues.length] = arShowValues[j];
6968							if (this.getCanBuy(tmpFilter))
6969								arCanBuyValues[arCanBuyValues.length] = arShowValues[j];
6970						}
6971					}
6972					else
6973					{
6974						arCanBuyValues = arShowValues;
6975					}
6976					if (this.selectedValues[strName] && BX.util.in_array(this.selectedValues[strName], arCanBuyValues))
6977					{
6978						arFilter[strName] = this.selectedValues[strName];
6979					}
6980					else
6981					{
6982						if (this.showAbsent)
6983							arFilter[strName] = (arCanBuyValues.length > 0 ? arCanBuyValues[0] : allValues[0]);
6984						else
6985							arFilter[strName] = arCanBuyValues[0];
6986					}
6987					this.updateRow(i, arFilter[strName], arShowValues, arCanBuyValues);
6988				}
6989				this.selectedValues = arFilter;
6990				this.changeInfo();
6991			}
6992			return true;
6993		},
6994
6995		updateRow: function(intNumber, activeID, showID, canBuyID)
6996		{
6997			var i = 0,
6998				value = '',
6999				isCurrent = false,
7000				rowItems = null;
7001
7002			var lineContainer = this.obTree.querySelectorAll('[data-entity="sku-line-block"]'),
7003				listContainer;
7004
7005			if (intNumber > -1 && intNumber < lineContainer.length)
7006			{
7007				listContainer = lineContainer[intNumber].querySelector('ul');
7008				rowItems = BX.findChildren(listContainer, {tagName: 'li'}, false);
7009				if (rowItems && 0 < rowItems.length)
7010				{
7011					for (i = 0; i < rowItems.length; i++)
7012					{
7013						value = rowItems[i].getAttribute('data-onevalue');
7014						isCurrent = value === activeID;
7015
7016						if (isCurrent)
7017						{
7018							BX.addClass(rowItems[i], 'selected');
7019						}
7020						else
7021						{
7022							BX.removeClass(rowItems[i], 'selected');
7023						}
7024
7025						if (BX.util.in_array(value, canBuyID))
7026						{
7027							BX.removeClass(rowItems[i], 'notallowed');
7028						}
7029						else
7030						{
7031							BX.addClass(rowItems[i], 'notallowed');
7032						}
7033
7034						rowItems[i].style.display = BX.util.in_array(value, showID) ? '' : 'none';
7035
7036						if (isCurrent)
7037						{
7038							lineContainer[intNumber].style.display = (value == 0 && canBuyID.length == 1) ? 'none' : '';
7039						}
7040					}
7041				}
7042			}
7043		},
7044
7045		getRowValues: function(arFilter, index)
7046		{
7047			var i = 0,
7048				j,
7049				arValues = [],
7050				boolSearch = false,
7051				boolOneSearch = true;
7052
7053			if (0 === arFilter.length)
7054			{
7055				for (i = 0; i < this.offers.length; i++)
7056				{
7057					if (!BX.util.in_array(this.offers[i].TREE[index], arValues))
7058					{
7059						arValues[arValues.length] = this.offers[i].TREE[index];
7060					}
7061				}
7062				boolSearch = true;
7063			}
7064			else
7065			{
7066				for (i = 0; i < this.offers.length; i++)
7067				{
7068					boolOneSearch = true;
7069					for (j in arFilter)
7070					{
7071						if (arFilter[j] !== this.offers[i].TREE[j])
7072						{
7073							boolOneSearch = false;
7074							break;
7075						}
7076					}
7077					if (boolOneSearch)
7078					{
7079						if (!BX.util.in_array(this.offers[i].TREE[index], arValues))
7080						{
7081							arValues[arValues.length] = this.offers[i].TREE[index];
7082						}
7083						boolSearch = true;
7084					}
7085				}
7086			}
7087			return (boolSearch ? arValues : false);
7088		},
7089
7090		getCanBuy: function(arFilter)
7091		{
7092			var i, j,
7093				boolSearch = false,
7094				boolOneSearch = true;
7095
7096			for (i = 0; i < this.offers.length; i++)
7097			{
7098				boolOneSearch = true;
7099				for (j in arFilter)
7100				{
7101					if (arFilter[j] !== this.offers[i].TREE[j])
7102					{
7103						boolOneSearch = false;
7104						break;
7105					}
7106				}
7107				if (boolOneSearch)
7108				{
7109					if (this.offers[i].CAN_BUY)
7110					{
7111						boolSearch = true;
7112						break;
7113					}
7114				}
7115			}
7116
7117			return boolSearch;
7118		},
7119
7120		setCurrent: function()
7121		{
7122			var i,
7123				j = 0,
7124				arCanBuyValues = [],
7125				strName = '',
7126				arShowValues = false,
7127				arFilter = {},
7128				tmpFilter = [],
7129				current = this.offers[this.offerNum].TREE;
7130
7131			for (i = 0; i < this.treeProps.length; i++)
7132			{
7133				strName = 'PROP_'+this.treeProps[i].ID;
7134				arShowValues = this.getRowValues(arFilter, strName);
7135				if (!arShowValues)
7136				{
7137					break;
7138				}
7139				if (BX.util.in_array(current[strName], arShowValues))
7140				{
7141					arFilter[strName] = current[strName];
7142				}
7143				else
7144				{
7145					arFilter[strName] = arShowValues[0];
7146					this.offerNum = 0;
7147				}
7148				if (this.showAbsent)
7149				{
7150					arCanBuyValues = [];
7151					tmpFilter = [];
7152					tmpFilter = BX.clone(arFilter, true);
7153					for (j = 0; j < arShowValues.length; j++)
7154					{
7155						tmpFilter[strName] = arShowValues[j];
7156						if (this.getCanBuy(tmpFilter))
7157						{
7158							arCanBuyValues[arCanBuyValues.length] = arShowValues[j];
7159						}
7160					}
7161				}
7162				else
7163				{
7164					arCanBuyValues = arShowValues;
7165				}
7166				this.updateRow(i, arFilter[strName], arShowValues, arCanBuyValues);
7167			}
7168			this.selectedValues = arFilter;
7169			this.changeInfo();
7170		},
7171
7172		changeInfo: function()
7173		{
7174			var i, j,
7175				index = -1,
7176				boolOneSearch = true,
7177				quantityChanged;
7178
7179			for (i = 0; i < this.offers.length; i++)
7180			{
7181				boolOneSearch = true;
7182				for (j in this.selectedValues)
7183				{
7184					if (this.selectedValues[j] !== this.offers[i].TREE[j])
7185					{
7186						boolOneSearch = false;
7187						break;
7188					}
7189				}
7190				if (boolOneSearch)
7191				{
7192					index = i;
7193					break;
7194				}
7195			}
7196			if (index > -1)
7197			{
7198				if (parseInt(this.offers[index].MORE_PHOTO_COUNT) > 1 && this.obPictSlider)
7199				{
7200					// hide pict and second_pict containers
7201					if (this.obPict)
7202					{
7203						this.obPict.style.display = 'none';
7204					}
7205
7206					if (this.obSecondPict)
7207					{
7208						this.obSecondPict.style.display = 'none';
7209					}
7210
7211					// clear slider container
7212					BX.cleanNode(this.obPictSlider);
7213
7214					// fill slider container with slides
7215					for (i in this.offers[index].MORE_PHOTO)
7216					{
7217						if (this.offers[index].MORE_PHOTO.hasOwnProperty(i))
7218						{
7219							this.obPictSlider.appendChild(
7220								BX.create('SPAN', {
7221									props: {className: 'product-item-image-slide item' + (i == 0 ? ' active' : '')},
7222									style: {backgroundImage: 'url(\'' + this.offers[index].MORE_PHOTO[i].SRC + '\')'}
7223								})
7224							);
7225						}
7226					}
7227
7228					// fill slider indicator if exists
7229					if (this.obPictSliderIndicator)
7230					{
7231						BX.cleanNode(this.obPictSliderIndicator);
7232
7233						for (i in this.offers[index].MORE_PHOTO)
7234						{
7235							if (this.offers[index].MORE_PHOTO.hasOwnProperty(i))
7236							{
7237								this.obPictSliderIndicator.appendChild(
7238									BX.create('DIV', {
7239										attrs: {'data-go-to': i},
7240										props: {className: 'product-item-image-slider-control' + (i == 0 ? ' active' : '')}
7241									})
7242								);
7243								this.obPictSliderIndicator.appendChild(document.createTextNode(' '));
7244							}
7245						}
7246
7247						this.obPictSliderIndicator.style.display = '';
7248					}
7249
7250					if (this.obPictSliderProgressBar)
7251					{
7252						this.obPictSliderProgressBar.style.display = '';
7253					}
7254
7255					// show slider container
7256					this.obPictSlider.style.display = '';
7257					this.initializeSlider();
7258				}
7259				else
7260				{
7261					// hide slider container
7262					if (this.obPictSlider)
7263					{
7264						this.obPictSlider.style.display = 'none';
7265					}
7266
7267					if (this.obPictSliderIndicator)
7268					{
7269						this.obPictSliderIndicator.style.display = 'none';
7270					}
7271
7272					if (this.obPictSliderProgressBar)
7273					{
7274						this.obPictSliderProgressBar.style.display = 'none';
7275					}
7276
7277					// show pict and pict_second containers
7278					if (this.obPict)
7279					{
7280						if (this.offers[index].PREVIEW_PICTURE)
7281						{
7282							BX.adjust(this.obPict, {style: {backgroundImage: 'url(\'' + this.offers[index].PREVIEW_PICTURE.SRC + '\')'}});
7283						}
7284						else
7285						{
7286							BX.adjust(this.obPict, {style: {backgroundImage: 'url(\'' + this.defaultPict.pict.SRC + '\')'}});
7287						}
7288
7289						this.obPict.style.display = '';
7290					}
7291
7292					if (this.secondPict && this.obSecondPict)
7293					{
7294						if (this.offers[index].PREVIEW_PICTURE_SECOND)
7295						{
7296							BX.adjust(this.obSecondPict, {style: {backgroundImage: 'url(\'' + this.offers[index].PREVIEW_PICTURE_SECOND.SRC + '\')'}});
7297						}
7298						else if (this.offers[index].PREVIEW_PICTURE.SRC)
7299						{
7300							BX.adjust(this.obSecondPict, {style: {backgroundImage: 'url(\'' + this.offers[index].PREVIEW_PICTURE.SRC + '\')'}});
7301						}
7302						else if (this.defaultPict.secondPict)
7303						{
7304							BX.adjust(this.obSecondPict, {style: {backgroundImage: 'url(\'' + this.defaultPict.secondPict.SRC + '\')'}});
7305						}
7306						else
7307						{
7308							BX.adjust(this.obSecondPict, {style: {backgroundImage: 'url(\'' + this.defaultPict.pict.SRC + '\')'}});
7309						}
7310
7311						this.obSecondPict.style.display = '';
7312					}
7313				}
7314
7315				if (this.showSkuProps && this.obSkuProps)
7316				{
7317					if (this.offers[index].DISPLAY_PROPERTIES.length)
7318					{
7319						BX.adjust(this.obSkuProps, {style: {display: ''}, html: this.offers[index].DISPLAY_PROPERTIES});
7320					}
7321					else
7322					{
7323						BX.adjust(this.obSkuProps, {style: {display: 'none'}, html: ''});
7324					}
7325				}
7326
7327				this.quantitySet(index);
7328				this.setPrice();
7329				this.setCompared(this.offers[index].COMPARED);
7330
7331				this.offerNum = index;
7332			}
7333		},
7334
7335		checkPriceRange: function(quantity)
7336		{
7337			if (typeof quantity === 'undefined'|| this.currentPriceMode != 'Q')
7338				return;
7339
7340			var range, found = false;
7341
7342			for (var i in this.currentQuantityRanges)
7343			{
7344				if (this.currentQuantityRanges.hasOwnProperty(i))
7345				{
7346					range = this.currentQuantityRanges[i];
7347
7348					if (
7349						parseInt(quantity) >= parseInt(range.SORT_FROM)
7350						&& (
7351							range.SORT_TO == 'INF'
7352							|| parseInt(quantity) <= parseInt(range.SORT_TO)
7353						)
7354					)
7355					{
7356						found = true;
7357						this.currentQuantityRangeSelected = range.HASH;
7358						break;
7359					}
7360				}
7361			}
7362
7363			if (!found && (range = this.getMinPriceRange()))
7364			{
7365				this.currentQuantityRangeSelected = range.HASH;
7366			}
7367
7368			for (var k in this.currentPrices)
7369			{
7370				if (this.currentPrices.hasOwnProperty(k))
7371				{
7372					if (this.currentPrices[k].QUANTITY_HASH == this.currentQuantityRangeSelected)
7373					{
7374						this.currentPriceSelected = k;
7375						break;
7376					}
7377				}
7378			}
7379		},
7380
7381		getMinPriceRange: function()
7382		{
7383			var range;
7384
7385			for (var i in this.currentQuantityRanges)
7386			{
7387				if (this.currentQuantityRanges.hasOwnProperty(i))
7388				{
7389					if (
7390						!range
7391						|| parseInt(this.currentQuantityRanges[i].SORT_FROM) < parseInt(range.SORT_FROM)
7392					)
7393					{
7394						range = this.currentQuantityRanges[i];
7395					}
7396				}
7397			}
7398
7399			return range;
7400		},
7401
7402		checkQuantityControls: function()
7403		{
7404			if (!this.obQuantity)
7405				return;
7406
7407			var reachedTopLimit = this.checkQuantity && parseFloat(this.obQuantity.value) + this.stepQuantity > this.maxQuantity,
7408				reachedBottomLimit = parseFloat(this.obQuantity.value) - this.stepQuantity < this.minQuantity;
7409
7410			if (reachedTopLimit)
7411			{
7412				BX.addClass(this.obQuantityUp, 'product-item-amount-field-btn-disabled');
7413			}
7414			else if (BX.hasClass(this.obQuantityUp, 'product-item-amount-field-btn-disabled'))
7415			{
7416				BX.removeClass(this.obQuantityUp, 'product-item-amount-field-btn-disabled');
7417			}
7418
7419			if (reachedBottomLimit)
7420			{
7421				BX.addClass(this.obQuantityDown, 'product-item-amount-field-btn-disabled');
7422			}
7423			else if (BX.hasClass(this.obQuantityDown, 'product-item-amount-field-btn-disabled'))
7424			{
7425				BX.removeClass(this.obQuantityDown, 'product-item-amount-field-btn-disabled');
7426			}
7427
7428			if (reachedTopLimit && reachedBottomLimit)
7429			{
7430				this.obQuantity.setAttribute('disabled', 'disabled');
7431			}
7432			else
7433			{
7434				this.obQuantity.removeAttribute('disabled');
7435			}
7436		},
7437
7438		setPrice: function()
7439		{
7440			var obData, price;
7441
7442			if (this.obQuantity)
7443			{
7444				this.checkPriceRange(this.obQuantity.value);
7445			}
7446
7447			this.checkQuantityControls();
7448
7449			price = this.currentPrices[this.currentPriceSelected];
7450
7451			if (this.obPrice)
7452			{
7453				if (price)
7454				{
7455					BX.adjust(this.obPrice, {html: BX.Currency.currencyFormat(price.RATIO_PRICE, price.CURRENCY, true)});
7456				}
7457				else
7458				{
7459					BX.adjust(this.obPrice, {html: ''});
7460				}
7461
7462				if (this.showOldPrice && this.obPriceOld)
7463				{
7464					if (price && price.RATIO_PRICE !== price.RATIO_BASE_PRICE)
7465					{
7466						BX.adjust(this.obPriceOld, {
7467							style: {display: ''},
7468							html: BX.Currency.currencyFormat(price.RATIO_BASE_PRICE, price.CURRENCY, true)
7469						});
7470					}
7471					else
7472					{
7473						BX.adjust(this.obPriceOld, {
7474							style: {display: 'none'},
7475							html: ''
7476						});
7477					}
7478				}
7479
7480				if (this.obPriceTotal)
7481				{
7482					if (price && this.obQuantity && this.obQuantity.value != this.stepQuantity)
7483					{
7484						BX.adjust(this.obPriceTotal, {
7485							html: BX.message('PRICE_TOTAL_PREFIX') + ' <strong>'
7486							+ BX.Currency.currencyFormat(price.PRICE * this.obQuantity.value, price.CURRENCY, true)
7487							+ '</strong>',
7488							style: {display: ''}
7489						});
7490					}
7491					else
7492					{
7493						BX.adjust(this.obPriceTotal, {
7494							html: '',
7495							style: {display: 'none'}
7496						});
7497					}
7498				}
7499
7500				if (this.showPercent)
7501				{
7502					if (price && parseInt(price.DISCOUNT) > 0)
7503					{
7504						obData = {style: {display: ''}, html: -price.PERCENT + '%'};
7505					}
7506					else
7507					{
7508						obData = {style: {display: 'none'}, html: ''};
7509					}
7510
7511					if (this.obDscPerc)
7512					{
7513						BX.adjust(this.obDscPerc, obData);
7514					}
7515
7516					if (this.obSecondDscPerc)
7517					{
7518						BX.adjust(this.obSecondDscPerc, obData);
7519					}
7520				}
7521			}
7522		},
7523
7524		compare: function(event)
7525		{
7526			var checkbox = this.obCompare.querySelector('[data-entity="compare-checkbox"]'),
7527				target = BX.getEventTarget(event),
7528				checked = true;
7529
7530			if (checkbox)
7531			{
7532				checked = target === checkbox ? checkbox.checked : !checkbox.checked;
7533			}
7534
7535			var url = checked ? this.compareData.compareUrl : this.compareData.compareDeleteUrl,
7536				compareLink;
7537
7538			if (url)
7539			{
7540				if (target !== checkbox)
7541				{
7542					BX.PreventDefault(event);
7543					this.setCompared(checked);
7544				}
7545
7546				switch (this.productType)
7547				{
7548					case 0: // no catalog
7549					case 1: // product
7550					case 2: // set
7551						compareLink = url.replace('#ID#', this.product.id.toString());
7552						break;
7553					case 3: // sku
7554						compareLink = url.replace('#ID#', this.offers[this.offerNum].ID);
7555						break;
7556				}
7557
7558				BX.ajax({
7559					method: 'POST',
7560					dataType: checked ? 'json' : 'html',
7561					url: compareLink + (compareLink.indexOf('?') !== -1 ? '&' : '?') + 'ajax_action=Y',
7562					onsuccess: checked
7563						? BX.proxy(this.compareResult, this)
7564						: BX.proxy(this.compareDeleteResult, this)
7565				});
7566			}
7567		},
7568
7569		compareResult: function(result)
7570		{
7571			var popupContent, popupButtons;
7572
7573			if (this.obPopupWin)
7574			{
7575				this.obPopupWin.close();
7576			}
7577
7578			if (!BX.type.isPlainObject(result))
7579				return;
7580
7581			this.initPopupWindow();
7582
7583			if (this.offers.length > 0)
7584			{
7585				this.offers[this.offerNum].COMPARED = result.STATUS === 'OK';
7586			}
7587
7588			if (result.STATUS === 'OK')
7589			{
7590				BX.onCustomEvent('OnCompareChange');
7591
7592				popupContent = '<div style="width: 100%; margin: 0; text-align: center;"><p>'
7593					+ BX.message('COMPARE_MESSAGE_OK')
7594					+ '</p></div>';
7595
7596				if (this.showClosePopup)
7597				{
7598					popupButtons = [
7599						new BasketButton({
7600							text: BX.message('BTN_MESSAGE_COMPARE_REDIRECT'),
7601							events: {
7602								click: BX.delegate(this.compareRedirect, this)
7603							},
7604							style: {marginRight: '10px'}
7605						}),
7606						new BasketButton({
7607							text: BX.message('BTN_MESSAGE_CLOSE_POPUP'),
7608							events: {
7609								click: BX.delegate(this.obPopupWin.close, this.obPopupWin)
7610							}
7611						})
7612					];
7613				}
7614				else
7615				{
7616					popupButtons = [
7617						new BasketButton({
7618							text: BX.message('BTN_MESSAGE_COMPARE_REDIRECT'),
7619							events: {
7620								click: BX.delegate(this.compareRedirect, this)
7621							}
7622						})
7623					];
7624				}
7625			}
7626			else
7627			{
7628				popupContent = '<div style="width: 100%; margin: 0; text-align: center;"><p>'
7629					+ (result.MESSAGE ? result.MESSAGE : BX.message('COMPARE_UNKNOWN_ERROR'))
7630					+ '</p></div>';
7631				popupButtons = [
7632					new BasketButton({
7633						text: BX.message('BTN_MESSAGE_CLOSE'),
7634						events: {
7635							click: BX.delegate(this.obPopupWin.close, this.obPopupWin)
7636						}
7637					})
7638				];
7639			}
7640
7641			this.obPopupWin.setTitleBar(BX.message('COMPARE_TITLE'));
7642			this.obPopupWin.setContent(popupContent);
7643			this.obPopupWin.setButtons(popupButtons);
7644			this.obPopupWin.show();
7645		},
7646
7647		compareDeleteResult: function()
7648		{
7649			BX.onCustomEvent('OnCompareChange');
7650
7651			if (this.offers && this.offers.length)
7652			{
7653				this.offers[this.offerNum].COMPARED = false;
7654			}
7655		},
7656
7657		setCompared: function(state)
7658		{
7659			if (!this.obCompare)
7660				return;
7661
7662			var checkbox = this.obCompare.querySelector('[data-entity="compare-checkbox"]');
7663			if (checkbox)
7664			{
7665				checkbox.checked = state;
7666			}
7667		},
7668
7669		setCompareInfo: function(comparedIds)
7670		{
7671			if (!BX.type.isArray(comparedIds))
7672				return;
7673
7674			for (var i in this.offers)
7675			{
7676				if (this.offers.hasOwnProperty(i))
7677				{
7678					this.offers[i].COMPARED = BX.util.in_array(this.offers[i].ID, comparedIds);
7679				}
7680			}
7681		},
7682
7683		compareRedirect: function()
7684		{
7685			if (this.compareData.comparePath)
7686			{
7687				location.href = this.compareData.comparePath;
7688			}
7689			else
7690			{
7691				this.obPopupWin.close();
7692			}
7693		},
7694
7695		checkDeletedCompare: function(id)
7696		{
7697			switch (this.productType)
7698			{
7699				case 0: // no catalog
7700				case 1: // product
7701				case 2: // set
7702					if (this.product.id == id)
7703					{
7704						this.setCompared(false);
7705					}
7706
7707					break;
7708				case 3: // sku
7709					var i = this.offers.length;
7710					while (i--)
7711					{
7712						if (this.offers[i].ID == id)
7713						{
7714							this.offers[i].COMPARED = false;
7715
7716							if (this.offerNum == i)
7717							{
7718								this.setCompared(false);
7719							}
7720
7721							break;
7722						}
7723					}
7724			}
7725		},
7726
7727		initBasketUrl: function()
7728		{
7729			this.basketUrl = (this.basketMode === 'ADD' ? this.basketData.add_url : this.basketData.buy_url);
7730			switch (this.productType)
7731			{
7732				case 1: // product
7733				case 2: // set
7734					this.basketUrl = this.basketUrl.replace('#ID#', this.product.id.toString());
7735					break;
7736				case 3: // sku
7737					this.basketUrl = this.basketUrl.replace('#ID#', this.offers[this.offerNum].ID);
7738					break;
7739			}
7740			this.basketParams = {
7741				'ajax_basket': 'Y'
7742			};
7743			if (this.showQuantity)
7744			{
7745				this.basketParams[this.basketData.quantity] = this.obQuantity.value;
7746			}
7747			if (this.basketData.sku_props)
7748			{
7749				this.basketParams[this.basketData.sku_props_var] = this.basketData.sku_props;
7750			}
7751		},
7752
7753		fillBasketProps: function()
7754		{
7755			if (!this.visual.BASKET_PROP_DIV)
7756			{
7757				return;
7758			}
7759			var
7760				i = 0,
7761				propCollection = null,
7762				foundValues = false,
7763				obBasketProps = null;
7764
7765			if (this.basketData.useProps && !this.basketData.emptyProps)
7766			{
7767				if (this.obPopupWin && this.obPopupWin.contentContainer)
7768				{
7769					obBasketProps = this.obPopupWin.contentContainer;
7770				}
7771			}
7772			else
7773			{
7774				obBasketProps = BX(this.visual.BASKET_PROP_DIV);
7775			}
7776			if (obBasketProps)
7777			{
7778				propCollection = obBasketProps.getElementsByTagName('select');
7779				if (propCollection && propCollection.length)
7780				{
7781					for (i = 0; i < propCollection.length; i++)
7782					{
7783						if (!propCollection[i].disabled)
7784						{
7785							switch (propCollection[i].type.toLowerCase())
7786							{
7787								case 'select-one':
7788									this.basketParams[propCollection[i].name] = propCollection[i].value;
7789									foundValues = true;
7790									break;
7791								default:
7792									break;
7793							}
7794						}
7795					}
7796				}
7797				propCollection = obBasketProps.getElementsByTagName('input');
7798				if (propCollection && propCollection.length)
7799				{
7800					for (i = 0; i < propCollection.length; i++)
7801					{
7802						if (!propCollection[i].disabled)
7803						{
7804							switch (propCollection[i].type.toLowerCase())
7805							{
7806								case 'hidden':
7807									this.basketParams[propCollection[i].name] = propCollection[i].value;
7808									foundValues = true;
7809									break;
7810								case 'radio':
7811									if (propCollection[i].checked)
7812									{
7813										this.basketParams[propCollection[i].name] = propCollection[i].value;
7814										foundValues = true;
7815									}
7816									break;
7817								default:
7818									break;
7819							}
7820						}
7821					}
7822				}
7823			}
7824			if (!foundValues)
7825			{
7826				this.basketParams[this.basketData.props] = [];
7827				this.basketParams[this.basketData.props][0] = 0;
7828			}
7829		},
7830
7831		add2Basket: function()
7832		{
7833			this.basketMode = 'ADD';
7834			this.basket();
7835		},
7836
7837		buyBasket: function()
7838		{
7839			this.basketMode = 'BUY';
7840			this.basket();
7841		},
7842
7843		sendToBasket: function()
7844		{
7845			if (!this.canBuy)
7846			{
7847				return;
7848			}
7849
7850			// check recommendation
7851			if (this.product && this.product.id && this.bigData)
7852			{
7853				this.rememberProductRecommendation();
7854			}
7855
7856			this.initBasketUrl();
7857			this.fillBasketProps();
7858			BX.ajax({
7859				method: 'POST',
7860				dataType: 'json',
7861				url: this.basketUrl,
7862				data: this.basketParams,
7863				onsuccess: BX.proxy(this.basketResult, this)
7864			});
7865		},
7866
7867		basket: function()
7868		{
7869			var contentBasketProps = '';
7870			if (!this.canBuy)
7871			{
7872				return;
7873			}
7874			switch (this.productType)
7875			{
7876				case 1: // product
7877				case 2: // set
7878					if (this.basketData.useProps && !this.basketData.emptyProps)
7879					{
7880						this.initPopupWindow();
7881						this.obPopupWin.setTitleBar(BX.message('TITLE_BASKET_PROPS'));
7882						if (BX(this.visual.BASKET_PROP_DIV))
7883						{
7884							contentBasketProps = BX(this.visual.BASKET_PROP_DIV).innerHTML;
7885						}
7886						this.obPopupWin.setContent(contentBasketProps);
7887						this.obPopupWin.setButtons([
7888							new BasketButton({
7889								text: BX.message('BTN_MESSAGE_SEND_PROPS'),
7890								events: {
7891									click: BX.delegate(this.sendToBasket, this)
7892								}
7893							})
7894						]);
7895						this.obPopupWin.show();
7896					}
7897					else
7898					{
7899						this.sendToBasket();
7900					}
7901					break;
7902				case 3: // sku
7903					this.sendToBasket();
7904					break;
7905			}
7906		},
7907
7908		basketResult: function(arResult)
7909		{
7910			var strContent = '',
7911				strPict = '',
7912				successful,
7913				buttons = [];
7914
7915			if (this.obPopupWin)
7916				this.obPopupWin.close();
7917
7918			if (!BX.type.isPlainObject(arResult))
7919				return;
7920
7921			successful = arResult.STATUS === 'OK';
7922
7923			if (successful)
7924			{
7925				this.setAnalyticsDataLayer('addToCart');
7926			}
7927
7928			if (successful && this.basketAction === 'BUY')
7929			{
7930				this.basketRedirect();
7931			}
7932			else
7933			{
7934				this.initPopupWindow();
7935
7936				if (successful)
7937				{
7938					BX.onCustomEvent('OnBasketChange');
7939
7940					if  (BX.findParent(this.obProduct, {className: 'bx_sale_gift_main_products'}, 10))
7941					{
7942						BX.onCustomEvent('onAddToBasketMainProduct', [this]);
7943					}
7944
7945					switch (this.productType)
7946					{
7947						case 1: // product
7948						case 2: // set
7949							strPict = this.product.pict.SRC;
7950							break;
7951						case 3: // sku
7952							strPict = (this.offers[this.offerNum].PREVIEW_PICTURE ?
7953									this.offers[this.offerNum].PREVIEW_PICTURE.SRC :
7954									this.defaultPict.pict.SRC
7955							);
7956							break;
7957					}
7958
7959					strContent = '<div style="width: 100%; margin: 0; text-align: center;"><img src="'
7960						+ strPict + '" height="130" style="max-height:130px"><p>' + this.product.name + '</p></div>' + getGuestBasketNotice();
7961
7962					if (this.showClosePopup)
7963					{
7964						buttons = [
7965							new BasketButton({
7966								text: BX.message("BTN_MESSAGE_BASKET_REDIRECT"),
7967								events: {
7968									click: BX.delegate(this.basketRedirect, this)
7969								},
7970								style: {marginRight: '10px'}
7971							}),
7972							new BasketButton({
7973								text: BX.message("BTN_MESSAGE_CLOSE_POPUP"),
7974								events: {
7975									click: BX.delegate(this.obPopupWin.close, this.obPopupWin)
7976								}
7977							})
7978						];
7979					}
7980					else
7981					{
7982						buttons = [
7983							new BasketButton({
7984								text: BX.message("BTN_MESSAGE_BASKET_REDIRECT"),
7985								events: {
7986									click: BX.delegate(this.basketRedirect, this)
7987								}
7988							})
7989						];
7990					}
7991				}
7992				else
7993				{
7994					strContent = '<div style="width: 100%; margin: 0; text-align: center;"><p>'
7995						+ (arResult.MESSAGE ? arResult.MESSAGE : BX.message('BASKET_UNKNOWN_ERROR'))
7996						+ '</p></div>';
7997					buttons = [
7998						new BasketButton({
7999							text: BX.message('BTN_MESSAGE_CLOSE'),
8000							events: {
8001								click: BX.delegate(this.obPopupWin.close, this.obPopupWin)
8002							}
8003						})
8004					];
8005				}
8006				this.obPopupWin.setTitleBar(successful ? BX.message('TITLE_SUCCESSFUL') : BX.message('TITLE_ERROR'));
8007				this.obPopupWin.setContent(strContent);
8008				this.obPopupWin.setButtons(buttons);
8009				this.obPopupWin.show();
8010			}
8011		},
8012
8013		basketRedirect: function()
8014		{
8015			location.href = (this.basketData.basketUrl ? this.basketData.basketUrl : BX.message('BASKET_URL'));
8016		},
8017
8018		initPopupWindow: function()
8019		{
8020			if (this.obPopupWin)
8021				return;
8022
8023			this.obPopupWin = BX.PopupWindowManager.create('CatalogSectionBasket_' + this.visual.ID, null, {
8024				autoHide: true,
8025				offsetLeft: 0,
8026				offsetTop: 0,
8027				overlay : true,
8028				closeByEsc: true,
8029				titleBar: true,
8030				closeIcon: true,
8031				contentColor: 'white',
8032				className: this.templateTheme ? 'bx-' + this.templateTheme + ' popup_add_basket' : 'popup_add_basket'
8033			});
8034		}
8035	};
8036})(window);
8037/* End */
8038;
8039; /* Start:"a:4:{s:4:"full";s:96:"/bitrix/components/bitrix/catalog.product.subscribe/templates/.default/script.js?175439038817434";s:6:"source";s:80:"/bitrix/components/bitrix/catalog.product.subscribe/templates/.default/script.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
8040(function (window) {
8041
8042	if (!!window.JCCatalogProductSubscribe)
8043	{
8044		return;
8045	}
8046
8047	var subscribeButton = function(params)
8048	{
8049		subscribeButton.superclass.constructor.apply(this, arguments);
8050		this.nameNode = BX.create('span', {
8051			props : { id : this.id },
8052			style: typeof(params.style) === 'object' ? params.style : {},
8053			text: params.text
8054		});
8055		this.buttonNode = BX.create('span', {
8056			attrs: { className: params.className },
8057			style: { marginBottom: '0', borderBottom: '0 none transparent' },
8058			children: [this.nameNode],
8059			events : this.contextEvents
8060		});
8061		if (BX.browser.IsIE())
8062		{
8063			this.buttonNode.setAttribute("hideFocus", "hidefocus");
8064		}
8065	};
8066	BX.extend(subscribeButton, BX.PopupWindowButton);
8067
8068	window.JCCatalogProductSubscribe = function(params)
8069	{
8070		this.buttonId = params.buttonId;
8071		this.buttonClass = params.buttonClass;
8072		this.jsObject = params.jsObject;
8073		this.ajaxUrl = '/bitrix/components/bitrix/catalog.product.subscribe/ajax.php';
8074		this.alreadySubscribed = params.alreadySubscribed;
8075		this.listIdAlreadySubscribed = params.listIdAlreadySubscribed;
8076		this.urlListSubscriptions = params.urlListSubscriptions;
8077		this.listOldItemId = {};
8078		this.landingId = params.landingId;
8079
8080		this.elemButtonSubscribe = null;
8081		this.elemPopupWin = null;
8082		this.defaultButtonClass = 'bx-catalog-subscribe-button';
8083
8084		this._elemButtonSubscribeClickHandler = BX.delegate(this.subscribe, this);
8085		this._elemHiddenClickHandler = BX.delegate(this.checkSubscribe, this);
8086
8087		BX.ready(BX.delegate(this.init,this));
8088	};
8089
8090	window.JCCatalogProductSubscribe.prototype.init = function()
8091	{
8092		if (!!this.buttonId)
8093		{
8094			this.elemButtonSubscribe = BX(this.buttonId);
8095			this.elemHiddenSubscribe = BX(this.buttonId+'_hidden');
8096		}
8097
8098		if (!!this.elemButtonSubscribe)
8099		{
8100			BX.bind(this.elemButtonSubscribe, 'click', this._elemButtonSubscribeClickHandler);
8101		}
8102
8103		if (!!this.elemHiddenSubscribe)
8104		{
8105			BX.bind(this.elemHiddenSubscribe, 'click', this._elemHiddenClickHandler);
8106		}
8107
8108		this.setButton(this.alreadySubscribed);
8109		this.setIdAlreadySubscribed(this.listIdAlreadySubscribed);
8110	};
8111
8112	window.JCCatalogProductSubscribe.prototype.checkSubscribe = function()
8113	{
8114		if(!this.elemHiddenSubscribe || !this.elemButtonSubscribe) return;
8115
8116		if(this.listOldItemId.hasOwnProperty(this.elemButtonSubscribe.dataset.item))
8117		{
8118			this.setButton(true);
8119		}
8120		else
8121		{
8122			BX.ajax({
8123				method: 'POST',
8124				dataType: 'json',
8125				url: this.ajaxUrl,
8126				data: {
8127					sessid: BX.bitrix_sessid(),
8128					checkSubscribe: 'Y',
8129					itemId: this.elemButtonSubscribe.dataset.item
8130				},
8131				onsuccess: BX.delegate(function (result) {
8132					if(result.subscribe)
8133					{
8134						this.setButton(true);
8135						this.listOldItemId[this.elemButtonSubscribe.dataset.item] = true;
8136					}
8137					else
8138					{
8139						this.setButton(false);
8140					}
8141				}, this)
8142			});
8143		}
8144	};
8145
8146	window.JCCatalogProductSubscribe.prototype.subscribe = function()
8147	{
8148		this.elemButtonSubscribe = BX.proxy_context;
8149		if(!this.elemButtonSubscribe) return false;
8150
8151		BX.ajax({
8152			method: 'POST',
8153			dataType: 'json',
8154			url: this.ajaxUrl,
8155			data: {
8156				sessid: BX.bitrix_sessid(),
8157				subscribe: 'Y',
8158				itemId: this.elemButtonSubscribe.dataset.item,
8159				siteId: BX.message('SITE_ID'),
8160				landingId: this.landingId
8161			},
8162			onsuccess: BX.delegate(function (result) {
8163				if(result.success)
8164				{
8165					this.createSuccessPopup(result);
8166					this.setButton(true);
8167					this.listOldItemId[this.elemButtonSubscribe.dataset.item] = true;
8168				}
8169				else if(result.contactFormSubmit)
8170				{
8171					this.initPopupWindow();
8172					this.elemPopupWin.setTitleBar(BX.message('CPST_SUBSCRIBE_POPUP_TITLE'));
8173					var form = this.createContentForPopup(result);
8174					this.elemPopupWin.setContent(form);
8175					this.elemPopupWin.setButtons([
8176						new subscribeButton({
8177							text: BX.message('CPST_SUBSCRIBE_BUTTON_NAME'),
8178							className : 'btn btn-primary',
8179							events: {
8180								click : BX.delegate(function() {
8181									if(!this.validateContactField(result.contactTypeData))
8182									{
8183										return false;
8184									}
8185									BX.ajax.submitAjax(form, {
8186										method : 'POST',
8187										url: this.ajaxUrl,
8188										processData : true,
8189										onsuccess: BX.delegate(function (resultForm) {
8190											resultForm = BX.parseJSON(resultForm, {});
8191											if(resultForm.success)
8192											{
8193												this.createSuccessPopup(resultForm);
8194												this.setButton(true);
8195												this.listOldItemId[this.elemButtonSubscribe.dataset.item] = true;
8196											}
8197											else if(resultForm.error)
8198											{
8199												if(resultForm.hasOwnProperty('setButton'))
8200												{
8201													this.listOldItemId[this.elemButtonSubscribe.dataset.item] = true;
8202													this.setButton(true);
8203												}
8204												var errorMessage = resultForm.message;
8205												if(resultForm.hasOwnProperty('typeName'))
8206												{
8207													errorMessage = resultForm.message.replace('USER_CONTACT',
8208														resultForm.typeName);
8209												}
8210												BX('bx-catalog-subscribe-form-notify').style.color = 'red';
8211												BX('bx-catalog-subscribe-form-notify').innerHTML = errorMessage;
8212											}
8213										}, this)
8214									});
8215								}, this)
8216							}
8217						}),
8218						new subscribeButton({
8219							text : BX.message('CPST_SUBSCRIBE_BUTTON_CLOSE'),
8220							className : 'btn',
8221							events : {
8222								click : BX.delegate(function() {
8223									this.elemPopupWin.destroy();
8224								}, this)
8225							}
8226						})
8227					]);
8228					this.elemPopupWin.show();
8229				}
8230				else if(result.error)
8231				{
8232					if(result.hasOwnProperty('setButton'))
8233					{
8234						this.listOldItemId[this.elemButtonSubscribe.dataset.item] = true;
8235						this.setButton(true);
8236					}
8237					this.showWindowWithAnswer({status: 'error', message: result.message});
8238				}
8239			}, this)
8240		});
8241	};
8242
8243	window.JCCatalogProductSubscribe.prototype.validateContactField = function(contactTypeData)
8244	{
8245		var inputFields = BX.findChildren(BX('bx-catalog-subscribe-form'),
8246			{'tag': 'input', 'attribute': {id: 'userContact'}}, true);
8247		if(!inputFields.length || typeof contactTypeData !== 'object')
8248		{
8249			BX('bx-catalog-subscribe-form-notify').style.color = 'red';
8250			BX('bx-catalog-subscribe-form-notify').innerHTML = BX.message('CPST_SUBSCRIBE_VALIDATE_UNKNOW_ERROR');
8251			return false;
8252		}
8253
8254		var contactTypeId, contactValue, useContact, errors = [], useContactErrors = [];
8255		for(var k = 0; k < inputFields.length; k++)
8256		{
8257			contactTypeId = inputFields[k].getAttribute('data-id');
8258			contactValue = inputFields[k].value;
8259			useContact = BX('bx-contact-use-'+contactTypeId);
8260			if(useContact && useContact.value == 'N')
8261			{
8262				useContactErrors.push(true);
8263				continue;
8264			}
8265			if(!contactValue.length)
8266			{
8267				errors.push(BX.message('CPST_SUBSCRIBE_VALIDATE_ERROR_EMPTY_FIELD').replace(
8268					'#FIELD#', contactTypeData[contactTypeId].contactLable));
8269			}
8270		}
8271
8272		if(inputFields.length == useContactErrors.length)
8273		{
8274			BX('bx-catalog-subscribe-form-notify').style.color = 'red';
8275			BX('bx-catalog-subscribe-form-notify').innerHTML = BX.message('CPST_SUBSCRIBE_VALIDATE_ERROR');
8276			return false;
8277		}
8278
8279		if(errors.length)
8280		{
8281			BX('bx-catalog-subscribe-form-notify').style.color = 'red';
8282			for(var i = 0; i < errors.length; i++)
8283			{
8284				BX('bx-catalog-subscribe-form-notify').innerHTML = errors[i];
8285			}
8286			return false;
8287		}
8288
8289		return true;
8290	};
8291
8292	window.JCCatalogProductSubscribe.prototype.reloadCaptcha = function()
8293	{
8294		BX.ajax.get(this.ajaxUrl+'?reloadCaptcha=Y', '', function(captchaCode) {
8295			BX('captcha_sid').value = captchaCode;
8296			BX('captcha_img').src = '/bitrix/tools/captcha.php?captcha_sid='+captchaCode+'';
8297		});
8298	};
8299
8300	window.JCCatalogProductSubscribe.prototype.createContentForPopup = function(responseData)
8301	{
8302		if(!responseData.hasOwnProperty('contactTypeData'))
8303		{
8304			return null;
8305		}
8306
8307		var contactTypeData = responseData.contactTypeData, contactCount = Object.keys(contactTypeData).length,
8308			styleInputForm = '', manyContact = 'N', content = document.createDocumentFragment();
8309
8310		if(contactCount > 1)
8311		{
8312			manyContact = 'Y';
8313			styleInputForm = 'display:none;';
8314			content.appendChild(BX.create('p', {
8315				text: BX.message('CPST_SUBSCRIBE_MANY_CONTACT_NOTIFY')
8316			}));
8317		}
8318
8319		content.appendChild(BX.create('p', {
8320			props: {id: 'bx-catalog-subscribe-form-notify'}
8321		}));
8322
8323		for(var k in contactTypeData)
8324		{
8325			if(contactCount > 1)
8326			{
8327				content.appendChild(BX.create('div', {
8328					props: {
8329						className: 'bx-catalog-subscribe-form-container'
8330					},
8331					children: [
8332						BX.create('div', {
8333							props: {
8334								className: 'checkbox'
8335							},
8336							children: [
8337								BX.create('lable', {
8338									props: {
8339										className: 'bx-filter-param-label'
8340									},
8341									attrs: {
8342										onclick: this.jsObject+'.selectContactType('+k+', event);'
8343									},
8344									children: [
8345										BX.create('input', {
8346											props: {
8347												type: 'hidden',
8348												id: 'bx-contact-use-'+k,
8349												name: 'contact['+k+'][use]',
8350												value: 'N'
8351											}
8352										}),
8353										BX.create('input', {
8354											props: {
8355												id: 'bx-contact-checkbox-'+k,
8356												type: 'checkbox'
8357											}
8358										}),
8359										BX.create('span', {
8360											props: {
8361												className: 'bx-filter-param-text'
8362											},
8363											text: contactTypeData[k].contactLable
8364										})
8365									]
8366								})
8367							]
8368						})
8369					]
8370				}));
8371			}
8372			content.appendChild(BX.create('div', {
8373				props: {
8374					id: 'bx-catalog-subscribe-form-container-'+k,
8375					className: 'bx-catalog-subscribe-form-container',
8376					style: styleInputForm
8377				},
8378				children: [
8379					BX.create('div', {
8380						props: {
8381							className: 'bx-catalog-subscribe-form-container-label'
8382						},
8383						text: BX.message('CPST_SUBSCRIBE_LABLE_CONTACT_INPUT').replace(
8384							'#CONTACT#', contactTypeData[k].contactLable)
8385					}),
8386					BX.create('div', {
8387						props: {
8388							className: 'bx-catalog-subscribe-form-container-input'
8389						},
8390						children: [
8391							BX.create('input', {
8392								props: {
8393									id: 'userContact',
8394									className: '',
8395									type: 'text',
8396									name: 'contact['+k+'][user]'
8397								},
8398								attrs: {'data-id': k}
8399							})
8400						]
8401					})
8402				]
8403			}));
8404		}
8405		if(responseData.hasOwnProperty('captchaCode'))
8406		{
8407			content.appendChild(BX.create('div', {
8408				props: {
8409					className: 'bx-catalog-subscribe-form-container'
8410				},
8411				children: [
8412					BX.create('span', {props: {className: 'bx-catalog-subscribe-form-star-required'}, text: '*'}),
8413					BX.message('CPST_ENTER_WORD_PICTURE'),
8414					BX.create('div', {
8415						props: {className: 'bx-captcha'},
8416						children: [
8417							BX.create('input', {
8418								props: {
8419									type: 'hidden',
8420									id: 'captcha_sid',
8421									name: 'captcha_sid',
8422									value: responseData.captchaCode
8423								}
8424							}),
8425							BX.create('img', {
8426								props: {
8427									id: 'captcha_img',
8428									src: '/bitrix/tools/captcha.php?captcha_sid='+responseData.captchaCode+''
8429								},
8430								attrs: {
8431									width: '180',
8432									height: '40',
8433									alt: 'captcha',
8434									onclick: this.jsObject+'.reloadCaptcha();'
8435								}
8436							})
8437						]
8438					}),
8439					BX.create('div', {
8440						props: {className: 'bx-catalog-subscribe-form-container-input'},
8441						children: [
8442							BX.create('input', {
8443								props: {
8444									id: 'captcha_word',
8445									className: '',
8446									type: 'text',
8447									name: 'captcha_word'
8448								},
8449								attrs: {maxlength: '50'}
8450							})
8451						]
8452					})
8453				]
8454			}));
8455		}
8456		var form = BX.create('form', {
8457			props: {
8458				id: 'bx-catalog-subscribe-form'
8459			},
8460			children: [
8461				BX.create('input', {
8462					props: {
8463						type: 'hidden',
8464						name: 'manyContact',
8465						value: manyContact
8466					}
8467				}),
8468				BX.create('input', {
8469					props: {
8470						type: 'hidden',
8471						name: 'sessid',
8472						value: BX.bitrix_sessid()
8473					}
8474				}),
8475				BX.create('input', {
8476					props: {
8477						type: 'hidden',
8478						name: 'itemId',
8479						value: this.elemButtonSubscribe.dataset.item
8480					}
8481				}),
8482				BX.create('input', {
8483					props: {
8484						type: 'hidden',
8485						name: 'landingId',
8486						value: this.landingId
8487					}
8488				}),
8489				BX.create('input', {
8490					props: {
8491						type: 'hidden',
8492						name: 'siteId',
8493						value: BX.message('SITE_ID')
8494					}
8495				}),
8496				BX.create('input', {
8497					props: {
8498						type: 'hidden',
8499						name: 'contactFormSubmit',
8500						value: 'Y'
8501					}
8502				})
8503			]
8504		});
8505
8506		form.appendChild(content);
8507
8508		return form;
8509	};
8510
8511	window.JCCatalogProductSubscribe.prototype.selectContactType = function(contactTypeId, event)
8512	{
8513		var contactInput = BX('bx-catalog-subscribe-form-container-'+contactTypeId), visibility = '',
8514			checkboxInput = BX('bx-contact-checkbox-'+contactTypeId);
8515		if(!contactInput)
8516		{
8517			return false;
8518		}
8519
8520		if(checkboxInput != event.target)
8521		{
8522			if(checkboxInput.checked)
8523			{
8524				checkboxInput.checked = false;
8525			}
8526			else
8527			{
8528				checkboxInput.checked = true;
8529			}
8530		}
8531
8532		if (contactInput.currentStyle)
8533		{
8534			visibility = contactInput.currentStyle.display;
8535		}
8536		else if (window.getComputedStyle)
8537		{
8538			var computedStyle = window.getComputedStyle(contactInput, null);
8539			visibility = computedStyle.getPropertyValue('display');
8540		}
8541
8542		if(visibility === 'none')
8543		{
8544			BX('bx-contact-use-'+contactTypeId).value = 'Y';
8545			BX.style(contactInput, 'display', '');
8546		}
8547		else
8548		{
8549			BX('bx-contact-use-'+contactTypeId).value = 'N';
8550			BX.style(contactInput, 'display', 'none');
8551		}
8552	};
8553
8554	window.JCCatalogProductSubscribe.prototype.createSuccessPopup = function(result)
8555	{
8556		this.initPopupWindow();
8557		this.elemPopupWin.setTitleBar(BX.message('CPST_SUBSCRIBE_POPUP_TITLE'));
8558		var content = BX.create('div', {
8559			props:{
8560				className: 'bx-catalog-popup-content'
8561			},
8562			children: [
8563				BX.create('p', {
8564					props: {
8565						className: 'bx-catalog-popup-message'
8566					},
8567					text: result.message
8568				})
8569			]
8570		});
8571		this.elemPopupWin.setContent(content);
8572		this.elemPopupWin.setButtons([
8573			new subscribeButton({
8574				text : BX.message('CPST_SUBSCRIBE_BUTTON_CLOSE'),
8575				className : 'btn btn-primary',
8576				events : {
8577					click : BX.delegate(function() {
8578						this.elemPopupWin.destroy();
8579					}, this)
8580				}
8581			})
8582		]);
8583		this.elemPopupWin.show();
8584	};
8585
8586	window.JCCatalogProductSubscribe.prototype.initPopupWindow = function()
8587	{
8588		this.elemPopupWin = BX.PopupWindowManager.create('CatalogSubscribe_'+this.buttonId, null, {
8589			autoHide: false,
8590			offsetLeft: 0,
8591			offsetTop: 0,
8592			overlay : true,
8593			closeByEsc: true,
8594			titleBar: true,
8595			closeIcon: true,
8596			contentColor: 'white'
8597		});
8598	};
8599
8600	window.JCCatalogProductSubscribe.prototype.setButton = function(statusSubscription)
8601	{
8602		this.alreadySubscribed = Boolean(statusSubscription);
8603		if(this.alreadySubscribed)
8604		{
8605			this.elemButtonSubscribe.className = this.buttonClass + ' ' + this.defaultButtonClass + ' disabled';
8606			this.elemButtonSubscribe.innerHTML = '<span>' + BX.message('CPST_TITLE_ALREADY_SUBSCRIBED') + '</span>';
8607			BX.unbind(this.elemButtonSubscribe, 'click', this._elemButtonSubscribeClickHandler);
8608		}
8609		else
8610		{
8611			this.elemButtonSubscribe.className = this.buttonClass + ' ' + this.defaultButtonClass;
8612			this.elemButtonSubscribe.innerHTML = '<span>' + BX.message('CPST_SUBSCRIBE_BUTTON_NAME') + '</span>';
8613			BX.bind(this.elemButtonSubscribe, 'click', this._elemButtonSubscribeClickHandler);
8614		}
8615	};
8616
8617	window.JCCatalogProductSubscribe.prototype.setIdAlreadySubscribed = function(listIdAlreadySubscribed)
8618	{
8619		if (BX.type.isPlainObject(listIdAlreadySubscribed))
8620		{
8621			this.listOldItemId = listIdAlreadySubscribed;
8622		}
8623	};
8624
8625	window.JCCatalogProductSubscribe.prototype.showWindowWithAnswer = function(answer)
8626	{
8627		answer = answer || {};
8628		if (!answer.message) {
8629			if (answer.status == 'success') {
8630				answer.message = BX.message('CPST_STATUS_SUCCESS');
8631			} else {
8632				answer.message = BX.message('CPST_STATUS_ERROR');
8633			}
8634		}
8635		var messageBox = BX.create('div', {
8636			props: {
8637				className: 'bx-catalog-subscribe-alert'
8638			},
8639			children: [
8640				BX.create('span', {
8641					props: {
8642						className: 'bx-catalog-subscribe-aligner'
8643					}
8644				}),
8645				BX.create('span', {
8646					props: {
8647						className: 'bx-catalog-subscribe-alert-text'
8648					},
8649					text: answer.message
8650				}),
8651				BX.create('div', {
8652					props: {
8653						className: 'bx-catalog-subscribe-alert-footer'
8654					}
8655				})
8656			]
8657		});
8658		var currentPopup = BX.PopupWindowManager.getCurrentPopup();
8659		if(currentPopup) {
8660			currentPopup.destroy();
8661		}
8662		var idTimeout = setTimeout(function () {
8663			var w = BX.PopupWindowManager.getCurrentPopup();
8664			if (!w || w.uniquePopupId != 'bx-catalog-subscribe-status-action') {
8665				return;
8666			}
8667			w.close();
8668			w.destroy();
8669		}, 3500);
8670		var popupConfirm = BX.PopupWindowManager.create('bx-catalog-subscribe-status-action', null, {
8671			content: messageBox,
8672			onPopupClose: function () {
8673				this.destroy();
8674				clearTimeout(idTimeout);
8675			},
8676			autoHide: true,
8677			zIndex: 2000,
8678			className: 'bx-catalog-subscribe-alert-popup'
8679		});
8680		popupConfirm.show();
8681		BX('bx-catalog-subscribe-status-action').onmouseover = function (e) {
8682			clearTimeout(idTimeout);
8683		};
8684		BX('bx-catalog-subscribe-status-action').onmouseout = function (e) {
8685			idTimeout = setTimeout(function () {
8686				var w = BX.PopupWindowManager.getCurrentPopup();
8687				if (!w || w.uniquePopupId != 'bx-catalog-subscribe-status-action') {
8688					return;
8689				}
8690				w.close();
8691				w.destroy();
8692			}, 3500);
8693		};
8694	};
8695
8696})(window);
8697
8698/* End */
8699;
8700; /* Start:"a:4:{s:4:"full";s:104:"/local/templates/fabrika38/components/bitrix/catalog.top/recommends_top/section/script.js?17543905645325";s:6:"source";s:89:"/local/templates/fabrika38/components/bitrix/catalog.top/recommends_top/section/script.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
8701(function() {
8702	'use strict';
8703
8704	if (!!window.JCCatalogTopComponent)
8705		return;
8706
8707	window.JCCatalogTopComponent = function(params)
8708	{
8709		this.formPosting = false;
8710		this.siteId = params.siteId || '';
8711		this.ajaxId = params.ajaxId || '';
8712		this.template = params.template || '';
8713		this.componentPath = params.componentPath || '';
8714		this.parameters = params.parameters || '';
8715
8716		this.bigData = params.bigData || {enabled: false};
8717		this.container = document.querySelector('[data-entity="' + params.container + '"]');
8718
8719		if (this.bigData.enabled && BX.util.object_keys(this.bigData.rows).length > 0)
8720		{
8721			BX.cookie_prefix = this.bigData.js.cookiePrefix || '';
8722			BX.cookie_domain = this.bigData.js.cookieDomain || '';
8723			BX.current_server_time = this.bigData.js.serverTime;
8724
8725			BX.ready(BX.delegate(this.bigDataLoad, this));
8726		}
8727
8728		if (params.initiallyShowHeader)
8729		{
8730			BX.ready(BX.delegate(this.showHeader, this));
8731		}
8732
8733		if (params.deferredLoad)
8734		{
8735			BX.ready(BX.delegate(this.deferredLoad, this));
8736		}
8737	};
8738
8739	window.JCCatalogTopComponent.prototype =
8740	{
8741		bigDataLoad: function()
8742		{
8743			var url = 'https://analytics.bitrix.info/crecoms/v1_0/recoms.php',
8744				data = BX.ajax.prepareData(this.bigData.params);
8745
8746			if (data)
8747			{
8748				url += (url.indexOf('?') !== -1 ? '&' : '?') + data;
8749			}
8750
8751			var onReady = BX.delegate(function(result){
8752				this.sendRequest({
8753					action: 'deferredLoad',
8754					bigData: 'Y',
8755					items: result && result.items || [],
8756					rid: result && result.id,
8757					count: this.bigData.count,
8758					rowsRange: this.bigData.rowsRange,
8759					shownIds: this.bigData.shownIds
8760				});
8761			}, this);
8762
8763			BX.ajax({
8764				method: 'GET',
8765				dataType: 'json',
8766				url: url,
8767				timeout: 3,
8768				onsuccess: onReady,
8769				onfailure: onReady
8770			});
8771		},
8772
8773		deferredLoad: function()
8774		{
8775			this.sendRequest({action: 'deferredLoad'});
8776		},
8777
8778		sendRequest: function(data)
8779		{
8780			var defaultData = {
8781				siteId: this.siteId,
8782				template: this.template,
8783				parameters: this.parameters
8784			};
8785
8786			if (this.ajaxId)
8787			{
8788				defaultData.AJAX_ID = this.ajaxId;
8789			}
8790
8791			BX.ajax({
8792				url: this.componentPath + '/ajax.php' + (document.location.href.indexOf('clear_cache=Y') !== -1 ? '?clear_cache=Y' : ''),
8793				method: 'POST',
8794				dataType: 'json',
8795				timeout: 60,
8796				data: BX.merge(defaultData, data),
8797				onsuccess: BX.delegate(function(result){
8798					if (!result || !result.JS)
8799						return;
8800
8801					BX.ajax.processScripts(
8802						BX.processHTML(result.JS).SCRIPT,
8803						false,
8804						BX.delegate(function(){this.showAction(result, data);}, this)
8805					);
8806				}, this)
8807			});
8808		},
8809
8810		showAction: function(result, data)
8811		{
8812			if (!data)
8813				return;
8814
8815			switch (data.action)
8816			{
8817				case 'deferredLoad':
8818					this.processDeferredLoadAction(result, data.bigData === 'Y');
8819					break;
8820			}
8821		},
8822
8823		processDeferredLoadAction: function(result, bigData)
8824		{
8825			if (!result)
8826				return;
8827
8828			var position = bigData ? this.bigData.rows : {};
8829
8830			this.processItems(result.items, BX.util.array_keys(position));
8831		},
8832
8833		processItems: function(itemsHtml, position)
8834		{
8835			if (!itemsHtml)
8836				return;
8837
8838			var processed = BX.processHTML(itemsHtml, false),
8839				temporaryNode = BX.create('DIV');
8840
8841			var items, k, origRows;
8842
8843			temporaryNode.innerHTML = processed.HTML;
8844			items = temporaryNode.querySelectorAll('[data-entity="items-row"]');
8845
8846			if (items.length)
8847			{
8848				this.showHeader(true);
8849
8850				for (k in items)
8851				{
8852					if (items.hasOwnProperty(k))
8853					{
8854						origRows = position ? this.container.querySelectorAll('[data-entity="items-row"]') : false;
8855						items[k].style.opacity = 0;
8856
8857						if (origRows && BX.type.isDomNode(origRows[position[k]]))
8858						{
8859							origRows[position[k]].parentNode.insertBefore(items[k], origRows[position[k]]);
8860						}
8861						else
8862						{
8863							this.container.appendChild(items[k]);
8864						}
8865					}
8866				}
8867
8868				new BX.easing({
8869					duration: 2000,
8870					start: {opacity: 0},
8871					finish: {opacity: 100},
8872					transition: BX.easing.makeEaseOut(BX.easing.transitions.quad),
8873					step: function(state){
8874						for (var k in items)
8875						{
8876							if (items.hasOwnProperty(k))
8877							{
8878								items[k].style.opacity = state.opacity / 100;
8879							}
8880						}
8881					},
8882					complete: function(){
8883						for (var k in items)
8884						{
8885							if (items.hasOwnProperty(k))
8886							{
8887								items[k].removeAttribute('style');
8888							}
8889						}
8890					}
8891				}).animate();
8892			}
8893
8894			BX.ajax.processScripts(processed.SCRIPT);
8895		},
8896
8897		showHeader: function(animate)
8898		{
8899			var parentNode = BX.findParent(this.container, {attr: {'data-entity': 'parent-container'}}),
8900				header;
8901
8902			if (parentNode && BX.type.isDomNode(parentNode))
8903			{
8904				header = parentNode.querySelector('[data-entity="header"]');
8905
8906				if (header && header.getAttribute('data-showed') != 'true')
8907				{
8908					header.style.display = '';
8909
8910					if (animate)
8911					{
8912						new BX.easing({
8913							duration: 2000,
8914							start: {opacity: 0},
8915							finish: {opacity: 100},
8916							transition: BX.easing.makeEaseOut(BX.easing.transitions.quad),
8917							step: function(state){
8918								header.style.opacity = state.opacity / 100;
8919							},
8920							complete: function(){
8921								header.removeAttribute('style');
8922								header.setAttribute('data-showed', 'true');
8923							}
8924						}).animate();
8925					}
8926					else
8927					{
8928						header.style.opacity = 100;
8929					}
8930				}
8931			}
8932		}
8933	};
8934})();
8935/* End */
8936;; /* /local/templates/fabrika38/components/bitrix/sale.basket.basket/basket_38/script.js?176337996838809*/
8937; /* /local/templates/fabrika38/components/bitrix/sale.basket.basket/basket_38/js/mustache.js?175439056419670*/
8938; /* /local/templates/fabrika38/components/bitrix/sale.basket.basket/basket_38/js/action-pool.js?17543905645918*/
8939; /* /local/templates/fabrika38/components/bitrix/sale.basket.basket/basket_38/js/filter.js?175439056414092*/
8940; /* /local/templates/fabrika38/components/bitrix/sale.basket.basket/basket_38/js/component.js?175439056462461*/
8941; /* /local/templates/fabrika38/components/bitrix/catalog.item/parrots_item/script.js?179135599363328*/
8942; /* /bitrix/components/bitrix/catalog.product.subscribe/templates/.default/script.js?175439038817434*/
8943; /* /local/templates/fabrika38/components/bitrix/catalog.top/recommends_top/section/script.js?17543905645325*/

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.