Working with bitrix: smart.filter
The last notes
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