Working with bitrix: smart.filter
Rus
Eng
Работа с bitrix:smart.filter

All English-language materials have been translated fully automatically using the Google service

Replace checkboxes in bitrix: smart.filter with select

I do not recommend using the selection directly, because of dancing with a tambourine when styling it. So I use a regular div styled like checkbox

At the beginning of your template add an arrow icon

<svg style = "display: none;">
<symbol version = "1.1" id = "arrowDown" x = "0px" y = "0px"
viewBox = "0 0 255 255" style = "enable-background: new 0 0 255 255;"
xml: space = "preserve">
<polygon points = "0.63.75 127.5,191.25 255.63.75" />
</symbol>
</svg></code> </pre>
<p> In the <code> template.php </code> of your <code> bitrix: smart.filter </code>, we find the block that displays the properties of the parameters in the loop. I usually have it (~ 534 lines) </p>
<pre><code>default://CHECKBOXES</code> </pre>
<p> And for the required properties, by condition, set a new output format. For example like this: </p>
<pre><code><? if ($ arItem ['CODE'] == 'BRAND') {?>
<p> Select <?=$arItem ['NAME'>?> </p>
<div class = "customSelector" data-attr = "<? = $ arItem ['CODE']?>">
<div class = "customSelectorTitle">
<? $ check = false;
foreach ($ arItem ["VALUES"] as $ val => $ ar) {
if ($ ar ["CHECKED"]) {echo $ ar ['VALUE']; $ check = true;}
}
if (! $ check) {echo $ arItem ["NAME"];}
?>
<svg class = "icon"> <use xlink: href = "# arrowDown" /> </svg>
</div>
<div class = "customSelectorOptions">
<? foreach ($ arItem ["VALUES"] as $ val => $ ar) {?>
<label class = "customSelect <? if ($ ar [" DISABLED "]) {?> disabled <?}?>" data-attr = "<? echo $ ar [" VALUE "];?>"> <input type = "checkbox" name = "<? echo $ ar [" CONTROL_NAME "]?>" id = "<? echo $ ar [" CONTROL_ID "]?>" value = "Y" onchange = "smartFilter.click (this ) "data-attr =" <? echo $ ar ["VALUE"];?> "<? echo $ ar [" CHECKED "]? 'checked = "checked"': ''?> <? if ($ ar ["DISABLED"]) {?> disabled <? }? >> <? echo $ ar ["VALUE"];?> </label>
<?}?>
</div>
</div>
<?} else {?>
<? foreach ($ arItem ["VALUES"] as $ val => $ ar):?>
<label data-role = "label _ <? = $ ar [" CONTROL_ID "]?>" class = "bx_filter_param_label <? echo $ ar [" DISABLED "]? 'disabled': ''?>" for = "<? echo $ ar ["CONTROL_ID"]?> ">
<span class = "bx_filter_input_checkbox">
<input
type = "checkbox"
value = "<? echo $ ar [" HTML_VALUE "]?>"
name = "<? echo $ ar [" CONTROL_NAME "]?>"
id = "<? echo $ ar [" CONTROL_ID "]?>"
<? echo $ ar ["CHECKED"]? 'checked = "checked"': ''?>
onclick = "smartFilter.click (this)"
/>
<span class = "bx_filter_param_text" title = "<? = $ ar [" VALUE "];?>"> <? = $ ar ["VALUE"];?> <?
if ($ arParams ["DISPLAY_ELEMENT_COUNT"]! == "N" && isset ($ ar ["ELEMENT_COUNT"])):
?> (<span data-role = "count _ <? = $ ar [" CONTROL_ID "]?>"> <? echo $ ar ["ELEMENT_COUNT"];?> </span>) <?
endif;?> </span>
</span>
</label>
<?endforeach;?></code> </pre>
<p> Add styles to the <code> style.css </code> template </p>
<pre> <code> .customSelectorTitle .icon
{-moz-transition: all 0.5s; -webkit-transition: all 0.5s; -o-transition: all 0.5s; -ms-transition: all 0.5s}

.customSelectorTitle {background-color: #fff; border: 1px solid #eee; -ms-align-items: center; align-items: center; padding-left: 12px; font-size: 13px; max-width: 100% ; line-height: 50px; cursor: pointer; vertical-align: middle; position: relative; white-space: nowrap; height: 50px; position: relative}
.customSelectorTitle: first-letter {text-transform: uppercase}
.customSelectorTitle .icon {position: absolute; right: 10px; top: 20px; width: 10px; height: 10px; transform: rotate (0)}
.customSelectorTitle.active .icon {transform: rotate (180deg)}
.customSelect {display: block; width: 100%; cursor: pointer; padding-left: 12px; margin-bottom: 0; line-height: 30px; font-size: 13px}
.customSelect.disabled {color: #fff; background-color: # e3e3e3}
.customSelect: hover {background-color: # e3e3e3}
.customSelect input {display: none;}
.customSelector {position: relative}
.customSelectorOptions {position: absolute; top: 50px; left: 0; width: 100%; height: auto; background-color: #fff; border: 1px solid #eee; display: none; z-index: 10; font- size: 16px;}
.main-calculator__card.active {display: flex} </code> </pre>
<p> Adding a <code> jQuery </code> Handler </p>
<pre> <code> (function ($) {
$ (document) .ready (function () {
$ ('body'). on ('click', '. customSelectorTitle', function () {
var el = $ (this);

if (el.hasClass ('active')) {
el.removeClass ('active');
el.next (). stop (). slideUp (200);
} else {
$ ('. customSelectorTitle.active ~ .customSelectorOptions'). slideUp (200);
$ ('. customSelectorTitle.active'). removeClass ('active');

el.addClass ('active');
el.next (). stop (). slideDown (200);
}

});

$ ('. customSelect input'). on ('change', function () {
var el = $ (this);

el.parents ('. customSelectorOptions'). prev (). text (el.attr ('data-attr')). removeClass ('active');
el.parents ('. customSelectorOptions'). find ('input'). not (el) .prop ('checked', false) .val ('N');
el.parents ('. customSelectorOptions'). stop (). slideUp (200);
});

$ (document) .mouseup (function (e) {// web document click event
var div = $ (". customSelector"); // specify the element ID here
if (! div.is (e.target) // if the click was not on our block
&& div.has (e.target) .length === 0) {// and not by its children
$ ('. customSelectorTitle.active ~ .customSelectorOptions'). slideUp (200);
$ ('. customSelectorTitle.active'). removeClass ('active');
}
});


});

}) (jQuery); </code> </pre>
<h3> AJAX update of filters <code> bitrix: smart.filter </code> in <code> bitrix: catalog </code> without <code>AJAX_MODE=Y</code> </h3> enabled
<p> In the <code> script.js </code> file of your component template <code> bitrix: smart.filter </code>, look for the <code> JCSmartFilter.prototype.postHandler </code> function and comment out the lines ( ~ 184 lines): </p>
<pre> <code> / * if (modef.style.display === 'none')
{
modef.style.display = 'inline-block';
} * / </code> </pre>
<p> Add immediately after them: </p>
<pre> <code> $ .get (
result.FILTER_AJAX_URL,
function (data) {
$ ('# catalogBlock'). html ($ (data) .find ('# catalogBlock'). html ());
}
);

history.pushState (null, null, result.FILTER_AJAX_URL); </code> </pre>
<p> Your catalog must be framed in a <code> div </code> c <code>id="catalogBlock"</code> </p>
<p> To make your pagination <code> ajax </code>, then use similar code </p>
<pre> <code> $ (document) .on ("click", '#catalogBlock .pagination a', function (e) {
e.preventDefault ();

var href = $ (this) .attr ('href');

history.pushState (null, null, href);

$ .get (
href,
function (data) {
$ ('# catalogBlock'). html ($ (data) .find ('# catalogBlock'). html ());
}
);
});
</code> </pre>
<p> Source <a href = "https://ftask.ru/2018/07/23/bitrix-ajax-%D0%BE%D0%B1%D0%BD%D0%BE%D0%B2%D0% BB% D0% B5% D0% BD% D0% B8% D0% B5-% D1% 81% D0% BF% D0% B8% D1% 81% D0% BA% D0% B0-bitrixcatalog-% D0% BF% D0% BE-% D1% 84% D0% B8% D0% BB% D1% 8C% D1% 82% D1% 80% D0% B0% D0% BC-% D0% B1 / "rel =" nofollow noopener noreferrer " target = "_ blank"> bitrix ajax updating the bitrix: catalog list by filters without standard ajax enabled AJAX_MODE = Y </a> </p>
<h3> Full listing of the <code> script.js </code> component of the <code> bitrix: smart.filter </code> component with ajax enabled from the example above, a custom preloader and a couple of fixes </h3>
<p> We take the preloader <a href='https://tichiy.ru/wiki/menyaem-standartnyj-preloader-bitriks'> from here </a> </p>
<p> Plus. since we have checkboxes, when choosing the second and further options, <code> bitrix: smart.filter </code> generates url from all included <code> checbox </code>, which does not suit us, and therefore we are looking for the <code> function JCSmartFilter.prototype.click </code> </p>
<p> And insert the zeroing of the values ​​of all previously selected parameters from a specific property </p>
<pre> <code> // Zero the values ​​of other property checkboxes
var clist = checkbox.closest (". customSelectorOptions"). getElementsByTagName ("input");
for (var i = 0; i <clist.length; ++ i) {
if (clist [i]! == checkbox) {
clist [i] .checked = false;
}
} </code> </pre>
<p> Then the complete listing looks like this: </p>
<pre> <code> function JCSmartFilter (ajaxURL, viewMode)
{
this.ajaxURL = ajaxURL;
this.form = null;
this.timer = null;
this.first = true;
this.cacheKey = '';
this.cache = [];
this.viewMode = viewMode;
}

JCSmartFilter.prototype.keyup = function (input)
{
if (!! this.timer)
{
clearTimeout (this.timer);
}
this.timer = setTimeout (BX.delegate (function () {
this.reload (input);
}, this), 500);
};

JCSmartFilter.prototype.click = function (checkbox)
{
if (!! this.timer)
{
clearTimeout (this.timer);
}

// Zero the values ​​of other checkboxes of the property
var clist = checkbox.closest (". customSelectorOptions"). getElementsByTagName ("input");
for (var i = 0; i <clist.length; ++ i) {
if (clist [i]! == checkbox) {
clist [i] .checked = false;
}
}

BX.showWait ();

this.timer = setTimeout (BX.delegate (function () {
this.reload (checkbox);
}, this), 1000);
};

JCSmartFilter.prototype.reload = function (input)
{
if (this.cacheKey! == '')
{
// Postprone backend query
if (!! this.timer)
{
clearTimeout (this.timer);
}
this.timer = setTimeout (BX.delegate (function () {
this.reload (input);
}, this), 1000);
return;
}
this.cacheKey = '|';

this.position = BX.pos (input, true);
this.form = BX.findParent (input, {'tag': 'form'});
if (this.form)
{
var values ​​= [];
values ​​[0] = {name: 'ajax', value: 'y'};
this.gatherInputsValues ​​(values, BX.findChildren (this.form, {'tag': new RegExp ('^ (input | select) $', 'i')}, true));

for (var i = 0; i <values.length; i ++)
this.cacheKey + = values ​​[i] .name + ':' + values ​​[i] .value + '|';

if (this.cache [this.cacheKey])
{
this.curFilterinput = input;
this.postHandler (this.cache [this.cacheKey], true);
}
else
{
this.curFilterinput = input;
BX.ajax.loadJSON (
this.ajaxURL,
this.values2post (values),
BX.delegate (this.postHandler, this)
);
}
}
};
JCSmartFilter.prototype.updateItem = function (PID, arItem)
{
if (arItem.PROPERTY_TYPE === 'N' || arItem.PRICE)
{
var trackBar = window ['trackBar' + PID];
if (! trackBar && arItem.ENCODED_ID)
trackBar = window ['trackBar' + arItem.ENCODED_ID];

if (trackBar && arItem.VALUES)
{
if (arItem.VALUES.MIN && arItem.VALUES.MIN.FILTERED_VALUE)
{
trackBar.setMinFilteredValue (arItem.VALUES.MIN.FILTERED_VALUE);
}

if (arItem.VALUES.MAX && arItem.VALUES.MAX.FILTERED_VALUE)
{
trackBar.setMaxFilteredValue (arItem.VALUES.MAX.FILTERED_VALUE);
}
}
}
else if (arItem.VALUES)
{
for (var i in arItem.VALUES)
{
if (arItem.VALUES.hasOwnProperty (i))
{
var value = arItem.VALUES [i];
var control = BX (value.CONTROL_ID);

if (!! control)
{
var label = document.querySelector ('[data-role = "label _' + value.CONTROL_ID + '"]');
if (value.DISABLED)
{
if (label)
BX.addClass (label, 'disabled');
else
BX.addClass (control.parentNode, 'disabled');
}
else
{
if (label)
BX.removeClass (label, 'disabled');
else
BX.removeClass (control.parentNode, 'disabled');
}

if (value.hasOwnProperty ('ELEMENT_COUNT'))
{
label = document.querySelector ('[data-role = "count _' + value.CONTROL_ID + '"]');
if (label)
label.innerHTML = value.ELEMENT_COUNT;
}
}
}
}
}
};

JCSmartFilter.prototype.postHandler = function (result, fromCache)
{
var hrefFILTER, url, curProp;
var modef = BX ('modef');
var modef_num = BX ('modef_num');

if (!! result && !! result.ITEMS)
{
for (var PID in result.ITEMS)
{
if (result.ITEMS.hasOwnProperty (PID))
{
this.updateItem (PID, result.ITEMS [PID]);
}
}

if (!! modef && !! modef_num)
{
modef_num.innerHTML = result.ELEMENT_COUNT;
hrefFILTER = BX.findChildren (modef, {tag: 'A'}, true);

if (result.FILTER_URL && hrefFILTER)
{
hrefFILTER [0] .href = BX.util.htmlspecialcharsback (result.FILTER_URL);
}

if (result.FILTER_AJAX_URL && result.COMPONENT_CONTAINER_ID)
{
BX.bind (hrefFILTER [0], 'click', function (e)
{
url = BX.util.htmlspecialcharsback (result.FILTER_AJAX_URL);
BX.ajax.insertToNode (url, result.COMPONENT_CONTAINER_ID);
return BX.PreventDefault (e);
});
}

if (result.INSTANT_RELOAD && result.COMPONENT_CONTAINER_ID)
{
url = BX.util.htmlspecialcharsback (result.FILTER_AJAX_URL);
BX.ajax.insertToNode (url, result.COMPONENT_CONTAINER_ID);
}
else
{
/ * if (modef.style.display === 'none')
{
modef.style.display = 'inline-block';
} * /

$ .get (
result.FILTER_AJAX_URL,
function (data) {
$ ('# catalogBlock'). html ($ (data) .find ('# catalogBlock'). html ());
BX.closeWait ();
}
);

history.pushState (null, null, result.FILTER_AJAX_URL);

if (this.viewMode == "vertical")
{
curProp = BX.findChild (BX.findParent (this.curFilterinput, {'class': 'bx_filter_parameters_box'}), {'class': 'bx_filter_container_modef'}, true, false);
curProp.appendChild (modef);
}
}
}

}
if (! fromCache && this.cacheKey! == '')
{
this.cache [this.cacheKey] = result;
}
this.cacheKey = '';
};

JCSmartFilter.prototype.gatherInputsValues ​​= function (values, elements)
{
if (elements)
{
for (var i = 0; i <elements.length; i ++)
{
var el = elements [i];
if (el.disabled ||! el.type)
continue;

switch (el.type.toLowerCase ())
{
case 'text':
case 'textarea':
case 'password':
case 'hidden':
case 'select-one':
if (el.value.length)
values ​​[values.length] = {name: el.name, value: el.value};
break;
case 'radio':
case 'checkbox':
if (el.checked)
values ​​[values.length] = {name: el.name, value: el.value};
break;
case 'select-multiple':
for (var j = 0; j <el.options.length; j ++)
{
if (el.options [j] .selected)
values ​​[values.length] = {name: el.name, value: el.options [j] .value};
}
break;
default:
break;
}
}
}
};

JCSmartFilter.prototype.values2post = function (values)
{
var post = [];
var current = post;
var i = 0;

while (i <values.length)
{
var p = values ​​[i] .name.indexOf ('[');
if (p == -1)
{
current [values ​​[i] .name] = values ​​[i] .value;
current = post;
i ++;
}
else
{
var name = values ​​[i] .name.substring (0, p);
var rest = values ​​[i] .name.substring (p + 1);
if (! current [name])
current [name] = [];

var pp = rest.indexOf (']');
if (pp == -1)
{
// Error - not balanced brackets
current = post;
i ++;
}
else if (pp == 0)
{
// No index specified - so take the next integer
current = current [name];
values ​​[i] .name = '' + current.length;
}
else
{
// Now index name becomes and name and we go deeper into the array
current = current [name];
values ​​[i] .name = rest.substring (0, pp) + rest.substring (pp + 1);
}
}
}
return post;
};

JCSmartFilter.prototype.hideFilterProps = function (element)
{
var easing;
var obj = element.parentNode;
var filterBlock = BX.findChild (obj, {className: "bx_filter_block"}, true, false);

if (BX.hasClass (obj, "active"))
{
easing = new BX.easing ({
duration: 300,
start: {opacity: 1, height: filterBlock.offsetHeight},
finish: {opacity: 0, height: 0},
transition: BX.easing.transitions.quart,
step: function (state) {
filterBlock.style.opacity = state.opacity;
filterBlock.style.height = state.height + "px";
},
complete: function () {
filterBlock.setAttribute ("style", "");
BX.removeClass (obj, "active");
}
});
easing.animate ();
}
else
{
filterBlock.style.display = "block";
filterBlock.style.opacity = 0;
filterBlock.style.height = "auto";

var obj_children_height = filterBlock.offsetHeight;
filterBlock.style.height = 0;

easing = new BX.easing ({
duration: 300,
start: {opacity: 0, height: 0},
finish: {opacity: 1, height: obj_children_height},
transition: BX.easing.transitions.quart,
step: function (state) {
filterBlock.style.opacity = state.opacity;
filterBlock.style.height = state.height + "px";
},
complete: function () {
}
});
easing.animate ();
BX.addClass (obj, "active");
}
};
JCSmartFilter.prototype.showDropDownPopup = function (element, popupId)
{
var contentNode = element.querySelector ('[data-role = "dropdownContent"]');
BX.PopupWindowManager.create ("smartFilterDropDown" + popupId, element, {
autoHide: true,
offsetLeft: 0,
offsetTop: 3,
overlay: false,
draggable: {restrict: true},
closeByEsc: true,
content: contentNode
}). show ();
};

JCSmartFilter.prototype.selectDropDownItem = function (element, controlId)
{
this.keyup (BX (controlId));

var wrapContainer = BX.findParent (BX (controlId), {className: "bx_filter_select_container"}, false);

var currentOption = wrapContainer.querySelector ('[data-role = "currentOption"]');
currentOption.innerHTML = element.innerHTML;
BX.PopupWindowManager.getCurrentPopup (). Close ();
};

BX.namespace ("BX.Iblock.SmartFilter");
BX.Iblock.SmartFilter = (function ()
{
var SmartFilter = function (arParams)
{
if (typeof arParams === 'object')
{
this.leftSlider = BX (arParams.leftSlider);
this.rightSlider = BX (arParams.rightSlider);
this.tracker = BX (arParams.tracker);
this.trackerWrap = BX (arParams.trackerWrap);

this.minInput = BX (arParams.minInputId);
this.maxInput = BX (arParams.maxInputId);

this.minPrice = parseFloat (arParams.minPrice);
this.maxPrice = parseFloat (arParams.maxPrice);

this.curMinPrice = parseFloat (arParams.curMinPrice);
this.curMaxPrice = parseFloat (arParams.curMaxPrice);

this.fltMinPrice = arParams.fltMinPrice? parseFloat (arParams.fltMinPrice): parseFloat (arParams.curMinPrice);
this.fltMaxPrice = arParams.fltMaxPrice? parseFloat (arParams.fltMaxPrice): parseFloat (arParams.curMaxPrice);

this.precision = arParams.precision || 0;

this.priceDiff = this.maxPrice - this.minPrice;

this.leftPercent = 0;
this.rightPercent = 0;

this.fltMinPercent = 0;
this.fltMaxPercent = 0;

this.colorUnavailableActive = BX (arParams.colorUnavailableActive); // gray
this.colorAvailableActive = BX (arParams.colorAvailableActive); // blue
this.colorAvailableInactive = BX (arParams.colorAvailableInactive); // light blue

this.isTouch = false;

this.init ();

if ('ontouchstart' in document.documentElement)
{
this.isTouch = true;

BX.bind (this.leftSlider, "touchstart", BX.proxy (function (event) {
this.onMoveLeftSlider (event)
}, this));

BX.bind (this.rightSlider, "touchstart", BX.proxy (function (event) {
this.onMoveRightSlider (event)
}, this));
}
else
{
BX.bind (this.leftSlider, "mousedown", BX.proxy (function (event) {
this.onMoveLeftSlider (event)
}, this));

BX.bind (this.rightSlider, "mousedown", BX.proxy (function (event) {
this.onMoveRightSlider (event)
}, this));
}

BX.bind (this.minInput, "keyup", BX.proxy (function (event) {
this.onInputChange ();
}, this));

BX.bind (this.maxInput, "keyup", BX.proxy (function (event) {
this.onInputChange ();
}, this));
}
};

SmartFilter.prototype.init = function ()
{
var priceDiff;

if (this.curMinPrice> this.minPrice)
{
priceDiff = this.curMinPrice - this.minPrice;
this.leftPercent = (priceDiff * 100) /this.priceDiff;

this.leftSlider.style.left = this.leftPercent + "%";
this.colorUnavailableActive.style.left = this.leftPercent + "%";
}

this.setMinFilteredValue (this.fltMinPrice);

if (this.curMaxPrice <this.maxPrice)
{
priceDiff = this.maxPrice - this.curMaxPrice;
this.rightPercent = (priceDiff * 100) /this.priceDiff;

this.rightSlider.style.right = this.rightPercent + "%";
this.colorUnavailableActive.style.right = this.rightPercent + "%";
}

this.setMaxFilteredValue (this.fltMaxPrice);
};

SmartFilter.prototype.setMinFilteredValue = function (fltMinPrice)
{
this.fltMinPrice = parseFloat (fltMinPrice);
if (this.fltMinPrice> = this.minPrice)
{
var priceDiff = this.fltMinPrice - this.minPrice;
this.fltMinPercent = (priceDiff * 100) /this.priceDiff;

if (this.leftPercent> this.fltMinPercent)
this.colorAvailableActive.style.left = this.leftPercent + "%";
else
this.colorAvailableActive.style.left = this.fltMinPercent + "%";

this.colorAvailableInactive.style.left = this.fltMinPercent + "%";
}
else
{
this.colorAvailableActive.style.left = "0%";
this.colorAvailableInactive.style.left = "0%";
}
};

	SmartFilter.prototype.setMaxFilteredValue = function (fltMaxPrice)
	{
		this.fltMaxPrice = parseFloat(fltMaxPrice);
		if (this.fltMaxPrice <= this.maxPrice)
		{
			var priceDiff = this.maxPrice - this.fltMaxPrice;
			this.fltMaxPercent = (priceDiff*100)/this.priceDiff;

			if (this.rightPercent > this.fltMaxPercent)
				this.colorAvailableActive.style.right = this.rightPercent + "%";
			else
				this.colorAvailableActive.style.right = this.fltMaxPercent + "%";

			this.colorAvailableInactive.style.right = this.fltMaxPercent + "%";
		}
		else
		{
			this.colorAvailableActive.style.right = "0%";
			this.colorAvailableInactive.style.right = "0%";
		}
	};

	SmartFilter.prototype.getXCoord = function(elem)
	{
		var box = elem.getBoundingClientRect();
		var body = document.body;
		var docElem = document.documentElement;

		var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft;
		var clientLeft = docElem.clientLeft || body.clientLeft || 0;
		var left = box.left + scrollLeft - clientLeft;

		return Math.round(left);
	};

	SmartFilter.prototype.getPageX = function(e)
	{
		e = e || window.event;
		var pageX = null;

		if (this.isTouch && event.targetTouches[0] != null)
		{
			pageX = e.targetTouches[0].pageX;
		}
		else if (e.pageX != null)
		{
			pageX = e.pageX;
		}
		else if (e.clientX != null)
		{
			var html = document.documentElement;
			var body = document.body;

			pageX = e.clientX + (html.scrollLeft || body && body.scrollLeft || 0);
			pageX -= html.clientLeft || 0;
		}

		return pageX;
	};

	SmartFilter.prototype.recountMinPrice = function()
	{
		var newMinPrice = (this.priceDiff*this.leftPercent)/100;
		newMinPrice = (this.minPrice + newMinPrice).toFixed(this.precision);

		if (newMinPrice != this.minPrice)
			this.minInput.value = newMinPrice;
		else
			this.minInput.value = "";
		smartFilter.keyup(this.minInput);
	};

	SmartFilter.prototype.recountMaxPrice = function()
	{
		var newMaxPrice = (this.priceDiff*this.rightPercent)/100;
		newMaxPrice = (this.maxPrice - newMaxPrice).toFixed(this.precision);

		if (newMaxPrice != this.maxPrice)
			this.maxInput.value = newMaxPrice;
		else
			this.maxInput.value = "";
		smartFilter.keyup(this.maxInput);
	};

	SmartFilter.prototype.onInputChange = function ()
	{
		var priceDiff;
		if (this.minInput.value)
		{
			var leftInputValue = this.minInput.value;
			if (leftInputValue < this.minPrice)
				leftInputValue = this.minPrice;

			if (leftInputValue > this.maxPrice)
				leftInputValue = this.maxPrice;

			priceDiff = leftInputValue - this.minPrice;
			this.leftPercent = (priceDiff*100)/this.priceDiff;

			this.makeLeftSliderMove(false);
		}

		if (this.maxInput.value)
		{
			var rightInputValue = this.maxInput.value;
			if (rightInputValue < this.minPrice)
				rightInputValue = this.minPrice;

			if (rightInputValue > this.maxPrice)
				rightInputValue = this.maxPrice;

			priceDiff = this.maxPrice - rightInputValue;
			this.rightPercent = (priceDiff*100)/this.priceDiff;

			this.makeRightSliderMove(false);
		}
	};

	SmartFilter.prototype.makeLeftSliderMove = function(recountPrice)
	{
		recountPrice = (recountPrice === false) ? false : true;

		this.leftSlider.style.left = this.leftPercent + "%";
		this.colorUnavailableActive.style.left = this.leftPercent + "%";

		var areBothSlidersMoving = false;
		if (this.leftPercent + this.rightPercent >= 100)
		{
			areBothSlidersMoving = true;
			this.rightPercent = 100 - this.leftPercent;
			this.rightSlider.style.right = this.rightPercent + "%";
			this.colorUnavailableActive.style.right = this.rightPercent + "%";
		}

		if (this.leftPercent >= this.fltMinPercent && this.leftPercent <= (100-this.fltMaxPercent))
		{
			this.colorAvailableActive.style.left = this.leftPercent + "%";
			if (areBothSlidersMoving)
			{
				this.colorAvailableActive.style.right = 100 - this.leftPercent + "%";
			}
		}
		else if(this.leftPercent <= this.fltMinPercent)
		{
			this.colorAvailableActive.style.left = this.fltMinPercent + "%";
			if (areBothSlidersMoving)
			{
				this.colorAvailableActive.style.right = 100 - this.fltMinPercent + "%";
			}
		}
		else if(this.leftPercent >= this.fltMaxPercent)
		{
			this.colorAvailableActive.style.left = 100-this.fltMaxPercent + "%";
			if (areBothSlidersMoving)
			{
				this.colorAvailableActive.style.right = this.fltMaxPercent + "%";
			}
		}

		if (recountPrice)
		{
			this.recountMinPrice();
			if (areBothSlidersMoving)
				this.recountMaxPrice();
		}
	};

	SmartFilter.prototype.countNewLeft = function(event)
	{
		var pageX = this.getPageX(event);

		var trackerXCoord = this.getXCoord(this.trackerWrap);
		var rightEdge = this.trackerWrap.offsetWidth;

		var newLeft = pageX - trackerXCoord;

		if (newLeft < 0)
			newLeft = 0;
		else if (newLeft > rightEdge)
			newLeft = rightEdge;

		return newLeft;
	};

	SmartFilter.prototype.onMoveLeftSlider = function(e)
	{
		if (!this.isTouch)
		{
			this.leftSlider.ondragstart = function() {
				return false;
			};
		}

		if (!this.isTouch)
		{
			document.onmousemove = BX.proxy(function(event) {
				this.leftPercent = ((this.countNewLeft(event)*100)/this.trackerWrap.offsetWidth);
				this.makeLeftSliderMove();
			}, this);

			document.onmouseup = function() {
				document.onmousemove = document.onmouseup = null;
			};
		}
		else
		{
			document.ontouchmove = BX.proxy(function(event) {
				this.leftPercent = ((this.countNewLeft(event)*100)/this.trackerWrap.offsetWidth);
				this.makeLeftSliderMove();
			}, this);

			document.ontouchend = function() {
				document.ontouchmove = document.touchend = null;
			};
		}

		return false;
	};

	SmartFilter.prototype.makeRightSliderMove = function(recountPrice)
	{
		recountPrice = (recountPrice === false) ? false : true;

		this.rightSlider.style.right = this.rightPercent + "%";
		this.colorUnavailableActive.style.right = this.rightPercent + "%";

		var areBothSlidersMoving = false;
		if (this.leftPercent + this.rightPercent >= 100)
		{
			areBothSlidersMoving = true;
			this.leftPercent = 100 - this.rightPercent;
			this.leftSlider.style.left = this.leftPercent + "%";
			this.colorUnavailableActive.style.left = this.leftPercent + "%";
		}

		if ((100-this.rightPercent) >= this.fltMinPercent && this.rightPercent >= this.fltMaxPercent)
		{
			this.colorAvailableActive.style.right = this.rightPercent + "%";
			if (areBothSlidersMoving)
			{
				this.colorAvailableActive.style.left = 100 - this.rightPercent + "%";
			}
		}
		else if(this.rightPercent <= this.fltMaxPercent)
		{
			this.colorAvailableActive.style.right = this.fltMaxPercent + "%";
			if (areBothSlidersMoving)
			{
				this.colorAvailableActive.style.left = 100 - this.fltMaxPercent + "%";
			}
		}
		else if((100-this.rightPercent) <= this.fltMinPercent)
		{
			this.colorAvailableActive.style.right = 100-this.fltMinPercent + "%";
			if (areBothSlidersMoving)
			{
				this.colorAvailableActive.style.left = this.fltMinPercent + "%";
			}
		}

		if (recountPrice)
		{
			this.recountMaxPrice();
			if (areBothSlidersMoving)
				this.recountMinPrice();
		}
	};

	SmartFilter.prototype.onMoveRightSlider = function(e)
	{
		if (!this.isTouch)
		{
			this.rightSlider.ondragstart = function() {
				return false;
			};
		}

		if (!this.isTouch)
		{
			document.onmousemove = BX.proxy(function(event) {
				this.rightPercent = 100-(((this.countNewLeft(event))*100)/(this.trackerWrap.offsetWidth));
				this.makeRightSliderMove();
			}, this);

			document.onmouseup = function() {
				document.onmousemove = document.onmouseup = null;
			};
		}
		else
		{
			document.ontouchmove = BX.proxy(function(event) {
				this.rightPercent = 100-(((this.countNewLeft(event))*100)/(this.trackerWrap.offsetWidth));
				this.makeRightSliderMove();
			}, this);

			document.ontouchend = function() {
				document.ontouchmove = document.ontouchend = null;
			};
		}

		return false;
	};

	return SmartFilter;
})();
(function ($) {
$ (document) .ready (function () {
$ ('body'). on ('click', '. customSelectorTitle', function () {
var el = $ (this);

if (el.hasClass ('active')) {
el.removeClass ('active');
el.next (). stop (). slideUp (200);
} else {
$ ('. customSelectorTitle.active ~ .customSelectorOptions'). slideUp (200);
$ ('. customSelectorTitle.active'). removeClass ('active');

el.addClass ('active');
el.next (). stop (). slideDown (200);
}

});

$ ('. customSelect input'). on ('change', function () {
var el = $ (this);

el.parents ('. customSelectorOptions'). prev (). text (el.attr ('data-attr')). removeClass ('active');
el.parents ('. customSelectorOptions'). find ('input'). not (el) .prop ('checked', false) .val ('N');
el.parents ('. customSelectorOptions'). stop (). slideUp (200);
});

$ (document) .mouseup (function (e) {// web document click event
var div = $ (". customSelector"); // specify the element ID here
if (! div.is (e.target) // if the click was not on our block
&& div.has (e.target) .length === 0) {// and not by its children
$ ('. customSelectorTitle.active ~ .customSelectorOptions'). slideUp (200);
$ ('. customSelectorTitle.active'). removeClass ('active');
}
});


});

}) (jQuery);

var lastWait = [];

/ * non-xhr loadings * /
BX.showWait = function (node, msg)
{
node = BX (node) || document.body || document.documentElement;
msg = msg || BX.message ('JS_CORE_LOADING');

var container_id = node.id || Math.random ();

var obMsg = node.bxmsg = document.body.appendChild (BX.create ('DIV', {
props: {
id: 'wait_' + container_id,
className: 'bx-core-waitwindow'
},
text: msg
}));

setTimeout (BX.delegate (_adjustWait, node), 10);

$ ('. pWrap'). show ();
lastWait [lastWait.length] = obMsg;
return obMsg;
};

BX.closeWait = function (node, obMsg)
{
$ ('. pWrap'). hide ();
if (node ​​&&! obMsg)
obMsg = node.bxmsg;
if (node ​​&&! obMsg && BX.hasClass (node, 'bx-core-waitwindow'))
obMsg = node;
if (node ​​&&! obMsg)
obMsg = BX ('wait_' + node.id);
if (! obMsg)
obMsg = lastWait.pop ();

if (obMsg && obMsg.parentNode)
{
for (var i = 0, len = lastWait.length; i <len; i ++)
{
if (obMsg == lastWait [i])
{
lastWait = BX.util.deleteFromArray (lastWait, i);
break;
}
}

obMsg.parentNode.removeChild (obMsg);
if (node)
node.bxmsg = null;
BX.cleanNode (obMsg, true);
}
};
function _adjustWait ()
{
if (! this.bxmsg)
return;

var arContainerPos = BX.pos (this),
div_top = arContainerPos.top;

if (div_top <BX.GetDocElement (). scrollTop)
div_top = BX.GetDocElement (). scrollTop + 5;

this.bxmsg.style.top = (div_top + 5) + 'px';

if (this == BX.GetDocElement ())
{
this.bxmsg.style.right = '5px';
}
else
{
this.bxmsg.style.left = (arContainerPos.right - this.bxmsg.offsetWidth - 5) + 'px';
}
} </code> </pre>
<h3> Ajax filtering <code> catalog.smart.filter </code> by <code> submit </code> forms </h3>
<p> Go to <code> script.js </code> of your filter template and find before the line <code> if (result.INSTANT_RELOAD && result.COMPONENT_CONTAINER_ID) </code> insert </p>
<pre><code>if (result.FILTER_AJAX_URL && result.COMPONENT_CONTAINER_ID)
{
	BX.bind(document.querySelector('#set_filter'), 'click', function(e)
	{
		url = BX.util.htmlspecialcharsback(result.FILTER_AJAX_URL);
		BX.ajax.insertToNode(url, result.COMPONENT_CONTAINER_ID);
		return BX.PreventDefault(e);
	});
}

Find the function JCSmartFilter.prototype.bindUrlToButton and comment out the lines:

BX.bind(button, 'click', proxy(url, function(url)
{
	window.location.href = url;
	return false;
}));

Filtering the catalog by the property of the list type

Place the code before calling bitrix:catalog.section

  // Filter the catalog by the property of the list type
if ($ sGetSort = $ request-> getQuery ("set")) {
switch ($ sGetSort) {
case '5':
$ arrFilter ['= PROPERTY_SET'] = '193';
break;
case '10':
$ arrFilter ['= PROPERTY_SET'] = '194';
break;
}
}
// Where PROPERTY_SET is the code of the filtered property
//, and 193 \ 194 is the ID of the filtered properties  

Display filter by parameter

Place an additional array with our parameter in the result_modifier.php file. The solution is dirty, but working

  $ arResult ['ITEMS'] [778] = [
    'ID' => 778,
    'IBLOCK_ID' => 9,
    'CODE' => 'SET',
    'NAME' => 'Seth',
    'PROPERTY_TYPE' => 'L',
    'DISPLAY_TYPE' => 'P',
    'DISPLAY_EXPANDED' => 'N',
    'VALUES' => [
            '779' => [
                'CONTROL_ID' => 'set_3390377895',
                'CONTROL_NAME' => 'set_3390377895',
                'CONTROL_NAME_ALT' => 'set',
                'HTML_VALUE_ALT' => '5',
                'HTML_VALUE' => 'Y',
                'VALUE' => '5 items in a set',
                'SORT' => '100',
                'UPPER' => '5 ITEMS IN A SET',
                'URL_ID' => rand (32),
            ],
            '780' => [
                'CONTROL_ID' => 'set_778_3390377895',
                'CONTROL_NAME' => 'set_3390377895',
                'CONTROL_NAME_ALT' => 'set',
                'HTML_VALUE_ALT' => '10',
                'HTML_VALUE' => 'Y',
                'VALUE' => '10 items in a set',
                'SORT' => '200',
                'UPPER' => '10 ITEMS IN A SET',
                'URL_ID' => rand (32),
            ],
    ]
];  

Comments

There are no comments yet, you can be the first to leave it

Leave a comment

The site uses a comment pre-moderation system, so your message will be published only after approval by the moderator

You are replying to a user's comment

Send

FEEDBACK

Email me

Are you developing a new service, making improvements to the existing one and want to be better than your competitors? You have come to the right place. I offer you a comprehensive studio-level website development. From me you can order design, layout, programming, development of non-traditional functionality, implementation of communication between CMS, CRM and Data Analitics, as well as everything else related to sites, except for promotion.

Contact, I will always advise on all questions and help you find the most effective solution for your business. I am engaged in the creation of sites in Novosibirsk and in other regions of Russia, I also work with the CIS countries. You will be satisfied with our cooperation

An error occurred while sending, please try again after a while
Message sent successfully

Phones

+7(993) 007-18-96

Email

info@tichiy.ru

Address

Россия, г. Москва

By submitting the form, you automatically confirm that you have read and accept the Privacy Policy site

Contact with me
Send message
By submitting the form, you automatically confirm that you have read and accept Privacy policy of site
Sending successful!
Thank you for contacting :) I will contact you as soon as possible
Sending failed
An error occurred while sending the request. Please wait and try again after a while or call my phone number