PageSourceSearch

https://suzukizap.ru/bitrix/templates/aspro-lite/js/item-action.js

js suzukizap.ru collected 2026-10-08 16:52:56 UTC 31,628 bytes, 1,272 lines download raw bytes

1if (typeof window.JItemAction === 'undefined') {
2	// class JItemAction
3	JItemAction = function(node, config) {
4		node = (typeof node === 'object' && node && node instanceof Node) ? node : null;
5		config = (typeof config === 'object' && config) ? config : {};
6
7		this.node = node;
8
9		var _private = {
10			inited: false,
11		};
12
13		let _config = JSON.stringify(config);
14
15		Object.defineProperties(this, {
16			inited: {
17				get: function () {
18					return _private.inited;
19				},
20				set: function (value) {
21					if (value) {
22					_private.inited = true;
23					}
24				},
25			},
26
27			config: {
28				get: function() {
29					return JSON.parse(_config);
30				},
31			},
32		});
33
34		this.init();
35	}
36
37	JItemAction.prototype = {
38		constructor: JItemAction,
39		busy: false,
40		parentNode: null,
41		prevState: null,
42
43		get class() {
44			return this.constructor.name;
45		},
46
47		get action() {
48			return '';
49		},
50
51		get requestUrl() {
52			return arAsproOptions.SITE_DIR + 'ajax/item.php';
53		},
54
55		get valid() {
56			return this.node && this.action;
57		},
58
59		get state() {
60			return this.valid && BX.hasClass(this.node, 'active');
61		},
62
63		set state(value) {
64			if (this.valid) {
65				if (value != this.state) {
66					if (value) {
67						BX.addClass(this.node, 'active');
68						if (this.parentNode) {
69							BX.addClass(this.parentNode, 'active');
70						}
71					} else {
72						BX.removeClass(this.node, 'active');
73						if (this.parentNode) {
74							BX.removeClass(this.parentNode, 'active');
75						}	
76					}
77	
78					let title = this.getStateTitle(value);
79					this.node.setAttribute('title', title);
80	
81					let button = this.node.querySelector('.info-buttons__item-text');
82					if (button) {
83						button.setAttribute('title', title);
84					}
85
86					if (BX.hasClass(this.node, 'btn')) {
87						this.node.textContent = title;
88					}
89				}
90			}
91		},
92
93		get data() {
94			let data = {};
95
96			if (this.valid) {
97				let mainNode = this.node.closest('.js-popup-block');
98				if (mainNode) {
99					let dataNode = mainNode.querySelector('[data-item]');
100					if (dataNode) {
101						if (typeof jQuery === 'function') {
102							data = jQuery(dataNode).data('item');
103						} else {
104							data = BX.data(dataNode, 'item');
105						}
106
107						if (
108							typeof data !== 'undefined' &&
109							typeof data !== 'object' &&
110							data
111						) {
112							try {
113								data = JSON.parse(data.toString());
114							} catch (e) {
115								data = {};
116							}
117						}
118					}
119				}
120			}
121
122			return (typeof data === 'object' && data) ? data : {};
123		},
124
125		init: function() {
126			if (!this.inited) {
127				this.inited = true;
128
129				if (this.valid) {
130					this.node.itemAction = this;
131					this.parentNode = this.node.parentElement;
132
133					this.bindEvents();
134				}
135			}
136		},
137
138		bindEvents: function() {
139			if (this.valid) {
140                if (typeof this.handlers.onClickNode === 'function') {
141                    BX.bind(this.node, 'click', BX.proxy(this.handlers.onClickNode, this));
142                }
143			}
144		},
145
146		unbindEvents: function() {
147			if (this.valid) {
148                if (typeof this.handlers.onClickNode === 'function') {
149                    BX.unbind(this.node, 'click', BX.proxy(this.handlers.onClickNode, this));
150                }
151			}
152		},
153
154		fireEvent: function(event) {
155			if (
156				this.valid &&
157				!this.busy &&
158				typeof event === 'object' &&
159				event
160			) {
161				let eventType = event.type;
162				if (eventType) {
163					if (eventType === 'click') {
164						(BX.proxy(this.handlers.onClickNode, this))(event);
165					}
166				}
167			}
168		},
169
170		isStateChanged: function() {
171			return this.prevState !== null && this.prevState != this.state;
172		},
173
174		getStateTitle: function(state) {
175			if (this.valid) {
176				if (state) {
177					return this.node.getAttribute('data-title_added') || '';
178				} else {
179					return this.node.getAttribute('data-title') || '';
180				}
181			}
182
183			return '';
184		},
185
186		getStateGoalCode: function(state) {
187			return 'goal_' + this.action + (state ? '_add' : '_remove');
188		},
189
190		showStateNotice: function(state) {
191			if (
192				this.valid &&
193				typeof JNoticeSurface === 'function'
194			) {
195				let surface = JNoticeSurface.get();
196				let actionCapitalize = this.action.replace(/^\w/, c => c.toUpperCase());
197				let noticeFunc = 'onAdd2' + actionCapitalize;
198
199				if (
200					noticeFunc &&
201					typeof surface[noticeFunc] === 'function') {
202					surface[noticeFunc]([this.node], state);
203				}
204			}
205		},
206
207		updateState: function() {
208			if (
209				this.valid &&
210				!this.busy
211			) {
212				this.busy = true;
213	
214				this.node.blur();
215
216				this.prevState = this.state;
217	
218				this.sendRequest();
219			}
220		},
221
222		collectRequestData: async function() {
223			let data = new FormData();
224
225			data.set('is_ajax_post', 'Y');
226			data.set('sessid', BX.bitrix_sessid());
227			data.set('lang', BX.message('LANGUAGE_ID'));
228			data.set('action', this.action);
229			data.set('state', this.state ? 1 : 0);
230			data.set('SITE_ID', BX.message('SITE_ID'));
231
232			let dataItem = this.data;
233			if (dataItem) {
234				data.set('ID', dataItem.ID);
235				data.set('IBLOCK_ID', dataItem.IBLOCK_ID);
236			}
237
238			return data;
239		},
240
241		makeRequestConfig: async function() {
242			return this.collectRequestData().then(
243				BX.proxy(
244					function(data) {
245						let config = {
246							url: this.requestUrl,
247							data: data,
248							method: 'POST',
249							dataType: 'json',
250							async: true,
251							processData: true,
252							preparePost: false,
253							scriptsRunFirst: true,
254							emulateOnload: true,
255							start: true,
256							cache: false,
257						};
258			
259						return config;
260					}, this
261				)
262			).catch(function(error) {
263				throw error;
264			});
265		},
266
267		sendRequest: function() {
268			if (this.valid) {
269				this.makeRequestConfig().then(
270					BX.proxy(
271						function(config) {	
272							config.onsuccess = BX.proxy(
273								function(response){	
274									if (typeof this.onRequestSuccess === 'function') {
275										this.onRequestSuccess(response);
276									}
277				
278									if (typeof this.onRequestComplete === 'function') {
279										this.onRequestComplete(config);
280									}
281								},
282								this
283							);
284			
285							config.onfailure = BX.proxy(
286								function(){
287									if (typeof this.onRequestFailure === 'function') {
288										this.onRequestFailure(xhr);
289									}
290				
291									if (typeof this.onRequestComplete === 'function') {
292										this.onRequestComplete(config);
293									}
294								},
295								this
296							);
297			
298							let xhr = BX.ajax(config);
299						}, 
300						this
301					)
302				).catch(
303					BX.proxy(
304						function(error) {
305							setTimeout(
306								BX.proxy(
307									function() {
308										if (this.isStateChanged()) {
309											// toggle state back
310											this.state = this.prevState;
311											this.prevState = null;
312										}
313
314										if (this.parentNode) {
315											BX.removeClass(this.parentNode, 'loadings');
316										}
317				
318										this.busy = false;
319									},
320									this
321								), 0
322							);
323						},
324						this
325					)
326				);
327			}
328		},
329
330		onRequestComplete: function(config) {
331			setTimeout(
332				BX.proxy(
333					function() {
334						if (this.parentNode) {
335							BX.removeClass(this.parentNode, 'loadings');
336						}
337
338						this.busy = false;
339					},
340					this
341				), 0
342			);
343		},
344
345		onRequestSuccess: function(response) {
346			let data = (typeof response === 'object' && response) ? response : {};
347
348			if (data.success) {
349				if (this.action) {
350					let actionUpper = this.action.toUpperCase();
351
352					if (typeof arAsproCounters !== 'object') {
353						arAsproCounters = {};
354					}
355	
356					if (typeof arAsproCounters[actionUpper] !== 'object') {
357						arAsproCounters[actionUpper] = {};
358					}
359
360					if ('items' in data) {
361						arAsproCounters[actionUpper].ITEMS = data.items;
362					}
363
364					if ('count' in data) {
365						arAsproCounters[actionUpper].COUNT = data.count;
366					}
367
368					if ('title' in data) {
369						arAsproCounters[actionUpper].TITLE = data.title;
370					}
371	
372					// update badges
373					if (
374						this.class &&
375						typeof window[this.class] === 'function' &&
376						typeof window[this.class].markBadges === 'function'
377					) {
378						window[this.class].markBadges();
379					}
380	
381					let state = this.state;
382	
383					if (this.isStateChanged()) {
384						// mark items
385						if (
386							this.class &&
387							typeof window[this.class] === 'function' &&
388							typeof window[this.class].markItems === 'function'
389						) {
390							window[this.class].markItems();
391						}
392
393						// show notice
394						this.showStateNotice(state);
395		
396						// fire goal
397						BX.onCustomEvent('onCounterGoals', [{
398							goal: this.getStateGoalCode(state),
399							params: {
400								id: this.node.getAttribute('data-id'),
401							}
402						}]);
403					}
404				}
405			} else {
406				console.error(data.error);
407
408				if (this.isStateChanged()) {
409					// toggle state back
410					this.state = this.prevState;
411				}
412
413				// show error notice
414				if (typeof JNoticeSurface === 'function') {
415					let surface = JNoticeSurface.get();
416					surface.onResultError(data);
417				}
418			}
419		},
420
421		onRequestFailure: function(xhr) {
422			if (this.isStateChanged()) {
423				// toggle state back
424				this.state = this.prevState;
425			}
426
427			// show error notice
428			if (typeof JNoticeSurface === 'function') {
429				let surface = JNoticeSurface.get();
430				surface.onRequestError(xhr);
431			}
432		},
433
434		handlers: {
435			onClickNode: function(event) {
436				if (
437					this.valid &&
438					!this.busy
439				) {
440					if (!event) {
441						event = window.event;
442					}
443	
444					let target = event.target || event.srcElement;
445	
446					if (
447						typeof target !== 'undefined' &&
448						target
449					) {
450						this.busy = true;
451		
452						this.node.blur();
453	
454						this.prevState = this.state;
455						this.state = !this.state;
456	
457						this.sendRequest();
458					}
459				}
460			},
461		},
462	}
463
464	// factory: returns a concrete JItemAction instance
465	JItemAction.factory = function(node, config) {
466		if (
467			typeof node === 'object' &&
468			node &&
469			node instanceof Node
470		) {
471			if (node.itemAction instanceof JItemAction) {
472				return node.itemAction;
473			} else {
474				let action = (node.getAttribute('data-action') || '').trim();
475				if (action) {
476					let actionCapitalize = action.replace(/^\w/, (c) => c.toUpperCase());
477					let className = 'JItemAction' + actionCapitalize;
478					if (typeof window[className] === 'function') {
479						return new window[className](node, config);
480					}
481				}
482			}
483		}
484
485		return new window.JItemAction(node, config);
486	};
487
488	// class JItemActionCompare
489	JItemActionCompare = function(node, config) {
490		JItemAction.apply(this, arguments);
491	}
492
493	JItemActionCompare.prototype = Object.create(JItemAction.prototype);
494	JItemActionCompare.prototype.constructor = JItemActionCompare;
495	Object.defineProperties(
496		JItemActionCompare.prototype,
497		{
498			action: {
499				get() {
500					return 'compare';
501				}
502			},
503		}
504	);
505
506	// setup active state for all current items
507	JItemActionCompare.markItems = function() {
508		if (
509			typeof arAsproCounters === 'object' && 
510			arAsproCounters && 
511			typeof arAsproCounters.COMPARE === 'object' &&
512			arAsproCounters.COMPARE &&
513			typeof arAsproCounters.COMPARE.ITEMS === 'object'
514		) {
515			let blocks = Array.prototype.slice.call(document.querySelectorAll('.js-item-action.active[data-action="compare"]'));
516			if (blocks.length) {
517				let list = Object.values(arAsproCounters.COMPARE.ITEMS);
518				for (let y in blocks) {
519					let id = BX.data(blocks[y], 'id');
520					if (
521						id &&
522						list.indexOf(id) == -1
523					) {
524						let itemAction = blocks[y].itemAction instanceof JItemAction ? blocks[y].itemAction : (new this(blocks[y]));
525						itemAction.state = false;
526					}
527				}
528			}
529
530			if (arAsproCounters.COMPARE.ITEMS) {
531				for (let i in arAsproCounters.COMPARE.ITEMS) {
532					let id = arAsproCounters.COMPARE.ITEMS[i];
533					let blocks = Array.prototype.slice.call(document.querySelectorAll('.js-item-action[data-action="compare"][data-id="' + id + '"]:not(.active)'));
534					if (blocks.length) {
535						for (let y in blocks) {
536							let itemAction = blocks[y].itemAction instanceof JItemAction ? blocks[y].itemAction : (new this(blocks[y]));
537							itemAction.state = true;
538						}
539					}
540				}
541			}
542		}
543	}
544
545	// set current count into badges
546	JItemActionCompare.markBadges = function() {
547		if (
548			typeof arAsproCounters === 'object' && 
549			arAsproCounters && 
550			typeof arAsproCounters.COMPARE === 'object' &&
551			arAsproCounters.COMPARE &&
552			typeof arAsproCounters.COMPARE.COUNT !== 'undefined'
553		) {
554			let blocks = Array.prototype.slice.call(document.querySelectorAll('.js-compare-block'));
555			if (blocks.length) {
556				if (arAsproCounters.COMPARE.COUNT > 0) {
557					for (let i in blocks) {
558						BX.addClass(blocks[i], 'icon-block-with-counter--count');
559					}
560				} else {
561					for (let i in blocks) {
562						BX.removeClass(blocks[i], 'icon-block-with-counter--count');
563					}
564				}
565			}
566		
567			blocks = Array.prototype.slice.call(document.querySelectorAll('.js-compare-block .count'));
568			if (blocks.length) {
569				for (let i in blocks) {
570					blocks[i].textContent = arAsproCounters.COMPARE.COUNT;
571				}
572			}
573		}
574	}
575
576	// class JItemActionFavorite
577	JItemActionFavorite = function(node, config) {
578		JItemAction.apply(this, arguments);
579	}
580
581	JItemActionFavorite.prototype = Object.create(JItemAction.prototype);
582	JItemActionFavorite.prototype.constructor = JItemActionFavorite;
583	Object.defineProperties(
584		JItemActionFavorite.prototype,
585		{
586			action: {
587				get() {
588					return 'favorite';
589				}
590			},
591	});
592
593	JItemActionFavorite.prototype.getStateGoalCode = function(state) {
594		return 'goal_wish' + (state ? '_add' : '_remove');
595	}
596
597	// set current count into badges
598	JItemActionFavorite.markBadges = function() {
599		if (
600			typeof arAsproCounters === 'object' && 
601			arAsproCounters && 
602			typeof arAsproCounters.FAVORITE === 'object' &&
603			arAsproCounters.FAVORITE &&
604			typeof arAsproCounters.FAVORITE.COUNT !== 'undefined'
605		) {
606			let blocks = Array.prototype.slice.call(document.querySelectorAll('.js-favorite-block'));
607			if (blocks.length) {
608				if (arAsproCounters.FAVORITE.COUNT > 0) {
609					for (let i in blocks) {
610						BX.addClass(blocks[i], 'icon-block-with-counter--count');
611					}
612				} else {
613					for (let i in blocks) {
614						BX.removeClass(blocks[i], 'icon-block-with-counter--count');
615					}
616				}
617			}
618		
619			blocks = Array.prototype.slice.call(document.querySelectorAll('.js-favorite-block .count'));
620			if (blocks.length) {
621				for (let i in blocks) {
622					blocks[i].textContent = arAsproCounters.FAVORITE.COUNT;
623				}
624			}
625		}
626	}
627
628	// setup active state for all current items
629	JItemActionFavorite.markItems = function() {
630		if (
631			typeof arAsproCounters === 'object' && 
632			arAsproCounters && 
633			typeof arAsproCounters.FAVORITE === 'object' &&
634			arAsproCounters.FAVORITE &&
635			typeof arAsproCounters.FAVORITE.ITEMS === 'object' &&
636			arAsproCounters.FAVORITE.ITEMS
637		) {
638			let blocks = Array.prototype.slice.call(document.querySelectorAll('.js-item-action.active[data-action="favorite"]'));
639			if (blocks.length) {
640				let list = Object.values(arAsproCounters.FAVORITE.ITEMS);
641				for (let y in blocks) {
642					let id = BX.data(blocks[y], 'id');
643					if (
644						id &&
645						list.indexOf(id) == -1
646					) {
647						let itemAction = blocks[y].itemAction instanceof JItemAction ? blocks[y].itemAction : (new this(blocks[y]));
648						itemAction.state = false;
649					}
650				}
651			}
652
653			if (arAsproCounters.FAVORITE.ITEMS) {
654				for (let i in arAsproCounters.FAVORITE.ITEMS) {
655					let id = arAsproCounters.FAVORITE.ITEMS[i];
656					let blocks = Array.prototype.slice.call(document.querySelectorAll('.js-item-action[data-action="favorite"][data-id="' + id + '"]:not(.active)'));
657					if (blocks.length) {
658						for (let y in blocks) {
659							let itemAction = blocks[y].itemAction instanceof JItemAction ? blocks[y].itemAction : (new this(blocks[y]));
660							itemAction.state = true;
661						}
662					}
663				}
664			}
665		}
666	}
667
668	// class JItemActionSubscribe
669	JItemActionSubscribe = function(node, config) {
670		JItemAction.apply(this, arguments);
671	}
672
673	JItemActionSubscribe.prototype = Object.create(JItemAction.prototype);
674	JItemActionSubscribe.prototype.constructor = JItemActionSubscribe;
675	Object.defineProperties(
676		JItemActionSubscribe.prototype,
677		{
678			action: {
679				get() {
680					return 'subscribe';
681				}
682			},
683		}
684	);
685
686	// setup active state for all current items
687	JItemActionSubscribe.markItems = function() {
688		if (
689			typeof arAsproCounters === 'object' && 
690			arAsproCounters && 
691			typeof arAsproCounters.SUBSCRIBE === 'object' &&
692			arAsproCounters.SUBSCRIBE &&
693			typeof arAsproCounters.SUBSCRIBE.ITEMS === 'object'
694		) {
695			let blocks = Array.prototype.slice.call(document.querySelectorAll('.js-item-action.active[data-action="subscribe"]'));
696			if (blocks.length) {
697				let list = Object.values(arAsproCounters.SUBSCRIBE.ITEMS);
698				for (let y in blocks) {
699					let id = BX.data(blocks[y], 'id');
700					if (
701						id &&
702						list.indexOf(id) == -1
703					) {
704						let itemAction = blocks[y].itemAction instanceof JItemAction ? blocks[y].itemAction : (new this(blocks[y]));
705						itemAction.state = false;
706					}
707				}
708			}
709
710			if (arAsproCounters.SUBSCRIBE.ITEMS) {
711				for (let i in arAsproCounters.SUBSCRIBE.ITEMS) {
712					let id = arAsproCounters.SUBSCRIBE.ITEMS[i];
713					let blocks = Array.prototype.slice.call(document.querySelectorAll('.js-item-action[data-action="subscribe"][data-id="' + id + '"]:not(.active)'));
714					if (blocks.length) {
715						for (let y in blocks) {
716							let itemAction = blocks[y].itemAction instanceof JItemAction ? blocks[y].itemAction : (new this(blocks[y]));
717							itemAction.state = true;
718						}
719					}
720				}
721			}
722		}
723	}
724
725	// class JItemActionBasket
726	JItemActionBasket = function(node, config) {
727		JItemAction.apply(this, arguments);
728	}
729
730	JItemActionBasket.prototype = Object.create(JItemAction.prototype);
731	JItemActionBasket.prototype.constructor = JItemActionBasket;
732	JItemActionBasket.prototype.basketPropsNode = null;
733	Object.defineProperties(
734		JItemActionBasket.prototype,
735		{
736			action: {
737				get() {
738					return 'basket';
739				}
740			},
741
742			state: {
743				get() {
744					return this.valid && BX.hasClass(this.node, 'active');
745				},
746				set(value) {
747					if (this.valid) {
748						if (value != this.state) {
749							if (value) {
750								BX.addClass(this.node, 'active');
751								if (this.parentNode) {
752									BX.addClass(this.parentNode, 'active');
753								}
754							} else {
755								BX.removeClass(this.node, 'active');
756								if (this.parentNode) {
757									BX.removeClass(this.parentNode, 'active');
758								}	
759							}
760			
761							let title = this.getStateTitle(value);
762							this.node.setAttribute('title', title);
763			
764							let button = this.node.querySelector('.info-buttons__item-text');
765							if (button) {
766								button.setAttribute('title', title);
767							}
768		
769							if (BX.hasClass(this.node, 'btn')) {
770								this.node.textContent = title;
771							}
772						}
773					}
774				}
775			},
776
777			quantity: {
778				get() {
779					if (this.valid) {
780						let buyBlock = this.node.closest('.buy_block');
781						if (buyBlock) {
782							let input = buyBlock.querySelector('.in_cart .counter__count');
783							if (input) {
784								return input.value;
785							}
786						}
787					}
788
789					return 1;
790				},
791				set(value) {
792					if (this.valid) {
793						this.node.setAttribute('data-quantity', value);
794
795						let buyBlock = this.node.closest('.buy_block');
796						if (buyBlock) {
797							let input = buyBlock.querySelector('.in_cart .counter__count');
798							if (input) {
799								input.value = value;
800							}
801						}
802					}
803				}
804			},
805
806			ratio: {
807				get() {
808					let ratio = 1;
809
810					if (this.valid) {
811						ratio = this.node.getAttribute('data-ratio') || 1;
812					}
813
814					if (ratio <= 0) {
815						ratio = 1;
816					}
817
818					return ratio;
819				},
820			},
821		}
822	);
823
824	JItemActionBasket.prototype.resetQuantity = function() {
825		if (this.valid) {
826			this.quantity = this.ratio;
827		}
828	}
829
830	JItemActionBasket.prototype.getBasketPropsNode = function() {
831		let basketPropsNode = null;
832
833		if (this.valid) {
834			let bakset_div = this.node.getAttribute('data-bakset_div') || '';
835			if (bakset_div) {
836				basketPropsNode = BX(bakset_div);
837			}
838
839			if (
840				!basketPropsNode && 
841				this.node.getAttribute('data-offers') !== 'Y' &&
842				this.node.closest('.grid-list__item')
843			) {
844				basketPropsNode = this.node.closest('.grid-list__item').querySelector('.basket_props_block');
845			}
846		}
847
848		return basketPropsNode;
849	}
850
851	JItemActionBasket.prototype.showStateNotice = function(state) {
852		if (
853			this.valid &&
854			typeof JNoticeSurface === 'function'
855		) {
856			let noticeFunc = '';
857			let surface = JNoticeSurface.get();
858
859			if (state) {
860				noticeFunc = 'onAdd2Cart';
861			}
862
863			if (
864				noticeFunc &&
865				typeof surface[noticeFunc] === 'function'
866			) {
867				surface[noticeFunc]([this.node]);
868			}
869		}
870	}	
871
872	JItemActionBasket.prototype.collectRequestData = async function() {
873		return JItemAction.prototype.collectRequestData.call(this, arguments).then(
874			BX.proxy(
875				function(data) {
876					data.set('quantity', this.quantity);
877
878					if (this.valid) {
879						let offers = this.node.getAttribute('data-offers') === 'Y' ? 'Y' : 'N';
880						data.set('offers', offers);
881
882						let add_props = this.node.getAttribute('data-add_props') === 'Y' ? 'Y' : 'N';
883						data.set('add_props', add_props);
884
885						let part_props = this.node.getAttribute('data-part_props') === 'Y' ? 'Y' : 'N';
886						data.set('part_props', part_props);
887						
888						let props = this.node.getAttribute('data-props') || '';
889						try {
890							props = props.length ? props.split(';') : [];
891						}
892						catch(e) {
893							props = [];
894						}
895						data.set('props', JSON.stringify(props));
896
897						let ridItem = document.querySelector('.rid_item');
898						let rid = (ridItem ? ridItem.getAttribute('rid') : this.node.getAttribute('rid') || false);
899						data.set('rid', rid);
900
901						// collect basket props
902						let foundValues = false;
903						let basketPropsNode = this.getBasketPropsNode();
904						if (basketPropsNode) {
905							let propCollection = basketPropsNode.getElementsByTagName('select');
906							if (!!propCollection && !!propCollection.length) {
907								for (i = 0; i < propCollection.length; i++) {
908									if (!propCollection[i].disabled) {
909										switch (propCollection[i].type.toLowerCase()) {
910										case 'select-one':
911											data.set(propCollection[i].name, propCollection[i].value);
912											foundValues = true;
913											break;
914										default:
915											break;
916										}
917									}
918								}
919							}
920
921							propCollection = basketPropsNode.getElementsByTagName('input');
922							if (!!propCollection && !!propCollection.length) {
923								for (i = 0; i < propCollection.length; i++) {
924									if (!propCollection[i].disabled) {
925										switch (propCollection[i].type.toLowerCase()) {
926										case 'hidden':
927											data.set(propCollection[i].name, propCollection[i].value);
928											foundValues = true;
929											break;
930										case 'radio':
931											if (propCollection[i].checked) {
932												data.set(propCollection[i].name, propCollection[i].value);
933												foundValues = true;
934											}
935											break;
936										default:
937											break;
938										}
939									}
940								}
941							}
942						}
943
944						if (!foundValues) {
945							data.set('prop[0]', 0);
946						}
947
948						if (this.isStateChanged()) {
949							let empty_props = this.node.getAttribute('data-empty_props') === 'Y' ? 'Y' : 'N';
950							if (empty_props === 'N') {
951								return this.showBasketPropsForm().then(
952									BX.proxy(function(extData) {
953										if (
954											typeof extData === 'object' &&
955											extData &&
956											extData instanceof FormData
957										) {
958											for (let key of extData.keys()) {
959												data.set(key, extData.get(key));
960											}
961										}
962
963										return data;
964									}, 
965									this)
966								).catch(
967									function(error) {
968										throw error;
969									}
970								);
971							}
972						}
973					}
974
975					return data;
976				},
977				this
978			)
979		);		
980	}
981
982	JItemActionBasket.prototype.showBasketPropsForm = async function() {
983		let that = this;
984
985		return new Promise(
986			BX.proxy(
987				function(resolve, reject) {
988					let trigger = BX.create({
989						tag: 'div',
990						attrs: {
991							'data-event': 'jqm',
992							'data-name': 'message',
993							'data-param-form_id': 'message',
994							'data-param-message_title': encodeURIComponent(BX.message('ADD_BASKET_PROPS_TITLE')),
995							'data-param-message_button_title': encodeURIComponent(BX.message('ADD_BASKET_PROPS_BUTTON_TITLE')),
996						},
997					});
998
999					BX.append(trigger, document.body);
1000
1001					$(trigger).jqmEx(
1002						BX.proxy(
1003							function(name, hash, _this) {
1004								let popup = hash.w[0];
1005								let popupBody = popup.querySelector('.form-body');
1006								let popupButton = popup.querySelector('.form-footer input[type="submit"]');
1007
1008								let basketPropsNode = this.getBasketPropsNode();
1009								if (
1010									basketPropsNode &&
1011									popupBody
1012								) {
1013									popupBody.innerHTML = basketPropsNode.innerHTML;
1014								}
1015
1016								BX.bind(
1017									popupButton,
1018									'click',
1019									BX.proxy(
1020										function() {
1021											let extData = new FormData();
1022
1023											let propCollection = popup.getElementsByTagName('select');
1024											if (!!propCollection && !!propCollection.length) {
1025												for (i = 0; i < propCollection.length; i++) {
1026													if (!propCollection[i].disabled) {
1027														switch (propCollection[i].type.toLowerCase()) {
1028														case 'select-one':
1029															extData.set(propCollection[i].name, propCollection[i].value);
1030															break;
1031														default:
1032															break;
1033														}
1034													}
1035												}
1036											}
1037
1038											propCollection = popup.getElementsByTagName('input');
1039											if (!!propCollection && !!propCollection.length) {
1040												for (i = 0; i < propCollection.length; i++) {
1041													if (!propCollection[i].disabled) {
1042														switch (propCollection[i].type.toLowerCase()) {
1043														case 'hidden':
1044															extData.set(propCollection[i].name, propCollection[i].value);
1045															break;
1046														case 'radio':
1047															if (propCollection[i].checked) {
1048																extData.set(propCollection[i].name, propCollection[i].value);
1049															}
1050															break;
1051														default:
1052															break;
1053														}
1054													}
1055												}
1056											}
1057
1058											resolve(extData);
1059
1060											let closer = popup.querySelector('.jqmClose');
1061											if (closer) {
1062												BX.fireEvent(closer, 'click');
1063											} else {
1064												let overlay = popup.parentElement.querySelector('.jqmOverlay');
1065												if (overlay) {
1066													BX.fireEvent(overlay, 'click');
1067												} else {
1068													popup.innerHTML = '';
1069												}
1070											}
1071										},
1072										this
1073									)
1074								);
1075							},
1076							that
1077						),
1078						BX.proxy(
1079							function(name, hash, _this) {
1080								if (this.valid) {
1081									if (this.busy) {
1082										reject();
1083									}
1084								}
1085							},
1086							that
1087						)
1088					);
1089
1090					BX.fireEvent(trigger, 'click');
1091					trigger.remove();
1092				}
1093			),
1094			that
1095		);
1096	}
1097
1098	JItemActionBasket.prototype.onRequestSuccess = function(response) {
1099		JItemAction.prototype.onRequestSuccess.call(this, response);
1100
1101		let blocks = Array.prototype.slice.call(document.querySelectorAll('.basket-dropdown'));
1102		if (blocks.length) {
1103			for (let i in blocks) {
1104				BX.removeClass(blocks[i], 'loaded');
1105			}
1106		}
1107	}
1108
1109	// set current count into badges
1110	JItemActionBasket.markBadges = function() {
1111		if (
1112			typeof arAsproCounters === 'object' && 
1113			arAsproCounters && 
1114			typeof arAsproCounters.BASKET === 'object' &&
1115			arAsproCounters.BASKET &&
1116			typeof arAsproCounters.BASKET.COUNT !== 'undefined'
1117		) {
1118			let blocks = Array.prototype.slice.call(document.querySelectorAll('.js-basket-block'));
1119			if (blocks.length) {
1120				if (arAsproCounters.BASKET.COUNT > 0) {
1121					for (let i in blocks) {
1122						BX.addClass(blocks[i], 'icon-block-with-counter--count');
1123						BX.removeClass(blocks[i], 'header-cart__inner--empty');
1124
1125						let title = blocks[i].closest('a');
1126						if (title) {
1127							blocks[i].closest('a').setAttribute('title', arAsproCounters.BASKET.TITLE);
1128						}
1129					}
1130				} else {
1131					for (let i in blocks) {
1132						BX.removeClass(blocks[i], 'icon-block-with-counter--count');
1133						BX.addClass(blocks[i], 'header-cart__inner--empty');
1134					}
1135				}
1136
1137				for (let i in blocks) {
1138					let title = blocks[i].closest('a');
1139					if (title) {
1140						title.setAttribute('title', arAsproCounters.BASKET.TITLE);
1141					}
1142				}
1143			}
1144		
1145			blocks = Array.prototype.slice.call(document.querySelectorAll('.js-basket-block .count'));
1146			if (blocks.length) {
1147				for (let i in blocks) {
1148					blocks[i].textContent = arAsproCounters.BASKET.COUNT;
1149				}
1150			}
1151		}
1152	}
1153
1154	// setup active state for all current items
1155	JItemActionBasket.markItems = function() {
1156		if (
1157			typeof arAsproCounters === 'object' && 
1158			arAsproCounters && 
1159			typeof arAsproCounters.BASKET === 'object' &&
1160			arAsproCounters.BASKET &&
1161			typeof arAsproCounters.BASKET.ITEMS === 'object' &&
1162			arAsproCounters.BASKET.ITEMS
1163		) {
1164			let blocks = Array.prototype.slice.call(document.querySelectorAll('.js-item-action.active[data-action="basket"]'));
1165			if (blocks.length) {
1166				let list = Object.keys(arAsproCounters.BASKET.ITEMS);
1167				for (let y in blocks) {
1168					let id = BX.data(blocks[y], 'id');
1169					if (
1170						id &&
1171						list.indexOf(id) == -1
1172					) {
1173						let itemAction = blocks[y].itemAction instanceof JItemAction ? blocks[y].itemAction : (new this(blocks[y]));
1174						itemAction.state = false;
1175						itemAction.resetQuantity();
1176					}
1177				}
1178			}
1179
1180			if (arAsproCounters.BASKET.ITEMS) {
1181				for (let i in arAsproCounters.BASKET.ITEMS) {
1182					let id = i;
1183					let quantity = arAsproCounters.BASKET.ITEMS[i];
1184					let blocks = Array.prototype.slice.call(document.querySelectorAll('.js-item-action[data-action="basket"][data-id="' + id + '"]:not(.active)'));
1185					if (blocks.length) {
1186						for (let y in blocks) {
1187							let itemAction = blocks[y].itemAction instanceof JItemAction ? blocks[y].itemAction : (new this(blocks[y]));
1188							itemAction.state = true;
1189							itemAction.quantity = quantity;
1190						}
1191					}
1192				}
1193			}
1194		}
1195	}
1196
1197	if (!funcDefined('reloadCounters')) {
1198		reloadCounters = function () {
1199			BX.ajax({
1200				url: arAsproOptions.SITE_DIR + 'ajax/actualBasket.php',
1201				data: {
1202					action: 'reload',
1203					sessid: BX.bitrix_sessid(),
1204				},
1205				method: 'POST',
1206				dataType: 'html',
1207				async: true,
1208				processData: true,
1209				preparePost: true,
1210				scriptsRunFirst: true,
1211				emulateOnload: true,
1212				start: true,
1213				cache: false,
1214				success: function(data) {					
1215					// fire action
1216					BX.onCustomEvent('onReloadCounters', [{
1217						data: data
1218					}]);
1219				}
1220			});
1221		}
1222	}
1223
1224	// bind handler for click on .js-item-action
1225	BX.bindDelegate(
1226		document,
1227		'click',
1228		{
1229			class: 'js-item-action',
1230		},
1231		function(event) {
1232			if (!event) {
1233				event = window.event;
1234			}
1235
1236			BX.PreventDefault(event);
1237
1238			let target = event.target || event.srcElement;
1239
1240			if (
1241				typeof target !== 'undefined' &&
1242				target
1243			) {
1244				if (!target.closest('.opt_action')) {
1245					JItemAction.factory(this).fireEvent(event);
1246				}
1247			}
1248		}
1249	);
1250
1251	// on complete loading content by ajax
1252	BX.addCustomEvent('onCompleteAction', function(eventdata) {
1253		try {
1254			if (eventdata.action === 'ajaxContentLoaded') {
1255				JItemActionBasket.markItems();
1256				JItemActionCompare.markItems();
1257				JItemActionFavorite.markItems();
1258				JItemActionSubscribe.markItems();
1259			}
1260		} catch (e) {
1261			console.error(e);
1262	  	}
1263	});
1264
1265	// set current items states
1266	readyDOM(function() {
1267		JItemActionBasket.markItems();
1268		JItemActionCompare.markItems();
1269		JItemActionFavorite.markItems();
1270		JItemActionSubscribe.markItems();
1271	});
1272}

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.