Тема: Как добавить ползунок цены в категории?

Задача: добавить ползунок цены в категорию.

1) минимум/максимум - это наим./наиб. стоимость товара в текущей категории/подкатегории.
2) если мы находимся в категории, то наим./наиб. стоимость берется включая все товары этой категории и подкатегорий в ней.
3) если находимся в подкатегории, то наим./наиб. стоимость берется включая товары этой подкатегории и подкатегорий в ней, далее по той же логике подподкатегории (то есть исключать родителей).
4) скрывать ползунок, если товаров менее двух или цена их равна (почти так же, как сейчас работают другие фильтры).

Повысить оценку Понизить оценку

2 Отредактировано Александр (20.08.2015 19:04:19)

Re: Как добавить ползунок цены в категории?

Интересный вопрос и сейчас я его раскрою.
Дело в том, что в системе для того, чтобы сформировать данный ползунок нужно каким-то образом получить максимальную и минимальную цену в зависимости от категории и применённых фильтров. По умолчанию мы не поддерживаем такое получение и не возвращаем сведений, поэтому придётся немного поколдовать, чтобы получить данные.
Первое что надо сделать это получить данные во фронт контроллере списка товаров, т.к. именно в нём применяются все фильтры. Соответственно там мы и должны получать данные.
Нам надо сделать копию файла
/modules/catalog/controller/front/listproducts.inc.php с таким же именем, но окончанием .my.inc.php

т.е.
/modules/catalog/controller/front/listproducts.my.inc.php

Откроем его и посмотрим в метод actionIndex().

Нам надо заменить:

$basefilter = $this->api->applyBaseFilters();
$total      = $this->api->getMultiDirCount();
                            
$this->api->queryObj()->groupby($this->api->defAlias().'.id');
//Устанавливаем сортировку
$sort_field = $this->cur_sort == 'rank' ? $this->cur_sort : $this->api->defAlias().'.'.$this->cur_sort;
$this->api->setSortOrder($sort_field, $this->cur_n_sort);

На:

/**
* @var \RS\Orm\Request
*/
$minmaxQuery = clone $this->api->queryObj();                                                  
                
$basefilter = $this->api->applyBaseFilters();
$total      = $this->api->getMultiDirCount();
                
//Добавим цены к запросу
$current_cost_type = \Catalog\Model\CostApi::getUserCost(); //Текущий тип цен
$current_cost_type = \Catalog\Model\CostApi::getInstance()->getManualType($current_cost_type);
$minmaxQuery->leftjoin(new \Catalog\Model\Orm\Xcost(), "A.id = XC.product_id AND XC.cost_id='{$current_cost_type}'", 'XC');

$minmaxQuery->orderby(''); 
$minmaxQuery->select = 'max(XC.cost_val) interval_to,min(XC.cost_val) interval_from';
$moneyArray = $minmaxQuery->exec()->fetchRow();
$moneyArray['step']  = 1;
$moneyArray['round'] = 1;
$moneyArray['unit']  = \Catalog\Model\CurrencyApi::getDefaultCurrency()->stitle;
$moneyArray['heterogeneity']  = $this->getHeterogeneity($moneyArray['interval_from'],$moneyArray['interval_to']);
                
$this->router->getCurrentRoute()->money_array = $moneyArray;
                            
$this->api->queryObj()->groupby($this->api->defAlias().'.id');
$this->api->setSortOrder($this->api->defAlias().'.'.$this->cur_sort, $this->cur_n_sort);

В указанном выше кусочке кода мы получаем массив $moneyArray на основе запроса максимальной и минимальной цены для формирования данных, которые нам понадобятся в шаблоне.
Эти значения мы поместим в наш класс роута который будет доступен по данному url в любом блок контроллере с помощью

$this->router->getCurrentRoute()->money_array = $moneyArray;

Это нам понадобится, чтобы передать в блок контроллер фильтров данные значения. Т.к. первым отработает фронт контроллер, то после него отработают блок контроллеры из обёртки. А это позволит нам передать туда наши данные для дальнейшего помещения в шаблон.

Функция getHeterogeneity это функция, которая подготавливает массив для рисочек нашего ползунка.
Теперь добавим эту функцию в наш класс.

