PageSourceSearch

https://tdmtdm.ru/local/templates/dm-neva/components/bitrix/sale.basket.basket/custom/script.js

js tdmtdm.ru collected 2026-10-05 22:51:03 UTC 38,246 bytes, 1,423 lines download raw bytes

1
2BasketPoolQuantity = function()
3{
4	this.processing = false;
5	this.poolQuantity = {};
6	this.updateTimer = null;
7	this.currentQuantity = {};
8	this.lastStableQuantities = {};
9
10	this.updateQuantity();
11};
12
13
14BasketPoolQuantity.prototype.updateQuantity = function()
15{
16	var items = BX('basket_items');
17
18	/*if (basketJSParams['USE_ENHANCED_ECOMMERCE'] === 'Y')
19	{
20		checkAnalytics(this.lastStableQuantities, items);
21	}*/
22
23	if (!!items && items.rows.length > 0)
24	{
25		for (var i = 1; items.rows.length > i; i++)
26		{
27			var itemId = items.rows[i].id;
28			this.currentQuantity[itemId] = BX('QUANTITY_' + itemId).value;
29		}
30	}
31
32	this.lastStableQuantities = BX.clone(this.currentQuantity, true);
33};
34
35
36BasketPoolQuantity.prototype.changeQuantity = function(itemId)
37{
38	var quantity = BX('QUANTITY_' + itemId).value;
39	var isPoolEmpty = this.isPoolEmpty();
40
41	if (this.currentQuantity[itemId] && this.currentQuantity[itemId] != quantity)
42	{
43		this.poolQuantity[itemId] = this.currentQuantity[itemId] = quantity;
44	}
45
46	if (!isPoolEmpty)
47	{
48		this.enableTimer(true);
49	}
50	else
51	{
52		this.trySendPool();
53	}
54};
55
56
57BasketPoolQuantity.prototype.trySendPool = function()
58{
59	if (!this.isPoolEmpty() && !this.isProcessing())
60	{
61		this.enableTimer(false);
62		recalcBasketAjax({});
63	}
64};
65
66BasketPoolQuantity.prototype.isPoolEmpty = function()
67{
68	return ( Object.keys(this.poolQuantity).length == 0 );
69};
70
71BasketPoolQuantity.prototype.clearPool = function()
72{
73	this.poolQuantity = {};
74};
75
76BasketPoolQuantity.prototype.isProcessing = function()
77{
78	return (this.processing === true);
79};
80
81BasketPoolQuantity.prototype.setProcessing = function(value)
82{
83	this.processing = (value === true);
84};
85
86BasketPoolQuantity.prototype.enableTimer = function(value)
87{
88	clearTimeout(this.updateTimer);
89	if (value === false)
90		return;
91
92	this.updateTimer = setTimeout(function(){ basketPoolQuantity.trySendPool(); }, 1500);
93};
94
95/**
96 * @param basketItemId
97 * @param {{BASKET_ID : string, BASKET_DATA : { GRID : { ROWS : {} }}, COLUMNS: {}, PARAMS: {}, DELETE_ORIGINAL : string }} res
98 */
99function updateBasketTable(basketItemId, res)
100{
101	var table = BX("basket_items"),
102		rows,
103		newBasketItemId,
104		arItem,
105		lastRow,
106		newRow,
107		arColumns,
108		bShowDeleteColumn = false,
109		bShowDelayColumn = false,
110		bShowPropsColumn = false,
111		bShowPriceType = false,
112		bUseFloatQuantity,
113		origBasketItem,
114		oCellMargin,
115		i,
116		oCellName,
117		imageURL,
118		cellNameHTML,
119		oCellItem,
120		cellItemHTML,
121		bSkip,
122		j,
123		val,
124		propId,
125		arProp,
126		bIsImageProperty,
127		countValues,
128		full,
129		fullWidth,
130		itemWidth,
131		arVal,
132		valId,
133		arSkuValue,
134		selected,
135		valueId,
136		k,
137		arItemProp,
138		oCellQuantity,
139		oCellQuantityHTML,
140		ratio,
141		isUpdateQuantity,
142		oldQuantity,
143		oCellPrice,
144		fullPrice,
145		id,
146		oCellDiscount,
147		oCellWeight,
148		oCellCustom,
149		customColumnVal,
150		propsMap,
151		selectedIndex,
152		counter,
153		marginLeft,
154		createNewItem;
155
156	if (!table || typeof res !== 'object')
157	{
158		return;
159	}
160
161	rows = table.rows;
162	lastRow = rows[rows.length - 1];
163	bUseFloatQuantity = (res.PARAMS.QUANTITY_FLOAT === 'Y');
164
165	// insert new row instead of original basket item row
166	if (basketItemId !== null && !!res.BASKET_DATA)
167	{
168		origBasketItem = BX(basketItemId);
169
170		newBasketItemId = res.BASKET_ID;
171		createNewItem = BX.type.isPlainObject(res.BASKET_DATA.GRID.ROWS[newBasketItemId]);
172		if (createNewItem)
173		{
174			arItem = res.BASKET_DATA.GRID.ROWS[newBasketItemId];
175			newRow = document.createElement('tr');
176
177			newRow.setAttribute('id', res.BASKET_ID);
178			newRow.setAttribute('data-item-name', arItem['NAME']);
179			newRow.setAttribute('data-item-brand', arItem[basketJSParams['BRAND_PROPERTY'] + '_VALUE']);
180			newRow.setAttribute('data-item-price', arItem['PRICE']);
181			newRow.setAttribute('data-item-currency', arItem['CURRENCY']);
182
183			lastRow.parentNode.insertBefore(newRow, origBasketItem.nextSibling);
184		}
185
186		if (res.DELETE_ORIGINAL === 'Y')
187		{
188			origBasketItem.parentNode.removeChild(origBasketItem);
189		}
190
191		if (createNewItem)
192		{
193			// fill row with fields' values
194			oCellMargin = newRow.insertCell(-1);
195			oCellMargin.setAttribute('class', 'margin');
196
197			arColumns = res.COLUMNS.split(',');
198
199			for (i = 0; i < arColumns.length; i++)
200			{
201				if (arColumns[i] === 'DELETE')
202				{
203					bShowDeleteColumn = true;
204				}
205				else if (arColumns[i] === 'DELAY')
206				{
207					bShowDelayColumn = true;
208				}
209				else if (arColumns[i] === 'PROPS')
210				{
211					bShowPropsColumn = true;
212				}
213				else if (arColumns[i] === 'TYPE')
214				{
215					bShowPriceType = true;
216				}
217			}
218
219			for (i = 0; i < arColumns.length; i++)
220			{
221				switch (arColumns[i])
222				{
223					case 'PROPS':
224					case 'DELAY':
225					case 'DELETE':
226					case 'TYPE':
227						break;
228					case 'NAME':
229						// first <td> - image and brand
230						oCellName = newRow.insertCell(-1);
231						imageURL = '';
232						cellNameHTML = '';
233
234						oCellName.setAttribute('class', 'itemphoto');
235
236						if (arItem.PREVIEW_PICTURE_SRC.length > 0)
237						{
238							imageURL = arItem.PREVIEW_PICTURE_SRC;
239						}
240						else if (arItem.DETAIL_PICTURE_SRC.length > 0)
241						{
242							imageURL = arItem.DETAIL_PICTURE_SRC;
243						}
244						else
245						{
246							imageURL = basketJSParams.TEMPLATE_FOLDER + '/images/no_photo.png';
247						}
248
249						if (arItem.DETAIL_PAGE_URL.length > 0)
250						{
251							cellNameHTML = '<div class="bx_ordercart_photo_container">\
252							<a href="' + arItem.DETAIL_PAGE_URL + '">\
253								<div class="bx_ordercart_photo" style="background-image:url(\'' + imageURL + '\')"></div>\
254							</a>\
255						</div>';
256						}
257						else
258						{
259							cellNameHTML = '<div class="bx_ordercart_photo_container">\
260							<div class="bx_ordercart_photo" style="background-image:url(\'' + imageURL + '\')"></div>\
261						</div>';
262						}
263
264						if (arItem.BRAND && arItem.BRAND.length > 0)
265						{
266							cellNameHTML += '<div class="bx_ordercart_brand">\
267							<img alt="" src="' + arItem.BRAND + '"/>\
268						</div>';
269						}
270
271						oCellName.innerHTML = cellNameHTML;
272
273						// second <td> - name, basket props, sku props
274						oCellItem = newRow.insertCell(-1);
275						cellItemHTML = '';
276						oCellItem.setAttribute('class', 'item');
277
278						if (arItem['DETAIL_PAGE_URL'].length > 0)
279							cellItemHTML += '<h2 class="bx_ordercart_itemtitle"><a href="' + arItem['DETAIL_PAGE_URL'] + '">' + arItem['NAME'] + '</a></h2>';
280						else
281							cellItemHTML += '<h2 class="bx_ordercart_itemtitle">' + arItem['NAME'] + '</h2>';
282
283						cellItemHTML += '<div class="bx_ordercart_itemart">';
284
285						if (bShowPropsColumn)
286						{
287							for (j = 0; j < arItem['PROPS'].length; j++)
288							{
289								val = arItem['PROPS'][j];
290
291								if (arItem.SKU_DATA)
292								{
293									bSkip = false;
294									for (propId in arItem.SKU_DATA)
295									{
296										if (arItem.SKU_DATA.hasOwnProperty(propId))
297										{
298											arProp = arItem.SKU_DATA[propId];
299
300											if (arProp['CODE'] === val['CODE'])
301											{
302												bSkip = true;
303												break;
304											}
305										}
306									}
307									if (bSkip)
308										continue;
309								}
310
311								cellItemHTML += BX.util.htmlspecialchars(val['NAME']) + ':&nbsp;<span>' + val['VALUE'] + '</span><br/>';
312							}
313						}
314						cellItemHTML += '</div>';
315
316						if (arItem.SKU_DATA)
317						{
318							propsMap = {};
319							for (k = 0; k < arItem['PROPS'].length; k++)
320							{
321								arItemProp = arItem['PROPS'][k];
322								propsMap[arItemProp['CODE']] = (BX.type.isNotEmptyString(arItemProp['~VALUE']) ? arItemProp['~VALUE'] : arItemProp['VALUE']);
323							}
324							for (propId in arItem.SKU_DATA)
325							{
326								if (arItem.SKU_DATA.hasOwnProperty(propId))
327								{
328									selectedIndex = 0;
329									arProp = arItem.SKU_DATA[propId];
330									bIsImageProperty = false;
331									countValues = BX.util.array_keys(arProp['VALUES']).length;
332									if (countValues > 5)
333									{
334										full = 'full';
335										fullWidth = (countValues*20) + '%';
336										itemWidth = (100/countValues) + '%';
337									}
338									else
339									{
340										full = '';
341										fullWidth = '100%';
342										itemWidth = '20%';
343									}
344
345									counter = 0;
346									for (valId in arProp['VALUES'])
347									{
348										counter++;
349										arVal = arProp['VALUES'][valId];
350										if (BX.type.isNotEmptyString(propsMap[arProp['CODE']]))
351										{
352											if (propsMap[arProp['CODE']] == arVal['NAME'] || propsMap[arProp['CODE']] == arVal['XML_ID'])
353												selectedIndex = counter;
354										}
355										if (!!arVal && typeof arVal === 'object' && !!arVal['PICT'])
356										{
357											bIsImageProperty = true;
358										}
359									}
360
361									marginLeft = '0';
362									if (full !== '' && selectedIndex > 5)
363										marginLeft = ((5 - selectedIndex) * 20) + '%';
364
365									// sku property can contain list of images or values
366									if (bIsImageProperty)
367									{
368										cellItemHTML += '<div class="bx_item_detail_scu_small_noadaptive ' + full + '">';
369										cellItemHTML += '<span class="bx_item_section_name_gray">' + BX.util.htmlspecialchars(arProp['NAME']) + '</span>';
370										cellItemHTML += '<div class="bx_scu_scroller_container">';
371										cellItemHTML += '<div class="bx_scu">';
372
373										cellItemHTML += '<ul id="prop_' + arProp['CODE'] + '_' + arItem['ID'] + '" style="width: ' + fullWidth + '; margin-left: ' + marginLeft + ';" class="sku_prop_list">';
374
375										counter = 0;
376										for (valueId in arProp['VALUES'])
377										{
378											counter++;
379											arSkuValue = arProp['VALUES'][valueId];
380											selected = (selectedIndex == counter ? ' bx_active' : '');
381
382											cellItemHTML += '<li style="width: ' + itemWidth + '; padding-top: ' + itemWidth + ';"\
383															class="sku_prop' + selected + '" \
384															data-sku-selector="Y" \
385															data-value-id="' + arSkuValue['XML_ID'] + '" \
386															data-sku-name="' + BX.util.htmlspecialchars(arSkuValue['NAME']) + '" \
387															data-element="' + arItem['ID'] + '" \
388															data-property="' + arProp['CODE'] + '"\
389															>\
390															<a href="javascript:void(0)" class="cnt"><span class="cnt_item" style="background-image:url(' + arSkuValue['PICT']['SRC'] + '"></span></a>\
391														</li>';
392										}
393
394										cellItemHTML += '</ul>';
395										cellItemHTML += '</div>';
396
397										cellItemHTML += '<div class="bx_slide_left" onclick="leftScroll(\'' + arProp['CODE'] + '\', ' + arItem['ID'] + ', ' + BX.util.array_keys(arProp['VALUES']).length + ');"></div>';
398										cellItemHTML += '<div class="bx_slide_right" onclick="rightScroll(\'' + arProp['CODE'] + '\', ' + arItem['ID'] + ', ' + BX.util.array_keys(arProp['VALUES']).length + ');"></div>';
399
400										cellItemHTML += '</div>';
401										cellItemHTML += '</div>';
402									}
403									else // not image
404									{
405										cellItemHTML += '<div class="bx_item_detail_size_small_noadaptive ' + full + '">';
406										cellItemHTML += '<span class="bx_item_section_name_gray">' + BX.util.htmlspecialchars(arProp['NAME']) + '</span>';
407										cellItemHTML += '<div class="bx_size_scroller_container">';
408										cellItemHTML += '<div class="bx_size">';
409
410										cellItemHTML += '<ul id="prop_' + arProp['CODE'] + '_' + arItem['ID'] + '" style="width: ' + fullWidth + '; margin-left: ' + marginLeft + ';" class="sku_prop_list">';
411
412										counter = 0;
413										for (valueId in arProp['VALUES'])
414										{
415											counter++;
416											arSkuValue = arProp['VALUES'][valueId];
417											selected = (selectedIndex == counter ? ' bx_active' : '');
418
419											cellItemHTML += '<li style="width: ' + itemWidth + ';"\
420															class="sku_prop ' + selected + '" \
421															data-sku-selector="Y" \
422															data-value-id="' + (arProp['TYPE'] === 'S' && arProp['USER_TYPE'] === 'directory' ? arSkuValue['XML_ID'] : BX.util.htmlspecialchars(arSkuValue['NAME'])) + '" \
423															data-sku-name="' + BX.util.htmlspecialchars(arSkuValue['NAME']) + '" \
424															data-element="' + arItem['ID'] + '" \
425															data-property="' + arProp['CODE'] + '" \
426															>\
427															<a href="javascript:void(0)" class="cnt">' + BX.util.htmlspecialchars(arSkuValue['NAME']) + '</a>\
428														</li>';
429										}
430
431										cellItemHTML += '</ul>';
432										cellItemHTML += '</div>';
433
434										cellItemHTML += '<div class="bx_slide_left" onclick="leftScroll(\'' + arProp['CODE'] + '\', ' + arItem['ID'] + ', ' + BX.util.array_keys(arProp['VALUES']).length + ');"></div>';
435										cellItemHTML += '<div class="bx_slide_right" onclick="rightScroll(\'' + arProp['CODE'] + '\', ' + arItem['ID'] + ', ' + BX.util.array_keys(arProp['VALUES']).length + ');"></div>';
436
437										cellItemHTML += '</div>';
438										cellItemHTML += '</div>';
439									}
440								}
441							}
442						}
443
444						oCellItem.innerHTML = cellItemHTML;
445						break;
446					case 'QUANTITY':
447						oCellQuantity = newRow.insertCell(-1);
448						oCellQuantityHTML = '';
449						ratio = (parseFloat(arItem['MEASURE_RATIO']) > 0) ? arItem['MEASURE_RATIO'] : 1;
450
451						isUpdateQuantity = false;
452
453						if (ratio != 0 && ratio != '')
454						{
455							oldQuantity = arItem['QUANTITY'];
456							arItem['QUANTITY'] = getCorrectRatioQuantity(arItem['QUANTITY'], ratio, bUseFloatQuantity);
457
458							if (oldQuantity != arItem['QUANTITY'])
459							{
460								isUpdateQuantity = true;
461							}
462						}
463
464						oCellQuantity.setAttribute('class', 'custom');
465						oCellQuantityHTML += '<span>' + getColumnName(res, arColumns[i]) + ':</span>';
466
467						oCellQuantityHTML += '<div class="centered">';
468						oCellQuantityHTML += '<table cellspacing="0" cellpadding="0" class="counter">';
469						oCellQuantityHTML += '<tr>';
470						oCellQuantityHTML += '<td>';
471
472						oCellQuantityHTML += '<input type="text" size="3" id="QUANTITY_INPUT_' + arItem['ID'] + '"\
473											name="QUANTITY_INPUT_' + arItem['ID'] + '"\
474											style="max-width: 50px"\
475											value="' + arItem['QUANTITY'] + '"\
476											onchange="updateQuantity(\'QUANTITY_INPUT_' + arItem['ID'] + '\',\'' + arItem['ID'] + '\', ' + ratio + ',' + bUseFloatQuantity + ')"\
477						>';
478
479						oCellQuantityHTML += '</td>';
480
481						if (ratio != 0
482							&& ratio != ''
483						) // if not Set parent, show quantity control
484						{
485							oCellQuantityHTML += '<td id="basket_quantity_control">\
486							<div class="basket_quantity_control">\
487								<a href="javascript:void(0);" class="plus" onclick="setQuantity(' + arItem['ID'] + ', ' + ratio + ', \'up\', ' + bUseFloatQuantity + ');"></a>\
488								<a href="javascript:void(0);" class="minus" onclick="setQuantity(' + arItem['ID'] + ', ' + ratio + ', \'down\', ' + bUseFloatQuantity + ');"></a>\
489							</div>\
490						</td>';
491						}
492
493						if (arItem.hasOwnProperty('MEASURE_TEXT') && arItem['MEASURE_TEXT'].length > 0)
494							oCellQuantityHTML += '<td style="text-align: left">' + BX.util.htmlspecialchars(arItem['MEASURE_TEXT']) + '</td>';
495
496						oCellQuantityHTML += '</tr>';
497						oCellQuantityHTML += '</table>';
498						oCellQuantityHTML += '</div>';
499
500						oCellQuantityHTML += '<input type="hidden" id="QUANTITY_' + arItem['ID'] + '" name="QUANTITY_' + arItem['ID'] + '" value="' + arItem['QUANTITY'] + '" />';
501
502						oCellQuantity.innerHTML = oCellQuantityHTML;
503
504						if (isUpdateQuantity)
505						{
506							updateQuantity('QUANTITY_INPUT_' + arItem['ID'], arItem['ID'], ratio, bUseFloatQuantity);
507						}
508						break;
509					case 'PRICE':
510						oCellPrice = newRow.insertCell(-1);
511						fullPrice = (arItem['DISCOUNT_PRICE_PERCENT'] > 0) ? arItem['FULL_PRICE_FORMATED'] : '';
512
513						oCellPrice.setAttribute('class', 'price');
514						oCellPrice.innerHTML = '<div class="current_price" id="current_price_' + arItem['ID'] + '">' + arItem['PRICE_FORMATED'] + '</div>' +
515							'<div class="old_price" id="old_price_' + arItem['ID'] + '">' + fullPrice + '</div>';
516
517						if (bShowPriceType && arItem['NOTES'].length > 0)
518						{
519							oCellPrice.innerHTML += '<div class="type_price">' + basketJSParams['SALE_TYPE'] + '</div>';
520							oCellPrice.innerHTML += '<div class="type_price_value">' + arItem['NOTES'] + '</div>';
521						}
522						break;
523					case 'DISCOUNT':
524						oCellDiscount = newRow.insertCell(-1);
525						oCellDiscount.setAttribute('class', 'custom');
526						oCellDiscount.innerHTML = '<span>' + getColumnName(res, arColumns[i]) + ':</span>';
527						oCellDiscount.innerHTML += '<div id="discount_value_' + arItem['ID'] + '">' + arItem['DISCOUNT_PRICE_PERCENT_FORMATED'] + '</div>';
528						break;
529					case 'WEIGHT':
530						oCellWeight = newRow.insertCell(-1);
531						oCellWeight.setAttribute('class', 'custom');
532						oCellWeight.innerHTML = '<span>' + getColumnName(res, arColumns[i]) + ':</span>';
533						oCellWeight.innerHTML += arItem['WEIGHT_FORMATED'];
534						break;
535					default:
536						oCellCustom = newRow.insertCell(-1);
537						customColumnVal = '';
538
539						oCellCustom.setAttribute('class', 'custom');
540						oCellCustom.innerHTML = '<span>' + getColumnName(res, arColumns[i]) + ':</span>';
541
542						if (arColumns[i] == 'SUM')
543							customColumnVal += '<div id="sum_' + arItem['ID'] + '">';
544
545						if (typeof(arItem[arColumns[i]]) != 'undefined')
546						{
547							customColumnVal += arItem[arColumns[i]];
548						}
549
550						if (arColumns[i] == 'SUM')
551							customColumnVal += '</div>';
552
553						oCellCustom.innerHTML += customColumnVal;
554						break;
555				}
556			}
557
558			if (bShowDeleteColumn || bShowDelayColumn)
559			{
560				var oCellControl = newRow.insertCell(-1);
561				oCellControl.setAttribute('class', 'control');
562
563				if (bShowDeleteColumn)
564					oCellControl.innerHTML = '<a href="' + basketJSParams['DELET
564E_URL'].replace('#ID#', arItem['ID']) + '">' + basketJSParams['SALE_DELETE'] + '</a><br />';
565
566				if (bShowDelayColumn)
567					oCellControl.innerHTML += '<a href="' + basketJSParams['DELAY_URL'].replace('#ID#', arItem['ID']) + '">' + basketJSParams['SALE_DELAY'] + '</a>';
568			}
569
570			var oCellMargin2 = newRow.insertCell(-1);
571			oCellMargin2.setAttribute('class', 'margin');
572		}
573	}
574
575	// update product params after recalculation
576	if (!!res.BASKET_DATA)
577	{
578		for (id in res.BASKET_DATA.GRID.ROWS)
579		{
580			if (res.BASKET_DATA.GRID.ROWS.hasOwnProperty(id))
581			{
582				var item = res.BASKET_DATA.GRID.ROWS[id];
583
584				if (BX('discount_value_' + id))
585					BX('discount_value_' + id).innerHTML = item.DISCOUNT_PRICE_PERCENT_FORMATED;
586
587				if (BX('current_price_' + id))
588					BX('current_price_' + id).innerHTML = item.PRICE_FORMATED;
589
590				if (BX('old_price_' + id))
591					BX('old_price_' + id).innerHTML = (item.DISCOUNT_PRICE_PERCENT > 0) ? item.FULL_PRICE_FORMATED : '';
592
593				if (BX('sum_' + id))
594					BX('sum_' + id).innerHTML = item.SUM;
595
596				// if the quantity was set by user to 0 or was too much, we need to show corrected quantity value from ajax response
597				if (BX('QUANTITY_' + id))
598				{
599					BX('QUANTITY_INPUT_' + id).value = item.QUANTITY;
600					BX('QUANTITY_INPUT_' + id).defaultValue = item.QUANTITY;
601
602					BX('QUANTITY_' + id).value = item.QUANTITY;
603				}
604			}
605		}
606	}
607
608	// update coupon info
609	if (!!res.BASKET_DATA)
610		couponListUpdate(res.BASKET_DATA);
611
612	// update warnings if any
613	if (res.hasOwnProperty('WARNING_MESSAGE'))
614	{
615		var warningText = '';
616
617		for (i = res['WARNING_MESSAGE'].length - 1; i >= 0; i--)
618			warningText += res['WARNING_MESSAGE'][i] + '<br/>';
619
620		BX('warning_message').innerHTML = warningText;
621	}
622
623	// update total basket values
624	if (!!res.BASKET_DATA)
625	{
626		if (BX('allWeight_FORMATED'))
627			BX('allWeight_FORMATED').innerHTML = res['BASKET_DATA']['allWeight_FORMATED'].replace(/\s/g, '&nbsp;');
628
629		if (BX('allSum_wVAT_FORMATED'))
630			BX('allSum_wVAT_FORMATED').innerHTML = res['BASKET_DATA']['allSum_wVAT_FORMATED'].replace(/\s/g, '&nbsp;');
631
632		if (BX('allVATSum_FORMATED'))
633			BX('allVATSum_FORMATED').innerHTML = res['BASKET_DATA']['allVATSum_FORMATED'].replace(/\s/g, '&nbsp;');
634
635		if (BX('allSum_FORMATED'))
636			BX('allSum_FORMATED').innerHTML = res['BASKET_DATA']['allSum_FORMATED'].replace(/\s/g, '&nbsp;');
637
638		if (BX('PRICE_WITHOUT_DISCOUNT'))
639		{
640			var showPriceWithoutDiscount = (res['BASKET_DATA']['PRICE_WITHOUT_DISCOUNT'] != res['BASKET_DATA']['allSum_FORMATED']);
641			BX('PRICE_WITHOUT_DISCOUNT').innerHTML = showPriceWithoutDiscount ? res['BASKET_DATA']['PRICE_WITHOUT_DISCOUNT'].replace(/\s/g, '&nbsp;') : '';
642			BX.style(BX('PRICE_WITHOUT_DISCOUNT').parentNode, 'display', (showPriceWithoutDiscount ? 'table-row' : 'none'));
643		}
644
645		BX.onCustomEvent('OnBasketChange');
646	}
647}
648/**
649 * @param couponBlock
650 * @param {COUPON: string, JS_STATUS: string} oneCoupon - new coupon.
651 */
652function couponCreate(couponBlock, oneCoupon)
653{
654	var couponClass = 'disabled';
655
656	if (!BX.type.isElementNode(couponBlock))
657		return;
658	if (oneCoupon.JS_STATUS === 'BAD')
659		couponClass = 'bad';
660	else if (oneCoupon.JS_STATUS === 'APPLYED')
661		couponClass = 'good';
662
663	couponBlock.appendChild(BX.create(
664		'div',
665		{
666			props: {
667				className: 'bx_ordercart_coupon'
668			},
669			children: [
670				BX.create(
671					'input',
672					{
673						props: {
674							className: couponClass,
675							type: 'text',
676							value: oneCoupon.COUPON,
677							name: 'OLD_COUPON[]'
678						},
679						attrs: {
680							disabled: true,
681							readonly: true
682						}
683					}
684				),
685				BX.create(
686					'span',
687					{
688						props: {
689							className: couponClass
690						},
691						attrs: {
692							'data-coupon': oneCoupon.COUPON
693						}
694					}
695				),
696				BX.create(
697					'div',
698					{
699						props: {
700							className: 'bx_ordercart_coupon_notes'
701						},
702						html: oneCoupon.JS_CHECK_CODE
703					}
704				)
705			]
706		}
707	));
708}
709
710/**
711 * @param {COUPON_LIST : []} res
712 */
713function couponListUpdate(res)
714{
715	var couponBlock,
716		couponClass,
717		fieldCoupon,
718		couponsCollection,
719		couponFound,
720		i,
721		j,
722		key;
723
724	if (!!res && typeof res !== 'object')
725	{
726		return;
727	}
728
729	couponBlock = BX('coupons_block');
730	if (!!couponBlock)
731	{
732		if (!!res.COUPON_LIST && BX.type.isArray(res.COUPON_LIST))
733		{
734			fieldCoupon = BX('coupon');
735			if (!!fieldCoupon)
736			{
737				fieldCoupon.value = '';
738			}
739			couponsCollection = BX.findChildren(couponBlock, { tagName: 'input', property: { name: 'OLD_COUPON[]' } }, true);
740
741			if (!!couponsCollection)
742			{
743				if (BX.type.isElementNode(couponsCollection))
744				{
745					couponsCollection = [couponsCollection];
746				}
747				for (i = 0; i < res.COUPON_LIST.length; i++)
748				{
749					couponFound = false;
750					key = -1;
751					for (j = 0; j < couponsCollection.length; j++)
752					{
753						if (couponsCollection[j].value === res.COUPON_LIST[i].COUPON)
754						{
755							couponFound = true;
756							key = j;
757							couponsCollection[j].couponUpdate = true;
758							break;
759						}
760					}
761					if (couponFound)
762					{
763						couponClass = 'disabled';
764						if (res.COUPON_LIST[i].JS_STATUS === 'BAD')
765							couponClass = 'bad';
766						else if (res.COUPON_LIST[i].JS_STATUS === 'APPLYED')
767							couponClass = 'good';
768
769						BX.adjust(couponsCollection[key], {props: {className: couponClass}});
770						BX.adjust(couponsCollection[key].nextSibling, {props: {className: couponClass}});
771						BX.adjust(couponsCollection[key].nextSibling.nextSibling, {html: res.COUPON_LIST[i].JS_CHECK_CODE});
772					}
773					else
774					{
775						couponCreate(couponBlock, res.COUPON_LIST[i]);
776					}
777				}
778				for (j = 0; j < couponsCollection.length; j++)
779				{
780					if (typeof (couponsCollection[j].couponUpdate) === 'undefined' || !couponsCollection[j].couponUpdate)
781					{
782						BX.remove(couponsCollection[j].parentNode);
783						couponsCollection[j] = null;
784					}
785					else
786					{
787						couponsCollection[j].couponUpdate = null;
788					}
789				}
790			}
791			else
792			{
793				for (i = 0; i < res.COUPON_LIST.length; i++)
794				{
795					couponCreate(couponBlock, res.COUPON_LIST[i]);
796				}
797			}
798		}
799	}
800	couponBlock = null;
801}
802
803function skuPropClickHandler()
804{
805	var target = this,
806		basketItemId,
807		property,
808		property_values = {},
809		postData = {},
810		action_var,
811		all_sku_props,
812		i,
813		sku_prop_value,
814		m;
815
816	if (!!target && target.hasAttribute('data-value-id'))
817	{
818		BX.showWait();
819
820		basketItemId = target.getAttribute('data-element');
821		property = target.getAttribute('data-property');
822		action_var = BX('action_var').value;
823
824		property_values[property] = BX.util.htmlspecialcharsback(target.getAttribute('data-value-id'));
825
826		// if already selected element is clicked
827		if (BX.hasClass(target, 'bx_active'))
828		{
829			BX.closeWait();
830			return;
831		}
832
833		// get other basket item props to get full unique set of props of the new product
834		all_sku_props = BX.findChildren(BX(basketItemId), {tagName: 'ul', className: 'sku_prop_list'}, true);
835		if (!!all_sku_props && all_sku_props.length > 0)
836		{
837			for (i = 0; all_sku_props.length > i; i++)
838			{
839				if (all_sku_props[i].id !== 'prop_' + property + '_' + basketItemId)
840				{
841					sku_prop_value = BX.findChildren(BX(all_sku_props[i].id), {tagName: 'li', className: 'bx_active'}, true);
842					if (!!sku_prop_value && sku_prop_value.length > 0)
843					{
844						for (m = 0; sku_prop_value.length > m; m++)
845						{
846							if (sku_prop_value[m].hasAttribute('data-value-id'))
847							{
848								property_values[sku_prop_value[m].getAttribute('data-property')] = BX.util.htmlspecialcharsback(sku_prop_value[m].getAttribute('data-value-id'));
849							}
850						}
851					}
852				}
853			}
854		}
855
856		postData = {
857			'basketItemId': basketItemId,
858			'sessid': BX.bitrix_sessid(),
859			'site_id': BX.message('SITE_ID'),
860			'props': property_values,
861			'action_var': action_var,
862			'select_props': BX('column_headers').value,
863			'offers_props': BX('offers_props').value,
864			'quantity_float': BX('quantity_float').value,
865			'price_vat_show_value': BX('price_vat_show_value').value,
866			'hide_coupon': BX('hide_coupon').value,
867			'use_prepayment': BX('use_prepayment').value
868		};
869
870		postData[action_var] = 'select_item';
871
872		BX.ajax({
873			url: '/bitrix/components/bitrix/sale.basket.basket/ajax.php',
874			method: 'POST',
875			data: postData,
876			dataType: 'json',
877			onsuccess: function(result)
878			{
879				BX.closeWait();
880				updateBasketTable(basketItemId, result);
881			}
882		});
883	}
884}
885
886function getColumnName(result, columnCode)
887{
888	if (BX('col_' + columnCode))
889	{
890		return BX.util.trim(BX('col_' + columnCode).innerHTML);
891	}
892	else
893	{
894		return '';
895	}
896}
897
898function leftScroll(prop, id, count)
899{
900	count = parseInt(count, 10);
901	var el = BX('prop_' + prop + '_' + id);
902
903	if (el)
904	{
905		var curVal = parseInt(el.style.marginLeft, 10);
906		if (curVal <= -20)
907			el.style.marginLeft = curVal + 20 + '%';
908	}
909}
910
911function rightScroll(prop, id, count)
912{
913	count = parseInt(count, 10);
914
915	var el = BX('prop_' + prop + '_' + id);
916
917	if (el)
918	{
919		var curVal = parseInt(el.style.marginLeft, 10);
920		if (curVal > (5 - count)*20)
921			el.style.marginLeft = curVal - 20 + '%';
922	}
923}
924
925function checkOut()
926{
927	if (!!BX('coupon'))
928		BX('coupon').disabled = true;
929	BX("basket_form").submit();
930	return true;
931}
932
933function updateBasket()
934{
935	recalcBasketAjax({});
936}
937
938function enterCoupon()
939{
940	var newCoupon = BX('coupon');
941	if (!!newCoupon && !!newCoupon.value)
942		recalcBasketAjax({'coupon' : newCoupon.value});
943}
944
945// check if quantity is valid
946// and update values of both controls (text input field for PC and mobile quantity select) simultaneously
947function updateQuantity(controlId, basketId, ratio, bUseFloatQuantity)
948{
949	var oldVal = BX(controlId).defaultValue,
950		newVal = parseFloat(BX(controlId).value) || 0,
951		bIsCorrectQuantityForRatio = false,
952		autoCalculate = ((BX("auto_calculation") && BX("auto_calculation").value == "Y") || !BX("auto_calculation"));
953
954	if (ratio === 0 || ratio == 1)
955	{
956		bIsCorrectQuantityForRatio = true;
957	}
958	else
959	{
960
961		var newValInt = newVal * 10000,
962			ratioInt = ratio * 10000,
963			reminder = newValInt % ratioInt,
964			newValRound = parseInt(newVal);
965
966		if (reminder === 0)
967		{
968			bIsCorrectQuantityForRatio = true;
969		}
970	}
971
972	var bIsQuantityFloat = false;
973
974	if (parseInt(newVal) != parseFloat(newVal))
975	{
976		bIsQuantityFloat = true;
977	}
978
979	newVal = (bUseFloatQuantity === false && bIsQuantityFloat === false) ? parseInt(newVal) : parseFloat(newVal).toFixed(4);
980	newVal = correctQuantity(newVal);
981
982	if (bIsCorrectQuantityForRatio)
983	{
984		BX(controlId).defaultValue = newVal;
985
986		BX("QUANTITY_INPUT_" + basketId).value = newVal;
987
988		// set hidden real quantity value (will be used in actual calculation)
989		BX("QUANTITY_" + basketId).value = newVal;
990
991		if (autoCalculate)
992		{
993			basketPoolQuantity.changeQuantity(basketId);
994		}
995	}
996	else
997	{
998		newVal = getCorrectRatioQuantity(newVal, ratio, bUseFloatQuantity);
999		newVal = correctQuantity(newVal);
1000
1001		if (newVal != oldVal)
1002		{
1003			BX("QUANTITY_INPUT_" + basketId).value = newVal;
1004			BX("QUANTITY_" + basketId).value = newVal;
1005
1006			if (autoCalculate)
1007			{
1008				basketPoolQuantity.changeQuantity(basketId);
1009			}
1010		}else
1011		{
1012			BX(controlId).value = oldVal;
1013		}
1014	}
1015}
1016
1017// used when quantity is changed by clicking on arrows
1018function setQuantity(basketId, ratio, sign, bUseFloatQuantity)
1019{
1020	var curVal = parseFloat(BX("QUANTITY_INPUT_" + basketId).value),
1021		newVal;
1022
1023	newVal = (sign == 'up') ? curVal + ratio : curVal - ratio;
1024
1025	if (newVal < 0)
1026		newVal = 0;
1027
1028	if (bUseFloatQuantity)
1029	{
1030		newVal = parseFloat(newVal).toFixed(4);
1031	}
1032	newVal = correctQuantity(newVal);
1033
1034	if (ratio > 0 && newVal < ratio)
1035	{
1036		newVal = ratio;
1037	}
1038
1039	if (!bUseFloatQuantity && newVal != newVal.toFixed(4))
1040	{
1041		newVal = parseFloat(newVal).toFixed(4);
1042	}
1043
1044	newVal = getCorrectRatioQuantity(newVal, ratio, bUseFloatQuantity);
1045	newVal = correctQuantity(newVal);
1046
1047	BX("QUANTITY_INPUT_" + basketId).value = newVal;
1048	BX("QUANTITY_INPUT_" + basketId).defaultValue = newVal;
1049
1050	updateQuantity('QUANTITY_INPUT_' + basketId, basketId, ratio, bUseFloatQuantity);
1051}
1052
1053function getCorrectRatioQuantity(quantity, ratio, bUseFloatQuantity)
1054{
1055	var newValInt = quantity * 10000,
1056		ratioInt = ratio * 10000,
1057		reminder = (quantity / ratio - ((quantity / ratio).toFixed(0))).toFixed(6),
1058		result = quantity,
1059		bIsQuantityFloat = false,
1060		i;
1061	ratio = parseFloat(ratio);
1062
1063	if (reminder == 0)
1064	{
1065		return result;
1066	}
1067
1068	if (ratio !== 0 && ratio != 1)
1069	{
1070		for (i = ratio, max = parseFloat(quantity) + parseFloat(ratio); i <= max; i = parseFloat(parseFloat(i) + parseFloat(ratio)).toFixed(4))
1071		{
1072			result = i;
1073		}
1074
1075	}else if (ratio === 1)
1076	{
1077		result = quantity | 0;
1078	}
1079
1080	if (parseInt(result, 10) != parseFloat(result))
1081	{
1082		bIsQuantityFloat = true;
1083	}
1084
1085	result = (bUseFloatQuantity === false && bIsQuantityFloat === false) ? parseInt(result, 10) : parseFloat(result).toFixed(4);
1086	result = correctQuantity(result);
1087	return result;
1088}
1089
1090function correctQuantity(quantity)
1091{
1092	return parseFloat((quantity * 1).toString());
1093}
1094
1095
1096/**
1097 *
1098 * @param {} params
1099 */
1100function recalcBasketAjax(params)
1101{
1102	if (basketPoolQuantity.isProcessing())
1103	{
1104		return false;
1105	}
1106
1107	BX.showWait();
1108
1109	var property_values = {},
1110		action_var = BX('action_var').value,
1111		items = BX('basket_items'),
1112		delayedItems = BX('delayed_items'),
1113		postData,
1114		i;
1115
1116	postData = {
1117		'sessid': BX.bitrix_sessid(),
1118		'site_id': BX.message('SITE_ID'),
1119		'props': property_values,
1120		'action_var': action_var,
1121		'select_props': BX('column_headers').value,
1122		'offers_props': BX('offers_props').value,
1123		'quantity_float': BX('quantity_float').value,
1124		'price_vat_show_value': BX('price_vat_show_value').value,
1125		'hide_coupon': BX('hide_coupon').value,
1126		'use_prepayment': BX('use_prepayment').value
1127	};
1128	postData[action_var] = 'recalculate';
1129	if (!!params && typeof params === 'object')
1130	{
1131		for (i in params)
1132		{
1133			if (params.hasOwnProperty(i))
1134				postData[i] = params[i];
1135		}
1136	}
1137
1138	if (!!items && items.rows.length > 0)
1139	{
1140		for (i = 1; items.rows.length > i; i++)
1141			postData['QUANTITY_' + items.rows[i].id] = BX('QUANTITY_' + items.rows[i].id).value;
1142	}
1143
1144	if (!!delayedItems && delayedItems.rows.length > 0)
1145	{
1146		for (i = 1; delayedItems.rows.length > i; i++)
1147			postData['DELAY_' + delayedItems.rows[i].id] = 'Y';
1148	}
1149
1150	basketPoolQuantity.setProcessing(true);
1151	basketPoolQuantity.clearPool();
1152
1153	BX.ajax({
1154		url: '/bitrix/components/bitrix/sale.basket.basket/ajax.php',
1155		method: 'POST',
1156		data: postData,
1157		dataType: 'json',
1158		onsuccess: function(result)
1159		{
1160			BX.closeWait();
1161			basketPoolQuantity.setProcessing(false);
1162
1163			if(params.coupon)
1164			{
1165				//hello, gifts!
1166				if(!!result && !!result.BASKET_DATA && !!result.BASKET_DATA.NEED_TO_RELOAD_FOR_GETTING_GIFT
1166S)
1167				{
1168					BX.reload();
1169				}
1170			}
1171
1172			if (basketPoolQuantity.isPoolEmpty())
1173			{
1174				updateBasketTable(null, result);
1175				basketPoolQuantity.updateQuantity();
1176			}
1177			else
1178			{
1179				basketPoolQuantity.enableTimer(true);
1180			}
1181		}
1182	});
1183}
1184
1185function showBasketItemsList(val)
1186{
1187	BX.removeClass(BX("basket_toolbar_button"), "current");
1188	BX.removeClass(BX("basket_toolbar_button_delayed"), "current");
1189	BX.removeClass(BX("basket_toolbar_button_subscribed"), "current");
1190	BX.removeClass(BX("basket_toolbar_button_not_available"), "current");
1191
1192	BX("normal_count").style.display = 'inline-block';
1193	BX("delay_count").style.display = 'inline-block';
1194	BX("subscribe_count").style.display = 'inline-block';
1195	BX("not_available_count").style.display = 'inline-block';
1196
1197	if (val == 2)
1198	{
1199		if (BX("basket_items_list"))
1200			BX("basket_items_list").style.display = 'none';
1201		if (BX("basket_items_delayed"))
1202		{
1203			BX("basket_items_delayed").style.display = 'block';
1204			BX.addClass(BX("basket_toolbar_button_delayed"), "current");
1205			BX("delay_count").style.display = 'none';
1206		}
1207		if (BX("basket_items_subscribed"))
1208			BX("basket_items_subscribed").style.display = 'none';
1209		if (BX("basket_items_not_available"))
1210			BX("basket_items_not_available").style.display = 'none';
1211	}
1212	else if(val == 3)
1213	{
1214		if (BX("basket_items_list"))
1215			BX("basket_items_list").style.display = 'none';
1216		if (BX("basket_items_delayed"))
1217			BX("basket_items_delayed").style.display = 'none';
1218		if (BX("basket_items_subscribed"))
1219		{
1220			BX("basket_items_subscribed").style.display = 'block';
1221			BX.addClass(BX("basket_toolbar_button_subscribed"), "current");
1222			BX("subscribe_count").style.display = 'none';
1223		}
1224		if (BX("basket_items_not_available"))
1225			BX("basket_items_not_available").style.display = 'none';
1226	}
1227	else if (val == 4)
1228	{
1229		if (BX("basket_items_list"))
1230			BX("basket_items_list").style.display = 'none';
1231		if (BX("basket_items_delayed"))
1232			BX("basket_items_delayed").style.display = 'none';
1233		if (BX("basket_items_subscribed"))
1234			BX("basket_items_subscribed").style.display = 'none';
1235		if (BX("basket_items_not_available"))
1236		{
1237			BX("basket_items_not_available").style.display = 'block';
1238			BX.addClass(BX("basket_toolbar_button_not_available"), "current");
1239			BX("not_available_count").style.display = 'none';
1240		}
1241	}
1242	else
1243	{
1244		if (BX("basket_items_list"))
1245		{
1246			BX("basket_items_list").style.display = 'block';
1247			BX.addClass(BX("basket_toolbar_button"), "current");
1248			BX("normal_count").style.display = 'none';
1249		}
1250		if (BX("basket_items_delayed"))
1251			BX("basket_items_delayed").style.display = 'none';
1252		if (BX("basket_items_subscribed"))
1253			BX("basket_items_subscribed").style.display = 'none';
1254		if (BX("basket_items_not_available"))
1255			BX("basket_items_not_available").style.display = 'none';
1256	}
1257}
1258
1259function deleteCoupon()
1260{
1261	var target = this,
1262		value;
1263
1264	if (BX.type.isElementNode(target) && target.hasAttribute('data-coupon'))
1265	{
1266		value = target.getAttribute('data-coupon');
1267		if (BX.type.isNotEmptyString(value))
1268		{
1269			recalcBasketAjax({'delete_coupon' : value});
1270		}
1271	}
1272}
1273
1274function deleteProductRow(target)
1275{
1276	var targetRow = BX.findParent(target, {tagName: 'TR'}),
1277		quantityNode,
1278		delItem;
1279
1280	if (targetRow)
1281	{
1282		quantityNode = BX('QUANTITY_' + targetRow.id);
1283		if (quantityNode)
1284		{
1285			delItem = getCurrentItemAnalyticsInfo(targetRow, quantityNode.value);
1286		}
1287	}
1288
1289	setAnalyticsDataLayer([], [delItem]);
1290
1291	document.location.href = target.href;
1292
1293	return false;
1294}
1295
1296function checkAnalytics(currentQuantity, newItems)
1297{
1298	if (!currentQuantity || !newItems || BX.util.array_values(currentQuantity).length === 0)
1299		return;
1300
1301	var itemId, diff,
1302		current = {}, addItems = [], delItems = [],
1303		i;
1304
1305	if (!!newItems && newItems.rows.length)
1306	{
1307		for (i = 1; newItems.rows.length > i; i++)
1308		{
1309			itemId = newItems.rows[i].id;
1310			diff = BX('QUANTITY_' + itemId).value - currentQuantity[itemId];
1311
1312			if (diff != 0)
1313			{
1314				current = getCurrentItemAnalyticsInfo(newItems.rows[i], diff);
1315
1316				if (diff > 0)
1317				{
1318					addItems.push(current);
1319				}
1320				else
1321				{
1322					delItems.push(current);
1323				}
1324			}
1325		}
1326	}
1327
1328	if (addItems.length || delItems.length)
1329	{
1330		setAnalyticsDataLayer(addItems, delItems);
1331	}
1332}
1333
1334function getCurrentItemAnalyticsInfo(row, diff)
1335{
1336	if (!row)
1337		return;
1338
1339	var temp, k, variants = [];
1340
1341	var current = {
1342		'name': row.getAttribute('data-item-name') || '',
1343		'id': row.id,
1344		'price': row.getAttribute('data-item-price') || 0,
1345		'brand': (row.getAttribute('data-item-brand') || '').split(',  ').join('/'),
1346		'variant': '',
1347		'quantity': Math.abs(diff)
1348	};
1349
1350	temp = row.querySelectorAll('.bx_active[data-sku-name]');
1351	for (k = 0; k < temp.length; k++)
1352	{
1353		variants.push(temp[k].getAttribute('data-sku-name'));
1354	}
1355
1356	current.variant = variants.join('/');
1357
1358	return current;
1359}
1360
1361function setAnalyticsDataLayer(addItems, delItems)
1362{
1363	window[basketJSParams['DATA_LAYER_NAME']] = window[basketJSParams['DATA_LAYER_NAME']] || [];
1364
1365	if (addItems && addItems.length)
1366	{
1367		window[basketJSParams['DATA_LAYER_NAME']].push({
1368			'event': 'addToCart',
1369			'ecommerce': {
1370				'currencyCode': getCurrencyCode(),
1371				'add': {
1372					'products': addItems
1373				}
1374			}
1375		});
1376	}
1377
1378	if (delItems && delItems.length)
1379	{
1380		window[basketJSParams['DATA_LAYER_NAME']].push({
1381			'event': 'removeFromCart',
1382			'ecommerce': {
1383				'currencyCode': getCurrencyCode(),
1384				'remove': {
1385					'products': delItems
1386				}
1387			}
1388		});
1389	}
1390}
1391
1392function getCurrencyCode()
1393{
1394	var root = BX('basket_items'),
1395		node,
1396		currency = '';
1397
1398	if (root)
1399	{
1400		node = root.querySelector('[data-item-currency');
1401		node && (currency = node.getAttribute('data-item-currency'));
1402	}
1403
1404	return currency;
1405
1406
1407}
1408
1409BX.ready(function() {
1410
1411	basketPoolQuantity = new BasketPoolQuantity();
1412	var couponBlock = BX('coupons_block'),
1413		basketItems = BX('basket_items');
1414
1415	if (BX.type.isElementNode(couponBlock))
1416		BX.bindDelegate(couponBlock, 'click', { 'attribute': 'data-coupon' }, deleteCoupon);
1417
1418	if (BX.type.isElementNode(basketItems))
1419		BX.bindDelegate(basketItems, 'click', {tagName: 'li', 'attr': { 'data-sku-selector': 'Y' }}, skuPropClickHandler);
1420
1421	/*if (BX.type.isNotEmptyString(basketJSParams['EVENT_ONCHANGE_ON_START']) && basketJSParams['EVENT_ONCHANGE_ON_START'] == "Y")
1422		BX.onCustomEvent('OnBasketChange');*/
1423});

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.