Связанный список ajax

Как обычно проходит свой путь развития веб-разработчик-самоучка? Он занимается тем, что ему кажется более простым. Считает, что ему вполне достаточно и этого для решения тех задач, которые стоят перед ним на начальном этапе. Но рано или поздно любой веб-разработчик приходит к пониманию того, что его знаний ему катастрофически не достаточно. Человек, мало-мальски знающий PHP (и, наверное, что-то понимающий в HTML и CSS), до последнего будет отрицать необходимость изучения JavaScript. Будет сам себя убеждать в том, что ему это сейчас не нужно, что хватит и того багажа знаний и навыков, которые имеются.

Но приходит он… и тут капитулируют все… Он заставляет неистово гуглить, усердно писать на форумы, искать, копать, латать дыры в знаниях. Он коварен. Он — динамический список, динамический select.

Почему? Что к этому приводит? Ну, так случается, что ВНЕЗАПНО нужно сделать так, чтобы при выборе одного параметра в раскрывающемся списке, что-то происходило. Например, при выборе Ростовской области из списка регионов нужно отфильтровывать список населенных пунктов, чтобы для Ростовкой области нельзя было выбрать города и села Еврейской автономной области. Или при выборе автопроизводителя происходила фильтрация по маркам машин. Примеров можно привести чуть больше 9000.

Подробнее изучим задачу. Допустим, у нас есть три поля раскрывающихся списков: Тип транспорта, Вид транспорта, Категории транспорта. В конечном итоге нам необходимо, чтобы пользователь указал нужую ему категорию транспорта. Но мы хотим упростить жизнь своему пользователю, и не желаем, чтобы он утруждал себя поиском нужной категории среди совсем ненужных ему данных. Ведь категорий транспорта может быть великое множество, но подразделяются они на разные виды и типы.

Мы решили, что нам хватит трех списков. Делая выбор в первом, пользователь получает отфильтрованный второй список. В него попадут только те значения, которые относятся к выбранной категории в первом списке. Далее, делая выбор во втором списке, пользователь получает третий, сформированный по описанному выше принципу.

Следующей задачей является вот что — нет смысла позволять пользователю раскрывать второй и третий список до того, как не будет сделан выбор в первом. Ведь что он там сможет увидеть? Данные туда подгружаются динамически, основываясь на выбранных значениях. Значит до момента выбора второй и третий списки должны быть неактивными.

И ещё одно уточнение. Если пользователь захочет изменить выбранные данные, зависимые от него поля должны быть сброшены в исходное состояние. Это должно происходить для того, чтобы в списках всегда были только значения, которые имеют отношение к выбранным категориям и типам.

Итак, создаем форму с тремя списками.

<!-- Пишем в соответствии со стандартом HTML5 --> <!DOCTYPE HTML> <html> <head> <!-- Пишем заголовок документа --> <title>Динамические списки</title> </head> <body> <!-- Форма для динамических списков --> <form action="" method="post" id="dynamic_selects"> <!-- Создаем заголовок для списка выбора типов транспорта --> <!-- Поле формы помещаем в контейнер с классом row --> <div class="row"> <label for="type">Тип транспорта:</label> <!-- Создаем поле со списком --> <select id="type"> <!-- В список сразу внесем значение по умолчанию, а также несколько значений видов транспорта. Предположим, что они нам известны заранее, и хранятся, допустим, в базе данных --> <option value="0">Выберите из списка</option> <option value="1">Наземный транспорт</option> <option value="2">Водный транспорт</option> <option value="3">Воздушный транспорт</option> </select> </div> <!-- Для списков видов и категорий транспорта мы создадим только значения по умолчанию, остальные значения мы будем подгружать в них тогда, когда будет сделан выбор в первом списке --> <div class="row"> <label for="kind">Вид транспорта:</label> <!-- Так как это список зависит от выбора в первом списке, отключаем его, добавив к тегу select атрибут disabled--> <select id="kind" disabled> <option value="0">Выберите из списка</option> </select> </div> <div class="row"> <label for="category">Категория транспорта:</label> <!-- Так как это список зависит от выбора во втором списке, отключаем его, добавив к тегу select атрибут disabled--> <select id="category" disabled> <option value="0">Выберите из списка</option> </select> </div> </form> </body> </html>

Создав данный HTML-документ с данным кодом и откроете его в своем броузере, вы увидите форму с тремя списками, два из которых будут неактивными. Не очень красиво они сейчас выглядят. Давайте изменим их внешний вид. Для этого нам нужно будет создать небольшой CSS-документ, который мы подключим в заголовке созданного ранее HTML-документа. В этот CSS-документ мы запишем следующее:

