PageSourceSearch

https://psymarket.ru/bitrix/cache/js/s1/psy/page_215aade83649d6d8e…9d6d8e389677f0a93d6a5_v1.js?177441799082921

js psymarket.ru collected 2026-10-01 14:42:47 UTC 82,921 bytes, 3,308 lines download raw bytes

1
2; /* Start:"a:4:{s:4:"full";s:103:"/local/templates/psy/components/bitrix/sale.basket.basket/bootstrap_v5/js/action-pool.js?17224267795918";s:6:"source";s:88:"/local/templates/psy/components/bitrix/sale.basket.basket/bootstrap_v5/js/action-pool.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
3;(function(){
4	'use strict';
5
6	BX.namespace('BX.Sale.BasketActionPool');
7
8	BX.Sale.BasketActionPool = function(component)
9	{
10		this.component = component;
11
12		this.requestProcessing = false;
13		this.updateTimer = null;
14
15		this.isBasketRefreshed = this.component.params.DEFERRED_REFRESH !== 'Y';
16		this.needFullRecalculation = this.component.params.DEFERRED_REFRESH === 'Y';
17
18		this.pool = {};
19		this.lastActualPool = {};
20
21		this.approvedAction = ['QUANTITY', 'DELETE', 'RESTORE', 'DELAY', 'OFFER', 'MERGE_OFFER'];
22
23		this.switchTimer();
24	};
25
26	BX.Sale.BasketActionPool.prototype.setRefreshStatus = function(status)
27	{
28		this.isBasketRefreshed = !!status;
29	};
30
31	BX.Sale.BasketActionPool.prototype.getRefreshStatus = function()
32	{
33		return this.isBasketRefreshed;
34	};
35
36	BX.Sale.BasketActionPool.prototype.isItemInPool = function(itemId)
37	{
38		return !!this.pool[itemId];
39	};
40
41	BX.Sale.BasketActionPool.prototype.clearLastActualQuantityPool = function(itemId)
42	{
43		this.lastActualPool[itemId] && delete this.lastActualPool[itemId].QUANTITY;
44	};
45
46	BX.Sale.BasketActionPool.prototype.checkItemPoolBefore = function(itemId)
47	{
48		if (!itemId)
49			return;
50
51		this.pool[itemId] = this.pool[itemId] || {};
52	};
53
54	BX.Sale.BasketActionPool.prototype.checkItemPoolAfter = function(itemId)
55	{
56		if (!itemId || !this.pool[itemId])
57			return;
58
59		if (Object.keys(this.pool[itemId]).length === 0)
60		{
61			delete this.pool[itemId];
62		}
63	};
64
65	BX.Sale.BasketActionPool.prototype.addCoupon = function(coupon)
66	{
67		this.pool.COUPON = coupon;
68
69		this.switchTimer();
70	};
71
72	BX.Sale.BasketActionPool.prototype.removeCoupon = function(coupon)
73	{
74		this.checkItemPoolBefore('REMOVE_COUPON');
75
76		this.pool.REMOVE_COUPON[coupon] = coupon;
77
78		this.switchTimer();
79	};
80
81	BX.Sale.BasketActionPool.prototype.changeQuantity = function(itemId, quantity, oldQuantity)
82	{
83		this.checkItemPoolBefore(itemId);
84
85		if (
86			(this.lastActualPool[itemId] && this.lastActualPool[itemId].QUANTITY !== quantity)
87			|| (!this.lastActualPool[itemId] && quantity !== oldQuantity)
88		)
89		{
90			this.pool[itemId].QUANTITY = quantity;
91		}
92		else
93		{
94			this.pool[itemId] && delete this.pool[itemId].QUANTITY;
95		}
96
97		this.checkItemPoolAfter(itemId);
98		this.switchTimer();
99	};
100
101	BX.Sale.BasketActionPool.prototype.deleteItem = function(itemId)
102	{
103		this.checkItemPoolBefore(itemId);
104
105		if (this.pool[itemId].RESTORE)
106		{
107			delete this.pool[itemId].RESTORE;
108		}
109		else
110		{
111			this.pool[itemId].DELETE = 'Y';
112		}
113
114		this.checkItemPoolAfter(itemId);
115		this.switchTimer();
116	};
117
118	BX.Sale.BasketActionPool.prototype.restoreItem = function(itemId, itemData)
119	{
120		this.checkItemPoolBefore(itemId);
121
122		if (this.pool[itemId].DELETE === 'Y')
123		{
124			delete this.pool[itemId].DELETE;
125		}
126		else
127		{
128			this.pool[itemId].RESTORE = itemData;
129		}
130
131		this.checkItemPoolAfter(itemId);
132		this.switchTimer();
133	};
134
135	BX.Sale.BasketActionPool.prototype.addDelayed = function(itemId)
136	{
137		this.checkItemPoolBefore(itemId);
138
139		this.pool[itemId].DELAY = 'Y';
140
141		this.checkItemPoolAfter(itemId);
142		this.switchTimer();
143	};
144
145	BX.Sale.BasketActionPool.prototype.removeDelayed = function(itemId)
146	{
147		this.checkItemPoolBefore(itemId);
148
149		this.pool[itemId].DELAY = 'N';
150
151		this.checkItemPoolAfter(itemId);
152		this.switchTimer();
153	};
154
155	BX.Sale.BasketActionPool.prototype.changeSku = function(itemId, props, oldProps)
156	{
157		if (JSON.stringify(props) !== JSON.stringify(oldProps))
158		{
159			this.checkItemPoolBefore(itemId);
160			this.pool[itemId].OFFER = props;
161		}
162		else
163		{
164			this.pool[itemId] && delete this.pool[itemId].OFFER;
165			this.checkItemPoolAfter(itemId);
166		}
167
168		this.switchTimer();
169	};
170
171	BX.Sale.BasketActionPool.prototype.mergeSku = function(itemId)
172	{
173		this.checkItemPoolBefore(itemId);
174		this.pool[itemId].MERGE_OFFER = 'Y';
175
176		this.switchTimer();
177	};
178
179	BX.Sale.BasketActionPool.prototype.switchTimer = function()
180	{
181		clearTimeout(this.updateTimer);
182
183		if (this.isProcessing())
184		{
185			return;
186		}
187
188		if (this.isPoolEmpty())
189		{
190			this.component.editPostponedBasketItems();
191			this.component.fireCustomEvents();
192		}
193
194		if (!this.isPoolEmpty())
195		{
196			this.updateTimer = setTimeout(BX.proxy(this.trySendPool, this), 300);
197		}
198		else if (!this.getRefreshStatus())
199		{
200			this.trySendPool();
201		}
202	};
203
204	BX.Sale.BasketActionPool.prototype.trySendPool = function()
205	{
206		if (this.isPoolEmpty() && this.getRefreshStatus())
207		{
208			return;
209		}
210
211		this.doProcessing(true);
212
213		if (!this.isPoolEmpty())
214		{
215			this.component.sendRequest('recalculateAjax', {
216				basket: this.getPoolData()
217			});
218
219			this.lastActualPool = this.pool;
220			this.pool = {};
221		}
222		else if (!this.getRefreshStatus())
223		{
224			this.component.sendRequest('refreshAjax', {
225				fullRecalculation: this.needFullRecalculation ? 'Y' : 'N'
226			});
227			this.needFullRecalculation = false;
228		}
229	};
230
231	BX.Sale.BasketActionPool.prototype.getPoolData = function()
232	{
233		var poolData = {},
234			currentPool = this.pool;
235
236		if (currentPool.COUPON)
237		{
238			poolData.coupon = currentPool.COUPON;
239			delete currentPool.COUPON;
240		}
241
242		if (currentPool.REMOVE_COUPON)
243		{
244			poolData.delete_coupon = currentPool.REMOVE_COUPON;
245			delete currentPool.REMOVE_COUPON;
246		}
247
248		for (var id in currentPool)
249		{
250			if (currentPool.hasOwnProperty(id))
251			{
252				for (var action in currentPool[id])
253				{
254					if (currentPool[id].hasOwnProperty(action) && BX.util.in_array(action, this.approvedAction))
255					{
256						poolData[action + '_' + id] = currentPool[id][action];
257					}
258				}
259			}
260		}
261
262		return poolData;
263	};
264
265	BX.Sale.BasketActionPool.prototype.isPoolEmpty = function()
266	{
267		return Object.keys(this.pool).length === 0;
268	};
269
270	BX.Sale.BasketActionPool.prototype.doProcessing = function(state)
271	{
272		this.requestProcessing = state === true;
273
274		if (this.requestProcessing)
275		{
276			this.component.startLoader();
277		}
278		else
279		{
280			this.component.endLoader();
281		}
282	};
283
284	BX.Sale.BasketActionPool.prototype.isProcessing = function()
285	{
286		return this.requestProcessing === true;
287	};
288})();
289/* End */
290;
291; /* Start:"a:4:{s:4:"full";s:99:"/local/templates/psy/components/bitrix/sale.basket.basket/bootstrap_v5/js/filter.js?172242677914035";s:6:"source";s:83:"/local/templates/psy/components/bitrix/sale.basket.basket/bootstrap_v5/js/filter.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
292;(function(){
293	'use strict';
294
295	BX.namespace('BX.Sale.BasketFilter');
296
297	BX.Sale.BasketFilter = function(component)
298	{
299		this.component = component;
300
301		this.activeFilterMode = false;
302		this.filterTimer = null;
303		this.mouseOverClearFilter = false;
304
305		this.realShownItems = [];
306		this.realSortedItems = [];
307		this.realScrollTop = 0;
308
309		this.lastShownItemsHash = '';
310		this.currentFilter = {
311			query: '',
312			similarHash: '',
313			warning: false,
314			notAvailable: false,
315			delayed: false
316		};
317
318		if (this.component.useItemsFilter)
319		{
320			this.bindEvents();
321		}
322	};
323
324	BX.Sale.BasketFilter.prototype.bindEvents = function()
325	{
326		var entity;
327		var filterNode = this.component.getEntity(
328			this.component.getCacheNode(this.component.ids.itemListWrapper),
329			'basket-filter'
330		);
331
332		entity = this.component.getEntity(filterNode, 'basket-filter-input');
333		if (BX.type.isDomNode(entity))
334		{
335			BX.bind(entity, 'focus', function() {
336				filterNode.style.flex = 3;
337			});
338			BX.bind(entity, 'blur', BX.delegate(function() {
339				if (!this.mouseOverClearFilter)
340				{
341					filterNode.style.flex = '';
342				}
343			}, this));
344
345			BX.bind(entity, 'keyup', BX.proxy(this.onFilterInput, this));
346			BX.bind(entity, 'cut', BX.proxy(this.onFilterInput, this));
347			BX.bind(entity, 'paste', BX.proxy(this.onFilterInput, this));
348		}
349
350		entity = this.component.getEntity(filterNode, 'basket-filter-clear-btn');
351		if (BX.type.isDomNode(entity))
352		{
353			BX.bind(entity, 'mouseenter', BX.delegate(function() {
354				this.mouseOverClearFilter = true;
355			}, this));
356			BX.bind(entity, 'mouseout', BX.delegate(function() {
357				this.mouseOverClearFilter = false;
358			}, this));
359			BX.bind(entity, 'click', BX.delegate(function() {
360				if (!this.filterInputEmpty())
361				{
362					this.clearFilterInput();
363					this.onFilterChange();
364				}
365
366				filterNode.style.flex = '';
367			}, this));
368		}
369	};
370
371	BX.Sale.BasketFilter.prototype.isActive = function()
372	{
373		return this.activeFilterMode;
374	};
375
376	BX.Sale.BasketFilter.prototype.showFilterByName = function(name)
377	{
378		if (!name)
379			return;
380
381		switch (name)
382		{
383			case 'not-available':
384				this.showNotAvailableItemsFilter();
385				break;
386			case 'delayed':
387				this.showDelayItemsFilter();
388				break;
389			case 'warning':
390				this.showWarningItemsFilter();
391				break;
392			case 'similar':
393				this.showSimilarItemsFilter();
394				break;
395			case 'all':
396			default:
397				this.clearAllFiltersExcept([]);
398				this.onFilterChange();
399		}
400	};
401
402	BX.Sale.BasketFilter.prototype.onFilterInput = function()
403	{
404		var value = BX.type.isDomNode(BX.proxy_context) ? BX.util.trim(BX.proxy_context.value).toLowerCase() : '';
405
406		if (this.currentFilter.query !== value)
407		{
408			this.currentFilter.query = value;
409
410			this.onFilterChange();
411		}
412	};
413
414	BX.Sale.BasketFilter.prototype.clearAllFiltersExcept = function(names)
415	{
416		if (!names || !BX.type.isArray(names))
417			return;
418
419		!BX.util.in_array('input', names) && this.clearFilterInput();
420		!BX.util.in_array('warning', names) && this.clearWarningItemsFilter();
421		!BX.util.in_array('delayed', names) && this.clearDelayItemsFilter();
422		!BX.util.in_array('not-available', names) && this.clearNotAvailableItemsFilter();
423
424		if (!BX.util.in_array('similar', names))
425		{
426			this.clearSimilarItemsFilter();
427			this.component.showSimilarCount(false);
428		}
429	};
430
431	BX.Sale.BasketFilter.prototype.filterInputEmpty = function()
432	{
433		return this.currentFilter.query.length === 0;
434	};
435
436	BX.Sale.BasketFilter.prototype.clearFilterInput = function()
437	{
438		this.currentFilter.query = '';
439
440		var input = this.component.getEntity(
441			this.component.getCacheNode(this.component.ids.itemListWrapper),
442			'basket-filter-input'
443		);
444		if (BX.type.isDomNode(input))
445		{
446			input.value = '';
447		}
448	};
449
450	BX.Sale.BasketFilter.prototype.addWarningItemsFilter = function()
451	{
452		this.currentFilter.warning = true;
453	};
454
455	BX.Sale.BasketFilter.prototype.clearWarningItemsFilter = function()
456	{
457		this.currentFilter.warning = false;
458	};
459
460	BX.Sale.BasketFilter.prototype.showWarningItemsFilter = function()
461	{
462		if (!this.currentFilter.warning)
463		{
464			this.clearAllFiltersExcept(['warning']);
465			this.addWarningItemsFilter();
466			this.onFilterChange();
467		}
468	};
469
470	BX.Sale.BasketFilter.prototype.addDelayItemsFilter = function()
471	{
472		this.currentFilter.delayed = true;
473	};
474
475	BX.Sale.BasketFilter.prototype.clearDelayItemsFilter = function()
476	{
477		this.currentFilter.delayed = false;
478	};
479
480	BX.Sale.BasketFilter.prototype.showDelayItemsFilter = function()
481	{
482		if (!this.currentFilter.delayed)
483		{
484			this.clearAllFiltersExcept(['delayed']);
485			this.addDelayItemsFilter();
486			this.onFilterChange();
487		}
488	};
489
490	BX.Sale.BasketFilter.prototype.addNotAvailableItemsFilter = function()
491	{
492		this.currentFilter.notAvailable = true;
493	};
494
495	BX.Sale.BasketFilter.prototype.clearNotAvailableItemsFilter = function()
496	{
497		this.currentFilter.notAvailable = false;
498	};
499
500	BX.Sale.BasketFilter.prototype.showNotAvailableItemsFilter = function()
501	{
502		if (!this.currentFilter.notAvailable)
503		{
504			this.clearAllFiltersExcept(['not-available']);
505			this.addNotAvailableItemsFilter();
506			this.onFilterChange();
507		}
508	};
509
510	BX.Sale.BasketFilter.prototype.addSimilarItemsFilter = function(item)
511	{
512		this.currentFilter.similarHash = item.HASH;
513	};
514
515	BX.Sale.BasketFilter.prototype.clearSimilarItemsFilter = function()
516	{
517		this.currentFilter.similarHash = '';
518	};
519
520	BX.Sale.BasketFilter.prototype.showSimilarItemsFilter = function()
521	{
522		var item = this.component.getItemDataByTarget(BX.proxy_context);
523
524		if (this.currentFilter.similarHash !== item.HASH)
525		{
526			this.clearAllFiltersExcept(['similar']);
527			this.addSimilarItemsFilter(item);
528			this.onFilterChange();
529		}
530	};
531
532	BX.Sale.BasketFilter.prototype.getTimeoutDuration = function()
533	{
534		return this.component.duration.filterTimer;
535	};
536
537	BX.Sale.BasketFilter.prototype.onFilterChange = function()
538	{
539		this.component.showItemsOverlay();
540
541		if (
542			this.currentFilter.query.length
543			|| this.currentFilter.similarHash.length
544			|| this.currentFilter.warning
545			|| this.currentFilter.notAvailable
546			|| this.currentFilter.delayed
547		)
548		{
549			clearTimeout(this.filterTimer);
550			this.filterTimer = setTimeout(BX.proxy(this.enableFilterMode, this), this.getTimeoutDuration());
551		}
552		else
553		{
554			this.disableFilterMode();
555		}
556	};
557
558	BX.Sale.BasketFilter.prototype.enableFilterMode = function()
559	{
560		var foundItemsHash;
561
562		if (!this.activeFilterMode)
563		{
564			this.activeFilterMode = true;
565			this.realShownItems = BX.util.array_values(this.component.shownItems);
566			this.realSortedItems = BX.util.array_values(this.component.sortedItems);
567			this.realScrollTop = this.component.getDocumentScrollTop();
568		}
569
570		this.component.scrollToFirstItem();
571
572		this.component.sortedItems = this.searchItems();
573
574		foundItemsHash = JSON.stringify(this.component.sortedItems);
575
576		if (this.lastShownItemsHash !== foundItemsHash)
577		{
578			this.lastShownItemsHash = foundItemsHash;
579
580			this.component.deleteBasketItems(BX.util.array_values(this.component.shownItems), false);
581
582			if (this.component.sortedItems.length)
583			{
584				this.component.initializeBasketItems();
585				this.hideEmptyFilterResult();
586			}
587			else
588			{
589				this.showEmptyFilterResult();
590			}
591
592			if (this.currentFilter.similarHash.length)
593			{
594				this.component.showSimilarCount(true);
595			}
596		}
597		else
598		{
599			this.highlightFoundItems();
600		}
601
602		this.component.hideItemsOverlay();
603	};
604
605	BX.Sale.BasketFilter.prototype.disableFilterMode = function()
606	{
607		clearTimeout(this.filterTimer);
608		this.lastShownItemsHash = '';
609
610		if (this.activeFilterMode)
611		{
612			this.activeFilterMode = false;
613			this.component.sortedItems = BX.util.array_values(this.realSortedItems);
614
615			this.component.deleteBasketItems(BX.util.array_values(this.component.shownItems), false);
616			this.hideEmptyFilterResult();
617
618			this.component.editBasketItems(BX.util.array_values(this.realShownItems));
619			window.scrollTo(0, this.realScrollTop);
620		}
621
622		this.component.hideItemsOverlay();
623	};
624
625	BX.Sale.BasketFilter.prototype.searchItems = function()
626	{
627		var items = [];
628
629		for (var i = 0; i < this.realSortedItems.length; i++)
630		{
631			var item = this.component.items[this.realSortedItems[i]];
632
633			if (item && this.searchItemMatch(item))
634			{
635				items.push(item.ID);
636			}
637		}
638
639		return items;
640	};
641
642	BX.Sale.BasketFilter.prototype.highlightFoundItems = function()
643	{
644		if (!this.activeFilterMode)
645			return;
646
647		for (var i in this.component.shownItems)
648		{
649			if (this.component.shownItems.hasOwnProperty(i))
650			{
651				this.highlightSearchMatch(this.component.items[this.component.shownItems[i]]);
652			}
653		}
654	};
655
656	BX.Sale.BasketFilter.prototype.searchItemMatch = function(item)
657	{
658		var match = false,
659			found = false;
660
661		if (this.currentFilter.notAvailable)
662		{
663			found = !!item.NOT_AVAILABLE;
664			if (!found)
665			{
666				return match;
667			}
668		}
669		else if (this.currentFilter.delayed)
670		{
671			found = !!item.DELAYED;
672			if (!found)
673			{
674				return match;
675			}
676		}
677		else if (this.currentFilter.warning)
678		{
679			found = BX.util.in_array(item.ID, this.component.warningItems);
680			if (!found)
681			{
682				return match;
683			}
684		}
685		else if (BX.type.isNotEmptyString(this.currentFilter.similarHash))
686		{
687			found = this.currentFilter.similarHash === item.HASH;
688			if (!found)
689			{
690				return match;
691			}
692		}
693
694		if (BX.type.isNotEmptyString(this.currentFilter.query))
695		{
696			if (item.NAME.toLowerCase().indexOf(this.currentFilter.query) !== -1)
697			{
698				match = 'NAME';
699			}
700
701			if (!match)
702			{
703				var floatValue = parseFloat(this.currentFilter.query);
704				if (!isNaN(floatValue))
705				{
706					if (parseFloat(item.PRICE) === floatValue)
707					{
708						match = 'PRICE';
709					}
710					else if (parseFloat(item.SUM_PRICE) === floatValue)
711					{
712						match = 'SUM_PRICE';
713					}
714				}
715			}
716
717			if (!match && this.currentFilter.query.length >= 3)
718			{
719				if (item.PRICE_FORMATED.toLowerCase().indexOf(this.currentFilter.query) !== -1)
720				{
721					match = 'PRICE';
722				}
723				else if (item.SUM_PRICE_FORMATED.toLowerCase().indexOf(this.currentFilter.query) !== -1)
724				{
725					match = 'SUM_PRICE';
726				}
727			}
728
729			var k, lcValue;
730
731			if (!match && item.PROPS.length)
732			{
733				for (k in item.PROPS)
734				{
735					if (item.PROPS.hasOwnProperty(k))
736					{
737						lcValue = item.PROPS[k].VALUE.toLowerCase();
738
739						if (
740							lcValue === this.currentFilter.query
741							|| (this.currentFilter.query.length >= 3 && lcValue.indexOf(this.currentFilter.query) !== -1)
742						)
743						{
744							match = 'PROPS';
745							break;
746						}
747					}
748				}
749			}
750
751			if (!match && item.COLUMN_LIST.length)
752			{
753				for (k in item.COLUMN_LIST)
754				{
755					if (item.COLUMN_LIST.hasOwnProperty(k) && BX.type.isString(item.COLUMN_LIST[k].VALUE))
756					{
757						lcValue = item.COLUMN_LIST[k].VALUE.toLowerCase();
758
759						if (
760							lcValue === this.currentFilter.query
761							|| (this.currentFilter.query.length >= 3 && lcValue.indexOf(this.currentFilter.query) !== -1)
762						)
763						{
764							match = 'COLUMNS';
765							break;
766						}
767					}
768				}
769			}
770		}
771		else if (found)
772		{
773			match = true;
774		}
775
776		return match;
777	};
778
779	BX.Sale.BasketFilter.prototype.highlightSearchMatch = function(itemData)
780	{
781		var searchMatch = this.searchItemMatch(itemData);
782
783		if (searchMatch)
784		{
785			var entity, i, k, code;
786
787			switch (searchMatch)
788			{
789				case 'NAME':
790					entity = this.component.getEntity(BX(this.component.ids.item + itemData.ID), 'basket-item-name');
791					if (BX.type.isDomNode(entity))
792					{
793						entity.innerHTML = itemData.NAME.replace(
794							new RegExp('(.*)(' + this.currentFilter.query.replace(/[.*+?^${}
794()|[\]\\]/g, "\\$&") + ')(.*)', 'gi'),
795							function (full, match1 , match2, match3)
796							{
797								return BX.util.htmlspecialchars(match1)
798									+ '<span class="basket-item-highlighted">'
799									+ BX.util.htmlspecialchars(match2)
800									+ '</span>' + BX.util.htmlspecialchars(match3);
801							}
802						);
803					}
804					break;
805				case 'PRICE':
806					entity = BX(this.component.ids.price + itemData.ID);
807					BX.addClass(entity, 'basket-item-highlighted');
808					break;
809				case 'SUM_PRICE':
810					entity = BX(this.component.ids.sumPrice + itemData.ID);
811					BX.addClass(entity, 'basket-item-highlighted');
812					break;
813				case 'PROPS':
814					entity = this.component.getEntities(BX(this.component.ids.item + itemData.ID), 'basket-item-property-value');
815
816					for (i = 0; i < entity.length; i++)
817					{
818						code = entity[i].getAttribute('data-property-code');
819
820						for (k in itemData.PROPS)
821						{
822							if (itemData.PROPS.hasOwnProperty(k) && itemData.PROPS[k].CODE === code)
823							{
824								entity[i].innerHTML = itemData.PROPS[k].VALUE.replace(
825									new RegExp('(' + this.currentFilter.query + ')', 'gi'),
826									'<span class="basket-item-highlighted">$1</span>'
827								);
828							}
829						}
830					}
831					break;
832				case 'COLUMNS':
833					entity = this.component.getEntities(BX(this.component.ids.item + itemData.ID), 'basket-item-property-column-value');
834
835					for (i = 0; i < entity.length; i++)
836					{
837						code = entity[i].getAttribute('data-column-property-code');
838
839						for (k in itemData.COLUMN_LIST)
840						{
841							if (itemData.COLUMN_LIST.hasOwnProperty(k) && itemData.COLUMN_LIST[k].CODE === code)
842							{
843								entity[i].innerHTML = itemData.COLUMN_LIST[k].VALUE.replace(
844									new RegExp('(' + this.currentFilter.query + ')', 'gi'),
845									'<span class="basket-item-highlighted">$1</span>'
846								);
847							}
848						}
849					}
850					break;
851			}
852		}
853	};
854
855	BX.Sale.BasketFilter.prototype.showEmptyFilterResult = function()
856	{
857		var itemListNode = this.component.getCacheNode(this.component.ids.itemList);
858
859		if (BX.type.isDomNode(itemListNode) && itemListNode.clientHeight >= 500)
860		{
861			var emptyResultNode = this.component.getCacheNode(this.component.ids.itemListEmptyResult);
862
863			if (BX.type.isDomNode(emptyResultNode))
864			{
865				emptyResultNode.style.display = '';
866			}
867		}
868	};
869
870	BX.Sale.BasketFilter.prototype.hideEmptyFilterResult = function()
871	{
872		var emptyResultNode = this.component.getCacheNode(this.component.ids.itemListEmptyResult);
873
874		if (BX.type.isDomNode(emptyResultNode))
875		{
876			emptyResultNode.style.display = 'none';
877		}
878	};
879})();
880/* End */
881;
882; /* Start:"a:4:{s:4:"full";s:102:"/local/templates/psy/components/bitrix/sale.basket.basket/bootstrap_v5/js/component.js?172242677961750";s:6:"source";s:86:"/local/templates/psy/components/bitrix/sale.basket.basket/bootstrap_v5/js/component.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
883;(function() {
884	'use strict';
885
886	BX.namespace('BX.Sale.BasketComponent');
887
888	BX.Sale.BasketComponent = {
889		maxItemsShowCount: 30,
890		precisionFactor: Math.pow(10, 6),
891		stickyHeaderOffset: 0,
892
893		duration: {
894			priceAnimation: 300,
895			filterTimer: 300
896		},
897
898		ids: {
899			item: 'basket-item-',
900			quantity: 'basket-item-quantity-',
901			price: 'basket-item-price-',
902			sumPrice: 'basket-item-sum-price-',
903			sumPriceOld: 'basket-item-sum-price-old-',
904			sumPriceDiff: 'basket-item-sum-price-difference-',
905			itemHeightAligner: 'basket-item-height-aligner-',
906			total: 'basket-total-price',
907			basketRoot: 'basket-root',
908			itemListWrapper: 'basket-items-list-wrapper',
909			itemListContainer: 'basket-items-list-container',
910			itemList: 'basket-item-list',
911			itemListTable: 'basket-item-table',
912			itemListEmptyResult: 'basket-item-list-empty-result',
913			itemListOverlay: 'basket-items-list-overlay',
914			warning: 'basket-warning'
915		},
916
917		initializePrimaryFields: function()
918		{
919			this.templates = {};
920			this.nodes = {};
921
922			/** Object of all basket items (itemId => itemArray) */
923			this.items = {};
924
925			/** Array of all basket items to show sorted by field SORT */
926			this.sortedItems = [];
927
928			/** Array of basket items showed on screen */
929			this.shownItems = [];
930
931			/** Array of basket items changed since last request */
932			this.changedItems = [];
933
934			/** Array of basket items postponed by pool to edit */
935			this.postponedItems = [];
936
937			/** Array of basket items with warnings */
938			this.warningItems = [];
939
940			this.isMobile = BX.browser.IsMobile();
941			this.isTouch = BX.hasClass(document.documentElement, 'bx-touch');
942
943			this.lastAction = 'initialLoad';
944			this.coupons = null;
945
946			this.imagePopup = null;
947			this.loadingScreen = null;
948
949			this.quantityDelay = null;
950			this.quantityTimer = null;
951		},
952
953		init: function(parameters)
954		{
955			this.initializePrimaryFields();
956
957			this.params = parameters.params || {};
958			this.template = parameters.template || '';
959			this.signedParamsString = parameters.signedParamsString || '';
960			this.siteId = parameters.siteId || '';
961			this.siteTemplateId = parameters.siteTemplateId || '';
962			this.ajaxUrl = this.params.AJAX_PATH || '';
963			this.templateFolder = parameters.templateFolder || '';
964
965			this.useDynamicScroll = this.params.USE_DYNAMIC_SCROLL === 'Y';
966			this.useItemsFilter = this.params.SHOW_FILTER === 'Y' && !this.isMobile;
967
968			this.initializeFilter();
969			this.applyBasketResult(parameters.result);
970			this.initializeActionPool();
971
972			if (this.useItemsFilter)
973			{
974				this.checkHeaderDisplay();
975				this.bindHeaderEvents();
976			}
977
978			this.initializeBasketItems();
979			this.editTotal();
980			this.editWarnings();
981
982			this.getCacheNode(this.ids.basketRoot).style.opacity = 1;
983
984			this.bindInitialEvents();
985		},
986
987		getTemplate: function(templateName)
988		{
989			if (!this.templates.hasOwnProperty(templateName))
990			{
991				var template = BX(templateName);
992				this.templates[templateName] = BX.type.isDomNode(template) ? template.innerHTML : '';
993			}
994
995			return this.templates[templateName];
996		},
997
998		getCacheNode: function(id)
999		{
1000			if (!this.nodes.hasOwnProperty(id))
1001			{
1002				this.nodes[id] = BX(id);
1003			}
1004
1005			return this.nodes[id];
1006		},
1007
1008		getEntity: function(parent, entity, additionalFilter)
1009		{
1010			if (!parent || !entity)
1011				return null;
1012
1013			additionalFilter = additionalFilter || '';
1014
1015			return parent.querySelector(additionalFilter + '[data-entity="' + entity + '"]');
1016		},
1017
1018		getEntities: function(parent, entity, additionalFilter)
1019		{
1020			if (!parent || !entity)
1021				return {length: 0};
1022
1023			additionalFilter = additionalFilter || '';
1024
1025			return parent.querySelectorAll(additionalFilter + '[data-entity="' + entity + '"]');
1026		},
1027
1028		bindInitialEvents: function()
1029		{
1030			this.bindWarningEvents();
1031
1032			BX.bind(window, 'scroll', BX.proxy(this.checkStickyHeaders, this));
1033			BX.bind(window, 'scroll', BX.proxy(this.lazyLoad, this));
1034
1035			BX.bind(window, 'resize', BX.throttle(this.checkStickyHeaders, 20, this));
1036		},
1037
1038		bindWarningEvents: function()
1039		{
1040			var showItemsNode = this.getEntity(BX(this.ids.warning), 'basket-items-warning-count');
1041
1042			if (BX.type.isDomNode(showItemsNode))
1043			{
1044				showItemsNode.style.display = '';
1045				BX.bind(showItemsNode, 'click', BX.delegate(function() {this.toggleFilter('warning');}, this));
1046			}
1047
1048			BX.bind(
1049				this.getEntity(BX(this.ids.warning), 'basket-items-warning-notification-close'),
1050				'click',
1051				BX.proxy(this.removeAllWarnings, this)
1052			);
1053		},
1054
1055		toggleFilter: function(event)
1056		{
1057			var target = BX.type.isNotEmptyString(event) ?
1058				this.getEntity(
1059					this.getCacheNode(this.ids.itemListWrapper),
1060					'basket-items-count',
1061					'[data-filter="' + event + '"]'
1062				)
1063				: BX.getEventTarget(event);
1064
1065			if (!BX.type.isDomNode(target) || BX.hasClass(target, 'active'))
1066				return;
1067
1068			var entityName = target.getAttribute('data-filter');
1069			var entities = target.parentNode.querySelectorAll('[data-filter]');
1070
1071			for (var i = 0; i < entities.length; i++)
1072			{
1073				if (entities[i].getAttribute('data-filter') === entityName)
1074				{
1075					BX.addClass(entities[i], 'active');
1076				}
1077				else if (BX.hasClass(entities[i], 'active'))
1078				{
1079					BX.removeClass(entities[i], 'active');
1080				}
1081			}
1082
1083			this.filter.showFilterByName(entityName);
1084		},
1085
1086		scrollToFirstItem: function()
1087		{
1088			var headerNode = this.getEntity(this.getCacheNode(this.ids.itemListWrapper), 'basket-items-list-header');
1089
1090			if (BX.type.isDomNode(headerNode))
1091			{
1092				var itemListTopPosition = BX.pos(this.getCacheNode(this.ids.itemListContainer)).top;
1093				var headerBottomPosition = BX.pos(headerNode).bottom;
1094
1095				if (itemListTopPosition < headerBottomPosition)
1096				{
1097					window.scrollTo(0, itemListTopPosition - this.stickyHeaderOffset);
1098				}
1099			}
1100		},
1101
1102		showItemsOverlay: function()
1103		{
1104			var overlay = this.getCacheNode(this.ids.itemListOverlay);
1105
1106			if (BX.type.isDomNode(overlay))
1107			{
1108				overlay.style.display = '';
1109			}
1110		},
1111
1112		hideItemsOverlay: function()
1113		{
1114			var overlay = this.getCacheNode(this.ids.itemListOverlay);
1115
1116			if (BX.type.isDomNode(overlay))
1117			{
1118				overlay.style.display = 'none';
1119			}
1120		},
1121
1122		checkHeaderDisplay: function()
1123		{
1124			var header = this.getCacheNode(this.ids.itemListWrapper);
1125
1126			if (BX.type.isDomNode(header))
1127			{
1128				BX.removeClass(header, 'basket-items-list-wrapper-light');
1129			}
1130		},
1131
1132		bindHeaderEvents: function()
1133		{
1134			var entities = this.getEntities(this.getCacheNode(this.ids.itemListWrapper), 'basket-items-count');
1135
1136			for (var i = 0; i < entities.length; i++)
1137			{
1138				BX.bind(entities[i], 'click', BX.proxy(this.toggleFilter, this));
1139			}
1140		},
1141
1142		checkStickyHeaders: function()
1143		{
1144			if (this.isMobile)
1145				return;
1146
1147			var node, position;
1148			var border = 2, offset = 0;
1149			var scrollTop = this.getDocumentScrollTop();
1150			var basketPosition = BX.pos(this.getCacheNode(this.ids.basketRoot));
1151			var basketScrolledToEnd = scrollTop + 200 >= basketPosition.bottom;
1152
1153			if (BX.util.in_array('top', this.params.TOTAL_BLOCK_DISPLAY))
1154			{
1155				var totalBlockNode = this.getEntity(this.getCacheNode(this.ids.basketRoot), 'basket-total-block');
1156				if (BX.type.isDomNode(totalBlockNode))
1157				{
1158					node = this.getEntity(totalBlockNode, 'basket-checkout-aligner');
1159					if (BX.type.isDomNode(node))
1160					{
1161						position = BX.pos(totalBlockNode);
1162
1163						if (scrollTop >= position.top)
1164						{
1165							offset += node.clientHeight;
1166
1167							if (!BX.hasClass(node, 'basket-checkout-container-fixed'))
1168							{
1169								totalBlockNode.style.height = position.height + 'px';
1170
1171								node.style.width = node.clientWidth + border + 'px';
1172								BX.addClass(node, 'basket-checkout-container-fixed');
1173							}
1174						}
1175						else if (BX.hasClass(node, 'basket-checkout-container-fixed'))
1176						{
1177							totalBlockNode.style.height = '';
1178
1179							node.style.width = '';
1180							BX.removeClass(node, 'basket-checkout-container-fixed');
1181						}
1182
1183						if (basketScrolledToEnd)
1184						{
1185							if (!BX.hasClass(node, 'basket-checkout-container-fixed-hide'))
1186							{
1187								BX.addClass(node, 'basket-checkout-container-fixed-hide');
1188							}
1189						}
1190						else if (BX.hasClass(node, 'basket-checkout-container-fixed-hide'))
1191						{
1192							BX.removeClass(node, 'basket-checkout-container-fixed-hide');
1193						}
1194					}
1195				}
1196			}
1197
1198			if (this.useItemsFilter)
1199			{
1200				var itemWrapperNode = this.getCacheNode(this.ids.itemListWrapper);
1201
1202				node = this.getEntity(itemWrapperNode, 'basket-items-list-header');
1203				if (BX.type.isDomNode(node))
1204				{
1205					position = BX.pos(itemWrapperNode);
1206
1207					if ((scrollTop + offset >= position.top) && !basketScrolledToEnd)
1208					{
1209						if (!BX.hasClass(node, 'basket-items-list-header-fixed'))
1210						{
1211							node.style.width = node.clientWidth + border + 'px';
1212
1213							itemWrapperNode.style.paddingTop = node.clientHeight + 'px';
1214
1215							BX.addClass(node, 'basket-items-list-header-fixed');
1216						}
1217
1218						if (offset)
1219						{
1220							node.style.top = offset + 'px';
1221						}
1222
1223						offset += node.clientHeight;
1224					}
1225					else if (BX.hasClass(node, 'basket-items-list-header-fixed'))
1226					{
1227						itemWrapperNode.style.paddingTop = '';
1228
1229						node.style.width = '';
1230						node.style.top = '';
1231
1232						BX.removeClass(node, 'basket-items-list-header-fixed');
1233					}
1234				}
1235			}
1236
1237			this.stickyHeaderOffset = offset;
1238		},
1239
1240		getDocumentScrollTop: function()
1241		{
1242			return window.scrollY
1243				|| window.pageYOffset
1244				|| document.body.scrollTop + (document.documentElement && document.documentElement.scrollTop || 0);
1245		},
1246
1247		lazyLoad: function()
1248		{
1249			var itemsNodePosition = BX.pos(this.getCacheNode(this.ids.itemListContainer));
1250
1251			if (this.getDocumentScrollTop() + window.innerHeight >= itemsNodePosition.bottom - 400)
1252			{
1253				var itemIds = this.getItemsAfter();
1254				if (itemIds.length)
1255				{
1256					this.editBasketItems(itemIds);
1257				}
1258			}
1259		},
1260
1261		fireCustomEvents: function()
1262		{
1263			if (this.result.EVENT_ONCHANGE_ON_START === 'Y')
1264			{
1265				BX.onCustomEvent('OnBasketChange');
1266			}
1267
1268			if (this.params.HIDE_COUPON !== 'Y')
1269			{
1270				if (this.coupons !== null && this.coupons !== this.result.COUPON_LIST)
1271				{
1272					BX.onCustomEvent('OnCouponApply');
1273				}
1274
1275				this.coupons = this.result.COUPON_LIST;
1276			}
1277		},
1278
1279		editTotal: function()
1280		{
1281			this.fillTotalBlocks();
1282			this.showItemsCount();
1283			this.showWarningItemsCount();
1284			this.showNotAvailableItemsCount();
1285			this.showDelayedItemsCount();
1286		},
1287
1288		fillTotalBlocks: function()
1289		{
1290			var totalNodes = this.getEntities(this.getCacheNode(this.ids.basketRoot), 'basket-total-block');
1291
1292			if (totalNodes && totalNodes.length)
1293			{
1294				var totalTemplate = this.getTemplate('basket-total-template');
1295				if (totalTemplate)
1296				{
1297					var totalRender = this.render(totalTemplate, this.result.TOTAL_RENDER_DATA);
1298
1299					for (var i in totalNodes)
1300					{
1301						if (totalNodes.hasOwnProperty(i) && BX.type.isDomNode(totalNodes[i])
1301)
1302						{
1303							totalNodes[i].innerHTML = totalRender;
1304
1305							this.bindTotalEvents(totalNodes[i]);
1306						}
1307					}
1308				}
1309			}
1310
1311			this.checkStickyHeaders();
1312		},
1313
1314		showItemsCount: function()
1315		{
1316			var itemCountNode = this.getEntity(
1317				this.getCacheNode(this.ids.itemListWrapper),
1318				'basket-items-count',
1319				'[data-filter="all"]'
1320			);
1321
1322			if (BX.type.isDomNode(itemCountNode))
1323			{
1324				itemCountNode.innerHTML = BX.message('SBB_IN_BASKET') + ' ' + this.result.BASKET_ITEMS_COUNT + ' ' + this.getGoodsMessage(this.result.BASKET_ITEMS_COUNT);
1325				itemCountNode.style.display = '';
1326			}
1327		},
1328
1329		showSimilarCount: function(state)
1330		{
1331			var itemCountNode = this.getEntity(
1332				this.getCacheNode(this.ids.itemListWrapper),
1333				'basket-items-count',
1334				'[data-filter="similar"]'
1335			);
1336
1337			if (BX.type.isDomNode(itemCountNode))
1338			{
1339				if (state)
1340				{
1341					itemCountNode.innerHTML = this.sortedItems.length + ' '
1342						+ this.getGoodsMessage(this.result.BASKET_ITEMS_COUNT, 'SBB_SIMILAR_ITEM');
1343					itemCountNode.style.display = '';
1344				}
1345				else
1346				{
1347					itemCountNode.style.display = 'none';
1348				}
1349			}
1350		},
1351
1352		showWarningItemsCount: function()
1353		{
1354			var itemCountNode = this.getEntity(
1355				this.getCacheNode(this.ids.itemListWrapper),
1356				'basket-items-count',
1357				'[data-filter="warning"]'
1358			);
1359
1360			if (BX.type.isDomNode(itemCountNode))
1361			{
1362				if (this.warningItems.length)
1363				{
1364					itemCountNode.innerHTML = this.warningItems.length + ' ' + BX.message('SBB_BASKET_ITEMS_WARNING');
1365					itemCountNode.style.display = '';
1366				}
1367				else
1368				{
1369					itemCountNode.style.display = 'none';
1370				}
1371			}
1372		},
1373
1374		showNotAvailableItemsCount: function()
1375		{
1376			var itemCountNode = this.getEntity(
1377				this.getCacheNode(this.ids.itemListWrapper),
1378				'basket-items-count',
1379				'[data-filter="not-available"]'
1380			);
1381
1382			if (BX.type.isDomNode(itemCountNode))
1383			{
1384				if (parseInt(this.result.NOT_AVAILABLE_BASKET_ITEMS_COUNT))
1385				{
1386					itemCountNode.innerHTML = this.result.NOT_AVAILABLE_BASKET_ITEMS_COUNT + ' '
1387						+ this.getGoodsMessage(this.result.NOT_AVAILABLE_BASKET_ITEMS_COUNT, 'SBB_NOT_AVAILABLE_ITEM');
1388					itemCountNode.style.display = '';
1389				}
1390				else
1391				{
1392					itemCountNode.style.display = 'none';
1393				}
1394			}
1395		},
1396
1397		showDelayedItemsCount: function()
1398		{
1399			var itemCountNode = this.getEntity(
1400				this.getCacheNode(this.ids.itemListWrapper),
1401				'basket-items-count',
1402				'[data-filter="delayed"]'
1403			);
1404
1405			if (BX.type.isDomNode(itemCountNode))
1406			{
1407				if (parseInt(this.result.DELAYED_BASKET_ITEMS_COUNT))
1408				{
1409					itemCountNode.innerHTML = this.result.DELAYED_BASKET_ITEMS_COUNT + ' '
1410						+ this.getGoodsMessage(this.result.DELAYED_BASKET_ITEMS_COUNT, 'SBB_DELAYED_ITEM');
1411					itemCountNode.style.display = '';
1412				}
1413				else
1414				{
1415					itemCountNode.style.display = 'none';
1416				}
1417			}
1418		},
1419
1420		getGoodsMessage: function(count, customMessage)
1421		{
1422			var mesCode;
1423			var countReminder = (count > 10 && count < 20) ? 0 : count % 10;
1424
1425			if (countReminder === 1)
1426			{
1427				mesCode = customMessage || 'SBB_GOOD';
1428			}
1429			else if (countReminder >= 2 && countReminder <= 4)
1430			{
1431				mesCode = customMessage ? customMessage + '_2' : 'SBB_GOOD_2';
1432			}
1433			else
1434			{
1435				mesCode = customMessage ? customMessage + 'S' : 'SBB_GOODS';
1436			}
1437
1438			return BX.message(mesCode);
1439		},
1440
1441		bindTotalEvents: function(node)
1442		{
1443			if (!this.result.TOTAL_RENDER_DATA.DISABLE_CHECKOUT)
1444			{
1445				BX.bind(this.getEntity(node, 'basket-checkout-button'), 'click', BX.proxy(this.checkOutAction, this));
1446			}
1447
1448			BX.bind(this.getEntity(node, 'basket-coupon-input'), 'change', BX.proxy(this.addCouponAction, this));
1449			BX.bind(this.getEntity(node, 'basket-coupon-input'), 'paste', BX.proxy(this.pasteCouponAction, this));
1450
1451			var couponNodes = this.getEntities(node, 'basket-coupon-delete');
1452			for (var i = 0, l = couponNodes.length; i < l; i++)
1453			{
1454				BX.bind(couponNodes[i], 'click', BX.proxy(this.removeCouponAction, this));
1455			}
1456
1457		},
1458
1459		checkOutAction: function()
1460		{
1461			document.location.href = this.params.PATH_TO_ORDER;
1462		},
1463
1464		addCouponAction: function(event)
1465		{
1466			var target = BX.getEventTarget(event);
1467			if (target && target.value)
1468			{
1469				this.actionPool.addCoupon(target.value);
1470				target.disabled = true;
1471			}
1472		},
1473
1474		pasteCouponAction: function(event)
1475		{
1476			setTimeout(BX.delegate(function() {
1477				this.addCouponAction(event);
1478			}, this), 10);
1479		},
1480
1481		removeCouponAction: function()
1482		{
1483			var value = BX.proxy_context && BX.util.trim(BX.proxy_context.getAttribute('data-coupon'));
1484			if (value)
1485			{
1486				this.actionPool.removeCoupon(value);
1487			}
1488		},
1489
1490		initializeActionPool: function()
1491		{
1492			this.actionPool = new BX.Sale.BasketActionPool(this);
1493		},
1494
1495		initializeFilter: function()
1496		{
1497			this.filter = new BX.Sale.BasketFilter(this);
1498		},
1499
1500		/**
1501		 * Send ajax request with basket data and executes callback by action
1502		 */
1503		sendRequest: function(action, data)
1504		{
1505			this.lastAction = action;
1506
1507			if (this.lastAction === 'recalculateAjax')
1508			{
1509				// we use it to reload all items if applied discounts changed
1510				data.lastAppliedDiscounts = BX.util.array_keys(this.result.FULL_DISCOUNT_LIST).join(',');
1511
1512				if (this.params.USE_ENHANCED_ECOMMERCE === 'Y')
1513				{
1514					this.checkAnalytics(data);
1515				}
1516			}
1517
1518			BX.ajax({
1519				method: 'POST',
1520				dataType: 'json',
1521				url: this.ajaxUrl,
1522				data: this.getData(data),
1523				onsuccess: BX.delegate(function(result) {
1524					this.actionPool.doProcessing(false);
1525
1526					if (!BX.type.isPlainObject(result))
1527						return;
1528
1529					this.actionPool.setRefreshStatus(result.BASKET_REFRESHED);
1530
1531					if (result.RESTORED_BASKET_ITEMS)
1532					{
1533						this.restoreBasketItems(result.RESTORED_BASKET_ITEMS);
1534					}
1535
1536					if (result.DELETED_BASKET_ITEMS)
1537					{
1538						this.deleteBasketItems(result.DELETED_BASKET_ITEMS, this.params.SHOW_RESTORE === 'Y');
1539					}
1540
1541					if (result.MERGED_BASKET_ITEMS)
1542					{
1543						this.deleteBasketItems(result.MERGED_BASKET_ITEMS, false, true);
1544					}
1545
1546					this.applyBasketResult(result.BASKET_DATA);
1547					this.editBasketItems(this.getItemsToEdit());
1548					this.editTotal();
1549
1550					this.applyPriceAnimation();
1551					this.editWarnings();
1552
1553					this.actionPool.switchTimer();
1554
1555					if (this.isBasketIntegrated() && this.isBasketChanged())
1556					{
1557						BX.Sale.OrderAjaxComponent.sendRequest();
1558					}
1559				}, this),
1560				onfailure: BX.delegate(function() {
1561					this.actionPool.doProcessing(false);
1562				}, this)
1563			});
1564		},
1565
1566		isBasketIntegrated: function()
1567		{
1568			return this.params.BASKET_WITH_ORDER_INTEGRATION === 'Y';
1569		},
1570
1571		isBasketChanged: function()
1572		{
1573			return this.changedItems.length;
1574		},
1575
1576		addPriceAnimationData: function(nodeId, start, finish, currency)
1577		{
1578			if (!BX.type.isPlainObject(this.priceAnimationData))
1579			{
1580				this.clearPriceAnimationData();
1581			}
1582
1583			this.priceAnimationData.start[nodeId] = parseFloat(start);
1584			this.priceAnimationData.finish[nodeId] = parseFloat(finish);
1585			this.priceAnimationData.currency[nodeId] = currency;
1586			this.priceAnimationData.int[nodeId] = (parseFloat(start) === parseInt(start)) && (parseFloat(finish) === parseInt(finish));
1587		},
1588
1589		clearPriceAnimationData: function()
1590		{
1591			this.priceAnimationData = {
1592				start: {},
1593				finish: {},
1594				currency: {},
1595				int: {}
1596			};
1597		},
1598
1599		applyBasketResult: function(result)
1600		{
1601			this.changedItems = [];
1602			this.clearPriceAnimationData();
1603
1604			if (!BX.type.isPlainObject(result))
1605			{
1606				return;
1607			}
1608
1609			if (result.BASKET_ITEM_RENDER_DATA)
1610			{
1611				var i, newData;
1612
1613				for (i in result.BASKET_ITEM_RENDER_DATA)
1614				{
1615					if (result.BASKET_ITEM_RENDER_DATA.hasOwnProperty(i))
1616					{
1617						newData = result.BASKET_ITEM_RENDER_DATA[i];
1618						newData.WARNINGS = this.checkBasketItemWarnings(newData, result.WARNING_MESSAGE_WITH_CODE);
1619
1620						if (this.items[newData.ID])
1621						{
1622							if (JSON.stringify(this.items[newData.ID]) === JSON.stringify(newData))
1623							{
1624								continue;
1625							}
1626						}
1627						else
1628						{
1629							this.addSortedItem(newData.ID, true);
1630						}
1631
1632						this.changedItems.push(newData.ID);
1633
1634						newData = this.checkBasketItemsAnimation(newData);
1635						this.items[newData.ID] = newData;
1636					}
1637				}
1638
1639				this.changedItems = BX.util.array_unique(this.changedItems.concat(this.getChangedSimilarOffers()));
1640
1641				if (this.isBasketChanged())
1642				{
1643					this.sortSortedItems(true);
1644				}
1645			}
1646
1647			if (result.TOTAL_RENDER_DATA)
1648			{
1649				result.TOTAL_RENDER_DATA = this.checkTotalAnimation(result.TOTAL_RENDER_DATA);
1650			}
1651
1652			this.result = result;
1653		},
1654
1655		itemSortFunction: function(a, b)
1656		{
1657			if (!this.items.hasOwnProperty(a) || !this.items.hasOwnProperty(b))
1658			{
1659				return 0;
1660			}
1661
1662			return parseFloat(this.items[a].SORT) - parseFloat(this.items[b].SORT);
1663		},
1664
1665		getChangedSimilarOffers: function()
1666		{
1667			var changedSimilarOffers = [];
1668
1669			var otherSimilarItemsQuantity, totalSimilarItemsQuantity;
1670			var hashMap = this.getHashMap();
1671
1672			for (var hash in hashMap)
1673			{
1674				if (hashMap.hasOwnProperty(hash))
1675				{
1676					if (hashMap[hash].length > 1)
1677					{
1678						for (var i = 0; i < hashMap[hash].length; i++)
1679						{
1680							otherSimilarItemsQuantity = 0;
1681							totalSimilarItemsQuantity = 0;
1682
1683							for (var k = 0; k < hashMap[hash].length; k ++)
1684							{
1685								if (hashMap[hash][k] != hashMap[hash][i])
1686								{
1687									otherSimilarItemsQuantity += parseFloat(this.items[hashMap[hash][k]].QUANTITY);
1688								}
1689
1690								totalSimilarItemsQuantity += parseFloat(this.items[hashMap[hash][k]].QUANTITY);
1691							}
1692
1693							if (
1694								!this.items[hashMap[hash][i]].HAS_SIMILAR_ITEMS
1695								|| this.items[hashMap[hash][i]].SIMILAR_ITEMS_QUANTITY != otherSimilarItemsQuantity
1696								|| this.items[hashMap[hash][i]].TOTAL_SIMILAR_ITEMS_QUANTITY != totalSimilarItemsQuantity
1697							)
1698							{
1699								changedSimilarOffers.push(hashMap[hash][i]);
1700
1701								this.items[hashMap[hash][i]].HAS_SIMILAR_ITEMS = true;
1702								this.items[hashMap[hash][i]].SIMILAR_ITEMS_QUANTITY = otherSimilarItemsQuantity;
1703								this.items[hashMap[hash][i]].TOTAL_SIMILAR_ITEMS_QUANTITY = totalSimilarItemsQuantity;
1704
1705								this.items[hashMap[hash][i]].ALL_AVAILABLE_QUANTITY = this.items[hashMap[hash][i]].AVAILABLE_QUANTITY;
1706								this.items[hashMap[hash][i]].AVAILABLE_QUANTITY = this.items[hashMap[hash][i]].ALL_AVAILABLE_QUANTITY - otherSimilarItemsQuantity;
1707							}
1708						}
1709					}
1710					else if (hashMap[hash][0] && this.items[hashMap[hash][0]].HAS_SIMILAR_ITEMS)
1711					{
1712						changedSimilarOffers.push(hashMap[hash][0]);
1713
1714						delete this.items[hashMap[hash][0]].HAS_SIMILAR_ITEMS;
1715						delete this.items[hashMap[hash][0]].SIMILAR_ITEMS_QUANTITY;
1716						delete this.items[hashMap[hash][0]].TOTAL_SIMILAR_ITEMS_QUANTITY;
1717
1718						this.items[hashMap[hash][0]].AVAILABLE_QUANTITY = this.items[hashMap[hash][0]].ALL_AVAILABLE_QUANTITY;
1719						delete this.items[hashMap[hash][0]].ALL_AVAILABLE_QUANTITY;
1720					}
1721				}
1722			}
1723
1724			return changedSimilarOffers;
1725		},
1726
1727		getHashMap: function()
1728		{
1729			var hashMap = {};
1730
1731			for (var id in this.items)
1732			{
1733				if (this.items.hasOwnProperty(id) && this.isItemAvailable(id))
1734				{
1735					if (!hashMap.hasOwnProperty(this.items[id].HASH))
1736					{
1737						hashMap[this.items[id].HASH] = [];
1738					}
1739
1740					hashMap[this.items[id].HASH].push(id);
1741				}
1742			}
1743
1744			return hashMap;
1745		},
1746
1747		isItemAvailable: function(itemId)
1748		{
1749			var sortedItems = this.filter.isActive() ? this.filter.realSortedItems : this.sortedItems;
1750
1751			return !this.items[itemId].NOT_AVAILABLE
1752				&& !this.items[itemId].SHOW_RESTORE
1753				&& BX.util.in_array(itemId, sortedItems);
1754		},
1755
1756		checkTotalAnimation: function(totalData)
1757		{
1758			if (this.result && this.result.TOTAL_RENDER_DATA && parseFloat(this.result.TOTAL_RENDER_DATA.PRICE) > parseFloat(totalData.PRICE))
1759			{
1760				totalData.PRICE_NEW = totalData.PRICE;
1761				totalData.PRICE = this.result.TOTAL_RENDER_DATA.PRICE;
1762
1763				totalData.PRICE_FORMATED_NEW = totalData.PRICE_FORMATED;
1764				totalData.PRICE_FORMATED = this.result.TOTAL_RENDER_DATA.PRICE_FORMATED;
1765
1766				this.addPriceAnimationData(this.ids.total, totalData.PRICE, totalData.PRICE_NEW, totalData.CURRENCY);
1767			}
1768
1769			return totalData;
1770		},
1771
1772		checkBasketItemsAnimation: function(itemData)
1773		{
1774			var itemId = itemData.ID;
1775
1776			if (this.items[itemId])
1777			{
1778				var quantityNode = BX(this.ids.quantity + itemId);
1779				if (
1780					BX.type.isDomNode(quantityNode)
1781					&& !this.actionPool.isItemInPool(itemId)
1782					&& parseFloat(quantityNode.value) !== parseFloat(itemData.QUANTITY)
1783				)
1784				{
1785					itemData.QUANTITY_ANIMATION = true;
1786					this.actionPool.clearLastActualQuantityPool(itemId);
1787				}
1788
1789				if (parseFloat(this.items[itemId].PRICE) > parseFloat(itemData.PRICE))
1790				{
1791					itemData.PRICE_NEW = itemData.PRICE;
1792					itemData.PRICE = this.items[itemId].PRICE;
1793
1794					itemData.PRICE_FORMATED_NEW = itemData.PRICE_FORMATED;
1795					itemData.PRICE_FORMATED = this.items[itemId].PRICE_FORMATED;
1796
1797					this.addPriceAnimationData(this.ids.price + itemId, itemData.PRICE, itemData.PRICE_NEW, itemData.CURRENCY);
1798				}
1799
1800				if (
1801					BX.util.in_array('SUM', this.params.COLUMNS_LIST)
1802					&& parseFloat(this.items[itemId].SUM_PRICE) > parseFloat(itemData.SUM_PRICE)
1803					&& parseFloat(this.items[itemId].QUANTITY) === parseFloat(itemData.QUANTITY)
1804				)
1805				{
1806					itemData.SUM_PRICE_NEW = itemData.SUM_PRICE;
1807					itemData.SUM_PRICE = this.items[itemId].SUM_PRICE;
1808
1809					itemData.SUM_PRICE_FORMATED_NEW = itemData.SUM_PRICE_FORMATED;
1810					itemData.SUM_PRICE_FORMATED = this.items[itemId].SUM_PRICE_FORMATED;
1811
1812					this.addPriceAnimationData(this.ids.sumPrice + itemId, itemData.SUM_PRICE, itemData.SUM_PRICE_NEW, itemData.CURRENCY);
1813				}
1814			}
1815
1816			return itemData;
1817		},
1818
1819		getData: function(data)
1820		{
1821			data = data || {};
1822
1823			data[this.params.ACTION_VARIABLE] = this.lastAction;
1824			data.via_ajax = 'Y';
1825			data.site_id = this.siteId;
1826			data.site_template_id = this.siteTemplateId;
1827			data.sessid = BX.bitrix_sessid();
1828			data.template = this.template;
1829			data.signedParamsString = this.signedParamsString;
1830
1831			return data;
1832		},
1833
1834		startLoader: function()
1835		{
1836			// if (!this.loadingScreen)
1837			// {
1838			// 	this.loadingScreen = new BX.PopupWindow('loading_screen', null, {
1839			// 		events: {
1840			// 			onAfterPopupShow: BX.delegate(function() {
1841			// 				BX.cleanNode(this.loadingScreen.popupContainer);
1842			// 				BX.removeClass(this.loadingScreen.popupContainer, 'popup-window');
1843			// 				this.loadingScreen.popupContainer.appendChild(
1844			// 					BX.create('IMG', {props: {src: this.templateFolder + '/images/loader.gif'}})
1845			// 				);
1846			// 				this.loadingScreen.popupContainer.removeAttribute('style');
1847			// 				this.loadingScreen.popupContainer.style.display = 'block';
1848			// 			}, this)
1849			// 		}
1850			// 	});
1851			// 	BX.addClass(this.loadingScreen.popupContainer, 'bx-step-opacity');
1852			// }
1853			//
1854			// this.loadingScreen.show();
1855		},
1856
1857		/**
1858		 * Hiding loader image with overlay.
1859		 */
1860		endLoader: function()
1861		{
1862			// if (this.loadingScreen && this.loadingScreen.isShown())
1863			// {
1864			// 	this.loadingScreen.close();
1865			// }
1866		},
1867
1868		editWarnings: function()
1869		{
1870			this.editGeneralWarnings();
1871			this.editBasketItemWarnings();
1872			this.toggleWarningBlock();
1873			this.showWarningItemsCount();
1874		},
1875
1876		editGeneralWarnings: function()
1877		{
1878			var warningsNode = this.getEntity(this.getCacheNode(this.ids.warning), 'basket-general-warnings');
1879
1880			if (BX.type.isDomNode(warningsNode))
1881			{
1882				var generalWarningText = warningsNode.innerHTML;
1883
1884				if (this.result.WARNING_MESSAGE_WITH_CODE)
1885				{
1886					for (var code in this.result.WARNING_MESSAGE_WITH_CODE)
1887					{
1888						if (this.result.WARNING_MESSAGE_WITH_CODE.hasOwnProperty(code))
1889						{
1890							if (
1891								!this.items[code]
1892								&& generalWarningText.indexOf(this.result.WARNING_MESSAGE_WITH_CODE[code]) === -1
1893							)
1894							{
1895								generalWarningText += this.result.WARNING_MESSAGE_WITH_CODE[code] + '<br/>';
1896							}
1897						}
1898					}
1899				}
1900
1901				if (generalWarningText)
1902				{
1903					warningsNode.innerHTML = generalWarningText;
1904					warningsNode.style.display = '';
1905				}
1906				else
1907				{
1908					warningsNode.style.display = 'none';
1909					warningsNode.innerHTML = '';
1910				}
1911			}
1912		},
1913
1914		editBasketItemWarnings: function()
1915		{
1916			var itemsWarningsNode = this.getEntity(this.getCacheNode(this.ids.warning), 'basket-item-warnings');
1917
1918			if (BX.type.isDomNode(itemsWarningsNode))
1919			{
1920				if (this.warningItems.length)
1921				{
1922					var warningCount = this.getEntity(itemsWarningsNode, 'basket-items-warning-count');
1923					if (BX.type.isDomNode(warningCount))
1924					{
1925						warningCount.innerHTML = this.warningItems.length + ' ' + this.getGoodsMessage(this.warningItems.length);
1926					}
1927
1928					itemsWarningsNode.style.display = '';
1929				}
1930				else if (itemsWarningsNode.style.display !== 'none')
1931				{
1932					itemsWarningsNode.style.display = 'none';
1933
1934					if (this.filter.isActive())
1935					{
1936						this.toggleFilter('all');
1937					}
1938				}
1939			}
1940		},
1941
1942		toggleWarningBlock: function()
1943		{
1944			var warningNode = this.getCacheNode(this.ids.warning);
1945
1946			if (BX.type.isDomNode(warningNode))
1947			{
1948				var generalWarningNode = this.getEntity(warningNode, 'basket-general-warnings');
1949				var itemsWarningsNode = this.getEntity(warningNode, 'basket-item-warnings');
1950
1951				if (
1952					(!BX.type.isDomNode(generalWarningNode) || generalWarningNode.style.display === 'none')
1953					&& (!BX.type.isDomNode(itemsWarningsNode) || itemsWarningsNode.style.display === 'none')
1954				)
1955				{
1956					warningNode.style.display = 'none';
1957				}
1958				else
1959				{
1960					warningNode.style.display = '';
1961				}
1962			}
1963		},
1964
1965		checkBasketItemWarnings: function(itemData, warnings)
1966		{
1967			if (!itemData)
1968				return;
1969
1970			var itemWarnings;
1971
1972			if (this.items[itemData.ID] && this.lastAction === 'refreshAjax')
1973			{
1974				itemWarnings = this.items[itemData.ID].WARNINGS;
1975			}
1976			else
1977			{
1978				itemWarnings = [];
1979			}
1980
1981			if (BX.type.isArray(warnings[itemData.ID]) && warnings[itemData.ID].length)
1982			{
1983				for (var i in warnings[itemData.ID])
1984				{
1985					if (warnings[itemData.ID].hasOwnProperty(i) && !BX.util.in_array(warnings[itemData.ID][i], itemWarnings))
1986					{
1987						itemWarnings.push(warnings[itemData.ID][i]);
1988					}
1989				}
1990			}
1991
1992			if (itemWarnings.length)
1993			{
1994				if (!BX.util.in_array(itemData.ID, this.warningItems))
1995				{
1996					this.warningItems.push(itemData.ID);
1997				}
1998			}
1999			else if (BX.util.in_array(itemData.ID, this.warningItems))
2000			{
2001				this.warningItems.splice(BX.util.array_search(itemData.ID, this.warningItems), 1);
2002			}
2003
2004			return itemWarnings;
2005		},
2006
2007		removeAllWarnings: function(event)
2008		{
2009			this.clearGeneralWarnings();
2010			this.clearBasketItemsWarnings();
2011
2012			this.editWarnings();
2013
2014			event && event.preventDefault();
2015		},
2016
2017		clearGeneralWarnings: function()
2018		{
2019			this.result.WARNING_MESSAGE_WITH_CODE = {};
2020
2021			var generalWarningNode = this.getEntity(this.getCacheNode(this.ids.warning), 'basket-general-warnings');
2022
2023			if (BX.type.isDomNode(generalWarningNode))
2024			{
2025				generalWarningNode.innerHTML = '';
2026			}
2027		},
2028
2029		clearBasketItemsWarnings: function()
2030		{
2031			var itemsToEdit = [];
2032
2033			for (var i in this.warningItems)
2034			{
2035				if (this.warningItems.hasOwnProperty(i))
2036				{
2037					this.items[this.warningItems[i]].WARNINGS = [];
2038
2039					if (this.isItemShown(this.warningItems[i]))
2040					{
2041						itemsToEdit.push(this.warningItems[i]);
2042					}
2043				}
2044			}
2045
2046			this.warningItems = [];
2047			this.editBasketItems(itemsToEdit);
2048		},
2049
2050		isItemShown: function(itemId)
2051		{
2052			return BX.util.in_array(itemId, this.shownItems);
2053		},
2054
2055		initializeBasketItems: function()
2056		{
2057			if (Object.keys(this.items).length === 0)
2058				return;
2059
2060			for (var i = 0; i < this.sortedItems.length; i++)
2061			{
2062				if (this.useDynamicScroll && this.shownItems.length >= this.maxItemsShowCount)
2063				{
2064					break;
2065				}
2066
2067				this.createBasketItem(this.sortedItems[i]);
2068			}
2069		},
2070
2071		createBasketItem: function(itemId)
2072		{
2073			if (!this.items[itemId])
2074			{
2075				return;
2076			}
2077
2078			var basketItemTemplate = this.getTemplate('basket-item-template');
2079			if (basketItemTemplate)
2080			{
2081				var basketItemHtml = this.renderBasketItem(basketItemTemplate, this.items[itemId]);
2082				var sortIndex = BX.util.array_search(itemId, this.sortedItems);
2083
2084				if (this.shownItems.length && sortIndex >= 0)
2085				{
2086					if (sortIndex < BX.util.array_search(this.shownItems[0], this.sortedItems))
2087					{
2088						// insert before
2089						BX(this.ids.item + this.shownItems[0]).insertAdjacentHTML('beforebegin', basketItemHtml);
2090						this.shownItems.unshift(itemId);
2091					}
2092					else if (sortIndex > BX.util.array_search(this.shownItems[this.shownItems.length - 1], this.sortedItems))
2093					{
2094						// insert after
2095						BX(this.ids.item + this.shownItems[this.shownItems.length - 1]).insertAdjacentHTML('afterend', basketItemHtml);
2096						this.shownItems.push(itemId);
2097					}
2098					else
2099					{
2100						// insert between
2101						BX(this.ids.item + this.sortedItems[sortIndex + 1]).insertAdjacentHTML('beforebegin', basketItemHtml);
2102						this.shownItems.splice(sortIndex + 1, 0, itemId);
2103					}
2104				}
2105				else
2106				{
2107					this.getCacheNode(this.ids.itemListTable).insertAdjacentHTML('beforeend', basketItemHtml);
2108					this.shownItems.push(itemId);
2109				}
2110
2111				this.bindBasketItemEvents(this.items[itemId]);
2112
2113				if (this.filter.isActive())
2114				{
2115					this.filter.highlightSearchMatch(this.items[itemId]);
2116				}
2117			}
2118		},
2119
2120		getItemsToEdit: function()
2121		{
2122			var itemIds = [];
2123
2124			if (this.isBasketChanged())
2125			{
2126				for (var i in this.changedItems)
2127				{
2128					if (this.changedItems.hasOwnProperty(i) && this.isItemShown(this.changedItems[i]))
2129					{
2130						itemIds.push(this.changedItems[i]);
2131					}
2132				}
2133			}
2134
2135			return itemIds;
2136		},
2137
2138		getItemsAfter: function()
2139		{
2140			var itemIdsAfter = [];
2141
2142			if (this.useDynamicScroll)
2143			{
2144				var lastShownItemId = this.shownItems[this.shownItems.length - 1] || false;
2145
2146				if (lastShownItemId)
2147				{
2148					var i = 0;
2149					var index = BX.util.array_search(lastShownItemId, this.sortedItems);
2150
2151					while (this.sortedItems[++index] && i++ < this.maxItemsShowCount)
2152					{
2153						itemIdsAfter.push(this.sortedItems[index]);
2154					}
2155				}
2156			}
2157
2158			return itemIdsAfter;
2159		},
2160
2161		editBasketItems: function(itemIds)
2162		{
2163			if (!itemIds || itemIds.length === 0)
2164			{
2165				return;
2166			}
2167
2168			var i, item;
2169
2170			for (i in itemIds)
2171			{
2172				if (!itemIds.hasOwnProperty(i) || !BX.type.isPlainObject(this.items[itemIds[i]]))
2173				{
2174					continue;
2175				}
2176
2177				item = this.items[itemIds[i]];
2178
2179				if (this.actionPool.isItemInPool(item.ID))
2180				{
2181					if (!BX.util.in_array(item.ID, this.postponedItems))
2182					{
2183						this.postponedItems.push(item.ID);
2184					}
2185
2186					continue;
2187				}
2188
2189				if (BX.type.isDomNode(BX(this.ids.item + item.ID)))
2190				{
2191					this.redrawBasketItemNode(item.ID);
2192					this.applyQuantityAnimation(item.ID);
2193				}
2194				else
2195				{
2196					this.createBasketItem(item.ID);
2197				}
2198			}
2199		},
2200
2201		editPostponedBasketItems: function()
2202		{
2203			if (!this.postponedItems.length)
2204				return;
2205
2206			var itemsToEdit = [];
2207
2208			for (var i in this.postponedItems)
2209			{
2210				if (this.postponedItems.hasOwnProperty(i) && this.isItemShown(this.postponedItems[i]))
2211				{
2212					itemsToEdit.push(this.postponedItems[i]);
2213				}
2214			}
2215
2216			this.postponedItems = [];
2217			this.editBasketItems(itemsToEdit);
2218		},
2219
2220		applyQuantityAnimation: function(itemId)
2221		{
2222			var basketItemNode = BX(this.ids.item + itemId);
2223
2224			if (BX.type.isDomNode(basketItemNode) && this.items[itemId])
2225			{
2226				if (this.items[itemId].QUANTITY_ANIMATION)
2227				{
2228					BX.addClass(BX(this.ids.quantity + itemId), 'basket-updated');
2229				}
2230			}
2231		},
2232
2233		applyPriceAnimation: function()
2234		{
2235			if (!this.priceAnimationData || Object.keys(this.priceAnimationData.start).length === 0)
2236				return;
2237
2238			var animationData = this.priceAnimationData,
2239				nodeCache = {};
2240
2241			new BX.easing({
2242				duration: this.params.USE_PRICE_ANIMATION === 'Y' ? this.duration.priceAnimation : 1,
2243				start: animationData.start,
2244				finish: animationData.finish,
2245				transition: BX.easing.makeEaseOut(BX.easing.transitions.quad),
2246				step: BX.delegate(function(state){
2247					for (var nodeId in animationData.start)
2248					{
2249						if (animationData.start.hasOwnProperty(nodeId))
2250						{
2251							if (!nodeCache[nodeId])
2252							{
2253								if (nodeId === this.ids.total)
2254								{
2255									nodeCache[nodeId] = this.getEntities(this.getCacheNode(this.ids.basketRoot), this.ids.total);
2256								}
2257								else
2258								{
2259									var node = BX(nodeId);
2260									nodeCache[nodeId] = node ? [node] : [];
2261								}
2262							}
2263
2264							if (!animationData.int[nodeId])
2265							{
2266								// fix price blinking
2267								state[nodeId] = (state[nodeId] + (state[nodeId] % 1000) / 1000).toFixed(5);
2268							}
2269
2270							for (var i = 0; i < nodeCache[nodeId].length; i++)
2271							{
2272								nodeCache[nodeId][i].innerHTML = this.getFormatPrice(state[nodeId], animationData.currency[nodeId]);
2273							}
2274						}
2275					}
2276				}, this),
2277				complete: BX.delegate(function() {
2278					var nodeId, formattedPrice, itemId, type;
2279
2280					for (nodeId in animationData.start)
2281					{
2282						if (animationData.start.hasOwnProperty(nodeId))
2283						{
2284							formattedPrice = this.getFormatPrice(animationData.finish[nodeId], animationData.currency[nodeId]);
2285
2286							for (var i = 0; i < nodeCache[nodeId].length; i++)
2287							{
2288								nodeCache[nodeId][i].innerHTML = formattedPrice;
2289							}
2290
2291							if (nodeId.indexOf(this.ids.sumPrice) !== -1)
2292							{
2293								type = 'SUM_PRICE';
2294								itemId = nodeId.substr(this.ids.sumPrice.length);
2295							}
2296							else if (nodeId.indexOf(this.ids.price) !== -1)
2297							{
2298								type = 'PRICE';
2299								itemId = nodeId.substr(this.ids.price.length);
2300							}
2301							else if (nodeId.indexOf(this.ids.total) !== -1)
2302							{
2303								type = 'TOTAL';
2304								itemId = '';
2305							}
2306							else
2307							{
2308								itemId = '';
2309								type = '';
2310							}
2311
2312							if (BX.type.isNotEmptyString(type))
2313							{
2314								if (itemId)
2315								{
2316									this.items[itemId][type] = animationData.finish[nodeId];
2317									delete this.items[itemId][type + '_NEW'];
2318									this.items[itemId][type + '_FORMATED'] = formattedPrice;
2319									delete this.items[itemId][type + '_FORMATED_NEW'];
2320								}
2321								else if (type === 'TOTAL')
2322								{
2323									this.result.TOTAL_RENDER_DATA.PRICE = animationData.finish[nodeId];
2324									delete this.result.TOTAL_RENDER_DATA.PRICE_NEW;
2325									this.result.TOTAL_RENDER_DATA.PRICE_FORMATED = formattedPrice;
2326									delete this.result.TOTAL_RENDER_DATA.PRICE_FORMATED_NEW;
2327								}
2328							}
2329						}
2330					}
2331
2332					this.filter.highlightFoundItems();
2333				}, this)
2334			}).animate();
2335		},
2336
2337		getFormatPrice: function(price, currency)
2338		{
2339			return BX.Currency.currencyFormat(price, currency, true);
2340		},
2341
2342		deleteBasketItems: function(items, restore, final)
2343		{
2344			if (!items || !items.length)
2345			{
2346				return;
2347			}
2348
2349			for (var i in items)
2350			{
2351				if (items.hasOwnProperty(i))
2352				{
2353					this.deleteBasketItem(items[i], restore, final);
2354				}
2355			}
2356		},
2357
2358		deleteBasketItem: function(itemId, restore, final)
2359		{
2360			// delete not available item with no chance to restore
2361			if (this.items[itemId].NOT_AVAILABLE && restore)
2362			{
2363				restore = false;
2364				final = true;
2365			}
2366
2367			if (restore)
2368			{
2369				this.items[itemId].SHOW_RESTORE = true;
2370				this.items[itemId].SHOW_LOADING = false;
2371				this.redrawBasketItemNode(itemId);
2372			}
2373			else
2374			{
2375				this.changeShownItem(itemId);
2376				BX.remove(BX(this.ids.item + itemId));
2377			}
2378
2379			if (final)
2380			{
2381				this.changeSortedItem(itemId, false, true);
2382				this.changeShownItem(itemId, false, true);
2383			}
2384		},
2385
2386		addSortedItem: function(itemId, all)
2387		{
2388			this.sortedItems.push(itemId.toString());
2389
2390			if (all && this.filter.isActive())
2391			{
2392				this.filter.realSortedItems.push(itemId.toString());
2393			}
2394		},
2395
2396		changeSortedItem: function(itemId, newItemId, all)
2397		{
2398			var index = BX.util.array_search(itemId, this.sortedItems);
2399
2400			if (index >= 0)
2401			{
2402				if (newItemId)
2403				{
2404					this.sortedItems.splice(index, 1, newItemId.toString());
2405				}
2406				else
2407				{
2408					this.sortedItems.splice(index, 1);
2409				}
2410			}
2411
2412			if (all && this.filter.isActive())
2413			{
2414				index = BX.util.array_search(itemId, this.filter.realSortedItems);
2415
2416				if (index >= 0)
2417				{
2418					if (newItemId)
2419					{
2420						this.filter.realSortedItems.splice(index, 1, newItemId.toString());
2421					}
2422					else
2423					{
2424						this.filter.realSortedItems.splice(index, 1);
2425					}
2426				}
2427			}
2428		},
2429
2430		sortSortedItems: function(all)
2431		{
2432			this.sortedItems.sort(BX.proxy(this.itemSortFunction, this));
2433
2434			if (all && this.filter.isActive())
2435			{
2436				this.filter.realSortedItems.sort(BX.proxy(this.itemSortFunction, this));
2437			}
2438		},
2439
2440		changeShownItem: function(itemId, newItemId, all)
2441		{
2442			var index = BX.util.array_search(itemId, this.shownItems);
2443
2444			if (index >= 0)
2445			{
2446				if (newItemId)
2447				{
2448					this.shownItems.splice(index, 1, newItemId.toString());
2449				}
2450				else
2451				{
2452					this.shownItems.splice(index, 1);
2453				}
2454			}
2455
2456			if (all && this.filter.isActive())
2457			{
2458				index = BX.util.array_search(itemId, this.filter.realShownItems);
2459
2460				if (index >= 0)
2461				{
2462					if (newItemId)
2463					{
2464						this.filter.realShownItems.splice(index, 1, newItemId.toString());
2465					}
2466					else
2467					{
2468						this.filter.realShownItems.splice(index, 1);
2469					}
2470				}
2471			}
2472		},
2473
2474		redrawBasketItemNode: function(itemId)
2475		{
2476			var basketItemNode = BX(this.ids.item + itemId);
2477
2478			if (!this.items[itemId] || !BX.type.isDomNode(basketItemNode))
2479				return;
2480
2481			var basketItemTemplate = this.getTemplate('basket-item-template');
2482			if (basketItemTemplate)
2483			{
2484				var nodeAligner = BX(this.ids.itemHeightAligner + itemId),
2485					oldHeight;
2486
2487				if (BX.type.isDomNode(nodeAligner))
2488				{
2489					oldHeight = nodeAligner.clientHeight;
2490				}
2491
2492				var basketItemHtml = this.renderBasketItem(basketItemTemplate, this.items[itemId]);
2493				basketItemNode.insertAdjacentHTML('beforebegin', basketItemHtml);
2494				BX.remove(basketItemNode);
2495
2496				if (oldHeight)
2497				{
2498					nodeAligner = BX(this.ids.itemHeightAligner + itemId);
2499
2500					if (BX.type.isDomNode(nodeAligner) && nodeAligner.clientHeight < oldHeight)
2501					{
2502						nodeAligner.style.minHeight = oldHeight + 'px';
2503						setTimeout(function(){nodeAligner.style.minHeight = '0px';}, 1);
2504					}
2505				}
2506
2507				this.bindBasketItemEvents(this.items[itemId]);
2508
2509				if (this.filter.isActive())
2510				{
2511					this.filter.highlightSearchMatch(this.items[itemId]);
2512				}
2513			}
2514		},
2515
2516		restoreBasketItems: function(items)
2517		{
2518			if (!items || Object.keys(items).length === 0)
2519			{
2520				return;
2521			}
2522
2523			var oldItemId, newItemId, basketItemNode;
2524
2525			for (oldItemId in items)
2526			{
2527				if (items.hasOwnProperty(oldItemId))
2528				{
2529					newItemId = items[oldItemId];
2530
2531					if (this.isItemShown(oldItemId))
2532					{
2533						this.changeShownItem(oldItemId, newItemId, true);
2534
2535						basketItemNode = BX(this.ids.item + oldItemId);
2536						if (BX.type.isDomNode(basketItemNode))
2537						{
2538							basketItemNode.id = this.ids.item + newItemId;
2539							basketItemNode.setAttribute('data-id', newItemId);
2540						}
2541					}
2542
2543					this.changeSortedItem(oldItemId, false, true);
2544				}
2545			}
2546		},
2547
2548		bindBasketItemEvents: function(itemData)
2549		{
2550			if (!itemData)
2551				return;
2552
2553			var itemNode = BX(this.ids.item + itemData.ID);
2554			if (BX.type.isDomNode(itemNode))
2555			{
2556				this.bindQuantityEvents(itemNode, itemData);
2557				this.bindSkuEvents(itemNode, itemData);
2558				this.bindImageEvents(itemNode, itemData);
2559				this.bindActionEvents(itemNode, itemData);
2560				this.bindRestoreAction(itemNode, itemData);
2561				this.bindItemWarningEvents(itemNode, itemData);
2562			}
2563		},
2564
2565		bindQuantityEvents: function(node, data)
2566		{
2567			if (!node || !data || !this.isItemAvailable(data.ID))
2568				return;
2569
2570			var entity;
2571
2572			var block = this.getEntity(node, 'basket-item-quantity-block');
2573			if (block)
2574			{
2575				var startEventName = this.isTouch ? 'touchstart' : 'mousedown';
2576				var endEventName = this.isTouch ? 'touchend' : 'mouseup';
2577
2578				entity = this.getEntity(block, 'basket-item-quantity-minus');
2579				BX.bind(entity, startEventName, BX.proxy(this.startQuantityInterval, this));
2580				BX.bind(entity, endEventName, BX.proxy(this.clearQuantityInterval, this));
2581				BX.bind(entity, 'mouseout', BX.proxy(this.clearQuantityInterval, this));
2582				BX.bind(entity, 'click', BX.proxy(this.quantityMinus, this));
2583
2584				entity = this.getEntity(block, 'basket-item-quantity-plus');
2585				BX.bind(entity, startEventName, BX.proxy(this.startQuantityInterval, this));
2586				BX.bind(entity, endEventName, BX.proxy(this.clearQuantityInterval, this));
2587				BX.bind(entity, 'mouseout', BX.proxy(this.clearQuantityInterval, this));
2588				BX.bind(entity, 'click', BX.proxy(this.quantityPlus, this));
2589
2590				entity = this.getEntity(block, 'basket-item-quantity-field');
2591				BX.bind(entity, 'change', BX.proxy(this.quantityChange, this));
2592			}
2593		},
2594
2595		startQuantityInterval: function()
2596		{
2597			var target = BX.proxy_context;
2598			var func = target.getAttribute('data-entity') === 'basket-item-quantity-minus'
2599				? BX.proxy(this.quantityMinus, this)
2600				: BX.proxy(this.quantityPlus, this);
2601
2602			this.quantityDelay = setTimeout(
2603				BX.delegate(function() {
2604					this.quantityTimer = setInterval(function(){func(target);}, 150);
2605				}, this),
2606				300
2607			);
2608		},
2609
2610		clearQuantityInterval: function()
2611		{
2612			clearTimeout(this.quantityDelay);
2613			clearInterval(this.quantityTimer);
2614		},
2615
2616		quantityPlus: function(target)
2617		{
2618			if (!BX.type.isDomNode(target))
2619			{
2620				target = BX.proxy_context;
2621				this.clearQuantityInterval();
2622			}
2623
2624			var itemData = this.getItemDataByTarget(target);
2625			if (itemData)
2626			{
2627				var quantityField = BX(this.ids.quantity + itemData.ID);
2628				var isQuantityFloat = this.isQuantityFloat(itemData);
2629
2630				var currentQuantity = isQuantityFloat ? parseFloat(quantityField.value) : Math.round(quantityField.value);
2631				var measureRatio = isQuantityFloat ? parseFloat(itemData.MEASURE_RATIO) : parseInt(itemData.MEASURE_RATIO);
2632
2633				var quantity = parseFloat((currentQuantity + measureRatio).toFixed(5));
2634				quantity = this.getCorrectQuantity(itemData, quantity);
2635
2636				this.setQuantity(itemData, quantity);
2637			}
2638		},
2639
2640		quantityMinus: function(target)
2641		{
2642			target = BX.type.isDomNode(target) ? target : BX.proxy_context;
2643
2644			var itemData = this.getItemDataByTarget(target);
2645			if (itemData)
2646			{
2647				var quantityField = BX(this.ids.quantity + itemData.ID);
2648				var isQuantityFloat = this.isQuantityFloat(itemData);
2649
2650				var currentQuantity = isQuantityFloat ? parseFloat(quantityField.value) : Math.round(quantityField.value);
2651				var measureRatio = isQuantityFloat ? parseFloat(itemData.MEASURE_RATIO) : parseInt(itemData.MEASURE_RATIO);
2652
2653				var quantity = parseFloat((currentQuantity - measureRatio).toFixed(5));
2654				quantity = this.getCorrectQuantity(itemData, quantity);
2655
2656				this.setQuantity(itemData, quantity);
2657			}
2658		},
2659
2660		quantityChange: function()
2661		{
2662			var itemData = this.getItemDataByTarget(BX.proxy_context);
2663			if (itemData)
2664			{
2665				var quantityField, quantity;
2666
2667				quantityField = BX(this.ids.quantity + itemData.ID);
2668				quantity = this.getCorrectQuantity(itemData, quantityField.value);
2669
2670				this.setQuantity(itemData, quantity);
2671			}
2672		},
2673
2674		isQuantityFloat: function(item)
2675		{
2676			return this.params.QUANTITY_FLOAT === 'Y' || (parseInt(item.MEASURE_RATIO) !== parseFloat(item.MEASURE_RATIO));
2677		},
2678
2679		getCorrectQuantity: function(itemData, quantity)
2680		{
2681			var isQuantityFloat = this.isQuantityFloat(itemData),
2682				measureRatio = isQuantityFloat ? parseFloat(itemData.MEASURE_RATIO) : parseInt(itemData.MEASURE_RATIO),
2683				availableQuantity = 0;
2684
2685			quantity = (isQuantityFloat ? parseFloat(quantity) : parseInt(quantity, 10)) || 0;
2686			if (quantity < 0)
2687			{
2688				quantity = 0;
2689			}
2690
2691			if (measureRatio > 0 && quantity < measureRatio)
2692			{
2693				quantity = measureRatio;
2694			}
2695
2696			if (itemData.CHECK_MAX_QUANTITY === 'Y')
2697			{
2698				availableQuantity = isQuantityFloat ? parseFloat(itemData.AVAILABLE_QUANTITY) : parseInt(itemData.AVAILABLE_QUANTITY);
2699				if (availableQuantity > 0 && quantity > availableQuantity)
2700				{
2701					quantity = availableQuantity;
2702				}
2703			}
2704
2705			var reminder = (quantity / measureRatio - ((quantity / measureRatio).toFixed(0))).toFixed(5),
2706				remain;
2707
2708			if (parseFloat(reminder) === 0)
2709			{
2710				return quantity;
2711			}
2712
2713			if (measureRatio !== 0 && measureRatio !== 1)
2714			{
2715				remain = (quantity * this.precisionFactor) % (measureRatio * this.precisionFactor) / this.precisionFactor;
2716
2717				if (measureRatio > 0 && remain > 0)
2718				{
2719					if (
2720						remain >= measureRatio / 2
2721						&& (
2722							availableQuantity === 0
2723							|| (quantity + measureRatio - remain) <= availableQuantity
2724						)
2725					)
2726					{
2727						quantity += (measureRatio - remain);
2728					}
2729					else
2730					{
2731						quantity -= remain;
2732					}
2733				}
2734			}
2735
2736			quantity = isQuantityFloat ? parseFloat(quantity) : parseInt(quantity, 10);
2737
2738			return quantity;
2739		},
2740
2741		setQuantity: function(itemData, quantity)
2742		{
2743			var quantityField = BX(this.ids.quantity + itemData.ID),
2744				currentQuantity;
2745
2746			if (quantityField)
2747			{
2748				quantity = parseFloat(quantity);
2749				currentQuantity = parseFloat(quantityField.getAttribute('data-value'));
2750
2751				quantityField.value = quantity;
2752
2753				if (parseFloat(itemData.QUANTITY) !== parseFloat(quantity))
2754				{
2755					this.animatePriceByQuantity(itemData, quantity);
2756					this.actionPool.changeQuantity(itemData.ID, quantity, currentQuantity);
2757				}
2758			}
2759		},
2760
2761		animatePriceByQuantity: function(itemData, quantity)
2762		{
2763			var priceNode = BX(this.ids.sumPrice + itemData.ID);
2764			if (!BX.type.isDomNode(priceNode))
2765				return;
2766
2767			var quantityMultiplier = quantity / parseFloat(itemData.MEASURE_RATIO);
2768
2769			var startPrice = parseFloat(itemData.SUM_PRICE),
2770				finalPrice = parseFloat(itemData.PRICE) * quantityMultiplier,
2771				isInt = parseInt(startPrice) === parseFloat(startPrice)
2772					&& parseInt(finalPrice) === parseFloat(finalPrice);
2773
2774			if (startPrice !== finalPrice)
2775			{
2776				this.items[itemData.ID].QUANTITY = quantity;
2777				this.items[itemData.ID].SUM_PRICE = finalPrice;
2778
2779				new BX.easing({
2780					duration: this.params.USE_PRICE_ANIMATION === 'Y' ? this.duration.priceAnimation : 1,
2781					start: {price: startPrice},
2782					finish: {price: finalPrice},
2783					transition: BX.easing.makeEaseOut(BX.easing.transitions.quad),
2784					step: BX.delegate(function(state){
2785						if (!isInt)
2786						{
2787							// fix price blinking
2788							state.price = (state.price + (state.price % 1000) / 1000).toFixed(5);
2789						}
2790
2791						priceNode.innerHTML = this.getFormatPrice(state.price, itemData.CURRENCY);
2792					}, this),
2793					complete: BX.delegate(function() {
2794						var node, price;
2795
2796						priceNode.innerHTML = this.getFormatPrice(finalPrice, itemData.CURRENCY);
2797
2798						node = BX(this.ids.sumPriceOld + itemData.ID);
2799						if (BX.type.isDomNode(node))
2800						{
2801							price = parseFloat(itemData.FULL_PRICE) * quantityMultiplier;
2802							node.innerHTML = this.getFormatPrice(price, itemData.CURRENCY);
2803						}
2804
2805						node = BX(this.ids.sumPriceDiff + itemData.ID);
2806						if (BX.type.isDomNode(node))
2807						{
2808							price = parseFloat(itemData.DISCOUNT_PRICE) * quantityMultiplier;
2809							node.innerHTML = this.getFormatPrice(price, itemData.CURRENCY);
2810						}
2811					}, this)
2812				}).animate();
2813			}
2814		},
2815
2816		getItemDataByTarget: function(target)
2817		{
2818			var data = false;
2819			var id;
2820
2821			var itemNode = BX.findParent(target, {attrs: {'data-entity': 'basket-item'}});
2822			if (itemNode)
2823			{
2824				id = itemNode.getAttribute('data-id');
2825				data = this.items[id];
2826			}
2827
2828			return data;
2829		},
2830
2831		bindSkuEvents: function(node, data)
2832		{
2833			if (!node || !data)
2834				return;
2835
2836			var blocks = this.getEntities(node, 'basket-item-sku-block');
2837			var blockEntities, i, l, ii, ll;
2838
2839			for (i = 0, l = blocks.length; i < l; i++)
2840			{
2841				blockEntities = this.getEntities(blocks[i], 'basket-item-sku-field');
2842
2843				for (ii = 0, ll = blockEntities.length; ii < ll; ii++)
2844				{
2845					BX.bind(blockEntities[ii], 'click', BX.proxy(this.changeSku, this));
2846				}
2847			}
2848		},
2849
2850		changeSku: function()
2851		{
2852			var i, l;
2853
2854			var target = BX.proxy_context;
2855
2856			if (BX.hasClass(target, 'selected'))
2857				return;
2858
2859			var itemData = this.getItemDataByTarget(target);
2860			if (itemData)
2861			{
2862				var basketItemNode = BX(this.ids.item + itemData.ID);
2863				if (basketItemNode)
2864				{
2865					var currentSkuListNodes = this.getEntities(target.parentNode, 'basket-item-sku-field');
2866					for (i = 0, l = currentSkuListNodes.length; i < l; i++)
2867					{
2868						if (currentSkuListNodes[i].isEqualNode(target))
2869						{
2870							BX.addClass(currentSkuListNodes[i], 'selected');
2871						}
2872						else
2873						{
2874							BX.removeClass(currentSkuListNodes[i], 'selected');
2875						}
2876					}
2877
2878					this.actionPool.changeSku(
2879						itemData.ID,
2880						this.getSkuPropertyValues(basketItemNode),
2881						this.getInitialSkuPropertyValues(basketItemNode)
2882					);
2883				}
2884			}
2885		},
2886
2887		getSkuPropertyValues: function(basketItemNode)
2888		{
2889			var propertyValues = {};
2890
2891			var propNodes = this.getEntities(basketItemNode, 'basket-item-sku-field', '.selected');
2892			for (var i = 0, l = propNodes.length; i < l; i++)
2893			{
2894				propertyValues[propNodes[i].getAttribute('data-property')] = BX.util.htmlspecialcharsback(propNodes[i].getAttribute('data-value-id'));
2895			}
2896
2897			return propertyValues;
2898		},
2899
2900		getInitialSkuPropertyValues: function(basketItemNode)
2901		{
2902			var propertyValues = {};
2903
2904			var propNodes = this.getEntities(basketItemNode, 'basket-item-sku-field', '[data-initial="true"]');
2905			for (var i = 0, l = propNodes.length; i < l; i++)
2906			{
2907				propertyValues[propNodes[i].getAttribute('data-property')] = BX.util.htmlspecialcharsback(propNodes[i].getAttribute('data-value-id'));
2908			}
2909
2910			return propertyValues;
2911		},
2912
2913		bindImageEvents: function(node, data)
2914		{
2915			if (!node || !data)
2916				return;
2917
2918			var images = node.querySelectorAll('.basket-item-custom-block-photo-item');
2919			for (var i = 0, l = images.length; i < l; i++)
2920			{
2921				BX.bind(images[i], 'click', BX.proxy(this.showPropertyImagePopup, this));
2922			}
2923		},
2924
2925		showPropertyImagePopup: function()
2926		{
2927			var target, propertyCode, imageIndex, item, imageSrc, i;
2928
2929			target = BX.proxy_context;
2930			item = this.getItemDataByTarget(target);
2931
2932			propertyCode = target.getAttribute('data-column-property-code');
2933			imageIndex = target.getAttribute('data-image-index');
2934
2935			if (item && item.COLUMN_LIST)
2936			{
2937				for (i in item.COLUMN_LIST)
2938				{
2939					if (
2940						item.COLUMN_LIST.hasOwnProperty(i)
2941						&& item.COLUMN_LIST[i].CODE === propertyCode
2942						&& item.COLUMN_LIST[i].VALUE[imageIndex]
2943					)
2944					{
2945						imageSrc = item.COLUMN_LIST[i].VALUE[imageIndex].IMAGE_SRC_ORIGINAL;
2946						break;
2947					}
2948				}
2949			}
2950
2951			if (!imageSrc)
2952			{
2953				return;
2954			}
2955
2956			if (this.imagePopup)
2957			{
2958				this.imagePopup.destroy();
2959			}
2960
2961			var imageId = 'bx-soa-image-popup-content';
2962			var that = this;
2963
2964			this.imagePopup = new BX.PopupWindow('bx-soa-image-popup', null, {
2965				lightShadow: true,
2966				offsetTop: 0,
2967				offsetLeft: 0,
2968				closeIcon: {top: '3px', right: '10px'},
2969				autoHide: true,
2970				bindOptions: {position: 'bottom'},
2971				closeByEsc: true,
2972				zIndex: 100,
2973				events: {
2974					onPopupShow: function() {
2975						BX.create('IMG', {
2976							props: {src: imageSrc},
2977							events: {
2978								load: function() {
2979									var content = BX(imageId);
2980									if (content)
2981									{
2982										var windowSize = BX.GetWindowInnerSize(),
2983											ratio = that.isMobile ? 0.5 : 0.9,
2984											contentHeight, contentWidth;
2985
2986										BX.cleanNode(content);
2987										content.appendChild(this);
2988
2989										contentHeight = content.offsetHeight;
2990										contentWidth = content.offsetWidth;
2991
2992										if (contentHeight >
2992 windowSize.innerHeight * ratio)
2993										{
2994											content.style.height = windowSize.innerHeight * ratio + 'px';
2995											content.style.width = contentWidth * (windowSize.innerHeight * ratio / contentHeight) + 'px';
2996											contentHeight = content.offsetHeight;
2997											contentWidth = content.offsetWidth;
2998										}
2999
3000										if (contentWidth > windowSize.innerWidth * ratio)
3001										{
3002											content.style.width = windowSize.innerWidth * ratio + 'px';
3003											content.style.height = contentHeight * (windowSize.innerWidth * ratio / contentWidth) + 'px';
3004										}
3005
3006										content.style.height = content.offsetHeight + 'px';
3007										content.style.width = content.offsetWidth + 'px';
3008
3009										that.imagePopup.adjustPosition();
3010									}
3011								}
3012							}
3013						});
3014					},
3015					onPopupClose: function() {
3016						this.destroy();
3017					}
3018				},
3019				content: BX.create('DIV', {props: {id: imageId}})
3020			});
3021			this.imagePopup.show();
3022		},
3023
3024		bindActionEvents: function(node, data)
3025		{
3026			if (!node || !data)
3027				return;
3028
3029			var entity;
3030
3031			if (BX.util.in_array('DELETE', this.params.COLUMNS_LIST))
3032			{
3033				entity = this.getEntities(node, 'basket-item-delete');
3034				for (var i = 0, l = entity.length; i < l; i++)
3035				{
3036					BX.bind(entity[i], 'click', BX.proxy(this.deleteAction, this));
3037				}
3038			}
3039
3040			if (BX.util.in_array('DELAY', this.params.COLUMNS_LIST))
3041			{
3042				entity = this.getEntity(node, 'basket-item-add-delayed');
3043				BX.bind(entity, 'click', BX.proxy(this.addDelayedAction, this));
3044			}
3045
3046			entity = this.getEntity(node, 'basket-item-remove-delayed');
3047			BX.bind(entity, 'click', BX.proxy(this.removeDelayedAction, this));
3048
3049			entity = this.getEntity(node, 'basket-item-merge-sku-link');
3050			BX.bind(entity, 'click', BX.proxy(this.mergeAction, this));
3051
3052			entity = this.getEntity(node, 'basket-item-show-similar-link');
3053			BX.bind(entity, 'click', BX.delegate(function() {this.toggleFilter('similar');}, this));
3054		},
3055
3056		deleteAction: function()
3057		{
3058			var itemData = this.getItemDataByTarget(BX.proxy_context);
3059			if (itemData)
3060			{
3061				this.actionPool.deleteItem(itemData.ID);
3062
3063				this.items[itemData.ID].SHOW_LOADING = true;
3064
3065				if (this.params.SHOW_RESTORE === 'Y' && this.isItemAvailable(itemData.ID))
3066				{
3067					this.items[itemData.ID].SHOW_RESTORE = true;
3068				}
3069
3070				this.redrawBasketItemNode(itemData.ID);
3071			}
3072		},
3073
3074		addDelayedAction: function()
3075		{
3076			var itemData = this.getItemDataByTarget(BX.proxy_context);
3077			if (itemData)
3078			{
3079				this.actionPool.addDelayed(itemData.ID);
3080
3081				this.items[itemData.ID].SHOW_LOADING = true;
3082				this.redrawBasketItemNode(itemData.ID);
3083			}
3084		},
3085
3086		removeDelayedAction: function()
3087		{
3088			var itemData = this.getItemDataByTarget(BX.proxy_context);
3089			if (itemData)
3090			{
3091				this.actionPool.removeDelayed(itemData.ID);
3092
3093				this.items[itemData.ID].SHOW_LOADING = true;
3094				this.redrawBasketItemNode(itemData.ID);
3095			}
3096		},
3097
3098		mergeAction: function()
3099		{
3100			var itemData = this.getItemDataByTarget(BX.proxy_context);
3101			if (itemData)
3102			{
3103				this.actionPool.mergeSku(itemData.ID);
3104			}
3105		},
3106
3107		bindRestoreAction: function(node, itemData)
3108		{
3109			if (!node || !itemData || this.params.SHOW_RESTORE !== 'Y')
3110				return;
3111
3112			BX.bind(
3113				this.getEntity(node, 'basket-item-restore-button'),
3114				'click',
3115				BX.delegate(function() {
3116					this.actionPool.restoreItem(itemData.ID, {
3117						PRODUCT_ID: itemData.PRODUCT_ID,
3118						QUANTITY: itemData.QUANTITY,
3119						PROPS: itemData.PROPS_ALL,
3120						SORT: itemData.SORT,
3121						MODULE: itemData.MODULE,
3122						PRODUCT_PROVIDER_CLASS: itemData.PRODUCT_PROVIDER_CLASS
3123					});
3124
3125					this.items[itemData.ID].SHOW_RESTORE = false;
3126					this.items[itemData.ID].SHOW_LOADING = true;
3127					this.redrawBasketItemNode(itemData.ID);
3128				}, this)
3129			);
3130			BX.bind(
3131				this.getEntity(node, 'basket-item-close-restore-button'),
3132				'click',
3133				BX.delegate(function() {
3134					this.deleteBasketItem(itemData.ID, false, true);
3135				}, this)
3136			);
3137		},
3138
3139		bindItemWarningEvents: function(node, data)
3140		{
3141			if (!node || !data)
3142				return;
3143
3144			BX.bind(
3145				this.getEntity(BX(this.ids.item + data.ID), 'basket-item-warning-close'),
3146				'click',
3147				BX.proxy(this.closeItemWarnings, this)
3148			);
3149		},
3150
3151		closeItemWarnings: function()
3152		{
3153			var target = BX.proxy_context;
3154
3155			if (BX.type.isDomNode(target))
3156			{
3157				var itemData = this.getItemDataByTarget(target);
3158
3159				this.items[itemData.ID].WARNINGS = [];
3160				this.warningItems.splice(BX.util.array_search(itemData.ID, this.warningItems), 1);
3161
3162				this.redrawBasketItemNode(itemData.ID);
3163				this.editWarnings();
3164			}
3165		},
3166
3167		renderBasketItem: function(template, data)
3168		{
3169			var clonedData = BX.clone(data);
3170
3171			if (BX.type.isPlainObject(clonedData))
3172			{
3173				clonedData.USE_FILTER = this.useItemsFilter
3174					&& !this.filter.currentFilter.similarHash.length;
3175			}
3176
3177			return Mustache.render(template, clonedData);
3178		},
3179
3180		render: function(template, data)
3181		{
3182			return Mustache.render(template, data);
3183		},
3184
3185		checkAnalytics: function(data)
3186		{
3187			if (!data || !data.basket)
3188				return;
3189
3190			var itemId, itemsDiff = {};
3191
3192			for (var i in data.basket)
3193			{
3194				if (data.basket.hasOwnProperty(i))
3195				{
3196					if (i.indexOf('QUANTITY_') >= 0)
3197					{
3198						itemId = i.substr(9);
3199
3200						if (this.items[itemId])
3201						{
3202							itemsDiff[itemId] = parseFloat(data.basket[i]) - parseFloat(BX(this.ids.quantity + itemId).getAttribute('data-value'));
3203						}
3204					}
3205					else if (i.indexOf('DELETE_') >= 0)
3206					{
3207						itemId = i.substr(7);
3208
3209						if (this.items[itemId])
3210						{
3211							itemsDiff[itemId] = -parseFloat(this.items[itemId].QUANTITY);
3212						}
3213					}
3214					else if (i.indexOf('RESTORE_') >= 0)
3215					{
3216						itemId = i.substr(8);
3217
3218						if (this.items[itemId])
3219						{
3220							itemsDiff[itemId] = parseFloat(this.items[itemId].QUANTITY);
3221						}
3222					}
3223				}
3224			}
3225
3226			this.setAnalyticsDataLayer(itemsDiff);
3227		},
3228
3229		setAnalyticsDataLayer: function(itemsDiff)
3230		{
3231			if (!itemsDiff || Object.keys(itemsDiff).length === 0)
3232				return;
3233
3234			window[this.params.DATA_LAYER_NAME] = window[this.params.DATA_LAYER_NAME] || [];
3235
3236			var plus = [], minus = [];
3237
3238			for (var itemId in itemsDiff)
3239			{
3240				if (itemsDiff.hasOwnProperty(itemId))
3241				{
3242					if (itemsDiff[itemId] > 0)
3243					{
3244						plus.push(this.getItemAnalyticsInfo(itemId, itemsDiff[itemId]));
3245					}
3246					else if (itemsDiff[itemId] < 0)
3247					{
3248						minus.push(this.getItemAnalyticsInfo(itemId, itemsDiff[itemId]));
3249					}
3250				}
3251			}
3252
3253			if (plus.length)
3254			{
3255				window[this.params.DATA_LAYER_NAME].push({
3256					event: 'addToCart',
3257					ecommerce: {
3258						currencyCode: this.items[itemId].CURRENCY || '',
3259						add: {
3260							products: plus
3261						}
3262					}
3263				});
3264			}
3265
3266			if (minus.length)
3267			{
3268				window[this.params.DATA_LAYER_NAME].push({
3269					event: 'removeFromCart',
3270					ecommerce: {
3271						currencyCode: this.items[itemId].CURRENCY || '',
3272						remove: {
3273							products: minus
3274						}
3275					}
3276				});
3277			}
3278		},
3279
3280		getItemAnalyticsInfo: function(itemId, diff)
3281		{
3282			if (!this.items[itemId])
3283				return {};
3284
3285			var brand = (this.items[itemId].BRAND || '').split(',  ').join('/');
3286			var variants = [];
3287
3288			var selectedSku = this.getEntities(BX(this.ids.item + itemId), 'basket-item-sku-field', '.selected');
3289			for (var i = 0, l = selectedSku.length; i < l; i++)
3290			{
3291				variants.push(selectedSku[i].getAttribute('data-sku-name'));
3292			}
3293
3294			return {
3295				'name': this.items[itemId].NAME || '',
3296				'id': this.items[itemId].PRODUCT_ID || '',
3297				'price': this.items[itemId].PRICE || 0,
3298				'brand': brand,
3299				'variant': variants.join('/'),
3300				'quantity': Math.abs(diff)
3301			};
3302		}
3303	};
3304})();
3305/* End */
3306;; /* /local/templates/psy/components/bitrix/sale.basket.basket/bootstrap_v5/js/action-pool.js?17224267795918*/
3307; /* /local/templates/psy/components/bitrix/sale.basket.basket/bootstrap_v5/js/filter.js?172242677914035*/
3308; /* /local/templates/psy/components/bitrix/sale.basket.basket/bootstrap_v5/js/component.js?172242677961750*/

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.