Иногда на сайте нужно добавить несколько связанных списков select, чтобы в зависимости от выбора посетителя в одном из списков, формировался набор связанных значений в следующем.
Например: Вы часто сталкиваетесь с этим при регистрации на сайтах и в социальных сетях, интернет-магазинах и форумах. Вам предлагают выбрать страну, после выбора страны рядом становится доступен выбор ее регионов, областей и городов. Причем все это происходит моментально: связанные между собою по смыслу значения меняются на лету в зависимости от Вашего выбора. Или, например, при выборе связанных характеристик товара в интернет магазине по продаже матрасов: размер, связанные с размером чехлы, каркас жесткости и т.п.
Итак, решений для формирования связанных между собою списков много. Но мне особенно понравился плагин jQuery Chained Selects своей простотой и отсутствием необходимости надолго нырять в документацию. Для того, чтобы работать с плагином jQuery Chained Selects, который формирует на сайте связанные списки (select), достаточно подготовить их соответствующим образом. Плагин не плодит дополнительных тегов, а работает с уже имеющимися, скрывая или показывая те или иные пункты списка в зависимости от выбора пользователя.
Рассмотрим небольшой пример: нам нужно выбрать машину для аренды (покупки). В первом select'е у нас будут марки автомобилей, а во втором - модельный ряд. Начнем формировать наши списки:
Чтобы связать между собою варианты выбора значений в родительском select со значениями в зависимом select, достаточно ко всем значениям option зависимого select добавить css
класс, равный значению option value
из родительского select.
Звучит немного мудрено, но сейчас вы все поймете. Взгляните на наш HTML-код:
<!-- родительский список -->
<select id="mark" name="mark">
<option value="">--</option>
<option value="bmw">BMW</option>
<option value="audi">Audi</option>
</select>
<!-- Зависимый список -->
<select id="series" name="series">
<option value="">--</option>
<option value="series-3" class="bmw">3 серия</option>
<option value="series-5" class="bmw">5 серия</option>
<option value="series-6" class="bmw">6 серия</option>
<option value="a3" class="audi">A3</option>
<option value="a4" class="audi">A4</option>
<option value="a5" class="audi">A5</option>
</select>
Чтобы связать наш автомобиль BMW с сериями 3, 5 и 6й мы задали значение соответствующего пункта списка равным bmw
, а потом это же значение прописали в классы для соответствующих пунктов зависимого списка. Обращаю ваше внимание, что значения и названия классов чувствительны к регистру, т.е. audi
и Audi
- это не одно и тоже. Будьте внимательны! Теперь скачаем с официального сайта плагин Chained Selects и подключим его вместе с библиотекой jquery к нашей странице:
<script src="jquery.min.js"></script>
<script src="jquery.chained.min.js"></script>
Запуск скрипта осуществляется всего одной строкой:
<script>
$(function(){
$("#series").chained("#mark");
})
</script>
Получили вот такие связанные select:
Если вам нужно 3 и более связанных списков, то нет ничего проще:
<select id=mark-3>
<option value="">--</option>
<option value=bmw>BMW</option>
<option value=audi>Audi</option>
</select>
<select id=series-3>
<option value="">--</option>
<option value=series-3 class=bmw>3 серия</option>
<option value=series-5 class=bmw>5 серия</option>
<option value=series-6 class=bmw>6 серия</option>
<option value=a3 class=audi>A3</option>
<option value=a4 class=audi>A4</option>
<option value=a5 class=audi>A5</option>
</select>
<select id=model-3>
<option value="">--</option>
<option value=coupe class="series-3 series-6 a5">Coupe</option>
<option value=cabrio class="series-3 series-6 a3 a5">Cabrio</option>
<option value=sedan class="series-3 series-5 a3 a4">Sedan</option>
<option value=sportback class="a3 a5">Sportback</option>
</select>
<select id=engine-3>
<option value="">--</option>
<option value=25-petrol class="series-3 a3 a4">2.5 бензин</option>
<option value=30-petrol class="series-3 series-5 series-6 a3 a4 a5">3.0 бензин</option>
<option value=30-diesel class="series-3\sedan series-5\sedan a5">3.0 дизель</option>
</select>
<script>
$(function(){
$("#series").chained("#mark");
$("#model").chained("#series");
})
</script>
Вот, какие три связанных select у нас получились с помощью плагина select chained:
Усложним задачу: пусть нам требуется привязать зависимый список к вариантам выбора нескольких родительских списков, т.е. выбор двигателя зависит от серии и модели. Наш код будет такой:
<select id=mark-3 class=span2>
<option value="">--</option>
<option value=bmw>BMW</option>
<option value=audi>Audi</option>
</select>
<select id=series-3 class=span2>
<option value="">--</option>
<option value="">--</option>
<option class="bmw" value="series-3">3 серия</option>
<option class="bmw" value="series-5">5 серия</option>
<option class="bmw" value="series-6">6 серия</option>
<option value=a3 class=audi>A3</option>
<option value=a4 class=audi>A4</option>
<option value=a5 class=audi>A5</option>
</select>
<select id=model-3 class=span2>
<option value="">--</option>
<option value=coupe class="series-3 series-6 a5">Купе</option>
<option value=cabrio class="series-3 series-6 a3 a5">Кабриолет</option>
<option value=sedan class="series-3 series-5 a3 a4">Седан</option>
</select>
<select id=engine-3 class=span2>
<option value="">--</option>
<option value=25-petrol class="series-3 a3 a4">2.5 бензин</option>
<option value=30-petrol class="series-3 series-5 series-6 a3 a4 a5">3.0 бензин</option>
<option value=30-diesel class="series-3\sedan series-5\sedan a5">3.0 дизель</option>
</select>
<script>
$(function(){
$("#series-3").chained("#mark-3");
$("#model-3").chained("#series-3");
$("#engine-3").chained("#series-3, #model-3");
});
</script>
Обратите внимание, что дизельный двигатель доступен только для BMW 3 и 5 сериях седанов. Это достигается с помощью классов series-3\sedan
и series-5\sedan
.
Подгрузка значений с помощью ajax
Метод работы с удаленной версией сходен с изложенным выше. Вначале подключаем библиотеку jQuery или Zepto и версию Chained Selects для удаленной работы:
<script src="jquery.min.js"></script>
<script src="jquery.chained.remote.min.js"></script>
В HTML коде вам нужно только прописать тэги option
для первого select. Содержимое других select’ов будет построено JSON-методом, возвращаемым в результате работы AJAX-запроса. AJAX-запрос выполняется при изменении значения родительского select.
<select id="mark" name="mark">
<option value="">--</option>
<option value="bmw">BMW</option>
<option value="audi">Audi</option>
</select>
<select id="series" name="series">
<option value="">--</option>
</select>
<select id="model" name="model">
<option value="">--</option>
</select>
<select id="engine" name="engine">
<option value="">--</option>
</select>
В коде мы используем метод remoteChained()
. Вторым параметром является URL, через который передается AJAX-запрос.
$("#series").remoteChained({
parents : "#mark",
url : "/api/series.json"
});
$("#model").remoteChained({
parents : "#series",
url : "/api/model.json"
});
$("#engine").remoteChained({
parents : "#series, #model",
url : "/api/engine.json"
});
Когда событие изменения срабатывает на родительском select-е, на заданный URL посылается GET-запрос. Этот запрос включает в себя имя и значение родительского элемента, сформированные в виде строковой величины. Например, когда пользователь в своей первой выборке задает BMW, то запрашивается следующее:
GET http://example.com/api/series.json?mark=bmw
При работе плагина Chained Selects ожидается создание JSON-запроса, содержащего значение в виде пары текстов для каждой опции.
{
"" : "--",
"series-1" : "1 серия",
"series-3" : "3 серия",
"series-5" : "5 серия",
"series-6" : "6 серия",
"series-7" : "7 серия",
"selected" : "series-6"
}
Если вам нужно иметь возможность сортировать записи на стороне сервера используйте массив массивов ...
[
[ "", "--" ],
[ "series-1", "1 серия" ],
[ "series-3", "3 серия" ],
[ "series-5", "5 серия" ],
[ "series-6", "6 серия" ],
[ "series-7", "7 серия" ],
[ "selected", "series-6" ]
]
... или массив объектов.
[
{ "" : "--" },
{ "series-1" : "1 series" },
{ "series-3" : "3 series" },
{ "series-5" : "5 series" },
{ "series-6" : "6 series" },
{ "series-7" : "7 series" },
{ "selected" : "series-6" }
]
Загружаемые select
Бывают случаи, когда вы знаете значений для выборки при загрузке страницы. Например, при прямой ссылке на сохраненный заказ или особую модель автомобиля. Когда вы знаете такие значения, то можете значительно ускорить процесс удаленного поиска. Для этого нужно задать значения для тэга option. Это также позволит избежать инициализации дополнительных AJAX-запросов. Вам нужно будет написать следующий HTML код:
<select id="mark" name="mark">
<option value="">--</option>
<option value="bmw" selected>BMW</option>
<option value="audi">Audi</option>n
</select>
<select id="series" name="series">
<option value="--">--</option>
</select>
Для того, чтобы BMW 3 серии было выбрано по-умолчанию, вы можете загрузить соответствующие значения в select
:
$("#series").remoteChained({
parents : "#mark",
url : "/api/series.json",
bootstrap : {
"" : "--",
"series-3" : "3 series",
"series-5" : "5 series",
"series-6" : "6 series",
"series-7" : "7 series",
"selected" : "series-3"
}
});
Обратите внимание, что bootstrap
в приведенном выше коде не имеет никакого отношения к Twitter Bootstrap - набору компонентов для создания адаптивных сайтов!
Отправка дополнительных значений
Иногда может потребоваться отправить значений больше, чем можно с помощью родительского select
. Допустим, у вас есть несколько вариантов трансмиссий (transmission). Cодержимое select’ов для выбора трансмиссии меняется, если пользователь выбирает новый двигатель. Однако возможность использования различных трансмиссий в вашей базе данных зависит также от серии машины. У вас есть четыре различных выпадающих списка select
:
<select id="mark" name="mark">
<option value="">--</option>
<option value="bmw" selected>BMW</option>
<option value="audi">Audi</option>
</select>
<select id="series" name="series">
<option value="--">--</option>
</select>
<select id="engine" name="engine">
<option value="--">--</option>
</select>
<select id="transmission" name="transmission">
<option value="--">--</option>
</select>
Тогда вы можете бы использовать следующий код, чтобы отправить серверу значения #series
и #engine
:
$("#transmission").remoteChained({
parents : "#engine",
url : "/api/transmissions.json",
depends : "#series"
});
Значения родительских select
отправляются всегда. Вам не нужно специально включать их для настройки зависимостей.
Показ текста "Идет загрузка" (Loading)
Если ваши запросы JSON медленно обрабатываются, вы можете показать текст "Идет загрузка", или любой другой, например, "Loading...":
$("#engine").remoteChained({
parents : "#engine, #model",
url : "/api/series.json",
loading : "Loading..."
});