/ Особо внешний вид страницы "причесывать" не будем Просто оформим поля нашей формы / / Для контейнера, который содержит поля формы / div.row { margin-bottom:15px; / Нижний отступ / } / Заголовки полей форм будут на отдельной строке / label { display:block; font-weight:bold; / Сделаем их жирными / margin-bottom:5px; / Нижний отступ от заголовка / } / Наши раскрывающиеся списки тоже "причешем" / select { width:300px; / Ширина / padding:3px 5px; / Величина внутренних отступов: сверху/снизу, справа/слева / }

Конечно же внешний вид формы у вас может быть своим :) Что дальше? Давайте подумаем. При выборе значения в первом списке мы должны получить перечень значений для второго. Даже не хочу сейчас описывать решение этого процесса одним только PHP. Нужно помнить одно: если речь идёт о последствиях действий пользователя, значит это JavaScript.

Но писать пригодный код на чистом JavaScript довольно не просто. Язык и сам по себе довольно не прост в понимании для тех людей, которые только-только стали осваивать PHP, а вдобавок ещё и каждый производитель броузера по-своему реализовал его в своем продукте. Для того, чтобы не заботиться о кроссбраузерности, мы воспользуемся библиотекой jQuery. Вопросы, связанные с синтаксисом данной библиотеки, здесь мы не обсуждаем.

Заголовок нашего HTML-документа мы перепишем, добавив в него подключение файла CSS и подключение библиотеки jQuery, которую мы возьмём у Яндекса. Следом мы подключим JavaScript-файл, в котором будем писать собственный JavaScript-сценарий.

Что должно происходить? При возникновении события выбора значения в первом списке, выбранное значение должно быть отправлено обработчику, который в ответ отправит перечень значений для второго списка, непосредственно связанных с первым. Этот перечень мы будем получать от сервера, так как предполагаем, что нужная нам информация хранится в базе данных (MySQL, к примеру). Значит из JavaScript-сценария нам нужно будет выполнить AJAX-запрос к серверу. После того, как сервер пришлет ответ, мы помещаем его во второй список, и делаем его активным. Начнем писать наш JavaScript-сценарий.

