Поступил вопрос — Чем можно сделать выбор диапазонов в Exposed Filter, как на Яндекс-маркете.
Отвечаю — сделать можно с помощью jQuery UI Slider Widget (в ядре) и небольшого количества кода.
1. Добавляем один или несколько раскрытых фильтров (в примере это фильтр по Nid) и в качестве оператора выбираем Is between:
Получаем:
2. Реализуем хук hook_form_views_exposed_form_alter()
в котором подключаем jQuery UI Slider, скрипт инициализации слайдера, стиль и экстра разметку:
/**
* Implements hook_form_views_exposed_form_alter()
*/
function mymodule_form_views_exposed_form_alter(&$form, $form_state) {
if ($form_state['view']->name == 'myview' && $form_state['view']->current_display == 'page') {
// Находим минимальное и максимальное значение
$query = db_select('node');
$query->addExpression('MIN(nid)', 'min');
$query->addExpression('MAX(nid)', 'max');
$limits = $query->execute()->fetch();
// Оборачиваем виджет враппером с информацией о минимуме и максимуме
$form['nid']['#prefix'] = '<div class="slider-widget-wrapper" data-min="' . $limits->min . '" data-max="' . $limits->max . '">';
$form['nid']['#suffix'] = '</div>';
// Подключаем js и css файлы
$form['#attached']['library'][] = array('system', 'ui.slider');
$form['#attached']['js'][] = drupal_get_path('module', 'mymodule') . '/slider-init.js';
$form['#attached']['css'][] = drupal_get_path('module', 'mymodule') . '/slider-style.css';
}
}
3. В slider-init.js
инициализируем виджет:
(function($) {
Drupal.behaviors.mymodule = {
attach: function (context, settings) {
$('.slider-widget-wrapper', context).once('slider-widget', function () {
var $sliderWrapper = $(this);
var $minInput = $sliderWrapper.find('input:first');
var $maxInput = $sliderWrapper.find('input:last');
// Прописываем минимум и максимум в placeholder
$minInput.attr('placeholder', $sliderWrapper.data('min'));
$maxInput.attr('placeholder', $sliderWrapper.data('max'));
// Создаём слайдер
var $slider = $('<div class="slider-widget" />').appendTo($sliderWrapper).slider({
range: true,
min: $sliderWrapper.data('min'),
max: $sliderWrapper.data('max'),
step: 1,
values: [
$minInput.val() === '' ? $sliderWrapper.data('min') : $minInput.val(),
$maxInput.val() === '' ? $sliderWrapper.data('max') : $maxInput.val()
],
slide: function (event, ui) {
$minInput.val(ui.values[0]);
$maxInput.val(ui.values[1]);
}
});
// Описываем реакцию слайдера на ввод данных в поля min/max
$minInput.keyup(function () {
$slider.slider('values', 0, this.value);
});
$maxInput.keyup(function () {
$slider.slider('values', 1, this.value);
});
});
}
};
})(jQuery);
Получаем:
4. В slider-style.css
наводим красоту:
.slider-widget-wrapper {
width: 200px;
}
.slider-widget-wrapper .form-item:nth-child(1) {
float: left;
}
.slider-widget-wrapper .form-item:nth-child(2) {
float: right;
}
.slider-widget-wrapper .form-item:nth-child(2) label {
display: none;
}
.slider-widget-wrapper .form-item:nth-child(2) .form-text {
text-align: right;
}
.slider-widget-wrapper .form-text {
width: 90px;
margin: 0 0 5px 0;
padding: 0;
border: 0;
background: transparent;
}
.slider-widget-wrapper .slider-widget {
clear: both;
}
Получаем:
Исходники примера (экспорт вьюхи в файле views-export.txt
).
Добавлено 19.01.2013
Поддержка jQuery UI Slider Widget появилась в модуле Better Exposed Filters (динамически указать минимум и максимум можно в хуке hook_better_exposed_filters_settings_alter
).
- Необязательное значение одной из дат в раскрытом фильтре с оператором BETWEEN
- Сменить тип раскрытого фильтра с select на checkboxes
- Необязательное одно из двух значений раскрытого фильтра с оператором BETWEEN
- Подменить значение раскрытого фильтра Views
- Раскрытый фильтр "С фото" в виде одиночного чекбокса
Комментарии
Респектище и спасибище! Люблю этот блог! :)
Не совсем понятно куда вставлять хук hook_form_views_exposed_form_alter()
и Актуально ли это для Drupal 6?
в файл модуля
Слайдер конечно клевый, но вот ребята модуль сделали и в установке проше http://drupal.org/project/jslider_form_api
Парни то Наши)))
Developers
Initial development: Roman Grachev
Futher development: Maslouski Yauheni
модуль может и хороший, только к раскрытым фильтрам views не имеет никакого отношения
Понял, а под DRUPAL 6 по раскрытым фильтрам views, что-нибудь у Вас и меется?
Спасибо большое, за полезную статью. Но нуждаюсь в вашей профессиональной помощи. При работе со стандартными фильтрами все ок, но например если пытаться делать тоже самое с фильтрами уберкарта ( с ценой к примеру ), то "ползунок" не работает, хотя и появляется около полей min\max . Спасибо, заранее за ответ.
xandeadx
Большое спасибо за статью. Супер. Просто и эфективно.
Подскажите пожалуйста направление куда копать что бы для таких фильтров определять фактическое максимальное и минимальное значение . К примеру для той же самой Ubercart-овской цены? Не абстрактные 0% и 100%.
xmik3l
Коллега, в фале slider_eaxample.module в строках
$form['nid']['#prefix'] = ....
$form['nid']['#suffix'] = ....
вместо 'nid' вставьте имя вашего exposed filtra и все заработает.
xmik3l
... прочитал внимательнее, у меня ползунок не работал из-за ошибок с разметкой,, один див другой накрывал.
@Galapogos делайте запрос в базу, узнавайте min/max, передавайте в js
Под Ubercart (Цена = sell_price)
Galapogos, Stan.Ezersky спасибо вам большое за советы, помогло :)
Ползунок от 0 до 100 показывает, если у вас товары более 100 руб., это неудобно.
@Stan.Ezersky http://xandeadx.ru/blog/drupal/532#comment-4956
классненько, работает!
э... только как сделать, чтобы представление обновлялось аяксом от этих слайдеров? ajax -представление сделал, а как отправку формы повесить на отпускание кнопки мыши со ползунка?
собственно со слайдером понятно
а вот как views сабмитить?
хм, во views есть автоотправка данных, но оно не срабатывает при смене значения поля слайдером
Добрый день xandeadx!
hook_form_views_exposed_form_alter()
куда писать? в Drupal 7 в файл field_ui.api.php или field_ui.module или в template.php?http://xandeadx.ru/blog/drupal/256
Спасибо за урок, сделал, вот только на поле "Цены", тут получается аргументы до 100, можно как нибудь или с фактическими ценами, в крайнем случае указанной мною диапазоне... например от (5000 до 15000)? пробовал капать тут
не получилось...
спасибо. жду ответа...
http://jqueryui.com/demos/slider/#options
Указал фиксированные аргументы, а как сделать начальные аргументы стояли в начале и конце, в max и min ?
настройки фильтра - значения по умолчанию
Добрый день!
Сделал виджет все работает, спасибо xandeadx за урок. Один вопрос при работе иногда JS выдает ошибки, в консоле видно
f is undefined и многое другое как предотвратить такие ошибки. Вот собсветнно код. Жду комметариев..
А как передать деволтное значение в фильтры? через hook_form_views_exposed_form_alter не получается
Дефолтное значение ставил в настройке виджета, вот так я залепил виджет http://www.mirkvartir.kz/ru
xandeadx, 1.загрузил и включил этот модуль, 2.импортировал вьювс - но не работает
пожалуйста помоги
поставил на чистый drupal, заработало! по одному буду отключать модули и посмотрю
xandeadx, такой вопрос, в папке лежит файл для импорта вьювс, но это страница
пытаюсь сделать блок - не получается, пожешь помочь??
заранее спасибо
Уважаемый xandeadx, не подскажите ли как передать в slider_example.js в настройки из http://xandeadx.ru/blog/drupal/532#comment-5265 min и max значения, если они у меня на момент формирования exposed filter уже вставлены в скрытые поля:
пробовал переменными, все время выдает missing : after property id
код скрытых полей, выше не вставились
пробовал - не выходит. причина этому оказалась более глубже - у меня во вьюхе в хедере jquery присваивал значения скрытым полям. поэтому срабатывало на ф5 только, а просто при переходе по ссылке - код обрабатывался позже.
вобщем
init_max = parseInt($("input#maxs").val());
а уже потом max: init_max,
причем как я понял перевод в целое необходим.
спасибо за предложенный способ
а ну и забыл добавить - jquery не использовать, а передавать скрытым значениям значения напрямую, с помощью php
А если данной вьюхе включить AJAX, то при перегрузке формы создается 2 слайдера постоянно. Как это обойти?
http://drupal.org/node/756722#jquery-once
Для D6 бы...
Какой модуль конфликтует со слайдером?
Добрый день. Слайдер не отображается на странице, только при редактировании view. В чем может быть проблема?
Только у меня после отправки формы дублируется слайдер?
Блин, просмотрел выше подсказку-)
Решение от дубликатов
xandeadx, спасибо за решение!
А каким образом можно выбрать диапазон не по полю nid, а по числовым фиелдам?
таким же. nid это и есть "числовой филд"
Я имею ввиду - фильтровать не по NID, а по другому полю. Создал я поле "цена", и диапазон оттуда чтобы брался, а не из nid.
всё по аналогии
Спасибо за статью. Я попробовал поставить слайдер на чистый друпал. Появился слайдер, но при попытке передвижения рычажка я получаю ошибку в jquery.ui.slider.min, которая гласит: TypeError: a is null. Возможно, вы сможете мне подсказать, как сделать, чтобы слайдер заработал. Спасибо
line 23
И версия jquery 1.8.7
заменил min на нормальный jQuery UI Slider 1.8.7 js и получил "undefined" на 286 строчке, когда попытался взять closestHandle = $( this.handles[index] );
в this.handles есть элемент 0, но index начинается с 1 и выходит undefined... может есть идеи, как это безболезненно починить?
У меня всё работает, достаточно включить мозги: http://u6969.krypton.vps-private.net/realty/flats (dev-сайт)
замечание, конечно, искрометное, но хотелось бы более конкретных советов, а не ссылок на рабочий сайт. я и так знаю, что все должно работать
Сделал все как ту описано, вставлял и пример с архива. И свой модуль делал. Ничего не работает вообще. Я даже не вижу что бы стили и js файл подгрузились.
Что не так делаю, уже второй день пробую)))
1) Ставлю на чистый Друпал 7.
2) Делаю импорт в представление с именем sliderexample.
3) Загружаю модуль slider-example не чего вних не меняю.
И все не чего не происходит есть только стандартная сортировка, что делаю не так помогите. Может имя где не то или что то не подключил(((
имя представления есть в файле views-export.txt
Спасибо большое за модуль.
При использовании модуля появилась одна проблемка. Если использовать ajax в exposed filter, то при каждом сабмите слайдер добавляется заново. То есть к одному фильтру добавляется на странице несколько слайдеров.
Не заметила ссылку выше, уже подправила.
Подскажите, можно как то добавить в фильтре раскрытом разделители тысячных?
Не сказал бы. Допустим у меня кроме этого фильтра есть другие. И нужно чтоб они работали вместе. Ну или, скажем, это цена товаров в какой-либо категории. Мне нужно чтоб был выдан диапазон цен в данной категории, а не вообще товаров по сайту. Как такое провернуть?
Для nid все работает. Пробую для поля цены сделать и ничего не получается. Бегунок появляется, но ползунок нельзя двигать
Что я не так делаю?
Спасибо всем, и в первую очередь xandeadx за прекрасный слайдер!
Ничего лучше и удобнее на данный момент не нашел.
Думаю многим будет интересно узнать, как для ubercart подставлять мин. и макс. значения в слайдер из текущего раздела каталога.
Сделал так:
1) Создал 2 обычных представления views для определения мин. и макс. значения цены.
Добавил их в представление uc_catalog как тип "Вложение".
Параметры стандартные: выводим один товар с сортировкой по мин./макс. значению цены.
Machine Name для созданных вложений: min_price и max_price соответственно.
2) Добавил в функцию function uc_slider_form_views_exposed_form_alter(&$form, $form_state) следующее:
2.1) //Определяем ID текущего термина таксономии
$term_id = arg(2);
2.2) // Находим минимальное и максимальное значение
$min_view = views_get_view_result('uc_catalog','min_price', $term_id);
$max_view = views_get_view_result('uc_catalog','max_price', $term_id);
$min_limit = $min_view[0]->uc_products_sell_price;
$max_limit = $max_view[0]->uc_products_sell_price;
2.3) Ну и подставляем эти значения $form['sell_price']['#prefix'] = '';
Должно заработать :)
в этом месте и происходит выбор минимума и максимума NID, а как должен выглядеть этот код, если необходимо сделать выбор минимума и максимума из поля "ЦЕНА"? Убил целый день и самостоятельно реализовать не смог. Буду очень признателен, если поможете.
id-раскрытой-формы это как подскажите. где это вообще смотреть.
И такой ещё вопрос если я возьму фильтр не по nid а по цене то что мне менять нужно?
xandeadx выручай как вытащить минимальное значение поля
и максимальное машинное имя поля (в базе field_vac_zp_value)
Как я понял нужно сюда вписать?
// Находим минимальное и максимальное значение
$query = db_select('node');
$query->addExpression('MIN(field_vac_zp_value)', 'min');
$query->addExpression('MAX(field_vac_zp_value)', 'max');
$limits = $query->execute()->fetch();
Но тогда он выдает ошибку:
PDOException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'field_vac_zp_value' in 'field list': SELECT MIN(field_vac_zp_value) AS min, MAX(field_vac_zp_value) AS max FROM {node} node; Array ( ) в функции slider_example_form_views_exposed_form_alter() (строка 12 в файле /slider_example/slider_example.module).
http://xandeadx.ru/blog/drupal/532#comment-8155
Спасибо xandeadx! Действительно супер слайдер!
Одно не смог побороть :( - слаб в жаваскрипт. Как вызвать событие keyup после загрузки страницы?
Ситуация:
зашел на страницу вьюса – выставились значения мин/макс (допустим 1/10).
Выбрал раздел, нажал сабмит: в слайдере так и стоить 1/10, а в div class="slider-widget-wrapper" уже 3/8. Клик по слайдеру- и в слайдере уже то-же 3/8
Т.к. как то «толкать» слайдер после загрузки всей страницы.
Как?
$(...).keyup();
xandeadx, много раз в сети натыкался на ваши статьи, модули. Спасибо вам огромное за проделанный труд. Вы - просто супер человек!
Подскажите плз, как определить id-раскрытой-формы?
debug($form['#id'])
Спасибо за ответ(причем быстрый)!
И извините за следующий вопрос, порожденный моим незнанием - а куда именно вставить - "debug($form['#id'])" для определения id формы. Спасибо за понимание.
А как бы сделать так, чтобы была автоотправка при смене слайдера. Когда руками вбиваешь цифры - отправляет, а так нет.
Это мне кажется очень полезная штука была бы, всем бы помогла
Скажите, есть возможность для цифр добавить разряды? То есть чтобы отображалось не "1000", а "1 000". Прописываю так в js файле
выводится с пробелами, но при этом при нажатии на submit эти данные не ищутся, потому что передаются GET'ом тоже с пробелом
Для лентяев, использующих Drupal + Commerce
ToDo:
1. Ограничить выбор цены только среди показанных товаров (с таким запросом показываются цены всех товаров. Если типов товаров много, надо ограничивать цену)
2. Привести значения в слайдере к форматированному виду, типа от 500 руб. до 10 000 руб.
Отличный у вас блог. Замечательные и простые решения. И это хорошее. Но то что мне нужно - совсем другой фильтр. Ищу как реализовать - гахожу только подобные решения. Может подскажете как решить мою задачку?
Суть в том, что мне надо фильтровать не по диапазону, а фильтровать диапазон. Например у меня в базе заданно что некто работал в конторе с Ymin по Ymax. Я хочу задавать в ОДНОМ! поле фильтра значение Y и если диапазон [Ymin, Ymax] его покрывает - запись выводить. Неужели ни кем такое не реализовано?
если Ymin и Ymax это два разных поля, то придётся писать свой хэндлер.
если это какой-нибудь doublefield, то там такое вроде идёт из коробки
В итоге оказалось проще с помощью search api сделать
для данного конкретного примера, могу предложить такой вариант
$slider.mouseup(function(eventObject){
// $('#views-exposed-form-slider-example-page').submit(); -- вариант №1
$('#edit-submit-slider-example').click(); -- вариант №1
});
Спасибо xandeadx за ответ. doblefield проверил. Нет того о чем вы говорите из коробки. Там в фильтрах доступны тупо first и second части двойного поля и все. Наверное свой хендлер - это вариант.
более правильный вариант описан здесь
https://drupal.org/node/1005884#comment-4870638
Спасибо. Очень помогла статья. Принцип стал понятен. Переписала под D6.
Для тех, кто испытывает сложности с поиском "правильного" поля для min|max, заходите в представления, делаете экспорт своего представления с раскрытым фильтром. Находите там название своего фильтра. Должно быть что-то вроде этого.
Первая выделенная строчка - название таблицы. Вторая, соответственно, — название поля с min и max значениями.
Вопрос. Имеем слайдеры с диапозоном значений, допустим 0-100. Необходимо добавить чекбокс, так что бы при его выборе значения слайдера игнорировались , а передавалось значение, которое было указано где то в конфиге (например в самом хуке).
Прошу помочь с данной реализацией. Если вопрос стоит в деньгах, то сумму можно оговорить.
Слайдер работает, все хорошо, но не могу понять как разделить тысячные пробелом..
вот что получилось
в какое место нужно вставить этот код?
number_format($number,0,'',' ');
Это чудо блог, чудо человека. Низкий поклон!
Уважаемый xandeadx, возможно у Вас имеются мысли как переопределить range min и range max значения в настройках BEF?
в принципе будет достаточно на загрузку формы вьюхи это проделывать. может есть хук какой?
минимальные и максимальные сидят в это время в переменных
hook_better_exposed_filters_settings_alter
что-то не получается, к тому же debug($form) не выводил те настройки.
вот так пробовал
вот еще такое работает, вывести могу
а как присвоить?
Подскажите, а данный способ работает с Field collection?
А не подскажите как можно исправить такой косяк - есть термины-категории в каждой категории раскрытые фильтры с этими ползунками, так вот, так как значения в ползунки берется из БД, то получается, что диапазон значений формируется с учетом и тех значений которых на данный момент нет на странице, то есть они принадлежат к другому термину, и если задать этот диапазон то отображается полностью пустая страница даже скрываются раскрытые фильтры. Не знаете как побороть? куда копать? Спасибо.
очевидно в запрос на минимум и максимум нужно добавить условие на выборку только с текущим термином
а не подскажите как это сделать?
http://xandeadx.ru/blog/drupal/88
спасибо!
а если не сложно, не могли бы один пример показать?
именно как будет выглядеть запрос SQL. не дружу с ним
*SOS*
а шаг у ползунков можно задавать?
выкладываю результат с фильтром по категории(мало ли кому нить понадобится):
Добавить комментарий