Некоторое время назад в нашем блоге публиковался пост о том, как сделать зависимые списки на JQuery/Ajax. В той статье был опубликован пример реализации двух списков, т.е. кода один список имеет зависимость от другого. Очевидно, для задач со списками более двух пришлось переделать скрипт, чтобы получить желаемый результат.
По этой теме ранее в комментариях был задан вопрос, о том, как реализовать 3 зависимых списка, при котором третий зависит от второго, второй от первого. В общем, пробуем делать 3 списка с зависимостями. Первым делом меняем структуру массива, в которых хранились наши данные, такой метод хранения позволит реализовать сколько угодно вложенностей в дальнейшем.
Допустим, у нас есть данные такой структуры:
BMW --5-series ----518 ----525 ----530 --7-series ----720 ----730 ----740 ----750 Mercedes-Benz --C-класс ----C 160 ----C 180 --E-класс ----C 200 ----E 220 ----E 230
В массиве разбиваем данные списка на уровни, плюс дополнительный параметр parent, который будет указывать на ключ в родительском списке.
$arParams = array( 'models' => array( 0 => 'BMW', 1 => 'Mercedes-Benz' ), 'series' => array( 0 => array('value' => '5-series' ,'parent' => 0), 1 => array('value' => '7-series' ,'parent' => 0), 2 => array('value' => 'C-класс', 'parent' => 1), 3 => array('value' => 'E-класс', 'parent' => 1), ), 'modif' => array( 0 => array('value' => '518', 'parent' => 0), 1 => array('value' => '525', 'parent' => 0), 2 => array('value' => '530', 'parent' => 0), 3 => array('value' => '720', 'parent' => 1), 4 => array('value' => '730', 'parent' => 1), 5 => array('value' => '740', 'parent' => 1), 6 => array('value' => '740', 'parent' => 1), 7 => array('value' => 'C 160', 'parent' => 2), 8 => array('value' => 'C 180', 'parent' => 2), 9 => array('value' => 'C 230', 'parent' => 2), 10 => array('value' => 'E 200', 'parent' => 3), 11 => array('value' => 'C 220', 'parent' => 3), 12 => array('value' => 'C 230', 'parent' => 3), ) );
Как и прежде, отдавать данные форме мы будет в ajax формате, однако в скрипте ajax.php пришлось сделать кардинальные изменения. Для получения данных скрипту нужно передать два параметра, listName и id. В listName передается параметр, который указывает на ключ массива, из которого запрашиваются элементы, в нашем примере это series – запрос серий модели и modif – запрос модификаций серии. Параметр id – указывает значение ключа в родительском списке.
<?php require_once('cars.php'); $arResult = array(); if (isset($_GET['listName']) && array_key_exists($_GET['listName'],$arParams) && isset($_GET['id']) && is_numeric($_GET['id'])){ foreach ($arParams[$_GET['listName']] as $id => $arItems){ if ($arItems['parent'] == $_GET['id']) $arResult[$id] = $arItems; } } echo json_encode ($arResult); ?>
Кроме того, сама форма так же поменялась:
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script> <select name="models" onchange="loadCar('models','series')"> <option>Модель</option> <?php require_once('cars.php'); foreach ($arParams['models'] as $mid => $model) echo '<option value="' . $mid . '">' . $model . '</option>' . "\n"; ?> </select> <select name="series" onchange="loadCar('series','modif');"><option>Серия</option></select> <select name="modif"><option>Модификация</option></select> <script> function loadCar(parent,child){ parentSel = $('select[name="'+parent+'"] option:selected'); childSel = $('select[name="'+child+'"]'); switch (parent){ case 'models': $('select[name="series"]').html('<option>Серия</option>'); $('select[name="modif"]').html('<option>Модификация</option>'); break; case 'series': $('select[name="modif"]').html('<option>Модификация</option>'); break; } if (isInt(parentSel.val())){ $.getJSON('ajax.php', { listName:child, id:parentSel.val() }, function(Items){ $.each(Items, function(i){ childSel.append('<option value="'+i+'">' + this.value + '</option>'); }); }); } } function isInt(n){ return n % 1 === 0; } </script>
В итоге можно посмотреть ПРИМЕР того что получилось, а вот ИСХОДНИКИ примера.
Как изменить код так, чтобы содержимое второго и третьего списков не выводилось до тех пор, пока не выбран пункт в первом и во втором соответственно? Так будет логичнее.
Пример зависимого списка в твоём случае. Изначально добавляем в CSS для вложенных списков значение display:none а уже после в js включаем показ при выборе значений.
Здравствуйте, как быть если используется в value не целые значения а с разделителем - точкой (реализация для калькулятора)
'models' => array(
'0' => 'BMW',
'1' => 'Rolls Roys',
),
'series' => array(
'1.18' => array('value' => 'Механика','parent' => '0'),
'1.15' => array('value' => 'Автомат','parent' => '0'),
),
'modif' => array(
'0' => array('value' => '2500000руб.', 'parent' => '1.18'),
'1' => array('value' => '1500000руб.', 'parent' => '1.15'),
)
Здравствуйте, можете описать задачу детальнее?
У меня калькулятор считает по значению value (это реализовано), но не могу реализовать что бы parent был равен к примеру 1.15, пример кода выше
Понятно, закоментируйте условие проверки на целочисленное значение:
if (isInt(parentSel.val())){
...
См. пример выше, условие находится на 27 строке
Как оказывается все элементарное - просто! Спасибо огромное. Удачи и процветания Вашему блогу!
спасибо!)
Если нужно добавить дополнительный 4 и 5 зависимый список?!
Добавляешь select с параметрами onchange, а так же новый элемент в массиве PHP.
Довольно простой и понятный пример!
Немного переписать и можно дёргать с БД.
Спасибо!
cars.php
$q=mysql_query("SELECT * FROM `cars` WHERE `selector`='1' ORDER BY `id` ASC");
while($f=mysql_fetch_assoc($q)){
$arParams['models'][$f['id']] = $f['name'];
}
$q=mysql_query("SELECT * FROM `cars` WHERE `selector`='2' ORDER BY `id` ASC");
while($f=mysql_fetch_assoc($q)){
$arParams['series'][$f['id']]=array('value' => $f['name'],'parent' => $f['id_pod_menu']);
}
$q=mysql_query("SELECT * FROM `cars` WHERE `selector`='3' ORDER BY `id` ASC");
while($f=mysql_fetch_assoc($q)){
$arParams['modif'][$f['id']]=array('value' => $f['name'],'parent' => $f['id_pod_menu']);
}
Спасиб ещё раз.
опечатка
WHERE `selector`='1'
WHERE `selector`='2'
WHERE `selector`='3'
Всем привет. Возник вопрос. Как при выборе последнего селекта перенаправить на юрл?
И еще, можно пример дампа бд выложить))
Здравствуйте, как реализовать следующую ситуацию у меня количество селектов отличается, где-то 3 уровня, где-то 5 уровней. как сделать так, чтобы это учитывалось и если мало уровней, то пустые уровни просто не показывались
Айнур, в вашем случае более правильно использовать рекурсию. Проверять длину массива возвращаемого с сервера, если длина == 0, то не показывать список.
Привет! Респект! Очень круто и понятно.
Вопрос такой: я создал зависимые списки, все работает. Вношу правки (добавляю данные) и при обычном обновлении данные не подтягиваются. Только когда сбросишь кеш либо зайдешь с другого браузера. Как решить эту проблему?
И еще вопрос, который уже задавали:
Как при выборе последнего селекта перенаправить на юрл?
1. Просмотрите в консоли браузера, происходит ли запрос к скрипту на сервере, возможно возникают ошибки на стороне браузера;
2. Пропишите условие в js для редиректа.
1. Исправил. Спасибо
2. Мне нужно сделать как тут: http://www.orafol.com/gp/europe/en/icc-profiles в конце появляется кнопка для скачивания профиля по параметрам выше. Что-то не догоняю как это реализовать...
Посмотри, что я сделал: https://yadi.sk/i/SPVA6CNa3FfSMv
Круто ! но вот у меня проблемка, выбор марки подгружается, во втором списке появляется "Серия" и больше ничего нету... код в стоке лишь "require_once" с путем в мою папку. Пробовал от прошлого урока с двумя списками - все отлично работает, в чем может быть проблема?
здравствуйте. скажите пожалуйста, а где это надо все прописать в php? html? как это реализовать? я только начал работать над этим.
У меня кв массиве есть ещё ссылки на соответствующие страницы. В форме у меня есть кнопка. Нужно, чтобы после выбора модификации в кнопку подгружалась ссылка соответствующая этой модификации. Подскажите, как это реализовать?