/ @author Evgeni Lezhenkin http://lezhenkin.ru В данном сценарии мы будем обрабатывать события выбора значений в списках тега select. Второе и третье поле списка являются зависимыми. При выборе значения в первом поле select должен отправляться AJAX-запрос, который вернет перечень значений для второго списка. Далее эти значения будут помещены во второй select, а сам список станет активным. После выбора значения во втором списке запускается тот же алгоритм, что описан выше. Все AJAX-запросы к серверу будут выполняться через скрипт query.php методом POST Если пользователь меняет значение в первом списке, все поля второго и третьего удаляются, и второй и третий списки становятся неактивными. Если Меняется значение второго списка, то удаляются все значения для третьего, и он становится неактивным. Данный сценарий будет работать во всех броузерах благодаря библеотеке jQuery Здесь не будет описываться синтаксис самого jQuery, синтаксис JavaScript. Также здесь не будет подробно описываться инструментарий / // Используем немедленно вызываемую функцию (function () { // Будем работать в соответствии с требованиями современного стандарта // ECMAScript. Включим строгий режим. "use strict"; // Весь наш основной сценарий будет работать уже после загрузки документа jQuery(function () { // Пишем обработчик события для выбора значения в первом списке // Нас интересует событие изменения значения поля $( '#type' ).change(function () { // При изменении значения первого списка мы должны удалить // все имеющиеся ajax значения во втором и третьем, а также // сделать их неактивными $( '#kind, #category' ).find( 'option:not(:first)' ) // Ищем все теги option, не являющиеся тегом по умолчанию.remove() // Удаляем эти теги // Чтобы сделать поля неактивными, неправильно менять значение атрибута disabled // Теперь нам нужно изменять значение свойства disabled объектов полей списка, // так как мы работаем с ними через библиотеку jQuery.end() // Возвращаемся к исходному объекту.prop( 'disabled',true ); // Делаем поля неактивными // Сохраним выбранное значение списка в переменную var type_id = $( this ).val(); // Если выбрано значение по умолчанию, ничего не делаем if (type_id == 0) { return; } // В ином случае нам необходимо отправить запрос на сервер // AJAX-запрос к серверу мы выполним, используя метод jQuery ajax() $.ajax({ type: "POST", // Тип запроса url: "query.php", // Путь к сценарию, обработающему запрос dataType: "json", // Тип данных, в которых сервер должен прислать ответ data: "query=getKinds&type_id=" + type_id, // Строка POST-запроса error: function () { // Обработчик, который будет запущен в случае неудачного запроса alert( "При выполнении запроса произошла ошибка :(" ); // Сообщение о неудачном запросе }, success: function ( data ) { // Обработчик, который будет запущен после успешного запроса // В ответ на наш запрос сервер должен прислать массив значений // Мы его вставим в поле второго списка с помощью цикла for for ( var i = 0; i < data.length; i++ ) { // Каждое полученное значение вставим в список видов транспорта $( '#kind' ).append( '<option value="' + data[i].kind_id + '">' + data[i].kind + '</option>' ); } // После того, как мы сформировали список, мы можем сделать его активным // обратившись к его свойству disabled $( '#kind' ).prop( 'disabled', false ); // Включаем поле } }); }); // Пишем обработчик события для выбора значения во втором списке // Нас интересует событие изменения значения поля $( '#kind' ).change(function () { // При изменении значения второго списка мы должны удалить // все имеющиеся значения в третьем, а также // сделать его неактивными $( '#category' ).find( 'option:not(:first)' ) // Ищем все теги option, не являющиеся тегом по умолчанию.remove() // Удаляем эти теги // Чтобы сделать поле неактивным, неправильно менять значение атрибута disabled // Теперь нам нужно изменять значение свойства disabled объекта поля списка, // так как мы работаем с ним через библиотеку jQuery.end() // Возвращаемся к исходному объекту.prop( 'disabled',true ); // Делаем поле неактивным // Сохраним выбранное значение списка в переменную var kind_id = $( this ).val(); // Сохраним выбранное значение типа транспорта в переменную var type_id = $( '#type' ).val(); // Если выбрано значение по умолчанию, ничего не делаем if (type_id === 0) { return; } // В ином случае нам необходимо отправить запрос на сервер // AJAX-запрос к серверу мы выполним, используя метод jQuery ajax() $.ajax({ type: "POST", // Тип запроса url: "query.php", // Путь к сценарию, обработающему запрос dataType: "json", // Тип данных, в которых сервер должен прислать ответ data: "query=getCategories&type_id=" + type_id + "&kind_id=" + kind_id, // Строка POST-запроса error: function () { // Обработчик, который будет запущен в случае неудачного запроса alert( "При выполнении запроса произошла ошибка :(" ); // Сообщение о неудачном запросе }, success: function ( data ) { // Обработчик, который будет запущен после успешного запроса // В ответ на наш запрос сервер должен прислать массив значений // Мы его вставим в поле третьего списка с помощью цикла for for ( var i = 0; i < data.length; i++ ) { // Каждое полученное значение вставим в список категорий транспорта $( '#category' ).append( '<option value="' + data[i].category_id + '">' + data[i].category + '</option>' ); } // После того, как мы сформировали список, мы можем сделать его активным // обратившись к его свойству disabled $( '#category' ).prop( 'disabled', false ); // Включаем поле } }); }); // Никакие обработчичик для поля третьего списка не нужны }); // Функция ожидания загрузки документа jQuery })(); // Немедленно вызываемая функция / Вы должны понимать, что данный код далек от идеала и является лишь примером решения конкретной задачи — динамического пополнения полей формы select. Здесь опущено очень много моментов, связанных с отладкой, безопасностью и многим другим. И вы должны понимать это очень хорошо. Данный пример просто показывает инструмент, с помощью которого решается озвученная задача. /

В представленном коде для вас будет достаточно много нового. Я снабдил его обширными комментариями, которые помогут вам понять суть процесса. Теперь пришла очередь взглянуть на сценарий-обработчик AJAX-запросов. Он у нас находится в файлеquery.php.

