Как переделать checkbox в select в компоненте catalog.smart.filter (умный фильтр) ?, Попытка переделать стандартный checkbox в умном фильтре в выпадающий список select
Всем добрый день! Задача следующая, мне необходимо переделать стандартный checkbox http://myscreenshot.info/i/0003/413641396771985763416605721618.png в умном фильтре в выпадающий список select http://myscreenshot.info/i/0003/409631396772069264378699606169.png. Через firebug выяснил какие параметры филтр передаёт в обработчик, по сути это имя параметра по которому мы фильтруем и его значение Y (т.е. истина) http://myscreenshot.info/i/0003/946951396772483147925146920077.png. В данном примере я выбрал материал "Трикотаж" фильтр передал обработчику 2 параметра ajax = y (я так понял это постоянный параметр говорящий системе что включён режим ajax) и arrFilter_9_3012990210 = Y , где arrFilter_9_3012990210 - это значение атрибута name нашего чекбокса (см.скриншот). Вся эта чудо конструкция обрабатывается методом smartFilter.click(this) срабатывающим на событие onClick на нашем чекбоксе. Что такое метод click() объекта smartFilter ? Заглянем в дерево шаблона компонента catalog.smart.filter http://myscreenshot.info/i/0003/324131396772989738348415892929.png находим там файл script.js который собственно и содержит описание класса smartFilter с набором соответствующих методов. Вот что представляет собой метод click():
Код
JCSmartFilter.prototype.click = function(checkbox)
{
if(this.timer)
clearTimeout(this.timer);
this.timer = setTimeout(BX.delegate(function(){
this.reload(checkbox); //На сколько понял с задержкой в секунду метод вызывает (BX.delegate()) метод reload
}, this), 1000);
}
По все видимости именно gatherInputsValues() считывает значение выбранных пользователем чекбоксов которые затем передаются в loadJSON, смотрим:
Код
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': //ОПАЧКИ! Разработчики предусмотрели работу фильтра с полями типа select (т.е. выпадающий список)
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;
}
}
}
}
Я так понял что набор этих методов позволяет обрабатывать не только chechkbox но так же и select, однако я не как не додумаюсь как правильно сверстать этот список чтобы данный скрипт понял что выбирает пользователь в фильтре без лишних костылей. Уважаемые разработчики 1С Битрикс - подскажите как правильно переделать checkbox в <select><option>...</option>...</select> так чтобы данный набор методов меня понял?
На текущий момент удалось частично реализовать задуманное рядом костылей. Я скопировал методы click и reload и переименовал копии в clickSelect и clickReload в каждом из этих методов я заменил input-ы на select вот так http://myscreenshot.info/i/0003/691531396774316164675678922975.png . А в шаблоне компонента умного фильтра (естественно скопированном в шаблон сайта) переделал вёрстку вот так:
Но чтобы у select-а подставлялся нужный name пришлось ещё дописать такую jquery функцию, она получает id выбранного option и подставляет значение этого id в name тега select, после чего срабатывает метод smartFilter.clickSelect(this) реагирующий теперь на событие onChange:
В принципе работает, правда пока после отработки фильтра (нажатия на кнопку или ссылку "Показать" ) в select не сохраняются выбранные значения фильтрации. Нужно допиливать обработчик. Но всётаки хотелось бы узнать как можно сделать select по задумке разработчиков битрикса чтобы нормально трабатывал метод gatherInputsValues() и никаких костылей делать не пришлось.
не заметил сразу $ar["CHECKED"] - булевское значение показывающее выбран ли этот параметр на предыдущей фильтрации ли нет. Однако столкнулся с другой проблемкой, после выбора параметра из любого select-а на всех select-ах пропадают классы т.е. атрибут class - очищается и перестаёт работать моя jquery функция:
1) в файле script.js папки шаблона компонента catalog.smart.filter копируем и переименовываем 2 метода click и reload и слегка меняем их атрибуты (везде меняем input на select) :
3) и тут же ниже добавляем "генератор jquery обработчиков select-ов" с селектами они будут связаны по id значением которого выступает код элемента $arItem['CODE'] - это добавит коду универсальности, с появлением дополнительных свойств в виде selec-ов не придётся лезть в код и дописывать обработчики для новых свойств.
Код
<script>
$(document).ready(function(){
<? //Формируем дополнительные jquery обработчики для select-ов
foreach($arResult["ITEMS"] as $key=>$arItem) {
if(!empty($arItem["VALUES"]) && !isset($arItem["PRICE"])) {
?>
//Проставляем name select-ам с уже выбранными свойствами
setTimeout(function(){
var SelectOption = $("#<?=$arItem['CODE']; ?> option:selected").attr('id');
$("#<?=$arItem['CODE']; ?>").attr('name',SelectOption);
},1500);
//заполнение name с реакцией на change
$("#<?=$arItem['CODE']; ?>").on('change', function(){
var SelectOption = $("#<?=$arItem['CODE']; ?> option:selected").attr('id');
$("#<?=$arItem['CODE']; ?>").attr('name',SelectOption);
<?
}
}?>
});
</script>
Собственно и всё.
Но ОЧЕНЬ ХОЧЕТСЯ ПОСМОТРЕТЬ НА ТО ЧТО ПРЕДЛАГАЮТ САМИ РАЗРАБОТЧИКИ, раз уж в методе gatherInputsValues() изначально была предусмотрена обработка select-ов наверняка в этом направлении должны были вестись какие-нибудь работы.
Огромное спасибо! У вас в последнем скрипте не хватает закрывающих скобок для события change:
Код
<script>
$(document).ready(function(){
<?//Формируем дополнительные jquery обработчики для select-ов?>
<?foreach($arResult["ITEMS"] as $key=>$arItem):?>
<?if(!empty($arItem["VALUES"]) && !isset($arItem["PRICE"])):?>
<?//Проставляем name select-ам с уже выбранными свойствами?>
setTimeout(function(){
var SelectOption = $("#<?=$arItem['CODE']; ?> option:selected").attr('id');
$("#<?=$arItem['CODE']; ?>").attr('name',SelectOption);
},1500);
<?//заполнение name с реакцией на change?>
$("#<?=$arItem['CODE']; ?>").on('change', function(){
var SelectOption = $("#<?=$arItem['CODE']; ?> option:selected").attr('id');
$("#<?=$arItem['CODE']; ?>").attr('name',SelectOption);
})
<?endif?>
<?endforeach?>
});
</script>
При внесении данного кода в фильтре, появились дубли параметров в ссылках. К примеру выбрав 1 свойство отфильтровав и отменив фильтрацию по нему получаем ссылку
Заур Чавтараев пишет: При внесении данного кода в фильтре, появились дубли параметров в ссылках. К примеру выбрав 1 свойство отфильтровав и отменив фильтрацию по нему получаем ссылку
Заур Чавтараев пишет: И еще проблемка при выборе с начало одного пункта фильтрации в списке а потом другого то товар отфильтровывается по обоим пунктам а не по активному
Ну это так и должно быть, мы выбрали цвет:красны, (красного цвета у нас 3 рубашки 46, 48, 50 размеров) потом выбираем 48 размер - получаем 1 рубашку. (пересечение множеств)
Александр Андреев пишет: Ну это так и должно быть, мы выбрали цвет:красны, (красного цвета у нас 3 рубашки 46, 48, 50 размеров) потом выбираем 48 размер - получаем 1 рубашку. ( пересечение множеств )
В фильтре две характеристики для фильтрации. По размерам выбрали "размер 1" и применили, ссылка стала иметь вид /?not-value=&arrFilter_26_1959405917=Y&set_filter=Y
после чего отменили сделанный нами выбор по размеру и ссылка стала иметь вид? /not-value=¬-value=&arrFilter_26_1959405917=Y¬-value=&set_filter=Y и при этом товар отображается только с размером "размер 1", тоесть фильтр не отменился
снова указали фильтрацию по размеру и выбрали вновь значение "размер 2" и применили ссылка изменилась на /?not-value=¬-value=&arrFilter_26_3675550256=Y&arrFilter_26_1959405917=Y&set_filter=Y и товар уже отображается и размера "размер 1" и размера "размер 2"
Получается так что человек хотел выбрать товар с одни размером и просмотреть и у него это получилось, после решил посмотреть с другим размером а тут уже накладка отображаются товары и предыдущей фильтрации.
После чего человек пытается отобразить товар всех размеров выбрав значение в фильтре исходное тоесть (<option id="not-value" value="" >- - - -</option> ;) Но тут человеку все равно отображается не весь товар а товар с учетом пред идущего фильтра а там фильтрация по размерам "размер 1" и "размер 2"
1. Как можно при каждой фильтрации не запоминать предыдущие значения фильтра, тоесть собирать массив фильтрации по новой без пред идущего фильтра.
и еще вопрос можно ли как то избавиться от значений в ссылках - not-value= , как то не красиво выглядит это?
Пока точно сказать не могу но у меня при выборе исходного значения <option> - - - </option> в фильтр отправляется только ajax=Y http://joxi.ru/HNdXU_3JTJAFaCgsGew а вот такие not-value появляются только если сбрасывать фильтр через кнопку "Сбросить". Чтобы этого небыло, думаю можно кнопку сбросить переделать в ссылку и тупо передать в текущий раздел ?del_filter=%D1%E1%F0%EE%F1%E8%F2%FC т.е. ?del_filter=Сбросить.
Как сложно люди бывает мыслят, читать все выше дольше, чем делать А если подумать, прежде чем делать, хорошо подумать Фиг разберешься потом после Вас, если попадется на доработки такой сайт.
По вашему решению работает только после того, как мы нажимаем основную кнопку "Показать в фильтре". А как быть с включенным AJAX_MODE когда всплывает окошечко с показанием количества найденных элементов?
Алексей Борисенко написал: По вашему решению работает только после того, как мы нажимаем основную кнопку "Показать в фильтре". А как быть с включенным AJAX_MODE когда всплывает окошечко с показанием количества найденных элементов?