PageSourceSearch

https://artdugout.ru/local/templates/artdugout/components/bitrix/s…/artdugout/js/component.js?172062948564253

js artdugout.ru collected 2026-10-07 18:54:12 UTC 64,253 bytes, 2,491 lines download raw bytes

1;(function() {
2	'use strict';
3
4	BX.namespace('BX.Sale.BasketComponent');
5
6	BX.Sale.BasketComponent = {
7		maxItemsShowCount: 30,
8		precisionFactor: Math.pow(10, 6),
9		stickyHeaderOffset: 0,
10
11		duration: {
12			priceAnimation: 300,
13			filterTimer: 300
14		},
15
16		ids: {
17			item: 'basket-item-',
18			quantity: 'basket-item-quantity-',
19			price: 'basket-item-price-',
20			sumPrice: 'basket-item-sum-price-',
21			sumPriceOld: 'basket-item-sum-price-old-',
22			sumPriceDiff: 'basket-item-sum-price-difference-',
23			itemHeightAligner: 'basket-item-height-aligner-',
24			total: 'basket-total-price',
25			basketRoot: 'basket-root',
26			itemListWrapper: 'basket-items-list-wrapper',
27			itemListContainer: 'basket-items-list-container',
28			itemList: 'basket-item-list',
29			itemListTable: 'basket-item-table',
30			itemListEmptyResult: 'basket-item-list-empty-result',
31			itemListOverlay: 'basket-items-list-overlay',
32			warning: 'basket-warning'
33		},
34
35		initializePrimaryFields: function()
36		{
37			this.templates = {};
38			this.nodes = {};
39
40			/** Object of all basket items (itemId => itemArray) */
41			this.items = {};
42
43			/** Array of all basket items to show sorted by field SORT */
44			this.sortedItems = [];
45
46			/** Array of basket items showed on screen */
47			this.shownItems = [];
48
49			/** Array of basket items changed since last request */
50			this.changedItems = [];
51
52			/** Array of basket items postponed by pool to edit */
53			this.postponedItems = [];
54
55			/** Array of basket items with warnings */
56			this.warningItems = [];
57
58			this.isMobile = BX.browser.IsMobile();
59			this.isTouch = BX.hasClass(document.documentElement, 'bx-touch');
60
61			this.lastAction = 'initialLoad';
62			this.coupons = null;
63
64			this.imagePopup = null;
65			this.loadingScreen = null;
66
67			this.quantityDelay = null;
68			this.quantityTimer = null;
69		},
70
71		init: function(parameters)
72		{
73			this.initializePrimaryFields();
74
75			this.params = parameters.params || {};
76			this.template = parameters.template || '';
77			this.signedParamsString = parameters.signedParamsString || '';
78			this.siteId = parameters.siteId || '';
79			this.siteTemplateId = parameters.siteTemplateId || '';
80			this.ajaxUrl = this.params.AJAX_PATH || '';
81			this.templateFolder = parameters.templateFolder || '';
82
83			this.useDynamicScroll = this.params.USE_DYNAMIC_SCROLL === 'Y';
84			this.useItemsFilter = this.params.SHOW_FILTER === 'Y' && !this.isMobile;
85
86			this.initializeFilter();
87			this.applyBasketResult(parameters.result);
88			this.initializeActionPool();
89
90			if (this.useItemsFilter)
91			{
92				this.checkHeaderDisplay();
93				this.bindHeaderEvents();
94			}
95
96			this.initializeBasketItems();
97			this.editTotal();
98			this.editWarnings();
99
100			this.adjustBasketWrapperHeight();
101			this.getCacheNode(this.ids.basketRoot).style.opacity = 1;
102
103			this.bindInitialEvents();
104		},
105
106		getTemplate: function(templateName)
107		{
108			if (!this.templates.hasOwnProperty(templateName))
109			{
110				var template = BX(templateName);
111				this.templates[templateName] = BX.type.isDomNode(template) ? template.innerHTML : '';
112			}
113
114			return this.templates[templateName];
115		},
116
117		getCacheNode: function(id)
118		{
119			if (!this.nodes.hasOwnProperty(id))
120			{
121				this.nodes[id] = BX(id);
122			}
123
124			return this.nodes[id];
125		},
126
127		getEntity: function(parent, entity, additionalFilter)
128		{
129			if (!parent || !entity)
130				return null;
131
132			additionalFilter = additionalFilter || '';
133
134			return parent.querySelector(additionalFilter + '[data-entity="' + entity + '"]');
135		},
136
137		getEntities: function(parent, entity, additionalFilter)
138		{
139			if (!parent || !entity)
140				return {length: 0};
141
142			additionalFilter = additionalFilter || '';
143
144			return parent.querySelectorAll(additionalFilter + '[data-entity="' + entity + '"]');
145		},
146
147		bindInitialEvents: function()
148		{
149			this.bindWarningEvents();
150
151			BX.bind(window, 'scroll', BX.proxy(this.checkStickyHeaders, this));
152			BX.bind(window, 'scroll', BX.proxy(this.lazyLoad, this));
153
154			BX.bind(window, 'resize', BX.throttle(this.checkStickyHeaders, 20, this));
155			BX.bind(window, 'resize', BX.throttle(this.adjustBasketWrapperHeight, 20, this));
156		},
157
158		bindWarningEvents: function()
159		{
160			var showItemsNode = this.getEntity(BX(this.ids.warning), 'basket-items-warning-count');
161
162			if (BX.type.isDomNode(showItemsNode))
163			{
164				showItemsNode.style.display = '';
165				BX.bind(showItemsNode, 'click', BX.delegate(function() {this.toggleFilter('warning');}, this));
166			}
167
168			BX.bind(
169				this.getEntity(BX(this.ids.warning), 'basket-items-warning-notification-close'),
170				'click',
171				BX.proxy(this.removeAllWarnings, this)
172			);
173		},
174
175		toggleFilter: function(event)
176		{
177			var target = BX.type.isNotEmptyString(event) ?
178				this.getEntity(
179					this.getCacheNode(this.ids.itemListWrapper),
180					'basket-items-count',
181					'[data-filter="' + event + '"]'
182				)
183				: BX.getEventTarget(event);
184
185			if (!BX.type.isDomNode(target) || BX.hasClass(target, 'active'))
186				return;
187
188			var entityName = target.getAttribute('data-filter');
189			var entities = target.parentNode.querySelectorAll('[data-filter]');
190
191			for (var i = 0; i < entities.length; i++)
192			{
193				if (entities[i].getAttribute('data-filter') === entityName)
194				{
195					BX.addClass(entities[i], 'active');
196				}
197				else if (BX.hasClass(entities[i], 'active'))
198				{
199					BX.removeClass(entities[i], 'active');
200				}
201			}
202
203			this.filter.showFilterByName(entityName);
204		},
205
206		scrollToFirstItem: function()
207		{
208			var headerNode = this.getEntity(this.getCacheNode(this.ids.itemListWrapper), 'basket-items-list-header');
209
210			if (BX.type.isDomNode(headerNode))
211			{
212				var itemListTopPosition = BX.pos(this.getCacheNode(this.ids.itemListContainer)).top;
213				var headerBottomPosition = BX.pos(headerNode).bottom;
214
215				if (itemListTopPosition < headerBottomPosition)
216				{
217					window.scrollTo(0, itemListTopPosition - this.stickyHeaderOffset);
218				}
219			}
220		},
221
222		showItemsOverlay: function()
223		{
224			var overlay = this.getCacheNode(this.ids.itemListOverlay);
225
226			if (BX.type.isDomNode(overlay))
227			{
228				overlay.style.display = '';
229			}
230		},
231
232		hideItemsOverlay: function()
233		{
234			var overlay = this.getCacheNode(this.ids.itemListOverlay);
235
236			if (BX.type.isDomNode(overlay))
237			{
238				overlay.style.display = 'none';
239			}
240		},
241
242		checkHeaderDisplay: function()
243		{
244			var header = this.getCacheNode(this.ids.itemListWrapper);
245
246			if (BX.type.isDomNode(header))
247			{
248				BX.removeClass(header, 'basket-items-list-wrapper-light');
249			}
250		},
251
252		bindHeaderEvents: function()
253		{
254			var entities = this.getEntities(this.getCacheNode(this.ids.itemListWrapper), 'basket-items-count');
255
256			for (var i = 0; i < entities.length; i++)
257			{
258				BX.bind(entities[i], 'click', BX.proxy(this.toggleFilter, this));
259			}
260		},
261
262		checkStickyHeaders: function()
263		{
264			if (this.isMobile)
265				return;
266
267			var node, position;
268			var border = 2, offset = 0;
269			var scrollTop = this.getDocumentScrollTop();
270			var basketPosition = BX.pos(this.getCacheNode(this.ids.basketRoot));
271			var basketScrolledToEnd = scrollTop + 200 >= basketPosition.bottom;
272
273			if (BX.util.in_array('top', this.params.TOTAL_BLOCK_DISPLAY))
274			{
275				var totalBlockNode = this.getEntity(this.getCacheNode(this.ids.basketRoot), 'basket-total-block');
276				if (BX.type.isDomNode(totalBlockNode))
277				{
278					node = this.getEntity(totalBlockNode, 'basket-checkout-aligner');
279					if (BX.type.isDomNode(node))
280					{
281						position = BX.pos(totalBlockNode);
282
283						if (scrollTop >= position.top)
284						{
285							offset += node.clientHeight;
286
287							if (!BX.hasClass(node, 'basket-checkout-container-fixed'))
288							{
289								totalBlockNode.style.height = position.height + 'px';
290
291								node.style.width = node.clientWidth + border + 'px';
292								BX.addClass(node, 'basket-checkout-container-fixed');
293							}
294						}
295						else if (BX.hasClass(node, 'basket-checkout-container-fixed'))
296						{
297							totalBlockNode.style.height = '';
298
299							node.style.width = '';
300							BX.removeClass(node, 'basket-checkout-container-fixed');
301						}
302
303						if (basketScrolledToEnd)
304						{
305							if (!BX.hasClass(node, 'basket-checkout-container-fixed-hide'))
306							{
307								BX.addClass(node, 'basket-checkout-container-fixed-hide');
308							}
309						}
310						else if (BX.hasClass(node, 'basket-checkout-container-fixed-hide'))
311						{
312							BX.removeClass(node, 'basket-checkout-container-fixed-hide');
313						}
314					}
315				}
316			}
317
318			if (this.useItemsFilter)
319			{
320				var itemWrapperNode = this.getCacheNode(this.ids.itemListWrapper);
321
322				node = this.getEntity(itemWrapperNode, 'basket-items-list-header');
323				if (BX.type.isDomNode(node))
324				{
325					position = BX.pos(itemWrapperNode);
326
327					if ((scrollTop + offset >= position.top) && !basketScrolledToEnd)
328					{
329						if (!BX.hasClass(node, 'basket-items-list-header-fixed'))
330						{
331							node.style.width = node.clientWidth + border + 'px';
332
333							itemWrapperNode.style.paddingTop = node.clientHeight + 'px';
334
335							BX.addClass(node, 'basket-items-list-header-fixed');
336						}
337
338						if (offset)
339						{
340							node.style.top = offset + 'px';
341						}
342
343						offset += node.clientHeight;
344					}
345					else if (BX.hasClass(node, 'basket-items-list-header-fixed'))
346					{
347						itemWrapperNode.style.paddingTop = '';
348
349						node.style.width = '';
350						node.style.top = '';
351
352						BX.removeClass(node, 'basket-items-list-header-fixed');
353					}
354				}
355			}
356
357			var offsetChanged = this.stickyHeaderOffset === offset;
358
359			this.stickyHeaderOffset = offset;
360
361			if (offsetChanged && !basketScrolledToEnd)
362			{
363				this.adjustBasketWrapperHeight();
364			}
365		},
366
367		getDocumentScrollTop: function()
368		{
369			return window.scrollY
370				|| window.pageYOffset
371				|| document.body.scrollTop + (document.documentElement && document.documentElement.scrollTop || 0);
372		},
373
374		lazyLoad: function()
375		{
376			var itemsNodePosition = BX.pos(this.getCacheNode(this.ids.itemListContainer));
377
378			if (this.getDocumentScrollTop() + window.innerHeight >= itemsNodePosition.bottom - 400)
379			{
380				var itemIds = this.getItemsAfter();
381				if (itemIds.length)
382				{
383					this.editBasketItems(itemIds);
384				}
385			}
386		},
387
388		fireCustomEvents: function()
389		{
390			if (this.result.EVENT_ONCHANGE_ON_START === 'Y')
391			{
392				BX.onCustomEvent('OnBasketChange');
393			}
394
395			if (this.params.HIDE_COUPON !== 'Y')
396			{
397				if (this.coupons !== null && this.coupons !== this.result.COUPON_LIST)
398				{
399					BX.onCustomEvent('OnCouponApply');
400				}
401
402				this.coupons = this.result.COUPON_LIST;
403			}
404		},
405
406		adjustBasketWrapperHeight: function()
407		{
408			var itemListContainer = this.getCacheNode(this.ids.itemListContainer),
409				itemList = this.getCacheNode(this.ids.itemList);
410
411			if (BX.type.isDomNode(itemListContainer) && BX.type.isDomNode(itemList))
412			{
413				if (itemListContainer.clientHeight + this.stickyHeaderOffset > window.innerHeight)
414				{
415					itemListContainer.style.minHeight = 'calc(100vh - 15px - ' + this.stickyHeaderOffset + 'px)';
416					itemList.style.minHeight = 'calc(100vh - 15px - ' + this.stickyHeaderOffset + 'px)';
417				}
418				else
419				{
420					itemListContainer.style.minHeight = itemListContainer.clientHeight + 'px';
421					itemList.style.minHeight = itemListContainer.clientHeight + 'px';
422				}
423			}
424		},
425
426		editTotal: function()
427		{
428			this.fillTotalBlocks();
429			this.showItemsCount();
430			this.showWarningItemsCount();
431			this.showNotAvailableItemsCount();
432			this.showDelayedItemsCount();
433		},
434
435		fillTotalBlocks: function()
436		{
437			var totalNodes = this.getEntities(this.getCacheNode(this.ids.basketRoot), 'basket-total-block');
438
439			if (totalNodes && totalNodes.length)
440			{
441				var totalTemplate = this.getTemplate('basket-total-template');
442				if (totalTemplate)
443				{
444					var totalRender = this.render(totalTemplate, this.result.TOTAL_RENDER_DATA);
445
446					for (var i in totalNodes)
447					{
448						if (totalNodes.hasOwnProperty(i) && BX.type.isDomNode(totalNodes[i])
448)
449						{
450							totalNodes[i].innerHTML = totalRender;
451
452							this.bindTotalEvents(totalNodes[i]);
453						}
454					}
455				}
456			}
457
458			this.checkStickyHeaders();
459		},
460
461		showItemsCount: function()
462		{
463			var itemCountNode = this.getEntity(
464				this.getCacheNode(this.ids.itemListWrapper),
465				'basket-items-count',
466				'[data-filter="all"]'
467			);
468
469			if (BX.type.isDomNode(itemCountNode))
470			{
471				itemCountNode.innerHTML = BX.message('SBB_IN_BASKET') + ' ' + this.result.BASKET_ITEMS_COUNT + ' ' + this.getGoodsMessage(this.result.BASKET_ITEMS_COUNT);
472				itemCountNode.style.display = '';
473			}
474		},
475
476		showSimilarCount: function(state)
477		{
478			var itemCountNode = this.getEntity(
479				this.getCacheNode(this.ids.itemListWrapper),
480				'basket-items-count',
481				'[data-filter="similar"]'
482			);
483
484			if (BX.type.isDomNode(itemCountNode))
485			{
486				if (state)
487				{
488					itemCountNode.innerHTML = this.sortedItems.length + ' '
489						+ this.getGoodsMessage(this.result.BASKET_ITEMS_COUNT, 'SBB_SIMILAR_ITEM');
490					itemCountNode.style.display = '';
491				}
492				else
493				{
494					itemCountNode.style.display = 'none';
495				}
496			}
497		},
498
499		showWarningItemsCount: function()
500		{
501			var itemCountNode = this.getEntity(
502				this.getCacheNode(this.ids.itemListWrapper),
503				'basket-items-count',
504				'[data-filter="warning"]'
505			);
506
507			if (BX.type.isDomNode(itemCountNode))
508			{
509				if (this.warningItems.length)
510				{
511					itemCountNode.innerHTML = this.warningItems.length + ' ' + BX.message('SBB_BASKET_ITEMS_WARNING');
512					itemCountNode.style.display = '';
513				}
514				else
515				{
516					itemCountNode.style.display = 'none';
517				}
518			}
519		},
520
521		showNotAvailableItemsCount: function()
522		{
523			var itemCountNode = this.getEntity(
524				this.getCacheNode(this.ids.itemListWrapper),
525				'basket-items-count',
526				'[data-filter="not-available"]'
527			);
528
529			if (BX.type.isDomNode(itemCountNode))
530			{
531				if (parseInt(this.result.NOT_AVAILABLE_BASKET_ITEMS_COUNT))
532				{
533					itemCountNode.innerHTML = this.result.NOT_AVAILABLE_BASKET_ITEMS_COUNT + ' '
534						+ this.getGoodsMessage(this.result.NOT_AVAILABLE_BASKET_ITEMS_COUNT, 'SBB_NOT_AVAILABLE_ITEM');
535					itemCountNode.style.display = '';
536				}
537				else
538				{
539					itemCountNode.style.display = 'none';
540				}
541			}
542		},
543
544		showDelayedItemsCount: function()
545		{
546			var itemCountNode = this.getEntity(
547				this.getCacheNode(this.ids.itemListWrapper),
548				'basket-items-count',
549				'[data-filter="delayed"]'
550			);
551
552			if (BX.type.isDomNode(itemCountNode))
553			{
554				if (parseInt(this.result.DELAYED_BASKET_ITEMS_COUNT))
555				{
556					itemCountNode.innerHTML = this.result.DELAYED_BASKET_ITEMS_COUNT + ' '
557						+ this.getGoodsMessage(this.result.DELAYED_BASKET_ITEMS_COUNT, 'SBB_DELAYED_ITEM');
558					itemCountNode.style.display = '';
559				}
560				else
561				{
562					itemCountNode.style.display = 'none';
563				}
564			}
565		},
566
567		getGoodsMessage: function(count, customMessage)
568		{
569			var mesCode;
570			var countReminder = (count > 10 && count < 20) ? 0 : count % 10;
571
572			if (countReminder === 1)
573			{
574				mesCode = customMessage || 'SBB_GOOD';
575			}
576			else if (countReminder >= 2 && countReminder <= 4)
577			{
578				mesCode = customMessage ? customMessage + '_2' : 'SBB_GOOD_2';
579			}
580			else
581			{
582				mesCode = customMessage ? customMessage + 'S' : 'SBB_GOODS';
583			}
584
585			return BX.message(mesCode);
586		},
587
588		bindTotalEvents: function(node)
589		{
590			if (!this.result.TOTAL_RENDER_DATA.DISABLE_CHECKOUT)
591			{
592				BX.bind(this.getEntity(node, 'basket-checkout-button'), 'click', BX.proxy(this.checkOutAction, this));
593			}
594
595			// BX.bind(this.getEntity(node, 'basket-coupon-input'), 'change', BX.proxy(this.addCouponAction, this));
596			// BX.bind(this.getEntity(node, 'basket-coupon-input'), 'paste', BX.proxy(this.pasteCouponAction, this));
597			BX.bind(this.getEntity(node, 'basket-coupon-button'), 'click', BX.proxy(this.btnCouponAction, this));
598
599			var couponNodes = this.getEntities(node, 'basket-coupon-delete');
600			for (var i = 0, l = couponNodes.length; i < l; i++)
601			{
602				BX.bind(couponNodes[i], 'click', BX.proxy(this.removeCouponAction, this));
603			}
604
605		},
606
607		checkOutAction: function()
608		{
609			// custom -->
610			var path_to_order = this.params.PATH_TO_ORDER;
611			$('.jsOverlayBasketTotal').addClass('is-active');
612			$('.jsOverlayBasketTotal').find('.catalog').addClass('is-loading');
613			ym(86417006,'reachGoal', 'checkout-1');
614			ym(86417006,'reachGoal', 'goal');
615			setTimeout(function() {
616				document.location.href = path_to_order;
617			}, 500);
618			// <-- custom
619
620			// document.location.href = this.params.PATH_TO_ORDER;
621		},
622
623		btnCouponAction: function(event)
624		{
625			var target = $('.cart-info__promo .input__field[data-entity="basket-coupon-input"]')[0];
626			if (target && target.value)
627			{
628				this.actionPool.addCoupon(target.value);
629				target.disabled = true;
630			}
631		},
632
633		addCouponAction: function(event)
634		{
635			var target = BX.getEventTarget(event);
636			if (target && target.value)
637			{
638				this.actionPool.addCoupon(target.value);
639				target.disabled = true;
640			}
641		},
642
643		pasteCouponAction: function(event)
644		{
645			setTimeout(BX.delegate(function() {
646				this.addCouponAction(event);
647			}, this), 10);
648		},
649
650		removeCouponAction: function()
651		{
652			var value = BX.proxy_context && BX.util.trim(BX.proxy_context.getAttribute('data-coupon'));
653			if (value)
654			{
655				this.actionPool.removeCoupon(value);
656        $.cookie('BITRIX_SM_retarget_promo', 'none')
657			}
658		},
659
660		removeCustomCouponAction: function(node)
661		{
662			var value = node && BX.util.trim(node.getAttribute('data-coupon'));
663			if (value) {
664        this.actionPool.removeCoupon(value);
665			}
666		},
667
668		initializeActionPool: function()
669		{
670			this.actionPool = new BX.Sale.BasketActionPool(this);
671		},
672
673		initializeFilter: function()
674		{
675			this.filter = new BX.Sale.BasketFilter(this);
676		},
677
678		/**
679		 * Send ajax request with basket data and executes callback by action
680		 */
681		sendRequest: function(action, data)
682		{
683			this.lastAction = action;
684
685			if (this.lastAction === 'recalculateAjax')
686			{
687				// we use it to reload all items if applied discounts changed
688				data.lastAppliedDiscounts = BX.util.array_keys(this.result.FULL_DISCOUNT_LIST).join(',');
689
690				if (this.params.USE_ENHANCED_ECOMMERCE === 'Y')
691				{
692					this.checkAnalytics(data);
693				}
694			}
695
696			BX.ajax({
697				method: 'POST',
698				dataType: 'json',
699				url: this.ajaxUrl,
700				data: this.getData(data),
701				onsuccess: BX.delegate(function(result) {
702					this.actionPool.doProcessing(false);
703
704					if (!BX.type.isPlainObject(result))
705						return;
706
707					this.actionPool.setRefreshStatus(result.BASKET_REFRESHED);
708
709					if (result.RESTORED_BASKET_ITEMS)
710					{
711						this.restoreBasketItems(result.RESTORED_BASKET_ITEMS);
712					}
713
714					if (result.DELETED_BASKET_ITEMS)
715					{
716						this.deleteBasketItems(result.DELETED_BASKET_ITEMS, this.params.SHOW_RESTORE === 'Y');
717					}
718
719					if (result.MERGED_BASKET_ITEMS)
720					{
721						this.deleteBasketItems(result.MERGED_BASKET_ITEMS, false, true);
722					}
723
724					this.applyBasketResult(result.BASKET_DATA);
725					this.editBasketItems(this.getItemsToEdit());
726					this.editTotal();
727
728					this.adjustBasketWrapperHeight();
729					this.applyPriceAnimation();
730					this.editWarnings();
731
732					this.actionPool.switchTimer();
733
734					if (this.isBasketIntegrated() && this.isBasketChanged())
735					{
736						BX.Sale.OrderAjaxComponent.sendRequest();
737					}
738				}, this),
739				onfailure: BX.delegate(function() {
740					this.actionPool.doProcessing(false);
741				}, this)
742			});
743		},
744
745		isBasketIntegrated: function()
746		{
747			return this.params.BASKET_WITH_ORDER_INTEGRATION === 'Y';
748		},
749
750		isBasketChanged: function()
751		{
752			return this.changedItems.length;
753		},
754
755		addPriceAnimationData: function(nodeId, start, finish, currency)
756		{
757			if (!BX.type.isPlainObject(this.priceAnimationData))
758			{
759				this.clearPriceAnimationData();
760			}
761
762			this.priceAnimationData.start[nodeId] = parseFloat(start);
763			this.priceAnimationData.finish[nodeId] = parseFloat(finish);
764			this.priceAnimationData.currency[nodeId] = currency;
765			this.priceAnimationData.int[nodeId] = (parseFloat(start) === parseInt(start)) && (parseFloat(finish) === parseInt(finish));
766		},
767
768		clearPriceAnimationData: function()
769		{
770			this.priceAnimationData = {
771				start: {},
772				finish: {},
773				currency: {},
774				int: {}
775			};
776		},
777
778		applyBasketResult: function(result)
779		{
780			this.changedItems = [];
781			this.clearPriceAnimationData();
782
783			if (!BX.type.isPlainObject(result))
784			{
785				return;
786			}
787
788			if (result.BASKET_ITEM_RENDER_DATA)
789			{
790				var i, newData;
791
792				for (i in result.BASKET_ITEM_RENDER_DATA)
793				{
794					if (result.BASKET_ITEM_RENDER_DATA.hasOwnProperty(i))
795					{
796						newData = result.BASKET_ITEM_RENDER_DATA[i];
797						newData.WARNINGS = this.checkBasketItemWarnings(newData, result.WARNING_MESSAGE_WITH_CODE);
798
799						if (this.items[newData.ID])
800						{
801							if (JSON.stringify(this.items[newData.ID]) === JSON.stringify(newData))
802							{
803								continue;
804							}
805						}
806						else
807						{
808							this.addSortedItem(newData.ID, true);
809						}
810
811						this.changedItems.push(newData.ID);
812
813						newData = this.checkBasketItemsAnimation(newData);
814						this.items[newData.ID] = newData;
815					}
816				}
817
818				this.changedItems = BX.util.array_unique(this.changedItems.concat(this.getChangedSimilarOffers()));
819
820				if (this.isBasketChanged())
821				{
822					this.sortSortedItems(true);
823				}
824			}
825
826			if (result.TOTAL_RENDER_DATA)
827			{
828				result.TOTAL_RENDER_DATA = this.checkTotalAnimation(result.TOTAL_RENDER_DATA);
829			}
830
831			this.result = result;
832		},
833
834		itemSortFunction: function(a, b)
835		{
836			if (!this.items.hasOwnProperty(a) || !this.items.hasOwnProperty(b))
837			{
838				return 0;
839			}
840
841			return parseFloat(this.items[a].SORT) - parseFloat(this.items[b].SORT);
842		},
843
844		getChangedSimilarOffers: function()
845		{
846			var changedSimilarOffers = [];
847
848			var otherSimilarItemsQuantity, totalSimilarItemsQuantity;
849			var hashMap = this.getHashMap();
850
851			for (var hash in hashMap)
852			{
853				if (hashMap.hasOwnProperty(hash))
854				{
855					if (hashMap[hash].length > 1)
856					{
857						for (var i = 0; i < hashMap[hash].length; i++)
858						{
859							otherSimilarItemsQuantity = 0;
860							totalSimilarItemsQuantity = 0;
861
862							for (var k = 0; k < hashMap[hash].length; k ++)
863							{
864								if (hashMap[hash][k] != hashMap[hash][i])
865								{
866									otherSimilarItemsQuantity += parseFloat(this.items[hashMap[hash][k]].QUANTITY);
867								}
868
869								totalSimilarItemsQuantity += parseFloat(this.items[hashMap[hash][k]].QUANTITY);
870							}
871
872							if (
873								!this.items[hashMap[hash][i]].HAS_SIMILAR_ITEMS
874								|| this.items[hashMap[hash][i]].SIMILAR_ITEMS_QUANTITY != otherSimilarItemsQuantity
875								|| this.items[hashMap[hash][i]].TOTAL_SIMILAR_ITEMS_QUANTITY != totalSimilarItemsQuantity
876							)
877							{
878								changedSimilarOffers.push(hashMap[hash][i]);
879
880								this.items[hashMap[hash][i]].HAS_SIMILAR_ITEMS = true;
881								this.items[hashMap[hash][i]].SIMILAR_ITEMS_QUANTITY = otherSimilarItemsQuantity;
882								this.items[hashMap[hash][i]].TOTAL_SIMILAR_ITEMS_QUANTITY = totalSimilarItemsQuantity;
883
884								this.items[hashMap[hash][i]].ALL_AVAILABLE_QUANTITY = this.items[hashMap[hash][i]].AVAILABLE_QUANTITY;
885								this.items[hashMap[hash][i]].AVAILABLE_QUANTITY = this.items[hashMap[hash][i]].ALL_AVAILABLE_QUANTITY - otherSimilarItemsQuantity;
886							}
887						}
888					}
889					else if (hashMap[hash][0] && this.items[hashMap[hash][0]].HAS_SIMILAR_ITEMS)
890					{
891						changedSimilarOffers.push(hashMap[hash][0]);
892
893						delete this.items[hashMap[hash][0]].HAS_SIMILAR_ITEMS;
894						delete this.items[hashMap[hash][0]].SIMILAR_ITEMS_QUANTITY;
895						delete this.items[hashMap[hash][0]].TOTAL_SIMILAR_ITEMS_QUANTITY;
896
897						this.items[hashMap[hash][0]].AVAILABLE_QUANTITY = this.items[hashMap[hash][0]].ALL_AVAILABLE_QUANTITY;
898						delete this.items[hashMap[hash][0]].ALL_AVAILABLE_QUANTITY;
899					}
900				}
901			}
902
903			return changedSimilarOffers;
904		},
905
906		getHashMap: function()
907		{
908			var hashMap = {};
909
910			for (var id in this.items)
911			{
912				if (this.items.hasOwnProperty(id) && this.isItemAvailable(id))
913				{
914					if (!hashMap.hasOwnProperty(this.items[id].HASH))
915					{
916						hashMap[this.items[id].HASH] = [];
917					}
918
919					hashMap[this.items[id].HASH].push(id);
920				}
921			}
922
923			return hashMap;
924		},
925
926		isItemAvailable: function(itemId)
927		{
928			var sortedItems = this.filter.isActive() ? this.filter.realSortedItems : this.sortedItems;
929
930			return !this.items[itemId].NOT_AVAILABLE
931				&& !this.items[itemId].SHOW_RESTORE
932				&& BX.util.in_array(itemId, sortedItems);
933		},
934
935		checkTotalAnimation: function(totalData)
936		{
937			if (this.result && this.result.TOTAL_RENDER_DATA && parseFloat(this.result.TOTAL_RENDER_DATA.PRICE) > parseFloat(totalData.PRICE))
938			{
939				totalData.PRICE_NEW = totalData.PRICE;
940				totalData.PRICE = this.result.TOTAL_RENDER_DATA.PRICE;
941
942				totalData.PRICE_FORMATED_NEW = totalData.PRICE_FORMATED;
943				totalData.PRICE_FORMATED = this.result.TOTAL_RENDER_DATA.PRICE_FORMATED;
944
945				this.addPriceAnimationData(this.ids.total, totalData.PRICE, totalData.PRICE_NEW, totalData.CURRENCY);
946			}
947
948			return totalData;
949		},
950
951		checkBasketItemsAnimation: function(itemData)
952		{
953			var itemId = itemData.ID;
954
955			if (this.items[itemId])
956			{
957				var quantityNode = BX(this.ids.quantity + itemId);
958				if (
959					BX.type.isDomNode(quantityNode)
960					&& !this.actionPool.isItemInPool(itemId)
961					&& parseFloat(quantityNode.value) !== parseFloat(itemData.QUANTITY)
962				)
963				{
964					itemData.QUANTITY_ANIMATION = true;
965					this.actionPool.clearLastActualQuantityPool(itemId);
966				}
967
968				if (parseFloat(this.items[itemId].PRICE) > parseFloat(itemData.PRICE))
969				{
970					itemData.PRICE_NEW = itemData.PRICE;
971					itemData.PRICE = this.items[itemId].PRICE;
972
973					itemData.PRICE_FORMATED_NEW = itemData.PRICE_FORMATED;
974					itemData.PRICE_FORMATED = this.items[itemId].PRICE_FORMATED;
975
976					this.addPriceAnimationData(this.ids.price + itemId, itemData.PRICE, itemData.PRICE_NEW, itemData.CURRENCY);
977				}
978
979				if (
980					BX.util.in_array('SUM', this.params.COLUMNS_LIST)
981					&& parseFloat(this.items[itemId].SUM_PRICE) > parseFloat(itemData.SUM_PRICE)
982					&& parseFloat(this.items[itemId].QUANTITY) === parseFloat(itemData.QUANTITY)
983				)
984				{
985					itemData.SUM_PRICE_NEW = itemData.SUM_PRICE;
986					itemData.SUM_PRICE = this.items[itemId].SUM_PRICE;
987
988					itemData.SUM_PRICE_FORMATED_NEW = itemData.SUM_PRICE_FORMATED;
989					itemData.SUM_PRICE_FORMATED = this.items[itemId].SUM_PRICE_FORMATED;
990
991					this.addPriceAnimationData(this.ids.sumPrice + itemId, itemData.SUM_PRICE, itemData.SUM_PRICE_NEW, itemData.CURRENCY);
992				}
993			}
994
995			return itemData;
996		},
997
998		getData: function(data)
999		{
1000			data = data || {};
1001
1002			data[this.params.ACTION_VARIABLE] = this.lastAction;
1003			data.via_ajax = 'Y';
1004			data.site_id = this.siteId;
1005			data.site_template_id = this.siteTemplateId;
1006			data.sessid = BX.bitrix_sessid();
1007			data.template = this.template;
1008			data.signedParamsString = this.signedParamsString;
1009
1010			return data;
1011		},
1012
1013		startLoader: function()
1014		{
1015			// if (!this.loadingScreen)
1016			// {
1017			// 	this.loadingScreen = new BX.PopupWindow('loading_screen', null, {
1018			// 		events: {
1019			// 			onAfterPopupShow: BX.delegate(function() {
1020			// 				BX.cleanNode(this.loadingScreen.popupContainer);
1021			// 				BX.removeClass(this.loadingScreen.popupContainer, 'popup-window');
1022			// 				this.loadingScreen.popupContainer.appendChild(
1023			// 					BX.create('IMG', {props: {src: this.templateFolder + '/images/loader.gif'}})
1024			// 				);
1025			// 				this.loadingScreen.popupContainer.removeAttribute('style');
1026			// 				this.loadingScreen.popupContainer.style.display = 'block';
1027			// 			}, this)
1028			// 		}
1029			// 	});
1030			// 	BX.addClass(this.loadingScreen.popupContainer, 'bx-step-opacity');
1031			// }
1032			//
1033			// this.loadingScreen.show();
1034		},
1035
1036		/**
1037		 * Hiding loader image with overlay.
1038		 */
1039		endLoader: function()
1040		{
1041			// if (this.loadingScreen && this.loadingScreen.isShown())
1042			// {
1043			// 	this.loadingScreen.close();
1044			// }
1045		},
1046
1047		editWarnings: function()
1048		{
1049			this.editGeneralWarnings();
1050			this.editBasketItemWarnings();
1051			this.toggleWarningBlock();
1052			this.showWarningItemsCount();
1053		},
1054
1055		editGeneralWarnings: function()
1056		{
1057			var warningsNode = this.getEntity(this.getCacheNode(this.ids.warning), 'basket-general-warnings');
1058
1059			if (BX.type.isDomNode(warningsNode))
1060			{
1061				var generalWarningText = warningsNode.innerHTML;
1062
1063				if (this.result.WARNING_MESSAGE_WITH_CODE)
1064				{
1065					for (var code in this.result.WARNING_MESSAGE_WITH_CODE)
1066					{
1067						if (this.result.WARNING_MESSAGE_WITH_CODE.hasOwnProperty(code))
1068						{
1069							if (
1070								!this.items[code]
1071								&& generalWarningText.indexOf(this.result.WARNING_MESSAGE_WITH_CODE[code]) === -1
1072							)
1073							{
1074								generalWarningText += this.result.WARNING_MESSAGE_WITH_CODE[code] + '<br/>';
1075							}
1076						}
1077					}
1078				}
1079
1080				if (generalWarningText)
1081				{
1082					warningsNode.innerHTML = generalWarningText;
1083					warningsNode.style.display = '';
1084				}
1085				else
1086				{
1087					warningsNode.style.display = 'none';
1088					warningsNode.innerHTML = '';
1089				}
1090			}
1091		},
1092
1093		editBasketItemWarnings: function()
1094		{
1095			var itemsWarningsNode = this.getEntity(this.getCacheNode(this.ids.warning), 'basket-item-warnings');
1096
1097			if (BX.type.isDomNode(itemsWarningsNode))
1098			{
1099				if (this.warningItems.length)
1100				{
1101					var warningCount = this.getEntity(itemsWarningsNode, 'basket-items-warning-count');
1102					if (BX.type.isDomNode(warningCount))
1103					{
1104						warningCount.innerHTML = this.warningItems.length + ' ' + this.getGoodsMessage(this.warningItems.length);
1105					}
1106
1107					itemsWarningsNode.style.display = '';
1108				}
1109				else if (itemsWarningsNode.style.display !== 'none')
1110				{
1111					itemsWarningsNode.style.display = 'none';
1112
1113					if (this.filter.isActive())
1114					{
1115						this.toggleFilter('all');
1116					}
1117				}
1118			}
1119		},
1120
1121		toggleWarningBlock: function()
1122		{
1123			var warningNode = this.getCacheNode(this.ids.warning);
1124
1125			if (BX.type.isDomNode(warningNode))
1126			{
1127				var generalWarningNode = this.getEntity(warningNode, 'basket-general-warnings');
1128				var itemsWarningsNode = this.getEntity(warningNode, 'basket-item-warnings');
1129
1130				if (
1131					(!BX.type.isDomNode(generalWarningNode) || generalWarningNode.style.display === 'none')
1132					&& (!BX.type.isDomNode(itemsWarningsNode) || itemsWarningsNode.style.display === 'none')
1133				)
1134				{
1135					warningNode.style.display = 'none';
1136				}
1137				else
1138				{
1139					warningNode.style.display = '';
1140				}
1141			}
1142		},
1143
1144		checkBasketItemWarnings: function(itemData, warnings)
1145		{
1146			if (!itemData)
1147				return;
1148
1149			var itemWarnings;
1150
1151			if (this.items[itemData.ID] && this.lastAction === 'refreshAjax')
1152			{
1153				itemWarnings = this.items[itemData.ID].WARNINGS;
1154			}
1155			else
1156			{
1157				itemWarnings = [];
1158			}
1159
1160			if (BX.type.isArray(warnings[itemData.ID]) && warnings[itemData.ID].length)
1161			{
1162				for (var i in warnings[itemData.ID])
1163				{
1164					if (warnings[itemData.ID].hasOwnProperty(i) && !BX.util.in_array(warnings[itemData.ID][i], itemWarnings))
1165					{
1166						itemWarnings.push(warnings[itemData.ID][i]);
1167					}
1168				}
1169			}
1170
1171			if (itemWarnings.length)
1172			{
1173				if (!BX.util.in_array(itemData.ID, this.warningItems))
1174				{
1175					this.warningItems.push(itemData.ID);
1176				}
1177			}
1178			else if (BX.util.in_array(itemData.ID, this.warningItems))
1179			{
1180				this.warningItems.splice(BX.util.array_search(itemData.ID, this.warningItems), 1);
1181			}
1182
1183			return itemWarnings;
1184		},
1185
1186		removeAllWarnings: function(event)
1187		{
1188			this.clearGeneralWarnings();
1189			this.clearBasketItemsWarnings();
1190
1191			this.editWarnings();
1192
1193			event && event.preventDefault();
1194		},
1195
1196		clearGeneralWarnings: function()
1197		{
1198			this.result.WARNING_MESSAGE_WITH_CODE = {};
1199
1200			var generalWarningNode = this.getEntity(this.getCacheNode(this.ids.warning), 'basket-general-warnings');
1201
1202			if (BX.type.isDomNode(generalWarningNode))
1203			{
1204				generalWarningNode.innerHTML = '';
1205			}
1206		},
1207
1208		clearBasketItemsWarnings: function()
1209		{
1210			var itemsToEdit = [];
1211
1212			for (var i in this.warningItems)
1213			{
1214				if (this.warningItems.hasOwnProperty(i))
1215				{
1216					this.items[this.warningItems[i]].WARNINGS = [];
1217
1218					if (this.isItemShown(this.warningItems[i]))
1219					{
1220						itemsToEdit.push(this.warningItems[i]);
1221					}
1222				}
1223			}
1224
1225			this.warningItems = [];
1226			this.editBasketItems(itemsToEdit);
1227		},
1228
1229		isItemShown: function(itemId)
1230		{
1231			return BX.util.in_array(itemId, this.shownItems);
1232		},
1233
1234		initializeBasketItems: function()
1235		{
1236			if (Object.keys(this.items).length === 0)
1237				return;
1238
1239			for (var i = 0; i < this.sortedItems.length; i++)
1240			{
1241				if (this.useDynamicScroll && this.shownItems.length >= this.maxItemsShowCount)
1242				{
1243					break;
1244				}
1245
1246				this.createBasketItem(this.sortedItems[i]);
1247			}
1248		},
1249
1250		createBasketItem: function(itemId)
1251		{
1252			if (!this.items[itemId])
1253			{
1254				return;
1255			}
1256
1257			var basketItemTemplate = this.getTemplate('basket-item-template');
1258			if (basketItemTemplate)
1259			{
1260				var basketItemHtml = this.renderBasketItem(basketItemTemplate, this.items[itemId]);
1261				var sortIndex = BX.util.array_search(itemId, this.sortedItems);
1262
1263				if (this.shownItems.length && sortIndex >= 0)
1264				{
1265					if (sortIndex < BX.util.array_search(this.shownItems[0], this.sortedItems))
1266					{
1267						// insert before
1268						BX(this.ids.item + this.shownItems[0]).insertAdjacentHTML('beforebegin', basketItemHtml);
1269						this.shownItems.unshift(itemId);
1270					}
1271					else if (sortIndex > BX.util.array_search(this.shownItems[this.shownItems.length - 1], this.sortedItems))
1272					{
1273						// insert after
1274						BX(this.ids.item + this.shownItems[this.shownItems.length - 1]).insertAdjacentHTML('afterend', basketItemHtml);
1275						this.shownItems.push(itemId);
1276					}
1277					else
1278					{
1279						// insert between
1280						BX(this.ids.item + this.sortedItems[sortIndex + 1]).insertAdjacentHTML('beforebegin', basketItemHtml);
1281						this.shownItems.splice(sortIndex + 1, 0, itemId);
1282					}
1283				}
1284				else
1285				{
1286					this.getCacheNode(this.ids.itemListTable).insertAdjacentHTML('beforeend', basketItemHtml);
1287					this.shownItems.push(itemId);
1288				}
1289
1290				this.bindBasketItemEvents(this.items[itemId]);
1291
1292				if (this.filter.isActive())
1293				{
1294					this.filter.highlightSearchMatch(this.items[itemId]);
1295				}
1296			}
1297		},
1298
1299		getItemsToEdit: function()
1300		{
1301			var itemIds = [];
1302
1303			if (this.isBasketChanged())
1304			{
1305				for (var i in this.changedItems)
1306				{
1307					if (this.changedItems.hasOwnProperty(i) && this.isItemShown(this.changedItems[i]))
1308					{
1309						itemIds.push(this.changedItems[i]);
1310					}
1311				}
1312			}
1313
1314			return itemIds;
1315		},
1316
1317		getItemsAfter: function()
1318		{
1319			var itemIdsAfter = [];
1320
1321			if (this.useDynamicScroll)
1322			{
1323				var lastShownItemId = this.shownItems[this.shownItems.length - 1] || false;
1324
1325				if (lastShownItemId)
1326				{
1327					var i = 0;
1328					var index = BX.util.array_search(lastShownItemId, this.sortedItems);
1329
1330					while (this.sortedItems[++index] && i++ < this.maxItemsShowCount)
1331					{
1332						itemIdsAfter.push(this.sortedItems[index]);
1333					}
1334				}
1335			}
1336
1337			return itemIdsAfter;
1338		},
1339
1340		editBasketItems: function(itemIds)
1341		{
1342			if (!itemIds || itemIds.length === 0)
1343			{
1344				return;
1345			}
1346
1347			var i, item;
1348
1349			for (i in itemIds)
1350			{
1351				if (!itemIds.hasOwnProperty(i) || !BX.type.isPlainObject(this.items[itemIds[i]]))
1352				{
1353					continue;
1354				}
1355
1356				item = this.items[itemIds[i]];
1357
1358				if (this.actionPool.isItemInPool(item.ID))
1359				{
1360					if (!BX.util.in_array(item.ID, this.postponedItems))
1361					{
1362						this.postponedItems.push(item.ID);
1363					}
1364
1365					continue;
1366				}
1367
1368				if (BX.type.isDomNode(BX(this.ids.item + item.ID)))
1369				{
1370					this.redrawBasketItemNode(item.ID);
1371					this.applyQuantityAnimation(item.ID);
1372				}
1373				else
1374				{
1375					this.createBasketItem(item.ID);
1376				}
1377			}
1378		},
1379
1380		editPostponedBasketItems: function()
1381		{
1382			if (!this.postponedItems.length)
1383				return;
1384
1385			var itemsToEdit = [];
1386
1387			for (var i in this.postponedItems)
1388			{
1389				if (this.postponedItems.hasOwnProperty(i) && this.isItemShown(this.postponedItems[i]))
1390				{
1391					itemsToEdit.push(this.postponedItems[i]);
1392				}
1393			}
1394
1395			this.postponedItems = [];
1396			this.editBasketItems(itemsToEdit);
1397		},
1398
1399		applyQuantityAnimation: function(itemId)
1400		{
1401			var basketItemNode = BX(this.ids.item + itemId);
1402
1403			if (BX.type.isDomNode(basketItemNode) && this.items[itemId])
1404			{
1405				if (this.items[itemId].QUANTITY_ANIMATION)
1406				{
1407					BX.addClass(BX(this.ids.quantity + itemId), 'basket-updated');
1408				}
1409			}
1410		},
1411
1412		applyPriceAnimation: function()
1413		{
1414			if (!this.priceAnimationData || Object.keys(this.priceAnimationData.start).length === 0)
1415				return;
1416
1417			var animationData = this.priceAnimationData,
1418				nodeCache = {};
1419
1420			new BX.easing({
1421				duration: this.params.USE_PRICE_ANIMATION === 'Y' ? this.duration.priceAnimation : 1,
1422				start: animationData.start,
1423				finish: animationData.finish,
1424				transition: BX.easing.makeEaseOut(BX.easing.transitions.quad),
1425				step: BX.delegate(function(state){
1426					for (var nodeId in animationData.start)
1427					{
1428						if (animationData.start.hasOwnProperty(nodeId))
1429						{
1430							if (!nodeCache[nodeId])
1431							{
1432								if (nodeId === this.ids.total)
1433								{
1434									nodeCache[nodeId] = this.getEntities(this.getCacheNode(this.ids.basketRoot), this.ids.total);
1435								}
1436								else
1437								{
1438									var node = BX(nodeId);
1439									nodeCache[nodeId] = node ? [node] : [];
1440								}
1441							}
1442
1443							if (!animationData.int[nodeId])
1444							{
1445								// fix price blinking
1446								state[nodeId] = (state[nodeId] + (state[nodeId] % 1000) / 1000).toFixed(5);
1447							}
1448
1449							for (var i = 0; i < nodeCache[nodeId].length; i++)
1450							{
1451								nodeCache[nodeId][i].innerHTML = this.getFormatPrice(state[nodeId], animationData.currency[nodeId]);
1452							}
1453						}
1454					}
1455				}, this),
1456				complete: BX.delegate(function() {
1457					var nodeId, formattedPrice, itemId, type;
1458
1459					for (nodeId in animationData.start)
1460					{
1461						if (animationData.start.hasOwnProperty(nodeId))
1462						{
1463							formattedPrice = this.getFormatPrice(animationData.finish[nodeId], animationData.currency[nodeId]);
1464
1465							for (var i = 0; i < nodeCache[nodeId].length; i++)
1466							{
1467								nodeCache[nodeId][i].innerHTML = formattedPrice;
1468							}
1469
1470							if (nodeId.indexOf(this.ids.sumPrice) !== -1)
1471							{
1472								type = 'SUM_PRICE';
1473								itemId = nodeId.substr(this.ids.sumPrice.length);
1474							}
1475							else if (nodeId.indexOf(this.ids.price) !== -1)
1476							{
1477								type = 'PRICE';
1478								itemId = nodeId.substr(this.ids.price.length);
1479							}
1480							else if (nodeId.indexOf(this.ids.total) !== -1)
1481							{
1482								type = 'TOTAL';
1483								itemId = '';
1484							}
1485							else
1486							{
1487								itemId = '';
1488								type = '';
1489							}
1490
1491							if (BX.type.isNotEmptyString(type))
1492							{
1493								if (itemId)
1494								{
1495									this.items[itemId][type] = animationData.finish[nodeId];
1496									delete this.items[itemId][type + '_NEW'];
1497									this.items[itemId][type + '_FORMATED'] = formattedPrice;
1498									delete this.items[itemId][type + '_FORMATED_NEW'];
1499								}
1500								else if (type === 'TOTAL')
1501								{
1502									this.result.TOTAL_RENDER_DATA.PRICE = animationData.finish[nodeId];
1503									delete this.result.TOTAL_RENDER_DATA.PRICE_NEW;
1504									this.result.TOTAL_RENDER_DATA.PRICE_FORMATED = formattedPrice;
1505									delete this.result.TOTAL_RENDER_DATA.PRICE_FORMATED_NEW;
1506								}
1507							}
1508						}
1509					}
1510
1511					this.filter.highlightFoundItems();
1512				}, this)
1513			}).animate();
1514		},
1515
1516		getFormatPrice: function(price, currency)
1517		{
1518			// return BX.Currency.currencyFormat(price, currency, true);
1519			return new Intl.NumberFormat('ru-RU').format(price) + " &#x20bd;";
1520			return BX.Currency.currencyFormat(price, currency, true);
1521		},
1522
1523		deleteBasketItems: function(items, restore, final)
1524		{
1525			if (!items || !items.length)
1526			{
1527				return;
1528			}
1529
1530			for (var i in items)
1531			{
1532				if (items.hasOwnProperty(i))
1533				{
1534					this.deleteBasketItem(items[i], restore, final);
1535				}
1536			}
1537		},
1538
1539		deleteBasketItem: function(itemId, restore, final)
1540		{
1541			// delete not available item with no chance to restore
1542			if (this.items[itemId].NOT_AVAILABLE && restore)
1543			{
1544				restore = false;
1545				final = true;
1546			}
1547
1548			if (restore)
1549			{
1550				this.items[itemId].SHOW_RESTORE = true;
1551				this.items[itemId].SHOW_LOADING = false;
1552				this.redrawBasketItemNode(itemId);
1553			}
1554			else
1555			{
1556				this.changeShownItem(itemId);
1557				BX.remove(BX(this.ids.item + itemId));
1558			}
1559
1560			if (final)
1561			{
1562				this.changeSortedItem(itemId, false, true);
1563				this.changeShownItem(itemId, false, true);
1564			}
1565		},
1566
1567		addSortedItem: function(itemId, all)
1568		{
1569			this.sortedItems.push(itemId.toString());
1570
1571			if (all && this.filter.isActive())
1572			{
1573				this.filter.realSortedItems.push(itemId.toString());
1574			}
1575		},
1576
1577		changeSortedItem: function(itemId, newItemId, all)
1578		{
1579			var index = BX.util.array_search(itemId, this.sortedItems);
1580
1581			if (index >= 0)
1582			{
1583				if (newItemId)
1584				{
1585					this.sortedItems.splice(index, 1, newItemId.toString());
1586				}
1587				else
1588				{
1589					this.sortedItems.splice(index, 1);
1590				}
1591			}
1592
1593			if (all && this.filter.isActive())
1594			{
1595				index = BX.util.array_search(itemId, this.filter.realSortedItems);
1596
1597				if (index >= 0)
1598				{
1599					if (newItemId)
1600					{
1601						this.filter.realSortedItems.splice(index, 1, newItemId.toString());
1602					}
1603					else
1604					{
1605						this.filter.realSortedItems.splice(index, 1);
1606					}
1607				}
1608			}
1609		},
1610
1611		sortSortedItems: function(all)
1612		{
1613			this.sortedItems.sort(BX.proxy(this.itemSortFunction, this));
1614
1615			if (all && this.filter.isActive())
1616			{
1617				this.filter.realSortedItems.sort(BX.proxy(this.itemSortFunction, this));
1618			}
1619		},
1620
1621		changeShownItem: function(itemId, newItemId, all)
1622		{
1623			var index = BX.util.array_search(itemId, this.shownItems);
1624
1625			if (index >= 0)
1626			{
1627				if (newItemId)
1628				{
1629					this.shownItems.splice(index, 1, newItemId.toString());
1630				}
1631				else
1632				{
1633					this.shownItems.splice(index, 1);
1634				}
1635			}
1636
1637			if (all && this.filter.isActive())
1638			{
1639				index = BX.util.array_search(itemId, this.filter.realShownItems);
1640
1641				if (index >= 0)
1642				{
1643					if (newItemId)
1644					{
1645						this.filter.realShownItems.splice(index, 1, newItemId.toString());
1646					}
1647					else
1648					{
1649						this.filter.realShownItems.splice(index, 1);
1650					}
1651				}
1652			}
1653		},
1654
1655		redrawBasketItemNode: function(itemId)
1656		{
1657			var basketItemNode = BX(this.ids.item + itemId);
1658
1659			if (!this.items[itemId] || !BX.type.isDomNode(basketItemNode))
1660				return;
1661
1662			var basketItemTemplate = this.getTemplate('basket-item-template');
1663			if (basketItemTemplate)
1664			{
1665				var nodeAligner = BX(this.ids.itemHeightAligner + itemId),
1666					oldHeight;
1667
1668				if (BX.type.isDomNode(nodeAligner))
1669				{
1670					oldHeight = nodeAligner.clientHeight;
1671				}
1672
1673				var basketItemHtml = this.renderBasketItem(basketItemTemplate, this.items[itemId]);
1674				basketItemNode.insertAdjacentHTML('beforebegin', basketItemHtml);
1675				BX.remove(basketItemNode);
1676
1677				if (oldHeight)
1678				{
1679					nodeAligner = BX(this.ids.itemHeightAligner + itemId);
1680
1681					if (BX.type.isDomNode(nodeAligner) && nodeAligner.clientHeight < oldHeight)
1682					{
1683						nodeAligner.style.minHeight = oldHeight + 'px';
1684						setTimeout(function(){nodeAligner.style.minHeight = '0px';}, 1);
1685					}
1686				}
1687
1688				this.bindBasketItemEvents(this.items[itemId]);
1689
1690				if (this.filter.isActive())
1691				{
1692					this.filter.highlightSearchMatch(this.items[itemId]);
1693				}
1694			}
1695		},
1696
1697		restoreBasketItems: function(items)
1698		{
1699			if (!items || Object.keys(items).length === 0)
1700			{
1701				return;
1702			}
1703
1704			var oldItemId, newItemId, basketItemNode;
1705
1706			for (oldItemId in items)
1707			{
1708				if (items.hasOwnProperty(oldItemId))
1709				{
1710					newItemId = items[oldItemId];
1711
1712					if (this.isItemShown(oldItemId))
1713					{
1714						this.changeShownItem(oldItemId, newItemId, true);
1715
1716						basketItemNode = BX(this.ids.item + oldItemId);
1717						if (BX.type.isDomNode(basketItemNode))
1718						{
1719							basketItemNode.id = this.ids.item + newItemId;
1720							basketItemNode.setAttribute('data-id', newItemId);
1721						}
1722					}
1723
1724					this.changeSortedItem(oldItemId, false, true);
1725				}
1726			}
1727		},
1728
1729		bindBasketItemEvents: function(itemData)
1730		{
1731			if (!itemData)
1732				return;
1733
1734			var itemNode = BX(this.ids.item + itemData.ID);
1735			if (BX.type.isDomNode(itemNode))
1736			{
1737				this.bindQuantityEvents(itemNode, itemData);
1738				this.bindSkuEvents(itemNode, itemData);
1739				this.bindImageEvents(itemNode, itemData);
1740				this.bindActionEvents(itemNode, itemData);
1741				this.bindRestoreAction(itemNode, itemData);
1742				this.bindItemWarningEvents(itemNode, itemData);
1743			}
1744		},
1745
1746		bindQuantityEvents: function(node, data)
1747		{
1748			if (!node || !data || !this.isItemAvailable(data.ID))
1749				return;
1750
1751			var entity;
1752
1753			var block = this.getEntity(node, 'basket-item-quantity-block');
1754			if (block)
1755			{
1756				var startEventName = this.isTouch ? 'touchstart' : 'mousedown';
1757				var endEventName = this.isTouch ? 'touchend' : 'mouseup';
1758
1759				entity = this.getEntity(block, 'basket-item-quantity-minus');
1760				BX.bind(entity, startEventName, BX.proxy(this.startQuantityInterval, this));
1761				BX.bind(entity, endEventName, BX.proxy(this.clearQuantityInterval, this));
1762				BX.bind(entity, 'mouseout', BX.proxy(this.clearQuantityInterval, this));
1763				BX.bind(entity, 'click', BX.proxy(this.quantityMinus, this));
1764
1765				entity = this.getEntity(block, 'basket-item-quantity-plus');
1766				BX.bind(entity, startEventName, BX.proxy(this.startQuantityInterval, this));
1767				BX.bind(entity, endEventName, BX.proxy(this.clearQuantityInterval, this));
1768				BX.bind(entity, 'mouseout', BX.proxy(this.clearQuantityInterval, this));
1769				BX.bind(entity, 'click', BX.proxy(this.quantityPlus, this));
1770
1771				entity = this.getEntity(block, 'basket-item-quantity-field');
1772				BX.bind(entity, 'change', BX.proxy(this.quantityChange, this));
1773			}
1774		},
1775
1776		startQuantityInterval: function()
1777		{
1778			var target = BX.proxy_context;
1779			var func = target.getAttribute('data-entity') === 'basket-item-quantity-minus'
1780				? BX.proxy(this.quantityMinus, this)
1781				: BX.proxy(this.quantityPlus, this);
1782
1783			this.quantityDelay = setTimeout(
1784				BX.delegate(function() {
1785					this.quantityTimer = setInterval(function(){func(target);}, 150);
1786				}, this),
1787				300
1788			);
1789		},
1790
1791		clearQuantityInterval: function()
1792		{
1793			clearTimeout(this.quantityDelay);
1794			clearInterval(this.quantityTimer);
1795		},
1796
1797		quantityPlus: function(target)
1798		{
1799			if (!BX.type.isDomNode(target))
1800			{
1801				target = BX.proxy_context;
1802				this.clearQuantityInterval();
1803			}
1804
1805			var itemData = this.getItemDataByTarget(target);
1806			if (itemData)
1807			{
1808				var quantityField = BX(this.ids.quantity + itemData.ID);
1809				var isQuantityFloat = this.isQuantityFloat(itemData);
1810
1811				var currentQuantity = isQuantityFloat ? parseFloat(quantityField.value) : Math.round(quantityField.value);
1812				var measureRatio = isQuantityFloat ? parseFloat(itemData.MEASURE_RATIO) : parseInt(itemData.MEASURE_RATIO);
1813
1814				var quantity = parseFloat((currentQuantity + measureRatio).toFixed(5));
1815				quantity = this.getCorrectQuantity(itemData, quantity);
1816
1817				this.setQuantity(itemData, quantity);
1818			}
1819		},
1820
1821		quantityMinus: function(target)
1822		{
1823			target = BX.type.isDomNode(target) ? target : BX.proxy_context;
1824
1825			var itemData = this.getItemDataByTarget(target);
1826			if (itemData)
1827			{
1828				var quantityField = BX(this.ids.quantity + itemData.ID);
1829				var isQuantityFloat = this.isQuantityFloat(itemData);
1830
1831				var currentQuantity = isQuantityFloat ? parseFloat(quantityField.value) : Math.round(quantityField.value);
1832				var measureRatio = isQuantityFloat ? parseFloat(itemData.MEASURE_RATIO) : parseInt(itemData.MEASURE_RATIO);
1833
1834				var quantity = parseFloat((currentQuantity - measureRatio).toFixed(5));
1835				quantity = this.getCorrectQuantity(itemData, quantity);
1836
1837				this.setQuantity(itemData, quantity);
1838			}
1839		},
1840
1841		quantityChange: function()
1842		{
1843			var itemData = this.getItemDataByTarget(BX.proxy_context);
1844			if (itemData)
1845			{
1846				var quantityField, quantity;
1847
1848				quantityField = BX(this.ids.quantity + itemData.ID);
1849				quantity = this.getCorrectQuantity(itemData, quantityField.value);
1850
1851				this.setQuantity(itemData, quantity);
1852			}
1853		},
1854
1855		isQuantityFloat: function(item)
1856		{
1857			return this.params.QUANTITY_FLOAT === 'Y' || (parseInt(item.MEASURE_RATIO) !== parseFloat(item.MEASURE_RATIO));
1858		},
1859
1860		getCorrectQuantity: function(itemData, quantity)
1861		{
1862			var isQuantityFloat = this.isQuantityFloat(itemData),
1863				measureRatio = isQuantityFloat ? parseFloat(itemData.MEASURE_RATIO) : parseInt(itemData.MEASURE_RATIO),
1864				availableQuantity = 0;
1865
1866			quantity = (isQuantityFloat ? parseFloat(quantity) : parseInt(quantity, 10)) || 0;
1867			if (quantity < 0)
1868			{
1869				quantity = 0;
1870			}
1871
1872			if (measureRatio > 0 && quantity < measureRatio)
1873			{
1874				quantity = measureRatio;
1875			}
1876
1877			if (itemData.CHECK_MAX_QUANTITY === 'Y')
1878			{
1879				availableQuantity = isQuantityFloat ? parseFloat(itemData.AVAILABLE_QUANTITY) : parseInt(itemData.AVAILABLE_QUANTITY);
1880				if (availableQuantity > 0 && quantity > availableQuantity)
1881				{
1882					quantity = availableQuantity;
1883				}
1884			}
1885
1886			var reminder = (quantity / measureRatio - ((quantity / measureRatio).toFixed(0))).toFixed(5),
1887				remain;
1888
1889			if (parseFloat(reminder) === 0)
1890			{
1891				return quantity;
1892			}
1893
1894			if (measureRatio !== 0 && measureRatio !== 1)
1895			{
1896				remain = (quantity * this.precisionFactor) % (measureRatio * this.precisionFactor) / this.precisionFactor;
1897
1898				if (measureRatio > 0 && remain > 0)
1899				{
1900					if (
1901						remain >= measureRatio / 2
1902						&& (
1903							availableQuantity === 0
1904							|| (quantity + measureRatio - remain) <= availableQuantity
1905						)
1906					)
1907					{
1908						quantity += (measureRatio - remain);
1909					}
1910					else
1911					{
1912						quantity -= remain;
1913					}
1914				}
1915			}
1916
1917			quantity = isQuantityFloat ? parseFloat(quantity) : parseInt(quantity, 10);
1918
1919			return quantity;
1920		},
1921
1922		setQuantity: function(itemData, quantity)
1923		{
1924			var quantityField = BX(this.ids.quantity + itemData.ID),
1925				currentQuantity;
1926
1927			if (quantityField)
1928			{
1929				quantity = parseFloat(quantity);
1930				currentQuantity = parseFloat(quantityField.getAttribute('data-value'));
1931
1932				quantityField.value = quantity;
1933
1934				if (parseFloat(itemData.QUANTITY) !== parseFloat(quantity))
1935				{
1936					this.animatePriceByQuantity(itemData, quantity);
1937					this.actionPool.changeQuantity(itemData.ID, quantity, currentQuantity);
1938				}
1939			}
1940		},
1941
1942		animatePriceByQuantity: function(itemData, quantity)
1943		{
1944			var priceNode = BX(this.ids.sumPrice + itemData.ID);
1945			if (!BX.type.isDomNode(priceNode))
1946				return;
1947
1948			var quantityMultiplier = quantity / parseFloat(itemData.MEASURE_RATIO);
1949
1950			var startPrice = parseFloat(itemData.SUM_PRICE),
1951				finalPrice = parseFloat(itemData.PRICE) * quantityMultiplier,
1952				isInt = parseInt(startPrice) === parseFloat(startPrice)
1953					&& parseInt(finalPrice) === parseFloat(finalPrice);
1954
1955			if (startPrice !== finalPrice)
1956			{
1957				this.items[itemData.ID].QUANTITY = quantity;
1958				this.items[itemData.ID].SUM_PRICE = finalPrice;
1959
1960				new BX.easing({
1961					duration: this.params.USE_PRICE_ANIMATION === 'Y' ? this.duration.priceAnimation : 1,
1962					start: {price: startPrice},
1963					finish: {price: finalPrice},
1964					transition: BX.easing.makeEaseOut(BX.easing.transitions.quad),
1965					step: BX.delegate(function(state){
1966						if (!isInt)
1967						{
1968							// fix price blinking
1969							state.price = (state.price + (state.price % 1000) / 1000).toFixed(5);
1970						}
1971
1972						priceNode.innerHTML = this.getFormatPrice(state.price, itemData.CURRENCY);
1973					}, this),
1974					complete: BX.delegate(function() {
1975						var node, price;
1976
1977						priceNode.innerHTML = this.getFormatPrice(finalPrice, itemData.CURRENCY);
1978
1979						node = BX(this.ids.sumPriceOld + itemData.ID);
1980						if (BX.type.isDomNode(node))
1981						{
1982							price = parseFloat(itemData.FULL_PRICE) * quantityMultiplier;
1983							node.innerHTML = this.getFormatPrice(price, itemData.CURRENCY);
1984						}
1985
1986						node = BX(this.ids.sumPriceDiff + itemData.ID);
1987						if (BX.type.isDomNode(node))
1988						{
1989							price = parseFloat(itemData.DISCOUNT_PRICE) * quantityMultiplier;
1990							node.innerHTML = this.getFormatPrice(price, itemData.CURRENCY);
1991						}
1992					}, this)
1993				}).animate();
1994			}
1995		},
1996
1997		getItemDataByTarget: function(target)
1998		{
1999			var data = false;
2000			var id;
2001
2002			var itemNode = BX.findParent(target, {attrs: {'data-entity': 'basket-item'}});
2003			if (itemNode)
2004			{
2005				id = itemNode.getAttribute('data-id');
2006				data = this.items[id];
2007			}
2008
2009			return data;
2010		},
2011
2012		bindSkuEvents: function(node, data)
2013		{
2014			if (!node || !data)
2015				return;
2016
2017			var blocks = this.getEntities(node, 'basket-item-sku-block');
2018			var blockEntities, i, l, ii, ll;
2019
2020			for (i = 0, l = blocks.length; i < l; i++)
2021			{
2022				blockEntities = this.getEntities(blocks[i], 'basket-item-sku-field');
2023
2024				for (ii = 0, ll = blockEntities.length; ii < ll; ii++)
2025				{
2026					BX.bind(blockEntities[ii], 'click', BX.proxy(this.changeSku, this));
2027				}
2028			}
2029		},
2030
2031		changeSku: function()
2032		{
2033			var i, l;
2034
2035			var target = BX.proxy_context;
2036
2037			if (BX.hasClass(target, 'selected'))
2038				return;
2039
2040			var itemData = this.getItemDataByTarget(target);
2041			if (itemData)
2042			{
2043				var basketItemNode = BX(this.ids.item + itemData.ID);
2044				if (basketItemNode)
2045				{
2046					var currentSkuListNodes = this.getEntities(target.parentNode, 'basket-item-sku-field');
2047					for (i = 0, l = currentSkuListNodes.length; i < l; i++)
2048					{
2049						if (currentSkuListNodes[i].isEqualNode(target))
2050						{
2051							BX.addClass(currentSkuListNodes[i], 'selected');
2052						}
2053						else
2054						{
2055							BX.removeClass(currentSkuListNodes[i], 'selected');
2056						}
2057					}
2058
2059					this.actionPool.changeSku(
2060						itemData.ID,
2061						this.getSkuPropertyValues(basketItemNode),
2062						this.getInitialSkuPropertyValues(basketItemNode)
2063					);
2064				}
2065			}
2066		},
2067
2068		getSkuPropertyValues: function(basketItemNode)
2069		{
2070			var propertyValues = {};
2071
2072			var propNodes = this.getEntities(basketItemNode, 'basket-item-sku-field', '.selected');
2073			for (var i = 0, l = propNodes.length; i < l; i++)
2074			{
2075				propertyValues[propNodes[i].getAttribute('data-property')] = BX.util.htmlspecialcharsback(propNodes[i].getAttribute('data-value-id'));
2076			}
2077
2078			return propertyValues;
2079		},
2080
2081		getInitialSkuPropertyValues: function(basketItemNode)
2082		{
2083			var propertyValues = {};
2084
2085			var propNodes = this.getEntities(basketItemNode, 'basket-item-sku-field', '[data-initial="true"]');
2086			for (var i = 0, l = propNodes.length; i < l; i++)
2087			{
2088				propertyValues[propNodes[i].getAttribute('data-property')] = BX.util.htmlspecialcharsback(propNodes[i].getAttribute('data-value-id'));
2089			}
2090
2091			return propertyValues;
2092		},
2093
2094		bindImageEvents: function(node, data)
2095		{
2096			if (!node || !data)
2097				return;
2098
2099			var images = node.querySelectorAll('.basket-item-custom-block-photo-item');
2100			for (var i = 0, l = images.length; i < l; i++)
2101			{
2102				BX.bind(images[i], 'click', BX.proxy(this.showPropertyImagePopup, this));
2103			}
2104		},
2105
2106		showPropertyImagePopup: function()
2107		{
2108			var target, propertyCode, imageIndex, item, imageSrc, i;
2109
2110			target = BX.proxy_context;
2111			item = this.getItemDataByTarget(target);
2112
2113			propertyCode = target.getAttribute('data-column-property-code');
2114			imageIndex = target.getAttribute('data-image-index');
2115
2116			if (item && item.COLUMN_LIST)
2117			{
2118				for (i in item.COLUMN_LIST)
2119				{
2120					if (
2121						item.COLUMN_LIST.hasOwnProperty(i)
2122						&& item.COLUMN_LIST[i].CODE === propertyCode
2123						&& item.COLUMN_LIST[i].VALUE[imageIndex]
2124					)
2125					{
2126						imageSrc = item.COLUMN_LIST[i].VALUE[imageIndex].IMAGE_SRC_ORIGINAL;
2127						break;
2128					}
2129				}
2130			}
2131
2132			if (!imageSrc)
2133			{
2134				return;
2135			}
2136
2137			if (this.imagePopup)
2138			{
2139				this.imagePopup.destroy();
2140			}
2141
2142			var imageId = 'bx-soa-image-popup-content';
2143			var that = this;
2144
2145			this.imagePopup = new BX.PopupWindow('bx-soa-image-popup', null, {
2146				lightShadow: true,
2147				offsetTop: 0,
2148				offsetLeft: 0,
2149				closeIcon: {top: '3px', right: '10px'},
2150				autoHide: true,
2151				bindOptions: {position: 'bottom'},
2152				closeByEsc: true,
2153				zIndex: 100,
2154				events: {
2155					onPopupShow: function() {
2156						BX.create('IMG', {
2157							props: {src: imageSrc},
2158							events: {
2159								load: function() {
2160									var content = BX(imageId);
2161									if (content)
2162									{
2163										var windowSize = BX.GetWindowInnerSize(),
2164											ratio = that.isMobile ? 0.5 : 0.9,
2165											contentHeight, contentWidth;
2166
2167										BX.cleanNode(content);
2168										content.appendChild(this);
2169
2170										contentHeight = content.offsetHeight;
2171										contentWidth = content.offsetWidth;
2172
2173										if (contentHeight >
2173 windowSize.innerHeight * ratio)
2174										{
2175											content.style.height = windowSize.innerHeight * ratio + 'px';
2176											content.style.width = contentWidth * (windowSize.innerHeight * ratio / contentHeight) + 'px';
2177											contentHeight = content.offsetHeight;
2178											contentWidth = content.offsetWidth;
2179										}
2180
2181										if (contentWidth > windowSize.innerWidth * ratio)
2182										{
2183											content.style.width = windowSize.innerWidth * ratio + 'px';
2184											content.style.height = contentHeight * (windowSize.innerWidth * ratio / contentWidth) + 'px';
2185										}
2186
2187										content.style.height = content.offsetHeight + 'px';
2188										content.style.width = content.offsetWidth + 'px';
2189
2190										that.imagePopup.adjustPosition();
2191									}
2192								}
2193							}
2194						});
2195					},
2196					onPopupClose: function() {
2197						this.destroy();
2198					}
2199				},
2200				content: BX.create('DIV', {props: {id: imageId}})
2201			});
2202			this.imagePopup.show();
2203		},
2204
2205		bindActionEvents: function(node, data)
2206		{
2207			if (!node || !data)
2208				return;
2209
2210			var entity;
2211
2212			if (BX.util.in_array('DELETE', this.params.COLUMNS_LIST))
2213			{
2214				entity = this.getEntities(node, 'basket-item-delete');
2215				for (var i = 0, l = entity.length; i < l; i++)
2216				{
2217					BX.bind(entity[i], 'click', BX.proxy(this.deleteAction, this));
2218				}
2219			}
2220
2221			if (BX.util.in_array('DELAY', this.params.COLUMNS_LIST))
2222			{
2223				entity = this.getEntity(node, 'basket-item-add-delayed');
2224				BX.bind(entity, 'click', BX.proxy(this.addDelayedAction, this));
2225			}
2226
2227			entity = this.getEntity(node, 'basket-item-remove-delayed');
2228			BX.bind(entity, 'click', BX.proxy(this.removeDelayedAction, this));
2229
2230			entity = this.getEntity(node, 'basket-item-merge-sku-link');
2231			BX.bind(entity, 'click', BX.proxy(this.mergeAction, this));
2232
2233			entity = this.getEntity(node, 'basket-item-show-similar-link');
2234			BX.bind(entity, 'click', BX.delegate(function() {this.toggleFilter('similar');}, this));
2235		},
2236
2237		deleteAction: function()
2238		{
2239			var itemData = this.getItemDataByTarget(BX.proxy_context);
2240			if (itemData)
2241			{
2242				this.actionPool.deleteItem(itemData.ID);
2243
2244				this.items[itemData.ID].SHOW_LOADING = true;
2245
2246				if (this.params.SHOW_RESTORE === 'Y' && this.isItemAvailable(itemData.ID))
2247				{
2248					this.items[itemData.ID].SHOW_RESTORE = true;
2249					// ym(56006068, 'reachGoal', 'analitycCartProductDelete');
2250					// gtag('event', 'click', {'event_category': 'button', 'event_label': 'analitycCartProductDelete'});
2251				}
2252
2253				this.redrawBasketItemNode(itemData.ID);
2254			}
2255		},
2256
2257		addDelayedAction: function()
2258		{
2259			var itemData = this.getItemDataByTarget(BX.proxy_context);
2260			if (itemData)
2261			{
2262				this.actionPool.addDelayed(itemData.ID);
2263
2264				this.items[itemData.ID].SHOW_LOADING = true;
2265				this.redrawBasketItemNode(itemData.ID);
2266			}
2267		},
2268
2269		removeDelayedAction: function()
2270		{
2271			var itemData = this.getItemDataByTarget(BX.proxy_context);
2272			if (itemData)
2273			{
2274				this.actionPool.removeDelayed(itemData.ID);
2275
2276				this.items[itemData.ID].SHOW_LOADING = true;
2277				this.redrawBasketItemNode(itemData.ID);
2278			}
2279		},
2280
2281		mergeAction: function()
2282		{
2283			var itemData = this.getItemDataByTarget(BX.proxy_context);
2284			if (itemData)
2285			{
2286				this.actionPool.mergeSku(itemData.ID);
2287			}
2288		},
2289
2290		bindRestoreAction: function(node, itemData)
2291		{
2292			if (!node || !itemData || this.params.SHOW_RESTORE !== 'Y')
2293				return;
2294
2295			BX.bind(
2296				this.getEntity(node, 'basket-item-restore-button'),
2297				'click',
2298				BX.delegate(function() {
2299					this.actionPool.restoreItem(itemData.ID, {
2300						PRODUCT_ID: itemData.PRODUCT_ID,
2301						QUANTITY: itemData.QUANTITY,
2302						PROPS: itemData.PROPS_ALL,
2303						SORT: itemData.SORT,
2304						MODULE: itemData.MODULE,
2305						PRODUCT_PROVIDER_CLASS: itemData.PRODUCT_PROVIDER_CLASS
2306					});
2307
2308					this.items[itemData.ID].SHOW_RESTORE = false;
2309					this.items[itemData.ID].SHOW_LOADING = true;
2310
2311					// ym(56006068, 'reachGoal', 'analitycCartProductRestore');
2312					// gtag('event', 'click', {'event_category': 'button', 'event_label': 'analitycCartProductRestore'});
2313					
2314					this.redrawBasketItemNode(itemData.ID);
2315				}, this)
2316			);
2317			BX.bind(
2318				this.getEntity(node, 'basket-item-close-restore-button'),
2319				'click',
2320				BX.delegate(function() {
2321					this.deleteBasketItem(itemData.ID, false, true);
2322				}, this)
2323			);
2324		},
2325
2326		bindItemWarningEvents: function(node, data)
2327		{
2328			if (!node || !data)
2329				return;
2330
2331			BX.bind(
2332				this.getEntity(BX(this.ids.item + data.ID), 'basket-item-warning-close'),
2333				'click',
2334				BX.proxy(this.closeItemWarnings, this)
2335			);
2336		},
2337
2338		closeItemWarnings: function()
2339		{
2340			var target = BX.proxy_context;
2341
2342			if (BX.type.isDomNode(target))
2343			{
2344				var itemData = this.getItemDataByTarget(target);
2345
2346				this.items[itemData.ID].WARNINGS = [];
2347				this.warningItems.splice(BX.util.array_search(itemData.ID, this.warningItems), 1);
2348
2349				this.redrawBasketItemNode(itemData.ID);
2350				this.editWarnings();
2351			}
2352		},
2353
2354		renderBasketItem: function(template, data)
2355		{
2356			var clonedData = BX.clone(data);
2357
2358			if (BX.type.isPlainObject(clonedData))
2359			{
2360				clonedData.USE_FILTER = this.useItemsFilter
2361					&& !this.filter.currentFilter.similarHash.length;
2362			}
2363
2364			return Mustache.render(template, clonedData);
2365		},
2366
2367		render: function(template, data)
2368		{
2369			return Mustache.render(template, data);
2370		},
2371
2372		checkAnalytics: function(data)
2373		{
2374			if (!data || !data.basket)
2375				return;
2376
2377			var itemId, itemsDiff = {};
2378
2379			for (var i in data.basket)
2380			{
2381				if (data.basket.hasOwnProperty(i))
2382				{
2383					if (i.indexOf('QUANTITY_') >= 0)
2384					{
2385						itemId = i.substr(9);
2386
2387						if (this.items[itemId])
2388						{
2389							itemsDiff[itemId] = parseFloat(data.basket[i]) - parseFloat(BX(this.ids.quantity + itemId).getAttribute('data-value'));
2390						}
2391					}
2392					else if (i.indexOf('DELETE_') >= 0)
2393					{
2394						itemId = i.substr(7);
2395
2396						if (this.items[itemId])
2397						{
2398							itemsDiff[itemId] = -parseFloat(this.items[itemId].QUANTITY);
2399						}
2400					}
2401					else if (i.indexOf('RESTORE_') >= 0)
2402					{
2403						itemId = i.substr(8);
2404
2405						if (this.items[itemId])
2406						{
2407							itemsDiff[itemId] = parseFloat(this.items[itemId].QUANTITY);
2408						}
2409					}
2410				}
2411			}
2412
2413			this.setAnalyticsDataLayer(itemsDiff);
2414		},
2415
2416		setAnalyticsDataLayer: function(itemsDiff)
2417		{
2418			if (!itemsDiff || Object.keys(itemsDiff).length === 0)
2419				return;
2420
2421			window[this.params.DATA_LAYER_NAME] = window[this.params.DATA_LAYER_NAME] || [];
2422
2423			var plus = [], minus = [];
2424
2425			for (var itemId in itemsDiff)
2426			{
2427				if (itemsDiff.hasOwnProperty(itemId))
2428				{
2429					if (itemsDiff[itemId] > 0)
2430					{
2431						plus.push(this.getItemAnalyticsInfo(itemId, itemsDiff[itemId]));
2432					}
2433					else if (itemsDiff[itemId] < 0)
2434					{
2435						minus.push(this.getItemAnalyticsInfo(itemId, itemsDiff[itemId]));
2436					}
2437				}
2438			}
2439
2440			if (plus.length)
2441			{
2442				window[this.params.DATA_LAYER_NAME].push({
2443					event: 'addToCart',
2444					ecommerce: {
2445						currencyCode: this.items[itemId].CURRENCY || '',
2446						add: {
2447							products: plus
2448						}
2449					}
2450				});
2451			}
2452
2453			if (minus.length)
2454			{
2455				window[this.params.DATA_LAYER_NAME].push({
2456					event: 'removeFromCart',
2457					ecommerce: {
2458						currencyCode: this.items[itemId].CURRENCY || '',
2459						remove: {
2460							products: minus
2461						}
2462					}
2463				});
2464			}
2465		},
2466
2467		getItemAnalyticsInfo: function(itemId, diff)
2468		{
2469			if (!this.items[itemId])
2470				return {};
2471
2472			var brand = (this.items[itemId].BRAND || '').split(',  ').join('/');
2473			var variants = [];
2474
2475			var selectedSku = this.getEntities(BX(this.ids.item + itemId), 'basket-item-sku-field', '.selected');
2476			for (var i = 0, l = selectedSku.length; i < l; i++)
2477			{
2478				variants.push(selectedSku[i].getAttribute('data-sku-name'));
2479			}
2480
2481			return {
2482				'name': this.items[itemId].NAME || '',
2483				'id': this.items[itemId].PRODUCT_ID || '',
2484				'price': this.items[itemId].PRICE || 0,
2485				'brand': brand,
2486				'variant': variants.join('/'),
2487				'quantity': Math.abs(diff)
2488			};
2489		}
2490	};
2491})();

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.