<?php / @author Evgeni Lezhenkin http://lezhenkin.ru Скрипт, обрабатывающий POST-запросы от JavaScript-сценариев Скрипт получает строку запроса, а в ответ отправляет массив с данными / // Непосредственно для этого скрипта мы создадим здесь массивы, в которых будут храниться // значения, запрашиваемые JavaScript-сценарием. В ваших сценариях этих массивов, скорее всего, // не будет. Информация, подобная этой, будет в вашей базе данных, и вам её придется оттуда // извлечь. Как вы это сделаете, это уже ваши предпочтения $types = array( 1 => array( // Наземный транспорт 1 => 'Железнодорожный транспорт', 2 => 'Автомобильный транспорт', 3 => 'Ручной транспорт' ), 2 => array( // Водный транспорт 1 => 'Речной транспорт', 2 => 'Морской транспорт', 3 => 'Подводный транспорт' ), 3 => array( // Воздушный транспорт 1 => 'Самолеты', 2 => 'Вертолеты', 3 => 'Ракета (шаттл)' ) ); $kinds = array( // Наземный транспорт 1 => array( // Железнодорожный транспорт 1 => array( 1 => 'Электропоезд', 2 => 'Дизельный поезд', 3 => 'Дрезина' ), // Автомобильный транспорт 2 => array( 1 => 'Легковой автомобиль', 2 => 'Грузовой автомобиль', 3 => 'Автобус' ), // Ручной транспорт 3 => array( 1 => 'Тачка', 2 => 'Тележка', 3 => 'Велосипед' ) ), // Водный транспорт 2 => array( // Речной транспорт 1 => array( 1 => 'Трамвай', 2 => 'Теплоход', 3 => 'Ракета' ), // Морской транспорт 2 => array( 1 => 'Крейсер', 2 => 'Круизный лайнер', 3 => 'Баржа' ), // Подводный транспорт 3 => array( 1 => 'Подводная лодка', 2 => 'Батискаф', 3 => 'Капсула смерти' ) ), // Воздушный транспорт 3 => array( // Самолет 1 => array( 1 => 'Боинг', 2 => 'Аэробус', 3 => 'Руслан' ), // Вертолеты 2 => array( 1 => 'МИ', 2 => 'Апач', 3 => 'Черная акула' ), // Ракета (шаттл) 3 => array( 1 => 'Союз', 2 => 'Апполон', 3 => 'Дискавери', 4 => 'Буран' ) ) ); // Проверяем наличие переменной, которая укажет данному сценарию какие именно данные нужны if (!isset($_POST['query']) ||!$_POST['query']) { exit("Нет данных определяющих тип запроса"); } else { // Сохраняем строку запроса данных в отдельной переменной $query = trim($_POST['query']); // Очищаем от лишних пробелов // Определяем тип запроса switch($query) { case 'getKinds': // Запрос на получение видов транспорта // Сохраним в переменную значение выбранного типа транспорта $type_id = trim($_POST['type_id']); // Очистим его от лишних пробелов // Формируем массив с ответом $result = NULL; $i = 0; foreach ($types[$type_id] as $kind_id => $kind) { $result[$i]['kind_id'] = $kind_id; $result[$i]['kind'] = $kind; $i++; } break; case 'getCategories': // Запрос на получение категорий транспорта // Сохраним в переменные значения выбранных типа транспорта и вида транспорта $type_id = trim($_POST['type_id']); // Очистим их от лишних пробелов $kind_id = trim($_POST['kind_id']); // Формируем массив с ответом $result = NULL; $i = 0; foreach ($kinds[$type_id][$kind_id] as $category_id => $category) { $result[$i]['category_id'] = $category_id; $result[$i]['category'] = $category; $i++; } break; default: // Если данные не определены $result = NULL; break; } } // Преобразуем данные в формат json, чтобы их смог обработать JavaScript-сценарий, приславший запрос echo json_encode($result); / Данный код не идеален. Сама идея представления исходных данных о транспорте в виде массива очень далека от идеала. И вы должны понимать почему. Данные должны храниться в реляционной базе данных, а представленный вариант написания сценария является лишь простейшим примером, который не стоит в таком виде применять на практике. Вы здесь должны лишь понять принципы работы языка и взаимодействия между языками программирования /?>

Можете проверять select-ы. Они отлично работают. Добавить ещё один select вы вполне сможете сами. Я помню, как много времени потратил когда-то на поиски нужной мне информации. Гуглил, искал, писал… что угодно делал, но только не читал книги и документацию. Поэтому, если вы пришли сюда и вам подошли описанные выше скрипты, не поленитесь — почитайте мануалы :)

P.S. Вам доступны описанные скрипты и в виде.


Закрыть ... [X]

Вебмастер: как создать свой сайт AJAX реализация связанных списков Мастер класс по бисероплетению из бусин

Связанный список ajax Связанные списки Страна-Регион-Город с использованием ajax. WeberSoft
Связанный список ajax Связанные динамичные списки Select без. / Programilla - WEB разработка
Связанный список ajax T Использование Ajax с клиентскими обратными вызовами
Связанный список ajax Javascript - Связанные списки Ajax - Stack Overflow на русском
Связанный список ajax AJAX реализация связанных списков информация
Связанный список ajax Зависимые списки select с помощью AJAX. Часть 1
Связанный список ajax Связанные между собой поля формы
Связанный список ajax Связанные с ajax списки (select) - jQuery
Связанные списки : jquery chained selects 2. Место психологии в системе наук, Лекция 1. Психология как наука Quot;Шишечка" крючком при вязании основного полотна спицами. Мастер Без переплат. Как пригнать б/у иномарку по новым правилам Блок питания для светодиодной ленты своими руками Вязаные спицами пинетки для детей. Подробные схемы с узорами Изящный и легкий топиарий из органзы Как рисовать человека Рисунки человека карандашом поэтапно