Добавляем в блок к объектами дополнительные атрибуты:
<?php
$products = $this->macros('catalog', 'getSmartCatalogCustom', array('', PAGE_ID, CATALOG_PER_PAGE, false, 10, SORT_FIELD, IS_ASC_DIRECTION, OBJECT_TYPE_ID));
$total = getArrayKey($products, 'total');
?>
<ul id="objects" data-total="<?=$total?>" data-module="catalog" data-category_id="<?=PAGE_ID;?>" data-type_id="<?=OBJECT_TYPE_ID;?>">
В шаблоне категории вызываем шаблон фильтра:
<?= $this->render($variables,'modules/catalog/blocks/category/filter'); ?>
Шаблон фильтра:
<?php /** @var umiTemplaterPHP|ViewPhpExtension|AjaxExtension|DemomarketPhpExtension|UpmixExtension $this */?> <?php /** @var array $variables */?> <!-- noindex --> <div id="filter" style="display:none"></div> <!-- /noindex -->
Создаем файл:
templates/xxx/php/ajax/templates/catalog/filter.phtml
Содержимое:
<?php /** @var umiTemplaterPHP|ViewPhpExtension|AjaxExtension|DemomarketPhpExtension|UpmixExtension $this */?>
<?php /** @var array $variables */?>
<?php
$filter = $this->macros('catalog', 'getSmartFiltersCustom', array('default', PAGE_ID, 0, 15, OBJECT_TYPE_ID));
?>
<form class="catalog_filter">
<?= $this->render($filter,'modules/catalog/blocks/category/getSmartFiltersCustom'); ?>
<div class="filter-buttons">
<input class="filtr-btn" type="submit" value="Показать" />
<input class="reset-btn" type="reset" value="Сбросить фильтр" />
</div>
</form>
<div class="goods-num" id="js_count_block">
<div class="top-triangle"></div>
<div class="bottom-triangle"></div>
<div class="clear-after goods-count-wp" >
<div class="goods-count">Найдено товаров: <span id="js_filtered_count"></span></div>
<div class="show-btn-wp"><span id="js_show_objects" class="btn-order">Показать</span></div>
</div>
<div class="form-btn-wp"><span class="js_close_filter">Скрыть фильтр</span><span class="js_reset_filter_mobile">Сбросить фильтр</span></div>
</div>
Создаем файл
templates/xxx/php/modules/catalog/blocks/category/getSmartFiltersCustom.phtml
Содержимое:
<?php /** @var umiTemplaterPHP|ViewPhpExtension|AjaxExtension|DemomarketPhpExtension|UpmixExtension $this */?>
<?php /** @var array $variables */?>
<?php
$filter = $variables;
$groups = $filter["group"] ?? null;
if (!empty($groups)){
foreach ($groups as $group){
//if ($group['name'] == 'tovar_dnya' || $group['name'] == 'manage_options') continue; //можно убрать некоторые группы из фильтра
$filterGroup[$group['name']] = $group['field'];
foreach ($filterGroup[$group['name']] as $field){
$key = $field["name"];
//убираем физ фильтра ненужные поля
if ($key=='razmer_lista' and ROOT_TYPE!='plitka') continue; //размер листа только в плитке
if ($key=='common_quantity') continue; //количество не показываем
if ($key=='tip') continue; //тип в фильтре не нужен
if ($key=='diler' and !USER_IS_SV) continue; //поставщик для админа
if ($key == 'price_rur_filter' or $key == 'cvet' or $key == 'material' or $key == 'forma_chipa' or $key == 'osobennosti'){
$filterGroupFirst[$group['name']][$key] = $field;
} else {
$filterGroupSecond[$group['name']][$key] = $field;
}
}
}
}
?>
<?php if(!empty($filterGroupFirst)):?>
<?php foreach ($filterGroupFirst as $keyGroup=>$group):?>
<?php foreach ($group as $keyField=>$field):?>
<?php if($keyField == 'price_rur_filter'):?>
<?php if(isset($field['minimum'])):?>
<?php echo($this->render(array('field' => $field), 'modules/catalog/blocks/category/filter/range')); ?>
<?php endif;?>
<?php else:?>
<?php echo($this->render(array('field' => $field), 'modules/catalog/blocks/category/filter/checkbox')); ?>
<?php endif;?>
<?php endforeach;?>
<?php endforeach;?>
<?php endif;?>
<?php if(!empty($filterGroupSecond)):?>
<?php foreach ($filterGroupSecond as $keyGroup=>$group):?>
<?php foreach ($group as $keyField=>$field):?>
<?php if(!USER_IS_SV and $keyField=="diler") continue;?>
<?php echo($this->render(array('field' => $field), 'modules/catalog/blocks/category/filter/checkbox')); ?>
<?php endforeach;?>
<?php endforeach;?>
<?php endif;?>
Создаем файл для фильтров типа чекбокс:
templates/xxx/php/modules/catalog/blocks/category/filter/checkbox.phtml
Содержимое:
<?php /** @var umiTemplaterPHP|ViewPhpExtension|AjaxExtension|DemomarketPhpExtension|UpmixExtension $this */?>
<?php /** @var array $variables */?>
<?php
$field = getArrayKey($variables, 'field');
$title = getArrayKey($variables, 'name') ?? $field['title'];
$name = $field['name'];
$tip = getArrayKey($field, 'tip') ?? false;
$filter = getRequest('filter');
$sqlType = 'or';
if (isset($filter[$name])){
reset($filter[$name]);
$sqlType = key($filter[$name]);
if ($sqlType === 0){ //для старых ссылок filter[cvet][]
$sqlType = 'or';
}
}
?>
<?php if(isset($field['item'])):?>
<div class="clear-after filter-wp<?php if (isset($filter[$name])) echo ' open'?>">
<div class="filter-title-js"><span class="filtr-title"><?=$title?> <?php if($tip):?><i data-tooltip-content="#tooltip_content_<?=$name?>" class="tooltip fas fa-question-circle"></i><?php endif;?> <i class="<?php if (isset($filter[$name])) echo 'hidden '?>fas fa-chevron-down"></i><i class="<?php if (!isset($filter[$name])) echo 'hidden '?>fas fa-chevron-up"></i></span></div>
<?php if($tip):?>
<div class="tooltip_templates">
<span id="tooltip_content_<?=$name?>">
<?=$tip?>
</span>
</div>
<?php endif;?>
<?php if (count($field['item'])>7):?>
<div class="filter-search"><input class="js_search" placeholder="поиск по свойствам" type="search"/></div>
<?php endif;?>
<?php //для некоторых фльтров делаем возможным искать сразу не нескольким характеритикам, например товары у которых есть сразу 2 цвета: белый и зеленый ?>
<?php if($name=='cvet' or $name=='osobennosti' or $name=='primenenie' or $name=='material' or $name=='sort_kamnya'):?>
<div class="checkbox-mode">
<span>Искать cвойства вместе</span>
<span class="switch">
<span id="c_<?=$name?>_mode" data-name="<?=$name?>" data-value="<?=$sqlType?>" class="slider round mode_selector<?php if($sqlType=='and') echo(' checked')?>"></span>
</span>
</div>
<?php endif;?>
<div class="filter-box<?php if (count($field['item'])>7):?> scroll-pane<?php endif;?>" id="<?=$name?>">
<?php foreach($field["item"] as $key=>$item):?>
<?php
if (!isset($item['value'])) continue;
$checkedKey = false;
$id = $this->translitStr($item["value"]);
$value = $item["value"];
if (isset($filter[$name])){
if (!empty($filter[$name][$sqlType])){
$checkedKey = array_search($value,$filter[$name][$sqlType]);
} else {
$checkedKey = array_search($value,$filter[$name]); //для старых ссылок filter[cvet][]
}
}
?>
<div class="checkbox">
<input data-name="<?=$name?>" type="checkbox" id="c_<?=$name?>_<?=$id?>" name="filter[<?=$name?>][<?=$sqlType?>][<?=$key?>]" value="<?=$value?>" <?php if(isset($filter[$name]) and $checkedKey!==false) echo ' checked'?>>
<label class="label" for="c_<?=$name?>_<?=$id?>"><?=$value?></label>
</div>
<?php endforeach;?>
</div>
</div>
<?php endif?>
Создаем файл для фильтров типа ползунки:
templates/xxx/php/modules/catalog/blocks/category/filter/range.phtml
Содержимое:
<?php /** @var umiTemplaterPHP|ViewPhpExtension|AjaxExtension|DemomarketPhpExtension|UpmixExtension $this */?>
<?php /** @var array $variables */?>
<?php
$field = getArrayKey($variables, 'field');
$title = getArrayKey($variables, 'name');
$name = $field["name"];
$filter = getRequest('filter');
$umiHierarchy = umiHierarchy::getInstance();
/* @var iUmiHierarchyElement $page */
$page = $umiHierarchy->getElement(PAGE_ID);
$valueMin = $page->getValue('minimum_price') ?? $field["min"];
$valueMax = $page->getValue('maximum_price') ?? $field["max"];
$valueCurMin = $filter[$name]['from'] ?? $valueMin;
$valueCurMax = $filter[$name]['to'] ?? $valueMax;
$range = 'range_'.$name;
?>
<div class="price-filtr filter-wp">
<?php if(!empty($title)):?><div><?=$title?></div><?php endif;?>
<input type="hidden" id="<?= $range;?>" class="js_range_slider" data-min="<?= $valueMin;?>" data-max="<?= $valueMax;?>" data-curmin="<?= $valueCurMin;?>" data-curmax="<?= $valueCurMax;?>">
<div>
<input type="text" maxlength="6" class="js_<?= $range;?>_from js_input_from" name="filter[<?= $name;?>][from]" value="<?php echo($valueCurMin);?>">
<label>₽<?=FILTER_EDIZM?></label>
</div>
<div class="right-align">
<input type="text" maxlength="6" class="js_<?= $range;?>_to js_input_to" name="filter[<?= $name;?>][to]" value="<?php echo($valueCurMax);?>">
<label>₽<?=FILTER_EDIZM?></label>
</div>
</div>
Создаем файл:
templates/xxx/js/custom/category/category.js
var $objectBlock = $('#objects'), //блок с объектами
$filter = $('#filter'), //фильтр
preloader = '<div id="js_loader" class="wait_for"><img src="/templates/xxx/images/loading.gif"/></div>',
pageId = $objectBlock.data('category_id'), //ID категории
typeId = $objectBlock.data('type_id'); //Тип товаров в категории
$(document).ready(function() {
if ($filter.length > 0) {
reloadFilter();
}
initInputFilters();
});
//изменение или добавление GET параметра
function changeParam(sParam, paramValue) {
var queryParameters = {},
queryString = location.search.substring(1),
re = /([^&=]+)=([^&]*)/g,
m;
while (m = re.exec(queryString)) {
queryParameters[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
}
queryParameters[sParam] = paramValue;
return '?' + $.param(queryParameters);
}
//удаление GET параметра из строки запроса "p=1&filter[cena]=100"
function removeParam(sParam) {
var urlQueue = window.location.search.substring(1),
rtn,
param,
params_arr = [];
if (urlQueue !== "") {
params_arr = urlQueue.split("&");
for (var i = params_arr.length - 1; i >= 0; i -= 1) {
param = params_arr[i].split("=")[0];
if (param === sParam) {
params_arr.splice(i, 1);
}
}
rtn = params_arr.join("&");
if (rtn !== "") {
rtn = '?' + rtn;
}
} else {
rtn = "";
}
return rtn;
}
//получение GET параметра
function getUrlParameter(sParam) {
var urlQueue = window.location.search.substring(1),
sURLVariables = urlQueue.split('&'),
sParameterName,
i;
for (i = 0; i < sURLVariables.length; i++) {
sParameterName = sURLVariables[i].split('=');
if (sParameterName[0] === sParam) {
return sParameterName[1] === undefined ? true : decodeURIComponent(sParameterName[1]);
}
}
}
//пересчет количества товаров при выборе фильтров
function recalcFiltredCount(element) {
var $countBlock = $('#js_count_block'); //блок: выбрано 10 товаров. Показать
var url_q = $filter.find('input[type!=hidden]').filter(function() {
if (this.value !== "" && this.value !== '0') { //если значение не пустое-используем в расчете
if ($(this).attr('name')==='filter[price_rur_filter][from]'){ //для слайдера
if (this.value != $('#range_price_rur_filter').data('min')){ //если не изменялась минимальная цена - не учитываем
return this.value;
}
}
else if ($(this).attr('name')==='filter[price_rur_filter][to]'){ //если не изменялась максимальная цена - не учитываем
if (this.value != $('#range_price_rur_filter').data('max')){
return this.value;
}
} else {
return this.value;
}
}
}).serialize();
if (url_q !== ''){
var url = "?" + url_q;
}
//запрос количества товаров
$.ajax(url, {
dataType: 'json',
async:true,
type: "POST",
data: {
template: 'catalog/filter-count',
r: Math.random()
},
success: function(response) {
$('#js_show_objects').attr('href', '?' + url_q); //ссылка показать
$('#js_filtered_count').text(response); //блок с количеством товара
//расположение блока
if ($(window).width() > 767) {
if (typeof (element) !== "undefined"){
var Y = element.offset().top-210;
var X = element.closest('.filter-wp').offset().left+239-$filter.offset().left;
$countBlock.css('top', Y+'px');
$countBlock.css('left', X+'px');
$countBlock.show();
}
}
}, //конец успешной отправки
error: function(xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
}
//показ фильтра
function reloadFilter() {
urlQueue = removeParam('p'); //убираем пагинацию
$.ajax({
url: urlQueue,
type: 'POST',
async: true,
data: {
template: 'catalog/filter',
r: Math.random()
},
success: function (html) {
$filter.html(html);
$('#js_filtered_count').text($objectBlock.data('total'));
$filter.fadeIn(700);
initFilter();
},
error: function (xhr, ajaxOptions, thrownError) {
console.log(thrownError + "\r\n" + xhr.statusText + "\r\n" + xhr.responseText);
}
});
}
//инициализация слайдера с ценами и других range слайдеров
function initFilter() {
$('.js_range_slider').each(function() {
var sliderName = $(this).attr('id'),
$slider = $("#"+sliderName),
$inputFrom = $(".js_"+sliderName+"_from"),
$inputTo = $(".js_"+sliderName+"_to"),
instance,
min = $(this).data('min'),
max = $(this).data('max'),
from = $(this).data('curmin'),
to = $(this).data('curmax');
$slider.ionRangeSlider({
skin: "round",
type: "double",
//postfix : 'm2',
min: min,
max: max,
from: from,
to: to,
grid: false,
onFinish: function (data) {
$($inputFrom).val(data.from);
$($inputTo).val(data.to);
recalcFiltredCount($inputTo);
processFilters($inputTo);
}
});
instance = $slider.data("ionRangeSlider");
$inputFrom.inputFilter(function(value) {
return /^\d*$/.test(value); });
$inputFrom.on("input", function (e) {
var val = $(this).prop("value");
if (val < min) {
val = min;
} else if (val > to) {
val = to;
}
instance.update({
from: val
});
recalcFiltredCount($inputTo);
processFilters($(this));
});
$inputTo.inputFilter(function(value) {
return /^\d*$/.test(value); });
$inputTo.on("input", function (e) {
var val = $(this).prop("value");
if (val < from) {
val = from;
} else if (val > max) {
val = max;
}
instance.update({
to: val
});
recalcFiltredCount($inputTo);
processFilters($(this));
});
});
$('.scroll-pane').jScrollPane({contentWidth: '0px'});
$('.tooltip').tooltipster({
theme: 'tooltipster-light',
trigger: 'custom',
triggerOpen: {
mouseenter: true,
touchstart: true
},
triggerClose: {
click: true,
scroll: true,
tap: true
}
});
}
//пересчет фильтров - делаем значения неактивными, если они неприменимы
function processFilters(e) {
var name = e.data('name');
var url_q = $filter.find('input[type!=hidden]').filter(function() {
if (this.value !== "" && this.value !== '0') { //если значение не пустое-используем в расчете
return this.value;
}
}).serialize();
if (url_q !== '') url_q = '?' + url_q;
var url = "/udata/catalog/getSmartFiltersCustom//"+pageId+"/0/15/"+typeId+"/.json" + url_q;
$.getJSON(url, function(data){
$filter.find('.checkbox').find('input:not(:checked)').each(function(){
if ($(this).attr('name').indexOf(name) !== -1){
if($(this).attr('name').indexOf('[or]') === -1){ //если AND
$(this).attr('disabled', true);
$(this).parent().addClass('disabled');
}
} else {
$(this).attr('disabled', true);
$(this).parent().addClass('disabled');
}
});
$.each(data.group, function() {
$.each(this.field, function() {
var name = this.name;
var items = this.item;
$.each(items, function() {
var value = this.value;
$('#'+name).find('input').each(function(index, element){
if (this.value === value){
$(this).attr('disabled', false);
$(this).parent().removeClass('disabled');
}
});
});
});
});
});
}
//изменение значений фильтра
$filter.on('change', '.checkbox input', function (e) {
processFilters($(this));
recalcFiltredCount($(this));
$(this).toggleClass('checked');
});
//Нажатие кнопки "показать"
$filter.on('click', '#js_show_objects', function (e) {
e.preventDefault();
var url = $(this).attr('href');
if ($(window).width() < 768) {
$('.js_get_popup').trigger('click');
} else {
$('#js_count_block').fadeOut(100);
}
processObjects(url, 'replace');
reloadFilter();
return false;
});
//Галочка выбирать несколько
$filter.on('click', '.mode_selector', function (e) {
e.preventDefault();
$(this).toggleClass('checked');
var mode = $(this).data('value')==='or'?'and':'or';
$(this).data('value', mode);
$(this).parents('.checkbox-mode').siblings('.filter-box').find('input').each(function() {
$(this).attr('name', function(index, name) {
if(mode==='or'){
return name.replace('[and]', '[or]');
} else {
return name.replace('[or]', '[and]');
}
});
$(this).attr('disabled', false);
$(this).parent().removeClass('disabled');
});
processFilters($(this));
recalcFiltredCount($(this));
return false;
});
//раскрытие-закрытие фильтра
$filter.on('click', '.filter-title-js', function () {
var $this = $(this);
var $parent = $this.parent('div');
$parent.toggleClass('open');
$this.find('.fa-chevron-up').toggleClass('hidden');
$this.find('.fa-chevron-down').toggleClass('hidden');
$('.scroll-pane').jScrollPane({contentWidth: '0px'});
});
//перемещение выбранного значения вверх
$filter.on('change', '.scroll-pane .checkbox input', function () {
var $this = $(this);
var $parent = $this.parent('div');
$parent.prependTo($parent.parent());
var api = $this.closest('.scroll-pane').data('jsp');
api.scrollToElement($this);
});
//поиск по значениям фильтра
$filter.on("keyup", '.js_search', function() {
var value = $(this).val().toLowerCase();
$(this).parent().siblings('.scroll-pane').find("label").filter(function() {
$(this).parent().toggle($(this).text().toLowerCase().indexOf(value) > -1)
});
});
//очистка строки поиска по фильтру
$filter.on("click", '.js_clear', function() {
var $input = $(this).siblings('input');
$input.val('');
$(this).parent().siblings('.scroll-pane').find('.checkbox').each(function() {
$(this).fadeIn();
});
});
//обнуление фильтра
$filter.on('click', '.reset-btn', function (e) {
processObjects('', 'replace');
reloadFilter();
});
//скрытие фильтра на мобиле
$filter.on('click', '.js_reset_filter_mobile', function (e) {
$('.js_get_popup').trigger('click');
processObjects('', 'replace');
reloadFilter();
});
//обнуление фильтра на мобиле
$filter.on('click', '.js_close_filter', function (e) {
$('.js_get_popup').trigger('click');
});
//
$('#show_filter').click(function () {
$('#sidebar').slideToggle(300);
$('.scroll-pane').jScrollPane({contentWidth: '0px'});
});
Создаем файл шаблона вывода количества отфильтрованных объектов
templates/xxx/php/ajax/templates/catalog/filter-count.phtml
Содержимое:
<?php /** @var umiTemplaterPHP|ViewPhpExtension|AjaxExtension|DemomarketPhpExtension|UpmixExtension $this */?>
<?php /** @var array $variables */?>
<?php
$countArray = $this->macros('catalog', 'getSmartCatalogCustom', array('', PAGE_ID, 99999, 1, 15, '', '', OBJECT_TYPE_ID, 1));
$count = getArrayKey($countArray, 'total') ?? 0;
echo ($count);
?>
Подключаем плагины:
http://ionden.com/a/plugins/ion.rangeSlider/ – для ползунков
http://jscrollpane.kelvinluck.com/examples/ – прокрутка в блоке с чекбоксами
https://iamceege.github.io/tooltipster/ – всплывающие подсказки
FontAwesome – понадобится brands и solid. Нет смысла все подключать.
Примерный CSS
.price-filtr{padding:20px 10px 40px 10px;}
#slider{background-color:#e6e6e6;height:5px;}
.filtr-title{color:#000;font-size:14px;font-weight:700;display:block;padding:10px;position:relative;cursor:pointer;line-height: 22px}
.price-filtr label{color:#000;font-size:13px;font-weight:500;margin-left:3px;}
.price-filtr div {width: 50%;float: left}
.price-filtr input{width:50%;height:26px;border: 1px solid #b2b2b2;text-align:center;color:#000;font-size:13px;}
.flex_price{display:flex;}
.flex_price_body{display:flex;justify-content:space-between;align-items:center;}
.slider-num{padding:17px 0 0 0;margin:0 0 12px 0;}
.num1,.num2,.num3{color:#808080;font-size:12px;float:left;display:block;position:relative;top:-10px;}
.num2{margin:0 0 0 111px;}
.num3{float:right;}
.checkbox-choice{position:relative;min-height:17px;margin:0 0 18px 10px;}
.checkbox-choice label{color:#000;font-size:14px;}
.checkbox-box{display:inline;position:relative;}
.color-filtr{border-bottom:1px solid #dadada;}
.filter-title-js{padding-right:10px;}
.hided_more{margin-bottom:10px;}
.cat-menu .more-cat-menu{padding:0;}
.filtr-btn{width:122px;height:38px;border:none;background-color:#e6e6e6;cursor:pointer;color:#4b4b4b;font-size:14px;margin:42px 16px 0 0;}
.reset-btn{border:none;background:none;cursor:pointer;color:#818181;font-size:13px;border-bottom:1px dashed #818181;padding:0;margin:54px 0 0 0;}
.filtr-btn:hover{background-color:#C6BFBF;}
.reset-btn:hover{border:none;}
:focus::-moz-placeholder{color:transparent;}
:focus:-moz-placeholder{color:transparent;}
:focus:-ms-input-placeholder{color:transparent;}
.scrollbar-inner{max-height:200px;display:none;}
.open .scrollbar-inner{display:block;padding:10px 0;}
.reset-btn{margin:17px auto 8px;display:block;}
.filtr-btn{margin:42px auto 0;display:block;}
@media screen and (max-width: 767px) {
.goods-num {
position: fixed;
bottom: 0;
z-index: 99999;
width: 100%;
background-color: #ffffff;
border: 1px solid #9c9c9c;
box-sizing: border-box;
}
.goods-count {
float:left;
width:calc(100% - 130px);
padding: 0 0 0 10px;
height: 60px;
line-height: 60px;
font-size:14px;
font-weight: 700;
}
}
.goods-count span{
color: #e35222;
font-size:17px;
font-weight: 700;
}
.form-btn-wp{
padding:10px 0;
}
.sidebar #filter {
padding: 0 0 140px 0;
}
.form-btn-wp span{
display: inline-block;
width: 50%;
text-align: center;
text-decoration: underline;
cursor: pointer;
}
.form-btn-wp span:hover, .form-btn-wp span:active{
text-decoration: none;
}
.show-btn-wp {
float:left;
width:100px;
margin:0 10px;
}
.filter-box
{
display: none;
}
.open .filter-box
{
display: block;
}
.scroll-pane {
width: 100%;
height: 200px;
overflow: auto;
padding: 7px 0;
}
.fa-times-circle {
position: absolute;
font-size: 20px;
right: 20px;
cursor: pointer;
padding-top: 5px;
color:#b2b2b2;
}
.hidden.fas {display: none}
.filtr-title .fas{font-size: 22px;float:right;color:#0077c6}
.filter-search {width:100%;height: 30px;border-bottom: 1px solid #b2b2b2;border-top: 1px solid #b2b2b2;display:none;background-color:#e9e9e9;}
.checkbox-mode{display: none; text-align: center;padding:3px 0;}
.open .filter-search, .open .checkbox-mode{display: block}
.filter-search input {padding: 0 0 0 10px;width: calc(100% - 10px);height: 90%;border: none;background-color:#e9e9e9;}
/* The switch - the box around the slider */
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
vertical-align: middle;
}
/* The slider */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #b2b2b2;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
.slider.checked {
background-color: #0077c6;
}
.slider:focus {
box-shadow: 0 0 1px #0077c6;
}
.slider.checked:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
.filter-wp {
border-top: 1px solid #b2b2b2;
}
.checkbox {
margin: 0 0 7px 10px;
}
.checkbox input{
width: 20px;
height: 20px;
vertical-align: middle;
}
.checkbox label{
display: inline-block;
width:calc(100% - 30px);
}
.checkbox.disabled label{
color:#b2b2b2;
}
.jspTrack{
background-color: #e9e9e9;
}
.jspDrag {
background-color: #b2b2b2;
}
.irs-from, .irs-to, .irs-single {
background-color: #0077c6;
}
.irs-bar {
height: 10px; top: 33px;
border-top: 1px solid #0077c6;
border-bottom: 1px solid #0077c6;
background: #0077c6;
background: linear-gradient(to top, rgba(0,119,198,1) 0%,rgba(129,195,231,1) 100%); /* W3C */
}
.irs-bar-edge {
height: 10px; top: 33px;
width: 14px;
border: 1px solid #0077c6;
border-right: 0;
background: #0077c6;
background: linear-gradient(to top, rgba(0,119,198,1) 0%,rgba(129,195,231,1) 100%); /* W3C */
border-radius: 16px 0 0 16px;
-moz-border-radius: 16px 0 0 16px;
}
.tooltip_templates { display: none; }
.filtr-title i.tooltip {
color:#b2b2b2;
font-size: 16px;
vertical-align: text-top;
float:none;
}
#filter form .filter-search input {
margin:0;
}
.jspPane .checkbox:first-child{
padding: 10px 0 0 0;
}
@media screen and (min-width: 768px){
.goods-num {
position: absolute;
z-index: 99999;
display: none;
}
.form-btn-wp {
display: none;
}
.goods-count-wp {
border-top: 2px solid #0053a4;
border-right: 2px solid #0053a4;
border-bottom: 2px solid #0053a4;
border-radius: 4px;
width: 260px;
height: 32px;
margin-left: 18px;
background-color: #fff;
}
.goods-count {
float: left;
font-size: 13px;
line-height: 32px;
padding: 0 0 0 10px;
}
.show-btn-wp {
float: right;
margin: 0;
width: auto;
}
.goods-count-wp .btn-order {
padding: 0 8px;
height: 26px;
margin: 2px 7px 0 5px;
line-height: 26px;
}
.top-triangle {
top: 3px;
left: 3px;
display: inline-block;
width: 0;
height: 0;
border-style: solid;
border-width: 15px 17px 15px 0;
border-color: transparent #fff transparent transparent;
position: absolute;
z-index: 99999999;
}
.bottom-triangle {
display: inline-block;
width: 0;
height: 0;
border-style: solid;
border-width: 18px 20px 18px 0;
border-color: transparent #0053a4 transparent transparent;
position: absolute;
z-index: 99999998;
}
}
В файле
templates/xxx/classes/modules/catalog/FilterQueriesMakerCustom.php
Cоздаем функцию parseFiltersCustom:
public function parseFiltersCustom() {
$allFilteredFields = $this->getAllFilteredFields();
$filters = getRequest('filter');
$event = new umiEventPoint('parse_filter');
$event->setMode('before');
$event->addRef('raw_filter', $filters);
$event->setParam('queries_maker', $this);
$event->call();
if (!$filters || !is_array($filters)) {
return $this->setFilters([]);
}
$isNeedToShowSelectedValues = $this->isNeedToShowSelectedValues();
foreach ($filters as $key => $value) {
//$type = array_key_first($value); //PHP 7.3
reset($value);
$sqlType = key($value);
if (!isset($allFilteredFields[$key])) {
unset($filters[$key]);
continue;
}
/* @var iUmiField $field */
$field = $allFilteredFields[$key];
if ($field->getDataType() == 'date') {
foreach ($value as $type => $date) {
if (!is_numeric($date) && is_string($date)) {
$value[$type] = strtotime($date);
}
}
}
if ($sqlType === 'and' or $sqlType === 'or'){
$condition = $this->getCondition($field, $key, $value[$sqlType]);
$condition = str_replace('OR', strtoupper($sqlType), $condition);
} elseif($sqlType === 0) { // если заходят по старым ссылкам filter[cvet][]
$condition = $this->getCondition($field, $key, $value[$sqlType]);
} else {
$condition = $this->getCondition($field, $key, $value);
}
if ($condition === null) {
unset($filters[$key]);
} else {
$filters[$key] = $condition;
}
if (!$isNeedToShowSelectedValues) {
continue;
}
$val = array();
if (is_array($value[$sqlType])) {
$value = array_map('htmlspecialchars', $value[$sqlType]);
} else {
$value = [htmlspecialchars($value[$sqlType])];
}
$val[$sqlType] = $value;
$this->pushSelectedFilterValue($key, $val);
}
$event->setMode('after');
$event->addRef('processed_filter', $filters);
$event->call();
return $filters;
}
Добавляем в lib/extensions/UpmixExtension.php
public function translitStr($s) {
$s = (string)$s; // преобразуем в строковое значение
$s = strip_tags($s); // убираем HTML-теги
$s = str_replace(array("\n", "\r"), " ", $s); // убираем перевод каретки
$s = preg_replace("/\s+/", ' ', $s); // удаляем повторяющие пробелы
$s = trim($s); // убираем пробелы в начале и конце строки
$s = function_exists('mb_strtolower') ? mb_strtolower($s) : strtolower($s); // переводим строку в нижний регистр (иногда надо задать локаль)
$s = strtr($s, array('а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd', 'е' => 'e', 'ё' => 'e', 'ж' => 'j', 'з' => 'z', 'и' => 'i', 'й' => 'y', 'к' => 'k', 'л' => 'l', 'м' => 'm', 'н' => 'n', 'о' => 'o', 'п' => 'p', 'р' => 'r', 'с' => 's', 'т' => 't', 'у' => 'u', 'ф' => 'f', 'х' => 'h', 'ц' => 'c', 'ч' => 'ch', 'ш' => 'sh', 'щ' => 'shch', 'ы' => 'y', 'э' => 'e', 'ю' => 'yu', 'я' => 'ya', 'ъ' => '', 'ь' => ''));
$s = preg_replace("/[^0-9a-z-_ ]/i", "", $s); // очищаем строку от недопустимых символов
$s = str_replace(" ", "-", $s); // заменяем пробелы знаком минус
return $s; // возвращаем результат
}
Добавляем файл: templates/xxx/php/ajax/templates/catalog/objects.phtml
Содержимое:
<?php $html = $this->render($variables, 'modules/catalog/category/blocks/object-list'); $response = $this->prepareAjaxResponseForTemplate($html); $this->sendAjaxResponse($response); ?>

Добавить комментарий