Всем добрый день! Задача следующая, мне необходимо переделать стандартный checkbox [url]http://myscreenshot.info/i/0003/413641396771985763416605721618.png[/url] в умном фильтре в выпадающий список select [url]http://myscreenshot.info/i/0003/409631396772069264378699606169.png[/url]. Через firebug выяснил какие параметры филтр передаёт в обработчик, по сути это имя параметра по которому мы фильтруем и его значение Y (т.е. истина) [url]http://myscreenshot.info/i/0003/946951396772483147925146920077.png[/url]. В данном примере я выбрал материал "Трикотаж" фильтр передал обработчику 2 параметра[B] ajax = y[/B] (я так понял это постоянный параметр говорящий системе что включён режим ajax) и [B]arrFilter_9_3012990210 = Y[/B] , где [B]arrFilter_9_3012990210[/B] - это значение атрибута [B]name [/B]нашего чекбокса (см.скриншот). Вся эта чудо конструкция обрабатывается методом [B]smartFilter.click(this)[/B] срабатывающим на событие [B]onClick [/B]на нашем чекбоксе. Что такое метод click() объекта smartFilter ? Заглянем в дерево шаблона компонента catalog.smart.filter [url]http://myscreenshot.info/i/0003/324131396772989738348415892929.png[/url] находим там файл [B]script.js[/B] который собственно и содержит описание класса [B]smartFilter[/B] с набором соответствующих методов. Вот что представляет собой метод click():
[CODE] 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);
}
[/CODE]Смотрим метод reload()
[CODE]JCSmartFilter.prototype.reload = function(input)
{
this.position = BX.pos(input, true);
this.form = BX.findParent(input, {'tag':'form'});
if(this.form)
{
var values = new Array;
values[0] = {name: 'ajax', value: 'y'};
this.gatherInputsValues(values, BX.findChildren(this.form, {'tag':'input'}, true)); //Привликает внимание метод gatherInputsValues()
BX.ajax.loadJSON(
this.ajaxURL,
this.values2post(values),
BX.delegate(this.postHandler, this)
);
}
}
[/CODE]По все видимости именно gatherInputsValues() считывает значение выбранных пользователем чекбоксов которые затем передаются в loadJSON, смотрим:
[CODE]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;
}
}
}
}
[/CODE]Я так понял что набор этих методов позволяет обрабатывать не только chechkbox но так же и select, однако я не как не додумаюсь как правильно сверстать этот список чтобы данный скрипт понял что выбирает пользователь в фильтре без лишних костылей. Уважаемые разработчики 1С Битрикс - подскажите как правильно переделать checkbox в <select><option>...</option>...</select> так чтобы данный набор методов меня понял?
На текущий момент удалось частично реализовать задуманное рядом костылей. Я скопировал методы click и reload и переименовал копии в clickSelect и clickReload в каждом из этих методов я заменил input-ы на select вот так [url]http://myscreenshot.info/i/0003/691531396774316164675678922975.png[/url] . А в шаблоне компонента умного фильтра (естественно скопированном в шаблон сайта) переделал вёрстку вот так:
[CODE] <div class="bx_filter_block" style="opacity: 0; height: 0px; overflow:hidden;">
<select class="property-select" id="<?=$arItem['CODE']; ?>" name="" onChange="smartFilter.clickSelect(this)" >
<option id="not-value" value="" >- - - -</option>
<?foreach($arItem["VALUES"] as $val => $ar) { ?>
<option id="<?echo $ar["CONTROL_NAME"]?>" <?if ($ar["DISABLED"]){ ?>disabled<? } ?> value="Y" ><?echo $ar["VALUE"];?></option>
<? } //end foreach property values ?>
</select>
</div>[/CODE]Но чтобы у select-а подставлялся нужный name пришлось ещё дописать такую jquery функцию, она получает id выбранного option и подставляет значение этого id в name тега select, после чего срабатывает метод [B]smartFilter.clickSelect(this)[/B] реагирующий теперь на событие [B]onChange[/B]:
[CODE] $(document).ready(function(){
$(".property-select").on('change', function(){
var SelectOption = $(".property-select option:selected").attr('id');
$(this).attr('name',SelectOption);
});
});
[/CODE]В принципе работает, правда пока после отработки фильтра (нажатия на кнопку или ссылку "Показать" ) в select не сохраняются выбранные значения фильтрации. Нужно допиливать обработчик. Но всётаки хотелось бы узнать как можно сделать select по задумке разработчиков битрикса чтобы нормально трабатывал метод [B]gatherInputsValues()[/B] и никаких костылей делать не пришлось.
[CODE] 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);
}
[/CODE]Смотрим метод reload()
[CODE]JCSmartFilter.prototype.reload = function(input)
{
this.position = BX.pos(input, true);
this.form = BX.findParent(input, {'tag':'form'});
if(this.form)
{
var values = new Array;
values[0] = {name: 'ajax', value: 'y'};
this.gatherInputsValues(values, BX.findChildren(this.form, {'tag':'input'}, true)); //Привликает внимание метод gatherInputsValues()
BX.ajax.loadJSON(
this.ajaxURL,
this.values2post(values),
BX.delegate(this.postHandler, this)
);
}
}
[/CODE]По все видимости именно gatherInputsValues() считывает значение выбранных пользователем чекбоксов которые затем передаются в loadJSON, смотрим:
[CODE]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;
}
}
}
}
[/CODE]Я так понял что набор этих методов позволяет обрабатывать не только chechkbox но так же и select, однако я не как не додумаюсь как правильно сверстать этот список чтобы данный скрипт понял что выбирает пользователь в фильтре без лишних костылей. Уважаемые разработчики 1С Битрикс - подскажите как правильно переделать checkbox в <select><option>...</option>...</select> так чтобы данный набор методов меня понял?
На текущий момент удалось частично реализовать задуманное рядом костылей. Я скопировал методы click и reload и переименовал копии в clickSelect и clickReload в каждом из этих методов я заменил input-ы на select вот так [url]http://myscreenshot.info/i/0003/691531396774316164675678922975.png[/url] . А в шаблоне компонента умного фильтра (естественно скопированном в шаблон сайта) переделал вёрстку вот так:
[CODE] <div class="bx_filter_block" style="opacity: 0; height: 0px; overflow:hidden;">
<select class="property-select" id="<?=$arItem['CODE']; ?>" name="" onChange="smartFilter.clickSelect(this)" >
<option id="not-value" value="" >- - - -</option>
<?foreach($arItem["VALUES"] as $val => $ar) { ?>
<option id="<?echo $ar["CONTROL_NAME"]?>" <?if ($ar["DISABLED"]){ ?>disabled<? } ?> value="Y" ><?echo $ar["VALUE"];?></option>
<? } //end foreach property values ?>
</select>
</div>[/CODE]Но чтобы у select-а подставлялся нужный name пришлось ещё дописать такую jquery функцию, она получает id выбранного option и подставляет значение этого id в name тега select, после чего срабатывает метод [B]smartFilter.clickSelect(this)[/B] реагирующий теперь на событие [B]onChange[/B]:
[CODE] $(document).ready(function(){
$(".property-select").on('change', function(){
var SelectOption = $(".property-select option:selected").attr('id');
$(this).attr('name',SelectOption);
});
});
[/CODE]В принципе работает, правда пока после отработки фильтра (нажатия на кнопку или ссылку "Показать" ) в select не сохраняются выбранные значения фильтрации. Нужно допиливать обработчик. Но всётаки хотелось бы узнать как можно сделать select по задумке разработчиков битрикса чтобы нормально трабатывал метод [B]gatherInputsValues()[/B] и никаких костылей делать не пришлось.