PageSourceSearch

https://sportzania.ru/local/templates/.default/components/bitrix/catalog.smart.filter/common/script.js

js sportzania.ru collected 2026-10-02 17:59:14 UTC 34,255 bytes, 1,255 lines download raw bytes

1function JCSmartFilter(ajaxURL, viewMode, params)
2{
3	this.ajaxURL = ajaxURL;
4	this.form = null;
5	this.timer = null;
6	this.cacheKey = '';
7	this.cache = [];
8	this.popups = [];
9	this.viewMode = viewMode;
10    this.action = '';
11	if (params && params.SEF_SET_FILTER_URL)
12	{
13		// this.bindUrlToButton('set_filter', params.SEF_SET_FILTER_URL);
14		this.sef = true;
15	}
16
17	if (params && params.SEF_DEL_FILTER_URL)
18	{
19		this.bindUrlToButton('del_filter', params.SEF_DEL_FILTER_URL);
20	}
21}
22
23JCSmartFilter.prototype.clickSelect = function(select)
24{
25	if(this.timer)
26		clearTimeout(this.timer);
27	this.timer = setTimeout(BX.delegate(function(){
28		this.reloadSelect(select);
29	}, this), 1000);
30}
31
32JCSmartFilter.prototype.reloadSelect = function(select)
33{
34	this.position = BX.pos(select, true);
35	this.form = BX.findParent(select, {'tag':'form'});
36
37	if(this.form)
38	{
39		var values = new Array;
40		values[0] = {name: 'ajax', value: 'y'};
41
42		this.gatherInputsValues(values, BX.findChildren(this.form, {'tag':'select'}, true));
43		BX.ajax.loadJSON(
44			this.ajaxURL,
45			this.values2post(values),
46			BX.delegate(this.postHandler, this)
47		);
48
49        this.setCountFilter();
50	}
51}
52
53JCSmartFilter.prototype.setCountFilter = function()
54{
55    let count = 0;
56    const form = $('#smartfilter_form');
57    const select = form.find('.property-select');
58    $.each(select, function(index, item){
59        if(item.value !== '') {
60            count++;
61        }
62    });
63    const range = form.find('.ui-range');
64    $.each(range, function(index, item){
65        const rangeInput = $(item).find('[type="range"]');
66        const min = rangeInput.data('min');
67        const max = rangeInput.data('max');
68        const minValue = $(item).find('.ui-from').val();
69        const maxValue = $(item).find('.ui-to').val();
70
71        if(parseFloat(min) !== parseFloat(minValue) || parseFloat(max) !== parseFloat(maxValue)) {
72            count++;
73        }
74    });
75    const checkbox = form.find('.ui-switch__input');
76    checkbox.each(function(){
77        if($(this).prop('checked')) {
78            count++;
79        }
80    });
81
82    const container = $('.sz-programs__filter-toggle-icon');
83    if(container.length) {
84        const filterAction = $('[data-entity="filter-action"]');
85        if(count > 0) {
86            container.addClass('active');
87            container.find('mark').text(count);
88        } else {
89            container.removeClass('active');
90            container.find('mark').text('0');
91        }
92        filterAction.addClass('hidden');
93        $('.sz-programs__filter-reset').addClass('hidden');
94        
95        setTimeout(()=>{
96            filterAction.removeClass('hidden');
97            $('.sz-programs__filter-reset').removeClass('hidden');
98        }, 300);
99    }
100};
101
102JCSmartFilter.prototype.keyup = function(input)
103{
104    /**
105     *
106     * update check input value region
107     */
108    var $input = $(input);
109    
110    if($input.attr('type') === 'text') {
111        if(window.timer === undefined) {
112            window.timer = null;
113        }
114
115        if(!!window.timer)
116        {
117            clearTimeout(window.timer);
118        }
119
120        window.timer = setTimeout(function(){
121            var value = parseInt($input.attr('value'));
122            var currentValue = parseInt($input.val());
123            var name = $input.attr('name');
124
125            $input.val(currentValue);
126
127            if(value === currentValue) {
128                $input.val(currentValue);
129                return;
130            }
131
132            var $block = $input.closest('[data-role="bx_filter_block"]');
133            var $range = '';
134
135            if($block.length) {
136                $range = $block.find('[type="range"]');
137            }
138
139            if($range.length) {
140                var min = parseInt($range.data('min'));
141                var max = parseInt($range.data('max'));
142
143                if(name.indexOf('MIN') !== -1 && currentValue < min) {
144                    currentValue = min;
145                }
146
147                if(name.indexOf('MIN') !== -1 && currentValue > max) {
148                    currentValue = max;
149                }
150
151                if(name.indexOf('MIN') !== -1 && isNaN(currentValue)) {
152                    currentValue = min;
153                }
154
155                if(name.indexOf('MIN') !== -1 && currentValue === max) {
156                    currentValue = max - 1;
157                }
158
159                if(name.indexOf('MAX') !== -1 && currentValue > max) {
160                    currentValue = max;
161                }
162
163                if(name.indexOf('MAX') !== -1 && currentValue < min) {
164                    currentValue = min;
165                }
166
167                if(name.indexOf('MAX') !== -1 && isNaN(currentValue)) {
168                    currentValue = max;
169                }
170
171                $input.val(currentValue);
172
173                if(name.indexOf('MIN') !== -1) {
174                    var instance = $range.data("ionRangeSlider");
175
176                    instance.update({
177                        from: currentValue
178                    });
179                }
180
181                if(name.indexOf('MAX') !== -1) {
182                    var instance = $range.data("ionRangeSlider");
183
184                    instance.update({
185                        to: currentValue
186                    });
187                }
188            }
189        }, 500);
190    } else {
191        if(!!this.timer)
192        {
193            clearTimeout(this.timer);
194        }
195        this.timer = setTimeout(BX.delegate(function(){
196            this.reload(input);
197        }, this), 500);
198    }
199    
200    this.setCountFilter();
201    /**
202     *
203     * update check input value region end
204     */
205
206};
207
208JCSmartFilter.prototype.click = function(checkbox)
209{
210	if(!!this.timer)
211	{
212		clearTimeout(this.timer);
213	}
214
215	this.timer = setTimeout(BX.delegate(function(){
216		this.reload(checkbox);
217	}, this), 500);
218};
219
220JCSmartFilter.prototype.reload = function(input)
221{
222	if (this.cacheKey !== '')
223	{
224		//Postprone backend query
225		if(!!this.timer)
226		{
227			clearTimeout(this.timer);
228		}
229		this.timer = setTimeout(BX.delegate(function(){
230			this.reload(input);
231		}, this), 2000);
232		return;
233	}
234	this.cacheKey = '|';
235
236	this.position = BX.pos(input, true);
237	this.form = BX.findParent(input, {'tag':'form'});
238	if (this.form)
239	{
240		var values = [];
241		values[0] = {name: 'ajax', value: 'y'};
242		this.gatherInputsValues(values, BX.findChildren(this.form, {'tag': new RegExp('^(input|select)$', 'i')}, true));
243
244		for (var i = 0; i < values.length; i++)
245			this.cacheKey += values[i].name + ':' + values[i].value + '|';
246
247		if (this.cache[this.cacheKey])
248		{
249			this.curFilterinput = input;
250			this.postHandler(this.cache[this.cacheKey], true);
251		}
252		else
253		{
254			if (this.sef)
255			{
256				var set_filter = BX('set_filter');
257				set_filter.disabled = true;
258			}
259
260			this.curFilterinput = input;
261			BX.ajax.loadJSON(
262				this.ajaxURL,
263				this.values2post(values),
264				BX.delegate(this.postHandler, this)
265			);
266		}
267	}
268};
269
270JCSmartFilter.prototype.updateItem = function (PID, arItem)
271{
272	if (arItem.PROPERTY_TYPE === 'N' || arItem.PRICE)
273	{
274		var trackBar = window['trackBar' + PID];
275		if (!trackBar && arItem.ENCODED_ID)
276			trackBar = window['trackBar' + arItem.ENCODED_ID];
277
278		if (trackBar && arItem.VALUES)
279		{
280			if (arItem.VALUES.MIN)
281			{
282				if (arItem.VALUES.MIN.FILTERED_VALUE)
283					trackBar.setMinFilteredValue(arItem.VALUES.MIN.FILTERED_VALUE);
284				else
285					trackBar.setMinFilteredValue(arItem.VALUES.MIN.VALUE);
286			}
287
288			if (arItem.VALUES.MAX)
289			{
290				if (arItem.VALUES.MAX.FILTERED_VALUE)
291					trackBar.setMaxFilteredValue(arItem.VALUES.MAX.FILTERED_VALUE);
292				else
293					trackBar.setMaxFilteredValue(arItem.VALUES.MAX.VALUE);
294			}
295		}
296	}
297	else if (arItem.VALUES)
298	{
299		for (var i in arItem.VALUES)
300		{
301			if (arItem.VALUES.hasOwnProperty(i))
302			{
303				var value = arItem.VALUES[i];
304				var control = BX(value.CONTROL_ID);
305
306
307				// selectic  add class disabled if(ELEMENT_COUNT == 0)
308				let parent = $(`#${value.CONTROL_NAME}`).closest('.ui-select');
309				let selectric = parent.find(".selectric-items .selectric-scroll ul > li");
310				let elemIndex = $(`#${value.CONTROL_NAME}`).index();
311				//
312				if(value.ELEMENT_COUNT <= 0 ){
313					if(elemIndex != -1 && (selectric[elemIndex] != null && selectric[elemIndex] != undefined)){
314						selectric[elemIndex].classList.add('disabled');
315					}
316
317				}else{
318					if(elemIndex != -1 && (selectric[elemIndex] != null && selectric[elemIndex] != undefined)){
319						let result = selectric[elemIndex].classList.contains('disabled');
320						if(result != false){
321							selectric[elemIndex].classList.remove('disabled');
322						}
323					}
324				}
325
326
327				if (!!control)
328				{
329					var label = document.querySelector('[data-role="label_'+value.CONTROL_ID+'"]');
330					if (value.DISABLED)
331					{
332						if (label)
333							BX.addClass(label, 'disabled');
334						else
335							BX.addClass(control.parentNode, 'disabled');
336					}
337					else
338					{
339						if (label)
340							BX.removeClass(label, 'disabled');
341						else
342							BX.removeClass(control.parentNode, 'disabled');
343					}
344
345					if (value.hasOwnProperty('ELEMENT_COUNT'))
346					{
347						label = document.querySelector('[data-role="count_'+value.CONTROL_ID+'"]');
348						if (label)
349							label.innerHTML = value.ELEMENT_COUNT;
350					}
351				}
352			}
353		}
354	}
355};
356
357JCSmartFilter.prototype.postHandler = function (result, fromCache)
358{
359	var hrefFILTER, url, curProp;
360	var modef = BX('modef');
361	var modef_num = BX('modef_num');
362    var button = BX('set_filter');
363    
364	if (!!result && !!result.ITEMS)
365	{
366        button.disabled = true;
367        
368		for(var popupId in this.popups)
369		{
370			if (this.popups.hasOwnProperty(popupId))
371			{
372				this.popups[popupId].destroy();
373			}
374		}
375		this.popups = [];
376
377		for(var PID in result.ITEMS)
378		{
379			if (result.ITEMS.hasOwnProperty(PID))
380			{
381				this.updateItem(PID, result.ITEMS[PID]);
382			}
383		}
384        
385		if (!!modef && !!modef_num)
386		{
387			modef_num.innerHTML = result.ELEMENT_COUNT;
388			hrefFILTER = BX.findChildren(modef, {tag: 'A'}, true);
389            result.COMPONENT_CONTAINER_ID = BX('ajax-items');
390            /*
391			if (result.FILTER_URL && hrefFILTER)
392			{
393				hrefFILTER[0].href = BX.util.htmlspecialcharsback(result.FILTER_URL);
394			}
395            */
396
397            /**
398             * sort include region
399             */            
400            result.FILTER_AJAX_URL = this.getAdditionalParamsFilter(result);
401
402			if (result.FILTER_AJAX_URL && result.COMPONENT_CONTAINER_ID)
403			{
404				BX.unbindAll(hrefFILTER[0]);
405				BX.bind(hrefFILTER[0], 'click', function(e)
406				{
407					url = BX.util.htmlspecialcharsback(result.FILTER_AJAX_URL);
408					BX.ajax.insertToNode(url, result.COMPONENT_CONTAINER_ID);
409					return BX.PreventDefault(e);
410				});
411			}
412            
413            //url = BX.util.htmlspecialcharsback(result.FILTER_AJAX_URL);
414            //BX.ajax.insertToNode(url, result.COMPONENT_CONTAINER_ID);
415
416            //$('[data-entity="filter-reset"]').removeClass('hidden');
417            //checkFilterForDelete();
418            
419            const media = window.matchMedia("(min-width: 1200px)");
420            const reload = media.matches || ( ( result.INSTANT_RELOAD && result.COMPONENT_CONTAINER_ID ) || this.action === 'sort' );
421
422            if (reload)
423			{
424                this.action = '';
425                button.disabled = false;
426				url = BX.util.htmlspecialcharsback(result.FILTER_AJAX_URL);
427				BX.ajax.insertToNode(url, result.COMPONENT_CONTAINER_ID);
428			}
429			else
430			{
431                /*
432				if (modef.style.display === 'none')
433				{
434					modef.style.display = 'inline-block';
435				}
436                
437                /*
438				if (this.viewMode == "VERTICAL")
439				{
440					curProp = BX.findChild(BX.findParent(this.curFilterinput, {'class':'smart-filter-parameters-box'}), {'class':'smart-filter-container-modef'}, true, false);
441					curProp.appendChild(modef);
442				}
443                */
444               
445                var proxy = function(j, func)
446                {
447                    return function()
448                    {
449                        return func(j);
450                    }
451                };
452
453				if (result.SEF_SET_FILTER_URL)
454				{
455                    button.disabled = false;
456                    BX.unbindAll(button);
457                    BX.bind(button, 'click', proxy(url, function(url)
458                    {
459                        url = BX.util.htmlspecialcharsback(result.FILTER_AJAX_URL);
460                        BX.ajax.insertToNode(url, result.COMPONENT_CONTAINER_ID);
461                        $('html').removeClass('is-sz-filter-open');
462                        return BX.PreventDefault();
463                    }));
464					//this.bindUrlToButton('set_filter', result.SEF_SET_FILTER_URL);
465				}
466			}
467		}
468	}
469
470	if (this.sef)
471	{
472		var set_filter = BX('set_filter');
473		set_filter.disabled = false;
474	}
475
476	if (!fromCache && this.cacheKey !== '')
477	{
478		this.cache[this.cacheKey] = result;
479	}
480	this.cacheKey = '';
481};
482
483
484JCSmartFilter.prototype.getAdditionalParamsFilter = function (result)
485{
486    var inputSort = $(this.form).parents('[data-entity="programs"]').find('input[name="filter-sort"]');
487    var currentValue = inputSort.val();
488    var sign = '?';
489
490    if(result.FILTER_AJAX_URL.indexOf(sign) !== -1) {
491        sign = '&';
492    }
493
494    result.FILTER_AJAX_URL += sign + 'sort=' + currentValue;
495    
496    var url = result.FILTER_AJAX_URL;
497    /**
498     * sort include region end
499     */
500    
501    const strUrlFilter = '/catalog/programs/filter/';
502    const index = strUrlFilter.length;
503    let monthsStr = '';
504    let seazon = [];
505
506    if(document.location.href.indexOf('spb') !== -1) {
507        result.FILTER_AJAX_URL += '&location=spb';
508    } else if(document.location.href.indexOf('moscow') !== -1) {
509        result.FILTER_AJAX_URL += '&location=moscow';
510    } else if(document.location.href.indexOf('sea') !== -1) {
511        result.FILTER_AJAX_URL += '&location=sea';
512    } else if(document.location.href.indexOf('cashback') !== -1) {
513        result.FILTER_AJAX_URL += '&cashback=1';
514    } else if(document.location.href.indexOf('notcamp') !== -1) {
515        result.FILTER_AJAX_URL += '&notcamp=1';
516    }
517
518    if(
519        result.FILTER_AJAX_URL.indexOf('months_list') === -1
520        &&
521            (document.location.href.indexOf('summer') !== -1
522            || document.location.href.indexOf('spring') !== -1
523            || document.location.href.indexOf('autumn') !== -1
524            || document.location.href.indexOf('winter') !== -1)
525    ) {
526        if(document.location.href.indexOf('summer') !== -1) {
527            seazon = [
528                'june',
529                'july',
530                'august'
531            ];
532        } else if(document.location.href.indexOf('spring') !== -1) {
533            seazon = [
534                'mart',
535                'april',
536                'may'
537            ];
538        } else if(document.location.href.indexOf('autumn') !== -1) {
539            seazon = [
540                'september',
541                'october',
542                'november'
543            ];
544        } else if(document.location.href.indexOf('winter') !== -1) {
545            seazon = [
546                'december',
547                'january',
548                'february'
549            ];
550        }
551
552        for (var key in result.ITEMS) {
553            if (result.ITEMS.hasOwnProperty(key) && String(parseInt(key, 10)) === key) {
554                if(result.ITEMS[key]['CODE'] == 'MONTHS_LIST') {
555                    for(var key1 in result.ITEMS[key]['VALUES']) {
556                        if (result.ITEMS[key]['VALUES'].hasOwnProperty(key1) && String(parseInt(key1, 10)) === key1 && seazon.indexOf(result.ITEMS[key]['VALUES'][key1]['URL_ID']) !== -1) {
557                            monthsStr += 'months_list-is-'+result.ITEMS[key]['VALUES'][key1]['URL_ID']+'/';
558                        }
559                    }
560                }
561            }
562        }
563    }
564    
565    url = result.FILTER_AJAX_URL.substr( 0, index ) + monthsStr + result.FILTER_AJAX_URL.substr( index );
566
567    return url;
568}
569
570JCSmartFilter.prototype.bindUrlToButton = function (buttonId, url)
571{
572    const matches = document.querySelectorAll('[name="del_filter"]');
573
574    if(matches) {
575        var proxy = function(j, func)
576		{
577			return function()
578			{
579				return func(j);
580			}
581		};
582        
583        matches.forEach((button) => {
584            if (button.type == 'submit')
585                button.type = 'button';
586            
587            BX.bind(button, 'click', proxy(url, function(url)
588            {
589                const select = $('#smartfilter_form').find('select');
590                if(select.length) {
591                    select.each(function(){
592                        const option = $(this).find('option');
593                        option.each(function(){
594                            $(this).prop('selected', false);
595                        });
596                        $(this).change().selectric('refresh');
597                    });
598                }
599                const range = $('#smartfilter_form').find('input[type="range"]');
600                if(range.length) {
601                    range.each(function(){
602                        var rangeItem = $(this),
603                            rangeDataFrom = rangeItem.data("min"),
604                            rangeDataTo = rangeItem.data("max");
605                        rangeItem.closest('.ui-range').find('.ui-from').val(rangeDataFrom);
606                        rangeItem.closest('.ui-range').find('.ui-to').val(rangeDataTo);
607                        var instance = rangeItem.data("ionRangeSlider");
608
609                        instance.update({
610                            from: rangeItem.data("min"),
611                            to: rangeItem.data("max")
612                        });
613                    });
614                }
615                
616                const container = BX('ajax-items');
617                BX.ajax.insertToNode(document.location.href, container);
618
619                $('html').removeClass('is-sz-filter-open');
620                $('.sz-programs__filter-toggle-icon').removeClass('active');
621                $('.ui-action').addClass('hidden');
622                $('.sz-programs__filter-reset').addClass('hidden');
623
624                return false;
625            }));
626        });
627    }
628};
629
630JCSmartFilter.prototype.gatherInputsValues = function (values, elements)
631{
632	if(elements)
633	{
634		for(var i = 0; i < elements.length; i++)
635		{
636
637			var el = elements[i];
638
639			if (el.disabled || !el.type)
640				continue;
641
642			switch(el.type.toLowerCase())
643			{
644
645				case 'text':
646				case 'textarea':
647				case 'password':
648				case 'hidden':
649				case 'select-one':
650
651					if(el.value.length)
652						values[values.length] = {name : el.name, value : el.value};
653					break;
654				case 'radio':
655				case 'checkbox':
656					if(el.checked)
657						values[values.length] = {name : el.name, value : el.value};
658					break;
659				case 'select-multiple':
660
661					for (var j = 0; j < el.options.length; j++)
662					{
663
664						if (el.options[j].selected)
665
666
667							//custom//
668							// values[values.length] = {name : el.name, value : el.options[j].value};
669							values[values.length] = {name : el.options[j].id, value : el.options[j].value};
670
671					}
672					break;
673				default:
674					break;
675			}
676		}
677	}
678};
679
680JCSmartFilter.prototype.values2post = function (values)
681{
682	var post = [];
683	var current = post;
684	var i = 0;
685
686	while(i < values.length)
687	{
688		var p = values[i].name.indexOf('[');
689		if(p == -1)
690		{
691			current[values[i].name] = values[i].value;
692			current = post;
693			i++;
694		}
695		else
696		{
697			var name = values[i].name.substring(0, p);
698			var rest = values[i].name.substring(p+1);
699			if(!current[name])
700				current[name] = [];
701
702			var pp = rest.indexOf(']');
703			if(pp == -1)
704			{
705				//Error - not balanced brackets
706				current = post;
707				i++;
708			}
709			else if(pp == 0)
710			{
711				//No index specified - so take the next integer
712				current = current[name];
713				values[i].name = '' + current.length;
714			}
715			else
716			{
717				//Now index name becomes and name and we go deeper into the array
718				current = current[name];
719				values[i].name = rest.substring(0, pp) + rest.substring(pp+1);
720			}
721		}
722	}
723	return post;
724};
725
726JCSmartFilter.prototype.hideFilterProps = function(element)
727{
728	var obj = element.parentNode,
729		filterBlock = obj.querySelector("[data-role='bx_filter_block']"),
730		propAngle = obj.querySelector("[data-role='prop_angle']");
731
732	if(BX.hasClass(obj, "bx-active"))
733	{
734		new BX.easing({
735			duration : 300,
736			start : { opacity: 1,  height: filterBlock.offsetHeight },
737			finish : { opacity: 0, height:0 },
738			transition : BX.easing.transitions.quart,
739			step : function(state){
740				filterBlock.style.opacity = state.opacity;
741				filterBlock.style.height = state.height + "px";
742			},
743			complete : function() {
744				filterBlock.setAttribute("style", "");
745				BX.removeClass(obj, "bx-active");
746			}
747		}).animate();
748
749		BX.addClass(propAngle, "fa-angle-down");
750		BX.removeClass(propAngle, "fa-angle-up");
751	}
752	else
753	{
754		filterBlock.style.display = "block";
755		filterBlock.style.opacity = 0;
756		filterBlock.style.height = "auto";
757
758		var obj_children_height = filterBlock.offsetHeight;
759		filterBlock.style.height = 0;
760
761		new BX.easing({
762			duration : 300,
763			start : { opacity: 0,  height: 0 },
764			finish : { opacity: 1, height: obj_children_height },
765			transition : BX.easing.transitions.quart,
766			step : function(state){
767				filterBlock.style.opacity = state.opacity;
768				filterBlock.style.height = state.height + "px";
769			},
770			complete : function() {
771			}
772		}).animate();
773
774		BX.addClass(obj, "bx-active");
775		BX.removeClass(propAngle, "fa-angle-down");
776		BX.addClass(propAngle, "fa-angle-up");
777	}
778};
779
780JCSmartFilter.prototype.showDropDownPopup = function(element, popupId)
781{
782	var contentNode = element.querySelector('[data-role="dropdownContent"]');
783	this.popups["smartFilterDropDown"+popupId] = BX.PopupWindowManager.create("smartFilterDropDown"+popupId, element, {
784		autoHide: true,
785		offsetLeft: 0,
786		offsetTop: 3,
787		overlay : false,
788		draggable: {restrict:true},
789		closeByEsc: true,
790		content: BX.clone(contentNode)
791	});
792	this.popups["smartFilterDropDown"+popupId].show();
793};
794
795JCSmartFilter.prototype.selectDropDownItem = function(element, controlId)
796{
797	this.keyup(BX(controlId));
798
799	var wrapContainer = BX.findParent(BX(controlId), {className:"bx-filter-select-container"}, false);
800
801	var currentOption = wrapContainer.querySelector('[data-role="currentOption"]');
802	currentOption.innerHTML = element.innerHTML;
803	BX.PopupWindowManager.getCurrentPopup().close();
804};
805
806BX.namespace("BX.Iblock.SmartFilter");
807BX.Iblock.SmartFilter = (function()
808{
809	/** @param {{
810			leftSlider: string,
811			rightSlider: string,
812			tracker: string,
813			trackerWrap: string,
814			minInputId: string,
815			maxInputId: string,
816			minPrice: float|int|string,
817			maxPrice: float|int|string,
818			curMinPrice: float|int|string,
819			curMaxPrice: float|int|string,
820			fltMinPrice: float|int|string|null,
821			fltMaxPrice: float|int|string|null,
822			precision: int|null,
823			colorUnavailableActive: string,
824			colorAvailableActive: string,
825			colorAvailableInactive: string
826		}} arParams
827	 */
828	var SmartFilter = function(arParams)
829	{
830		if (typeof arParams === 'object')
831		{
832			this.leftSlider = BX(arParams.leftSlider);
833			this.rightSlider = BX(arParams.rightSlider);
834			this.tracker = BX(arParams.tracker);
835			this.trackerWrap = BX(arParams.trackerWrap);
836
837			this.minInput = BX(arParams.minInputId);
838			this.maxInput = BX(arParams.maxInputId);
839
840			this.minPrice = parseFloat(arParams.minPrice);
841			this.maxPrice = parseFloat(arParams.maxPrice);
842
843			this.curMinPrice = parseFloat(arParams.curMinPrice);
844			this.curMaxPrice = parseFloat(arParams.curMaxPrice);
845
846			this.fltMinPrice = arParams.fltMinPrice ? parseFloat(arParams.fltMinPrice) : parseFloat(arParams.curMinPrice);
847			this.fltMaxPrice = arParams.fltMaxPrice ? parseFloat(arParams.fltMaxPrice) : parseFloat(arParams.curMaxPrice);
848
849			this.precision = arParams.precision || 0;
850
851			this.priceDiff = this.maxPrice - this.minPrice;
852
853			this.leftPercent = 0;
854			this.rightPercent = 0;
855
856			this.fltMinPercent = 0;
857			this.fltMaxPercent = 0;
858
859			this.colorUnavailableActive = BX(arParams.colorUnavailableActive);//gray
860			this.colorAvailableActive = BX(arParams.colorAvailableActive);//blue
861			this.colorAvailableInactive = BX(arParams.colorAvailableInactive);//light blue
862
863			this.isTouch = false;
864
865			this.init();
866
867			if ('ontouchstart' in document.documentElement)
868			{
869				this.isTouch = true;
870
871				BX.bind(this.leftSlider, "touchstart", BX.proxy(function(event){
872					this.onMoveLeftSlider(event)
873				}, this));
874
875				BX.bind(this.rightSlider, "touchstart", BX.proxy(function(event){
876					this.onMoveRightSlider(event)
877				}, this));
878			}
879			else
880			{
881				BX.bind(this.leftSlider, "mousedown", BX.proxy(function(event){
882					this.onMoveLeftSlider(event)
883				}, this));
884
885				BX.bind(this.rightSlider, "mousedown", BX.proxy(function(event){
886					this.onMoveRightSlider(event)
887				}, this));
888			}
889
890			BX.bind(this.minInput, "keyup", BX.proxy(function(event){
891				this.onInputChange();
892			}, this));
893
894			BX.bind(this.maxInput, "keyup", BX.proxy(function(event){
895				this.onInputChange();
896			}, this));
897		}
898	};
899
900	SmartFilter.prototype.init = function()
901	{
902		var priceDiff;
903
904		if (this.curMinPrice > this.minPrice)
905		{
906			priceDiff = this.curMinPrice - this.minPrice;
907			this.leftPercent = (priceDiff*100)/this.priceDiff;
908
909			this.leftSlider.style.left = this.leftPercent + "%";
910			this.colorUnavailableActive.style.left = this.leftPercent + "%";
911		}
912
913		this.setMinFilteredValue(this.fltMinPrice);
914
915		if (this.curMaxPrice < this.maxPrice)
916		{
917			priceDiff = this.maxPrice - this.curMaxPrice;
918			this.rightPercent = (priceDiff*100)/this.priceDiff;
919
920			this.rightSlider.style.right = this.rightPercent + "%";
921			this.colorUnavailableActive.style.right = this.rightPercent + "%";
922		}
923
924		this.setMaxFilteredValue(this.fltMaxPrice);
925	};
926
927	SmartFilter.prototype.setMinFilteredValue = function (fltMinPrice)
928	{
929		this.fltMinPrice = parseFloat(fltMinPrice);
930		if (this.fltMinPrice >= this.minPrice)
931		{
932			var priceDiff = this.fltMinPrice - this.minPrice;
933			this.fltMinPercent = (priceDiff*100)/this.priceDiff;
934
935			if (this.leftPercent > this.fltMinPercent)
936				this.colorAvailableActive.style.left = this.leftPercent + "%";
937			else
938				this.colorAvailableActive.style.left = this.fltMinPercent + "%";
939
940			this.colorAvailableInactive.style.left = this.fltMinPercent + "%";
941		}
942		else
943		{
944			this.colorAvailableActive.style.left = "0%";
945			this.colorAvailableInactive.style.left = "0%";
946		}
947	};
948
949	SmartFilter.prototype.setMaxFilteredValue = function (fltMaxPrice)
950	{
951		this.fltMaxPrice = parseFloat(fltMaxPrice);
952		if (this.fltMaxPrice <= this.maxPrice)
953		{
954			var priceDiff = this.maxPrice - this.fltMaxPrice;
955			this.fltMaxPercent = (priceDiff*100)/this.priceDiff;
956
957			if (this.rightPercent > this.fltMaxPercent)
958				this.colorAvailableActive.style.right = this.rightPercent + "%";
959			else
960				this.colorAvailableActive.style.right = this.fltMaxPercent + "%";
961
962			this.colorAvailableInactive.style.right = this.fltMaxPercent + "%";
963		}
964		else
965		{
966			this.colorAvailableActive.style.right = "0%";
967			this.colorAvailableInactive.style.right = "0%";
968		}
969	};
970
971	SmartFilter.prototype.getXCoord = function(elem)
972	{
973		var box = elem.getBoundingClientRect();
974		var body = document.body;
975		var docElem = document.documentElement;
976
977		var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft;
978		var clientLeft = docElem.clientLeft || body.clientLeft || 0;
979		var left = box.left + scrollLeft - clientLeft;
980
981		return Math.round(left);
982	};
983
984	SmartFilter.prototype.getPageX = function(e)
985	{
986		e = e || window.event;
987		var pageX = null;
988
989		if (this.isTouch && event.targetTouches[0] != null)
990		{
991			pageX = e.targetTouches[0].pageX;
992		}
993		else if (e.pageX != null)
994		{
995			pageX = e.pageX;
996		}
997		else if (e.clientX != null)
998		{
999			var html = document.documentElement;
1000			var body = document.body;
1001
1002			pageX = e.clientX + (html.scrollLeft || body && body.scrollLeft || 0);
1003			pageX -= html.clientLeft || 0;
1004		}
1005
1006		return pageX;
1007	};
1008
1009	SmartFilter.prototype.recountMinPrice = function()
1010	{
1011		var newMinPrice = (this.priceDiff*this.leftPercent)/100;
1012		newMinPrice = (this.minPrice + newMinPrice).toFixed(this.precision);
1013
1014		if (newMinPrice != this.minPrice)
1015			this.minInput.value = newMinPrice;
1016		else
1017			this.minInput.value = "";
1018		/** @global JCSmartFilter smartFilter */
1019		smartFilter.keyup(this.minInput);
1020	};
1021
1022	SmartFilter.prototype.recountMaxPrice = function()
1023	{
1024		var newMaxPrice = (this.priceDiff*this.rightPercent)/100;
1025		newMaxPrice = (this.maxPrice - newMaxPrice).toFixed(this.precision);
1026
1027		if (newMaxPrice != this.maxPrice)
1028			this.maxInput.value = newMaxPrice;
1029		else
1030			this.maxInput.value = "";
1031		/** @global JCSmartFilter smartFilter */
1032		smartFilter.keyup(this.maxInput);
1033	};
1034
1035	SmartFilter.prototype.onInputChange = function ()
1036	{
1037		var priceDiff;
1038		if (this.minInput.value)
1039		{
1040			var leftInputValue = this.minInput.value;
1041			if (leftInputValue < this.minPrice)
1042				leftInputValue = this.minPrice;
1043
1044			if (leftInputValue > this.maxPrice)
1045				leftInputValue = this.maxPrice;
1046
1047			priceDiff = leftInputValue - this.minPrice;
1048			this.leftPercent = (priceDiff*100)/this.priceDiff;
1049
1050			this.makeLeftSliderMove(false);
1051		}
1052
1053		if (this.maxInput.value)
1054		{
1055			var rightInputValue = this.maxInput.value;
1056			if (rightInputValue < this.minPrice)
1057				rightInputValue = this.minPrice;
1058
1059			if (rightInputValue > this.maxPrice)
1060				rightInputValue = this.maxPrice;
1061
1062			priceDiff = this.maxPrice - rightInputValue;
1063			this.rightPercent = (priceDiff*100)/this.priceDiff;
1064
1065			this.makeRightSliderMove(false);
1066		}
1067	};
1068
1069	SmartFilter.prototype.makeLeftSliderMove = function(recountPrice)
1070	{
1071		recountPrice = (recountPrice !== false);
1072
1073		this.leftSlider.style.left = this.leftPercent + "%";
1074		this.colorUnavailableActive.style.left = this.leftPercent + "%";
1075
1076		var areBothSlidersMoving = false;
1077		if (this.leftPercent + this.rightPercent >= 100)
1078		{
1079			areBothSlidersMoving = true;
1080			this.rightPercent = 100 - this.leftPercent;
1081			this.rightSlider.style.right = this.rightPercent + "%";
1082			this.colorUnavailableActive.style.right = this.rightPercent + "%";
1083		}
1084
1085		if (this.leftPercent >= this.fltMinPercent && this.leftPercent <= (100-this.fltMaxPercent))
1086		{
1087			this.colorAvailableActive.style.left = this.leftPercent + "%";
1088			if (areBothSlidersMoving)
1089			{
1090				this.colorAvailableActive.style.right = 100 - this.leftPercent + "%";
1091			}
1092		}
1093		else if(this.leftPercent <= this.fltMinPercent)
1094		{
1095			this.colorAvailableActive.style.left = this.fltMinPercent + "%";
1096			if (areBothSlidersMoving)
1097			{
1098				this.colorAvailableActive.style.right = 100 - this.fltMinPercent + "%";
1099			}
1100		}
1101		else if(this.leftPercent >= this.fltMaxPercent)
1102		{
1103			this.colorAvailableActive.style.left = 100-this.fltMaxPercent + "%";
1104			if (areBothSlidersMoving)
1105			{
1106				this.colorAvailableActive.style.right = this.fltMaxPercent + "%";
1107			}
1108		}
1109
1110		if (recountPrice)
1111		{
1112			this.recountMinPrice();
1113			if (areBothSlidersMoving)
1114				this.recountMaxPrice();
1115		}
1116	};
1117
1118	SmartFilter.prototype.countNewLeft = function(event)
1119	{
1120		var pageX = this.getPageX(event);
1121
1122		var trackerXCoord = this.getXCoord(this.trackerWrap);
1123		var rightEdge = this.trackerWrap.offsetWidth;
1124
1125		var newLeft = pageX - trackerXCoord;
1126
1127		if (newLeft < 0)
1128			newLeft = 0;
1129		else if (newLeft > rightEdge)
1130			newLeft = rightEdge;
1131
1132		return newLeft;
1133	};
1134
1135	SmartFilter.prototype.onMoveLeftSlider = function(e)
1136	{
1137		if (!this.isTouch)
1138		{
1139			this.leftSlider.ondragstart = function() {
1140				return false;
1141			};
1142		}
1143
1144		if (!this.isTouch)
1145		{
1146			document.onmousemove = BX.proxy(function(event) {
1147				this.leftPercent = ((this.countNewLeft(event)*100)/this.trackerWrap.offsetWidth);
1148				this.makeLeftSliderMove();
1149			}, this);
1150
1151			document.onmouseup = function() {
1152				document.onmousemove = document.onmouseup = null;
1153			};
1154		}
1155		else
1156		{
1157			document.ontouchmove = BX.proxy(function(event) {
1158				this.leftPercent = ((this.countNewLeft(event)*100)/this.trackerWrap.offsetWidth);
1159				this.makeLeftSliderMove();
1160			}, this);
1161
1162			document.ontouchend = function() {
1163				document.ontouchmove = document.touchend = null;
1164			};
1165		}
1166
1167		return false;
1168	};
1169
1170	SmartFilter.prototype.makeRightSliderMove = function(recountPrice)
1171	{
1172		recountPrice = (recountPrice !== false);
1173
1174		this.rightSlider.style.right = this.rightPercent + "%";
1175		this.colorUnavailableActive.style.right = this.rightPercent + "%";
1176
1177		var areBothSlidersMoving = false;
1178		if (this.leftPercent + this.rightPercent >= 100)
1179		{
1180			areBothSlidersMoving = true;
1181			this.leftPercent = 100 - this.rightPercent;
1182			this.leftSlider.style.left = this.leftPercent + "%";
1183			this.colorUnavailableActive.style.left = this.leftPercent + "%";
1184		}
1185
1186		if ((100-this.rightPercent) >= this.fltMinPercent && this.rightPercent >= this.fltMaxPercent)
1187		{
1188			this.colorAvailableActive.style.right = this.rightPercent + "%";
1189			if (areBothSlidersMoving)
1190			{
1191				this.colorAvailableActive.style.left = 100 - this.rightPercent + "%";
1192			}
1193		}
1194		else if(this.rightPercent <= this.fltMaxPercent)
1195		{
1196			this.colorAvailableActive.style.right = this.fltMaxPercent + "%";
1197			if (areBothSlidersMoving)
1198			{
1199				this.colorAvailableActive.style.left = 100 - this.fltMaxPercent + "%";
1200			}
1201		}
1202		else if((100-this.rightPercent) <= this.fltMinPercent)
1203		{
1204			this.colorAvailableActive.style.right = 100-this.fltMinPercent + "%";
1205			if (areBothSlidersMoving)
1206			{
1207				this.colorAvailableActive.style.left = this.fltMinPercent + "%";
1208			}
1209		}
1210
1211		if (recountPrice)
1212		{
1213			this.recountMaxPrice();
1214			if (areBothSlidersMoving)
1215				this.recountMinPrice();
1216		}
1217	};
1218
1219	SmartFilter.prototype.onMoveRightSlider = function(e)
1220	{
1221		if (!this.isTouch)
1222		{
1223			this.rightSlider.ondragstart = function() {
1224				return false;
1225			};
1226		}
1227
1228		if (!this.isTouch)
1229		{
1230			document.onmousemove = BX.proxy(function(event) {
1231				this.rightPercent = 100-(((this.countNewLeft(event))*100)/(this.trackerWrap.offsetWidth));
1232				this.makeRightSliderMove();
1233			}, this);
1234
1235			document.onmouseup = function() {
1236				document.onmousemove = document.onmouseup = null;
1237			};
1238		}
1239		else
1240		{
1241			document.ontouchmove = BX.proxy(function(event) {
1242				this.rightPercent = 100-(((this.countNewLeft(event))*100)/(this.trackerWrap.offsetWidth));
1243				this.makeRightSliderMove();
1244			}, this);
1245
1246			document.ontouchend = function() {
1247				document.ontouchmove = document.ontouchend = null;
1248			};
1249		}
1250
1251		return false;
1252	};
1253
1254	return SmartFilter;
1255})();

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.