Постановка задачи
Модуль Better Exposed Filters улучшает функциональность раскрытых фильтров Views в Drupal, предоставляя в частности, виджет Jquery UI Slider (ползунок) для раскрытого фильтра с диапазоном значений. Однако при этом имеется возможность указать только фиксированные значения «от» и «до» для фильтра, что в ряде случаев может нам не подойти. Например, если у нас сайт-каталог или интернет-магазин товаров, то логично для каждой категории товаров задавать минимальные и максимальные цены на товары из данной категории, а не всего каталога.
О том, как я решил подобную задачу на одном из проектов и пойдет речь в данной статье.
Настройка Better Exposed Filters
Рассмотрим настройку раскрытого фильтра по цене на примере магазина на Drupal Commerce. Устанавливаем модуль Better Exposed Filters, во вьюшке для товаров (ее создание и настройка не входят в рамки данной статьи) добавляем раскрытый фильтр по цене товара, как это показано на рисунке:
Далее в настройках раскрытых фильтров вьюшки выбираем Better Exposed Filters, в дополнительных настройках для фильтра по цене выбираем «Jquery UI Slider»:
Настройки можно оставить по умолчанию, так как диапазон значений мы будем задавать в коде. Можно указать размер шага Step ползунка.
Программное изменение минимального и максимального значений фильтра
Как оказалось, модуль Better Exposed Filters не предоставляет хука для изменения настроек плагина Jquery UI Slider, поэтому пришлось немного поломать голову, каким же образом задать нужные значения. В конце концов, остановился на варианте с хуком hook_js_alter():
$query = db_select('field_data_commerce_price');
$query->addExpression('MIN(commerce_price_amount)');
$min = $query->execute()->fetchField();
$min_price = commerce_currency_amount_to_decimal($min, 'RUB');
$query = db_select('field_data_commerce_price');
$query->addExpression('MAX(commerce_price_amount)');
$max = $query->execute()->fetchField();
$max_price = commerce_currency_amount_to_decimal($max, 'RUB');
foreach ($javascript['settings']['data'] as $key => $value) {
if (array_key_exists('better_exposed_filters', $value)) {
$javascript['settings']['data'][$key]['better_exposed_filters']['slider_options']['commerce_price_amount']['min'] = floor($min_price);
$javascript['settings']['data'][$key]['better_exposed_filters']['slider_options']['commerce_price_amount']['max'] = ceil($max_price);
}
}
}
Приведенный выше код находит в базе данных сайта минимальную и максимальную цены товаров интернет-магазина на Drupal Commerce, округляет их и устанавливает в качестве интервальных значений фильтра. На использование именно хука hook_js_alter() меня натолкнуло то обстоятельство, что значения фильтра попадают в свойства settings js-объекта Drupal. Если у вас есть другие мысли по решению данной задачи, поделитесь ими, пожалуйста, в комментариях.
Комментарии
Подскажите, если сайт не на
Подскажите, если сайт не на comerce и не нужно ничего округлять, то $min_price = commerce_currency_amount_to_decimal($min, 'RUB'); не нужно? Ну и макс,соответственно тоже...
Уже сам разобрался))) все
Уже сам разобрался))) все заработало! Спасибо огромное!!! Только почему-то если обновить цену в ноде, то после сохранения значения становятся по дефолту... и только после чистки кеша появляются наши. Как поправить?
Алексей, уточните, пожалуйста
Алексей, уточните, пожалуйста, какие значения вам нужно вывести?
Сейчас все выводится, только
Сейчас все выводится, только если отредактировать ноду, то в блоке фильтров максимальное и минимальное становится опять по дефолту 0 и 100000... и только после чистки кеша появляются реальные максимальные и минимальные.
Попробуйте обновить цену, а
Попробуйте обновить цену, а страницу с фильтрами открыть в другом браузере, скорее всего дело в кешировании скриптов.
Не помогает...
Не помогает...
Я проверю и дополню статью,
Я проверю и дополню статью, если обнаружу источник вашей проблемы. У вас блок с фильтрами есть на той же странице, что и сама нода? И приведите фрагмент вашего кода на всякий случай.
Блок есть.
Блок есть.
function better_exposed_filters_js_alter(&$javascript) {
$query = db_select('field_data_field_price');
$query->addExpression('MIN(field_price_value)');
$min_price = $query->execute()->fetchField();
$query = db_select('field_data_field_price');
$query->addExpression('MAX(field_price_value)');
$max_price = $query->execute()->fetchField();
foreach ($javascript['settings']['data'] as $key => $value) {
if (array_key_exists('better_exposed_filters', $value)) {
$javascript['settings']['data'][$key]['better_exposed_filters']['slider_options']['field_price_value']['min'] = floor($min_price);
$javascript['settings']['data'][$key]['better_exposed_filters']['slider_options']['field_price_value']['max'] = ceil($max_price);
}
}
}
А вы что этот код поместили
А вы что этот код поместили прямо в файл модуля Better Exposed Filters? Для этих целей нужно создавать свой кастомный модуль, ведь при обновлении все ваши изменения затрутся.
В template.php...
В template.php...
Подскажите как будет
Подскажите как будет выглядеть код если необходимо сделать десятичный разделитель в минимальном и максимальном значении.
Пример
от 1 000 до 10 000
Решал такую задачу созданием
Решал такую задачу созданием специальных div-контейнеров, куда записывал начальные значения, отформатированные с помощью number_format(), затем в js-коде перехватывал события изменения положений ползунков (см. http://api.jqueryui.com/slider/), форматировал значения min и max уже в js и изменял соответственно значения в этих div, а поля ввода самого ползунка скрывал через CSS.