/**
* Получает риски для цен диапозона цен
* 
* @return string
*/
function getHeterogeneity($min,$max){
       $max = floatval($max); 
       $min = floatval($min); 
       //Проверим возможно ли это
       if ($max==$min) return "";
       $delta = $max-$min;
       $d25 = ceil($min + (($delta/100)*25)); 
       $d50 = ceil($min + (($delta/100)*50)); 
       $d75 = ceil($min + (($delta/100)*75)); 
       return '"25/'.$d25.'","50/'.$d50.'","75/'.$d75.'"';
}

С этой часть мы покончили. Теперь нам необходимо перейти к блок контроллеру фильтров в которых обработать наши сведения и поместить в шаблон фильтров дополнительные сведения.
Для этого делаем копию блок контроллера фильтров

/modules/catalog/controller/block/sidefilters.inc.php

и  также

/modules/catalog/controller/block/sidefilters.my.inc.php

И заходим в класс SideFilters нашего нового файла в метод actionIndex().

Добавим в шаблон в массив через $this->view->assign новый элемента массива

$this->view->assign(array(
     ...
     'moneyArray' => $this->router->getCurrentRoute()->money_array,
     ...
));

Троеточие используется для примера данных.

Теперь нам нужен шаблон "blocks/sidefilters/filters.tpl" (У каждой темы соответственно в своей папке).
Строки, которые отвечают у нас за отображение фильтра надо заменить на:

{if $param.show_cost_filter}
                        <div class="priceFilter typeInterval">
                            <span class="title">Цена:</span>
                            <div class="typeInterval fromToPrice">
                                <input type="hidden" class="textinp fromto" name="bfilter[cost][from]" value="{$basefilters.cost.from}" data-start-value="">
                                <input type="hidden" class="textinp fromto" name="bfilter[cost][to]" value="{$basefilters.cost.to}" data-start-value="">
                            </div>
                            
                            <div class="priceInterval fromToLine">               
                                <input type="hidden" data-slider='{ "from":{$moneyArray.interval_from}, "to":{$moneyArray.interval_to}, "step": "{$moneyArray.step}", "round": {$moneyArray.round}, "dimension": " {$moneyArray.unit}", "heterogeneity": [{$moneyArray.heterogeneity}]  }' value="{$basefilters.cost.from|default:$moneyArray.interval_from};{$basefilters.cost.to|default:$moneyArray.interval_to}" class="pluginInput" data-closest=".fromToPrice" data-start-value="{$basefilters.cost.from|default:$moneyArray.interval_from};{$basefilters.cost.to|default:$moneyArray.interval_to}">
                            </div>  
                            <input type="submit" value="Применить" class="onemore submitFilter" style="display:none;"/>
   </div>
{/if}

html у нас готов теперь надо активировать js.
В примере я воспользуюсь нашим стандартным слайдером (jslider - jquery.slider.min.js), который есть во всех наших темах.
У нас это указано так.


<script type="text/javascript">
                $(function() {
                    $('.typeInterval .pluginInput').each(function() {
                        var $this = $(this);
                        
                        var fromTo = $($this.data('closest'));  
                        fromTo.hide(); 
                        $this.jslider( $.extend( $(this).data('slider'), { callback: function(value) {
                            
                            var values = value.split(';');
                            $('input[name$="[from]"]', fromTo).val(values[0]);
                            $('input[name$="[to]"]', fromTo).val(values[1]);
                            $this.trigger('change');
                        }}));
                        
                        $('input[name$="[from]"], input[name$="[to]"]', fromTo).change(function() {
                            var from = $('input[name$="[from]"]', fromTo).val();
                            var to = $('input[name$="[to]"]', fromTo).val();
                            $this.jslider('value', from, to);
                        });
                    });
</script>

Re: Как добавить ползунок цены в категории?

Получилось?

Re: Как добавить ползунок цены в категории?

В одном из ближайших обновлений этого можно будет избежать. В настройках модуля каталог появится флажок "Показывать фильтр по цене в виде слайдера". Если его установить, то всё будет работать сразу.

5

Re: Как добавить ползунок цены в категории?

Отличная новость!