css, html, php, javascript, jQuery, ajax … – решения, примеры, рецепты
6 Фев
При создании приложений для Web часто бывает необходимо установить в элементе select варианты выбора, значения которых зависят от параметров другого элемента select. Простой пример – выбор страны в одном раскрывающемся списке приводит к загрузке в следующий такой список перечня автомобилей, производимых в этой стране. А при выборе марки автомобиля, в следующий список загружаются модели этого авто. Вот и давайте попробуем вместе решить эту задачу, создав каскад раскрывающихся списков.
Для начала определим задачу: первый список будет содержать предварительно загруженные названия стран и всегда находиться в активном состоянии. Два оставшихся списка – выбора авто и выбора модели, пустые и находятся в неактивном состоянии. После того, как в первом списке будет выбрана страна необходимо заполнить второй список названиями автомобилей и перевести его в активное состояние. А после выбора названия автомобиля – заполнить список названиями моделей именно этого автомобиля и тоже активировать список. Кроме того, мы должны гарантировать, что пользователь никогда не сможет выбрать автомобиль «HONDA Vectra произведеный в Ю.Корее». Для обмена данными с сервером будем использовать популярный нынче формат JSON.
Итак, задача определена. Поехали?
Начнем с чего-нибудь очень простого. Например с подключения библиотеки jQuery и создания HTML-разметки:
В HEAD страницы подключаем библиотеку:
<script src="js/jquery-1.3.1.js" type="text/javascript"></script>
В BODY создаем HTML-разметку:
<div class="border">
<label>Страна</label><br />
<select id="country">
<option value="">Выбрать страну</option>
<option value="1">Германия</option>
<option value="2">Ю.Корея</option>
<option value="3">Япония</option>
</select>
</div>
<div class="border">
<label>Автомобиль</label><br />
<select id="auto" disabled="disabled"></select>
</div>
<div class="border">
<label>Модель</label><br />
<select id="model" disabled="disabled"></select>
</div>
Легко и просто! Каждому списку – по id. Первый раскрывающийся список заполняем названиями стран. Два других ничем не заполняем и мало того, устанавливаем в неактивное состояние с помощью атрибута disabled. Описания стилей я приводить не буду – это дело вкуса каждого и не в тему этой статьи.
Что дальше? Задача оказалась не так уж и проста, как казалось в начале. Поэтому предлагаю пораскинуть мозгами и решить, какие общие действия мы будем производить над всеми списками. Я придумал два – заполнение списка и очистка списка. Давайте оформим эти операции в виде методов jQuery, чтобы иметь возможность в любой момент вызвать этот метод в цепочке команд jQuery.
Расширение для jQUery может быть либо методом, оперирующим с набором элементов, либо вспомогательной функцией, которая определяется непосредственно в $. Простой пример: в составе библиотеки есть метод each(callback), который работает как раз с набором элементов, выполняя функцию, определенную в параметре callback в контексте каждого элемента набора и вспомогательная функция $.each(object,callback), которая применяется для обхода массива или объекта, переданного в первом параметре с выполнением функции callback для каждого элемента массива(объекта). Почувствовали разницу?
(function($){
// очищаем select
$.fn.clearSelect = function() {
return this.each(function(){
if(this.tagName=='SELECT') {
this.options.length = 0;
$(this).attr('disabled','disabled');
}
});
}
// заполняем select
$.fn.fillSelect = function(dataArray) {
return this.clearSelect().each(function(){
if(this.tagName=='SELECT') {
var currentSelect = this;
$.each(dataArray,function(index,data){
var option = new Option(data.text,data.value);
if($.support.cssFloat) {
currentSelect.add(option,null);
} else {
currentSelect.add(option);
}
});
}
});
}
})(jQuery);
Итак, что мы тут написали?
При написании метода clearSelect() мы воспользовались методом each(callback) для того, чтобы произвести необходимые операции над каждым элементом, переданным в наборе jQuery. Сначала производим проверку – если tagName переданного элемента действительно SELECT, то удаляем все элементы option и устанавливаем атрибуту disabled значение disabled.
Метод fillSelect(dataArray) несколько сложнее. Он получает в качестве параметра массив dataArray, содержащий данные, которыми необходимо заполнить выпадающий список. Правда перед тем, как заполнять список, мы вызовем метод clearSelect, чтобы очистить список от возможно оставшихся там данных. С помощью метода each(callback) мы перебираем все элементы, переданные в наборе jQuery, проверяем, действительно ли это элемент select и, если да, то сначала запоминаем его в переменной currentSelect. Затем воспользуемся вспомогательной функцией $.each(object,callback) для обхода массива dataArray. В каждой итерации создаем элемент options, заполняем его соответствующими данными и добавляем в select.
При добавлении option мы вынуждены учитывать различия между браузерами. К счастью и тут поможет jQuery. Здесь используем новую вспомогательную функцию $.support, которая появилась в jQuery с версии 1.3 взамен $.browser. Проверим значение свойства cssFloat – false укажет нам на IE, а true на FF, Opera, Safari. Вы можете применить свой способ проверки.
Обратите внимание: при написании метода fillSelect(dataArray) мы использовали метод each(callback) и вспомогательную функцию $.each(object,callback) – это разные вещи.
Теперь оба наших новых метода могут работать с набором элементов jQuery, который им будет передан. Этот код можно было бы вынести в отдельный файл – к тому же эти методы могут пригодиться и в других приложениях, а использовать их можно проще простого:
// очищаем select
$('select').clearSelect();
// заполняем select
$('select').fillSelect(dataArray);
Двигаемся дальше. Теперь мы напишем пару функций, которые будут обслуживать списки выбора автомобиля и выбора модели.
// выбор автомобиля
function adjustAuto(){
var countryValue = $('#country').val();
var tmpSelect = $('#auto');
if(countryValue.length == 0) {
tmpSelect.attr('disabled','disabled');
tmpSelect.clearSelect();
adjustModel();
} else {
$.getJSON(
'cascadeSelectAuto.php',
{country:countryValue},
function(data) {
tmpSelect.fillSelect(data).attr('disabled','');
adjustModel();
});
}
};
Здесь мы сначала запоминаем в переменной countryValue значение, выбранное в списке стран #country. В переменной tmpSelect будем хранить ссылку на элемент select с идентификатором #auto – список выбора автомобиля. Далее следует проверка:
Если страна не выбрана, то мы устанавливаем атрибуту disabled элемента select с идентификатором #auto значение ‘disabled’ и вызываем метод clearSelect() для очистки этого списка от возможно находящихся там значений. Также мы вызовем функцию adjustModel() (про нее чуть позже).
Иначе, мы отправляем с помощью вспомогательной функции $.getJSON запрос к файлу cascadeSelectAuto.php, передавая в качестве данных значение, сохраненное в переменной countryValue. При получении ответа сервера вызываем функцию, в которой определена нужная нам последовательность действий. А именно – к переменной tmpSelect (не забыли – это список с идентификатором #auto) применяем нами же написанный метод fillSelect(data), который заполнит список данными, которые получены от сервера и наконец переводим элемент в активное состояние с помощью атрибута disabled. Остается не забыть вызвать функцию adjustModel(), чтобы обработать выпадающий список моделей.
Функция adjustModel(), которая обрабатывает список моделей, очень похожа на adjustAuto(), поэтому нет смысла ее детально рассматривать. Обратите внимание разве на то, что теперь мы запоминаем значение из списка не только выбранной страны, но и выбранного автомобиля. И еще в if – else не вызываем что-то похожее на adjustModel(), поскольку список выбора модели у нас последний – дальше обрабатывать просто нечего.
// выбор модели
function adjustModel(){
var countryValue = $('#country').val();
var autoValue = $('#auto').val();
var tmpSelect = $('#model');
if(countryValue.length == 0||autoValue.length == 0) {
tmpSelect.attr('disabled','disabled');
tmpSelect.clearSelect();
} else {
$.getJSON(
'cascadeSelectModel.php',
{country:countryValue,auto:autoValue},
function(data) {
tmpSelect.fillSelect(data).attr('disabled','');
});
}
};
Поздравляю! Самая сложная часть пути уже позади! Остались сущие пустяки.
$('#country').change(function(){
adjustAuto();
}).change();
Связываем с выпадающим списком стран событие change(fn), при наступлении которого вызываем adjustAuto() – функцию, которая заполнит выпадающий список автомобилей. В цепочке команд вызываем change(), чтобы вызвать событие при начальной загрузке страницы.
$('#auto').change(adjustModel);
С выпадающим списком автомобилей связываем событие change(fn), при наступлении которого будет выполнена функция adjustModel(), которая заполнит список моделей.
$('#model').change(function(){
if($(this).val().length != 0) {
alert('Выбор сделан!');
}
});
И наконец, при изменении списка моделей выполним небольшую проверку – если действительно выбрана какая-либо модель, выведем в alert сообщение. Ну а в действительности тут можно придумать все, что угодно. Например вывести подробную информацию о технических характеристиках, красивую фотографию авто, чтобы его захотелось купить и конечно цену…
Ах, да! Совсем забыл – работающий пример:
Вы можете открыть пример в новом окне, чтобы посмотреть исходный код. Вы можете скачать архив, который содержит файлы примера (в том числе cascadeSelectAuto.php и cascadeSelectModel.php).
Отзывов (104) на «Каскад раскрывающихся списков»
Елки, как же разобраться со всей этой арифметикой? Можете посоветовать книжку – «для чайников» так сказатЬ, где бы было описано вот эти форматы, при помощи которых обменивается локалка с серваком, основы пхп…?
Спасибо за урок. Сейчас работаю над чем-то подобным, только в более сложной форме – у меня не 3 селекта, а неопределенное количество. Т.е. нужно раскрыть последовательно ветвящийся граф, в котором каждая ветвь может содержать неопределенное количество узлов.
Отличная идея с использованием $.fn.
Один вопрос только: вам не кажется, что быстрее будет работать вариант, который один раз получит от сервера все дерево и закеширует его в data, а потом только будет отображать нужные данные в селектах?
To: Алексей Качаев
Я старался разобрать принцип, объяснить как это реализовано, а не предложить какое-то готовое решение. Чтобы на основе этого можно было делать что-то свое…
To: Алексей Качаев
ты глубоко ошибаешься, почему? а что если у меня не модели автомобилей а города, которых 50 тыс. а то и больше, ты хочешь сказать загрузив в один массив будет быстрее?? ошибаешься глубоко…
спасибо за статью, очень полезная. Подскажи ещё как можно применить списки два раза на одной странице, допустим у меня этот список выбора расположен в меню колонке и выводится на всём сайте, также если зайти на страницу добавления чего-то, то там тоже нужно сделать выбор, и если разместить две эти одинаковые формы что сбоку и по центру страницы то вторая такая форма не работает т.к. ID у них одинаковые, а как разграничить?
Имхо даже в обучающей статье сразу стоит расширять объект jQuery функцией extend(), а html создавать $(html)
сам с младых ногтей явняюсь, увы, примером неверного обучения: набитое глупой книжкой в самом начале, как ни странно, держится до последнего: до сих пор в SQL вместо TINYINT на автомате пишу INT(1), и считаю что это один байт %)
Добрый день, подскажите пожалуйста, как к вашему скрипту можно подключить Базу данных, вот БД всех стран регионов и городов:
hxxp://ekimoff.ru/download/db_city/city.rar
спасибо
To о_О Тынц:
Умничаешь? Только не очень по делу-то. Ткни пальцем в то место, где по твоему мнению надо использовать extend()? А лучше почитай http://www.learningjquery.com/2007/10/a-plugin-development-pattern
А в чем проблема? Ваше ‘country’ – тоже, что и страны в примере – выводите сразу в первый список. Далее ‘region’ – все равно что выбор авто и наконец ‘city’ – выбор модели. Передавайте на сервер нужные данные и на их основе – запрос к Вашей БД.
В примере же есть даже файлы серверного сценария. Конечно там все искусственно сделано, но какая разница? Смысл-то один.
Спасибо за ваш сайт, много чего полезного нашёл, вот бы ещё бы написали отдельную статью про форму добавление, вы как то уже писали недавно «Плагин Live Query», но сейчас вышла новая версия jQuery 1.3 и там уже встроенный плагин Live. Хотел чтобы при заходе выводилась форма, при заполнении после нажатии кнопки передавались данные PHP скрипту, если некоторые поля небыли заполнены, выводилось сообщение, при успешном заполнении форма исчезала, и появлялось сообщение об успешном добавлении. Если будет время напишите пожалуйста, вам цены не будет. Я ваш постоянный посетитель.
jQuery Form – делаем ajax-форму
[...] подобную иерархию списков, можно прочитать здесь. Но. Такое решение не снимает проблем, ведь оно создано [...]
To Костя:
id – это идентификатор, он по определению должен быть уникальным. Почему обязательно id? Используйте для выбора элемента его класс например. А лучше всего для начала почитайте:
селекторы jQuery: базовые и иерархические селекторы, базовые фильтры
селекторы jQuery: фильтры контента, visibility-фильтры, фильтры атрибутов, child-фильтры
селекторы jQuery: селекторы форм и фильтры форм
Это поможет не задавать вопросы, которые можно было бы не задавать.
во, спасибо, странно что я не обнаружил статью у вас. Сейчас буду смотреть. Я обычно пользуюсь JsHttpRequest от Котерова, интересно будет попробовать при помощи jQuery. Интересно как будет обстоять дела с кодировками, загрузкой фотографиями и т.п.
Подскажите пожалуйста, а как можно подключить переход по урлу при выборе значения в третье колонке?
Вместо alert’a – window.location.href=’someurl.html’;
В таком случае перенаправит на один урл, а у меня урлов будет много, каждый соотв. выбранному значению. Такое можно реализовать?
Можно конечно, почему нет? Просто Вам надо продумать алгоритм. Ну например, вместо вызова alert’a будем вызывать функцию, которая должна «построить» нужный URL. Как это сделать? Ну, например собрать значения выбранных элементов в каждом из трех списков. При выборе Германия – BMW -X6 это будет 1,2,3. Сделайте из них строку запроса – например:
url.php?country=1&auto=2&model=3
К сожалению в языках программирования я не очень хорошо разбираюсь, можно представить как-нибудь более наглядно как это сделать?
Спасибо.
window.location.href = ‘url.php?c=’ + $(‘#country’).val() + ‘&a=’ + $(‘#auto’).val() + ‘&m=’ + $(this).val();
Я так понял что это надо было вставить сюда:
$(‘#country’).change(function(){
adjustAuto();
}).change();
$(‘#auto’).change(adjustModel);
$(‘#model’).change(function(){
if($(this).val().length != 0) { alert(‘Выбор сделан!’); }
});
вместо алерта, но я пробовал убрать алерт и не заработал выпадающий список, подскажите так ли я заменил
$(‘#country’).change(function(){
adjustAuto();
}).change();
$(‘#auto’).change(adjustModel);
$(‘#model’).change(function(){
if($(this).val().length != 0) { window.location.href = ‘url.php?c=’ + $(’#country’).val() + ‘&a=’ + $(’#auto’).val() + ‘&m=’ + $(this).val(); }
});
а нет, все теперь заработало, ошибка была в кавычках =)
Gennady, я столкнулся с проблемой автоматического выделения первых пунктов в select-ах, таким образом пытаюсь достичь автоматического заполнения всех подчиненный select-ов, в зависимости от выбора в старших select-ах, пожалуйста подскажите как это сделать…
>> я столкнулся с проблемой автоматического выделения первых пунктов в select-ах…
Я сначала подумал, что у Вас опции в select’ах сами вдруг выбираться начали….
Подскажу в каком направлении думать:
Вы не только можете получить значение выбранной опции элемента select, но и установить это значение для нужного элемента:
$(‘#country’).val(‘2′);
Таким образом будет выбрана опция со значением Ю.Корея. Далее по аналогии…
Gennady, я хотел бы все select’ы связать друг с другом, т.е выбирая значение в первом select’е, происходит изменения в третьем…а именно чтобы значения второго и третьего select’а зависили от выбранного элемента в первом, предположим что мы уберем из вашего примера неактивные элементы «выбрать страну» и «выбрать автомобиль» хотелось бы сделать так: при загрузке формы автоматически выделяется первый элемент первого select’а «Германия» и заполняется второй select, и в нем снова выделятся(активируется) первый элемент, тут «Audi», далее заполняется третий select :»A4″,»Q7″,»TT». А при выборе любого другого элемента в первом select’e значения остальных двух select’ов менялись соответственно…
To: Андрей, Pavel
Ребята, давайте без обид… Я дал направление в котором надо думать, но решать за Вас Ваши задачи я не буду. Это – принципиально. Задача блога не выдавать каждому его готовые решения, а научить решать задачи самостоятельно.
Gennady, а можно ли каким-нибудь хитрым образам вновь создаваемым элементам SELECT присваивать какой либо id?
Почему хитрым? Вы же можете создать любой элемент и добавить ему необходимые атрибуты. Ну, например:
$("body").append("<select id='someid'></select>");Но вообще-то в статье не шла речь о создании select’ов. Говорилось о заполнении select’ов элементами option.
тяжело соображалось, и я неправиль выразился :о)
я имел ввиду именно создаваемым option`ам добавить id. :о)
Очень хорошой пример, но одна проблемка, пытаюсь переделать под кодировку windows-1251 с utf-8 и скрипт перестает работать, не подскажите как грамотно можно решить проблему?
Gennady, а как сделать так, чтобы вместо последнего select’а появлялась форма типа checkbox, в случае если пользователю нужно будет выбрать несколько моделей для сравнения?
To selex:
Такие проблемы решаются перекодировкой данных на стороне сервера. Поглядите статью Как работать с JSON?, в комментах к ней проблема обсуждается…
To Андрей:
Дополняйте функцию adjustAuto(), т.е. при получении данных от сервера анализируйте их, создавайте на их основании нужное количество чекбоксов и добавляйте их в DOM.
Спасибо за статью..
Подскажите, как вместо get использовать POST при передаче ?
Вопрос отпадает, почитал и понял что getJSON использует только GET
Cпасиб!
Gennady все получилось!! Огромное спасибо, переделал скрипт под себя.
Еще хотелось бы сделать, что в момент отправки данных с второго списка, на третем отображалась какая нибудь картинка типа «Ждем ответ от сервера».
Читал что это можно сделать с помощью beforeSend:
но как применить в вашем примере, не знаю(
При использовании именно $.getJSON это не получится. Вместо $.getJSON надо просто использовать $.ajax(options). Примерно так:
$.ajax({ url: 'cascadeSelectAuto.php', // обработчик data: 'country=' + countryValue, // данные dataType: 'json', // тип данных, ожидаемых в ответе beforeSend: function(){ ... // показываем сообщение }, success: function(data) { ... // скрываем сообщение tmpSelect.fillSelect(data).attr('disabled',''); adjustModel(); } });Аналогично можно сделать и при выборе модели.
Gennady спасибо еще раз..
Вот переделал ваш пример. Но в вашем примере в обработчике под value Страны есть value(значения) всех автомобилей.. При єтом первое значение пустое (Выберите автомобиль).
В моем же случае выборка идет з БД и есть случаи когда например под value «Страна» нету значения для «автомобиль». Как результат я получаю от обработчика только —— []—— (квадратные скобки) – это из за того что мне пришлось изменить «ответ» под функцию function(data). Так как данные не обрабатываются если они не заключены в квадратные скобки..
Как результат, я получаю пустой второй селект «Автомобиль».
Как мне сделать, что в случае если я получил —— []——, то второй селект был disabled и быда надпись «Данные отсутсвуют»?
Заранее благодарен!!
Не проще ли обработку такого случая на сервере сделать? И данных меньше передавать придется…
Спасибо! Сделал.. Теперь если у меня отст. значения то я получаю value «0″ text «Значение отсутствует»
Но проблема в IE. Не зависимо от параметра первого первого списка, второй в Disabled и все остальные.
Пример 4 selecta
————
1. Страна
2. Область
3. Город
4. Курорт
————
В Лисе и Осле При выборе 1. Страна >
Область и Город заполняются автом. ( если есть значения) Курорт остается в Disabled и не обновляется . Тут мне так и нужно…
В IE выходит что при выборе 1. Страна >
Область обновляется но находится в Disabled.
Город и Курорт не обновляются и тоже в Disabled.
IE 7.0
Что это?
Господа, как сделать, чтобы значения select’ов model и auto добавлялись в querystring при нажатии на кнопку отправки формы?
Вопрос снят
Gennady помоги пожалуйста составить «function» для кнопки с обработчиком onClick, которая бы брала переменную с последнего списка и отправляла бы его на какой-нибудь php-файл для дальнейшей обработки.
$('button').click(function(){ var data = $('#model').val(); $.ajax({ url: 'some.php', data: data, success: function(answ){ alert(answ); } }); });ого спасибо, скажи а если php-код-обработчик находится на этой же странице, тогда как функции «click» указать что бы она переменную отправляла в этот php-код, которой бы предположим для начало вывел бы ее просто на экран по средством например «print»?
Gennady, а что означает success: function(answ)? откуда это берется?
success – одна из опций вспомогательной функции $.ajax, function(answ) – callback-функция, которая будет вызвана при наступлении ajax-события success, т.е. получения успешного ответа от сервера. Ну а answ – данные, полученные в качестве ответа сервера.
p.s. Серверный обработчик делают отдельно, иначе какой смысл в использовании ajax?
еще раз спасибо)) твой блог супер!
Gennady, извини за навязчивость, обещаю последний раз)),
но что-то я никак не могу написать код на стороне сервера, принцип и последовательность понял, а вот грамматику не совсем… у меня из последнего списка выходит примерно такая переменная: x_xx_xxx_xxxx_xxxx (она и несет в себе все информацию), я ее пытаюсь эксплодить по символу «_», чтобы вместо этой одной переменной получить на выходе пять, но что-то никак не выходит, помоги пожалуйста))
А зачем делать лишние телодвижения? Ведь передача данных с помощью ajax все равно подразумевает методы GET или POST. Просто на стороне клиента постройте обычную строку запроса (как при использовании GET). Например:
Далее, в опции data вспомогательной функции $.ajax указываете:
data: myData,
method: ‘POST’,
…………….
ну и так далее.
На сервере обрабатываете эти данные как обычный POST-запрос:
if($_POST) { $a = $_POST['a']; $b = $_POST['b']; $c = $_POST['c']; }Gennady, а эту строку запроса нужно встраивать в нашу «$(‘button’).click(function()», или же надо писать для нее отдельную функцию? в первом случае все ясно при нажатии кнопки скрипт берет выделенную переменную из последнего списка и отправляет ее посредством ajax на php, и «function(answ)» срабатывает при получении ответа. A теперь куда дописать строку запроса, чтоб не нарушить последовательность? как совместить data: data,
и
data: myData, ?
В первом случае (это же всего лишь пример) я показал как взять значение из списка и отправить на сервер. Одно значение. Тоже самое и тут, только надо собрать уже все нужные значения, построить из них строку запроса и отправить серверу.
В общем, ответ на вопрос: нужно встраивать в нашу $(‘button’).click(function()’
Gennady, не понимаю, что я делаю не так?
if($_SERVER['HTTP_X_REQUESTED_WITH']==’XMLHttpRequest’) {
$str = $_GET['data'];
$new_array = explode(«_», $str);
print_r($new_array);
}
Давайте поточнее. Проблема в чем именно? Вы не видите массива $new_array или что? Я так подозреваю, что Вы очень буквально поняли пример, где показано как получить данные из выбранного пункта списка. Наверное мне надо было более точно расписывать.
Поменяйте
var data = $(‘#model’).val();
на
var data = ‘data=’ + $(‘#model’).val();
тогда на сервере Вы и получите эти данные.
Очень хорошая статья. Использовал приведенный пример в своей разработке. Хотел спросить не приходилось ли вам решать задачу со связанными таблицами. Т.е. выбирая срочку в одной из таблиц, в другой таблице меняется содержимое?
спасибо все заработало)))
Здравствуйте.
Отличный пример, очень понравился. Но в результате доработки(точнее переделки) возникли проблемы, поэтому я хочу задать вопросы, ответы на которые возможно помогут мне решить проблему:
1) Возможно ли использование только одной функции? К примеру я использую только 2 селекта. Первый уже заполнен, второй как раз таки нуждается в заполнении.
2) Шаг за шагом переделал все под свой вариант. Но возникли проблемы – не заполняется второй элемент селект (при выборе элемента из 1го селекта). Точно знаю что данные передаются в функцию и передаются скрипту, который работает с базой и возвращает все данные в формате JSON. В чем загвоздка может быть?
3) В своем скрипте для вызова функции использовал только одну функцию:
$('#categ').change(function(){
adjustObject();
}).change();
Правильно ли это?
Вопрос снят.
Gennady, а каким образом нужно дополнить «function adjustAuto» что бы вместо последнего списка появился checkbox, можете на примере показать?
Вместо последнего? Тогда наверное adjustModel() имелась ввиду? И как это – вместо списка чекбокс, один только? Я пока не очень понял, что Вы хотите реализовать, если множественный выбор, то почему не добавить в select всего лишь атрибут multiple?
я тоже сначала подумал о multiple, вот только пользователь может так и не узнать, что у него в последнем списке была такая возможность, как множественный выбор, а с checkbox все ясно: все знают что такое галочки… Я хочу реализовать подбор различной комплектации выбранной модели.
Понятно. Тогда не морочтесь ни с какими изменениями. Каскад списков – он и есть каскад… Найдите в коде место, где по выбору модели вызывается
alert(‘Выбор сделан!’);
и вместо alert’а напишите свою функцию, которая обратиться к отдельному обработчику на сервере и подгрузит то, что Вам нужно (и куда нужно) через ajax. Будет намного проще, чем что-то менять – нужно будет просто дополнить.
Gennady, если бы я смог написать такую функцию, да и тому же еще обработчик на сервере, то я точно бы не мучил бы вас в вашем блоге)) если вам не сложно вы бы могли показать как это выглядит для вашего примера, вместо списка «модели» встроить checkbox…
Как можно в данном скрипте сделать два нововведения?
1. чтобы первый список так же брался из БД
2. Чтобы при выборе конечного значения из БД отдавалось некоторое значение.
а как загрузить список с помощью ф-ии реализованной на java? (для вывода информации использую jsp)
Андрей & Илья! Ребята, не обижайтесь, но Вы хотите, чтобы я сделал за Вас Вашу работу. Но у меня своей по горло и выше.
Понимаете, я только показал пример, общий подход, принципы. Не ждите от меня, чтобы я каждому написал кусок кода именно под его нужды.
Т.е. это своего рода принцип моего блога – делиться знаниями, а не решать чужие задачи.
To: Ольга
Если Вы используете JSP чтобы просто сгенерировать HTML на сервере, то никаких принципиальных отличий от того же PHP наверное и нет, верно?
Если же Вы про внедрении java-кода в содержимое страницы – не знаю, поскольку практически не знаком с технологией.
а как бы это все к БД подключить?
Написать серверный сценарий, который будет, получая соответствующий запрос, выбирать их из БД.
а пример можно?
Но пример чего? SQL-запроса к БД?
$items=$dbh->prepare("SELECT * FROM table");$items->execute();
$a = $items->fetchAll();
foreach ($a as $row){
....
}
* – в примере используется PDO.
Уважаемый Gennady!
Сайт у Вас то что надо! Особенно новичку. Я с javascript почти не работал, а тем более с библиотеками типа jquery и прочими.
У меня возникла такая необходимость и в принципе во многом разобрался, но…
Делаю список авто->модель
Подключил все к базе, причем первый список для value берет из нее id, во второй загоняю строку через implode. Вкратце:
$json[id] = implode(‘,’,$model);
print ‘['.$json[id].’]';
Но когда в cascadeSelectAuto.php вызываю функцию обработки базы, ничего не работает.
Пошел другим путем: В массиве сначала кэшируются данные models от [id]->parent-auto и в cascadeSelectAuto.php просто отображается строка массива от [id], что в принципе тоже самое, только уже без запросов к базе. Тоже не работает!
Потом обнаружил что если есть еще какие-то данные передаваемые браузеру, то скрипт просто не видит их как ’select’.
Собственно вопрос: как заставить java-скрипт брать не все, а только то что нужно? Или это можно обработать другой командой?
Или проще! Как java-скрипту правильно обработать не все данные, отдаваемые cascadeSelectAuto.php, а именно переменную $json ?
У меня ощущение, что Вы не очень знакомы с форматом JSON…
Можете почитать это: Что такое JSON? и Как работать с JSON?.
Лучше конечно же разобраться – всегда пригодится. Или тогда использовать у себя на сервер-сайде точно такой же формат вывода данных как в примере:
[{value:"",text:"Выбрать модель"},{value:"1",text:"Astra"},{value:"2",text:"Corsa"},{value:"3",text:"Vectra"}]‘
Тогда все будет обрабатываться как надо.
Я немного разобрался. Если вывести переменную на экран, то именно такой формат и есть.
Вызываю функцию из другого php-скрипта:
$autos = array();
foreach ($parentid as $row) {
…….
$autos[] = ‘{value:»‘.$row->id.’»,text:»‘.$row->name.’»}’;
…….
}
$models[$id] = implode(‘,’,$autos);
В cascadeSelectAuto.php набираю
print ‘['.$models[$id].’]';
и ничего!
Но если до этого в самом cascadeSelectAuto.php
присвоить $models[$id] = [{value:”",text:”Выбрать модель”},{value:”1″,text:”Astra”},{value:”2″,text:”Corsa”},{value:”3″,text:”Vectra”}];, скрипт его видит как надо. Не работает переменная извне!
Если со скрипта передается еще что-то помимо этого клиенту, то скрипт его не распознает по всей видимости. Достаточно в cascadeSelectAuto.php ввести еще что-то типа «print 1;» или «echo что-нибудь;» например или вызвать стороннюю функцию.
А так как я действительно мало знаком с JSON, я и прошу помочь.
Подскажите как передать из cascadeSelectAuto.php массив и чтобы скрипт именно его и обрабатывал помимо других данных.
Может я где-то правильно понимаю, где-то нет, но уже неделю бьюсь. Без примера трудно.
… Если со скрипта передается еще что-то помимо этого клиенту, то скрипт его не распознает по всей видимости….
И это правильно, потому что на клиенте используется getJSON, который ожидает данные именно в таком формате. Если формат не соблюден – вполне естественно, что ничего и не заработает.
…. В cascadeSelectAuto.php набираю print [’.$models[$id].’]’; и ничего! …
Значит проблема в php-коде. В файле cascadeSelectAuto.php закомментируйте строку, где проверяется условие существования объекта XMLHttpRequest и пробуйте его вызывать в браузере – Ваш print ‘[’.$models[$id].’]’; должен вернуть данные в формате JSON и Вы должны их увидеть на мониторе. Когда этого добьетесь, тогда и заработает.
Пробовал убрать проверку. Тоже самое.
Могу на мониторе увидеть строку при закоментированной …XMLHttpRequest…, когда в основном скрипте подключаю его через ‘include’
У меня вроде задача простая так чувствую.
$.getJSON передает в cascadeSelectAuto.php value = ‘$id’, тот в свою очередь вызывает функцию обработки базы. Через implode пакую строку с данными от ‘parentID’, переменная возвращается в cascadeSelectAuto.php и ‘print или echo’ результата. Но как не бьюсь, не получается.
Думаю я где-то логику недопонимаю.
еще! в браузере видно, а в списке нет!
здравствуйте,
а возможно сделать так что бы поля были активными и заполнялись автоматически т.е. допустим что поля ввода у нас стоят в обратном порядке (Модель,
Автомобиль,Страна). Тогда первое поле будет Модель и при её заполнении остальные поля автоматически заполняются. Подскажите пожалуйста как осуществить мой замысел.
заранее спасибо
Gennady …. расскажи просто принцеп код можешь не писать )
спасибо
Хм, если первое поле – модель, то при выборе одной-единственной модели, названиями каких автомобилей будет заполнен второй список? По логике – только одним названием. И третий список – тоже, только одной страной. И зачем тогда каскад списков нужен? Может быть можно реализовать как-то иначе? Озвучьте задачу – попробуем вместе алгоритм придумать…
To Alexandr:
Мы можем так долго писать какие-то детали и не выяснить главного…. Как совет – пробуйте на каком-либо очень простом примере разобраться в принципе с ajax-запросами (это совсем-совсем несложно) и понемногу усложняйте примеры. Даю гарантию, что через несколько часов Вы просто «почувствуете» как данные уходят на сервер и как возвращаются в клиент.
Конечно это надо весь код выложить тут. Не буду обременять и буду разбираться сам.
Главное, что здесь можно найти ответы на некоторые вопросы, описания которых в сети найти не просто.
Спасибо.
допустим у нас есть некая форма в которой все поля(напимер унас их 3) input type=»text».
-Поле 1-марка уля
-Поле 2-теплота
-Поле 3- летучие
в поле «Марка угля» есть автозаполнение, и если при вводе, в списке автозаполнения, находится известная мака угля, то поле 2,3 заполняются автоматически, теми параметрами которые относятся к конкретной марке угля.
Вот такая вот задачка…
Геннадий, у вообще какая то митсика с этим скриптом.
Расказываю..
Три селекта.
Все заполняются с MySQL.
Смысл заполнения, один и тот же
Данные селекта передаютсья обработчику, он далает запрос к бд и возвращает необходимые стоки для заноса во второй селект..
Вот так:
0){
if($name_city)
{
print «[";
// Так как запрос возвращает несколько строк, применяем цикл
while($name_city_s = mysql_fetch_array($name_city))
{
print "
{value:\"".$name_city_s['itemid_city'].»\»,text:\»".$name_city_s['name_city'].»\»}, «; //создаем цеклический список
}
print «]»;
}
else
{
echo «Error: «.mysql_error().»«;
exit();
}
} else { echo «[ {value:\"\",text:\"Данные еще не внесены\"}, ]«; } // вывод сообщения если строк в базе нет
}
//——————————————————————————
?>
Вот так формируется строка которая отдается на Ajax
print «[";
// Так как запрос возвращает несколько строк, применяем цикл
while($name_city_s = mysql_fetch_array($name_city))
{
print "
{value:\"".$name_city_s['itemid_city'].»\»,text:\»".$name_city_s['name_city'].»\»}, «; //создаем цеклический список
}
print «]»;
В результате получаем на выходе к примеру
[
{value:"843",text:"Алупка"},
]
Если строка не будет иметь такой вид
{value:»843″,text:»Алупка»},
то данные не обработаются вторым селектом. Так же?
У меня все работало. Потом начала добавлять новые данные в SQL. Добавлял одним и тем же способом.
Когда добавил первый список (около 1000 записей), все продолжало работать.
Потом тем же способо добавляю еще хоть одну запись, и все.
Ответ от php обработчика не Ajax приходят в таком виде:
{value:»841″,text:»Алупка»
},
{value:»843″,text:»Алушта
«},
Строка просто рвется, соответсвенно второй селект не может обработать, так как нарушена структура.
Чего так, даже ума не приложу.
Одна база
Один и тот же обработчик
Записи вносились в базу одним и тем же способом.
Но одни данные нормально приходят, а вот эти в таком виде.
Даже не знаю с какой стороны подойти, где искать ошибку..
Скоро как ребенок плакать буду..
Геннадий, очень прошу.. Хоть тыкните меня носом куда нибуть..
Заранее благодарен.
Ну у Вас и списки…. Смысл каскада в том, чтобы разделить данные, сделать более удобным и компактным выбор… Ну, да ладно – это отступление.
Поскольку я писал всего лишь пример, поэтому и данные брал не из реальной базы, а выдуманные из головы.
Что можно посоветовать – попробуйте использовать какой-либо существующий инструментарий на стороне сервера. Если на сервере php5, то в большинстве случаев он собран с поддержкой json. Если php4 – можно воспользоваться утилитой JSON-PHP.
Об этом можно почитать статьи: Что такое JSON? и Как работать с JSON?
To GTi:
Но тогда задача Ваша всего лишь в том, чтобы в кое-каких местах убрать воздействие на атрибут disabled select’а и самое основное – по выбору в первом select’е должны выполняться сразу оба запроса к серверу. Можно состряпать это и в одном запросе, конечно соответствующим образом написав обработчик на сервере и позаботившись о разделении возвращенных данных в клиенте по какому-либо признаку.
Спасибо Геннадий. Уже нашел проблему. Она была в неправильном вводе данных в бд. При вводе, писались пробелы, которые визуально нельзя было определить…
Добрый день,
хочу использовать предложенный Вами метод на Битриксе
$.ajax({…});
В IE всё замечательно работает, а в Опере и в FF в результат попадает не строка типа json, а вся страница
Так понимаю, вся беда случается из-за подключения хеадера Битрикса (а без него невозможно работать с API Битрикса)
очистка буфера типа
ob_clean();
ob_end_clean();
не помогает
Не подскажете, как можно решить проблему?
Вопрос снят
как бы прикрутить четвёртый уровень селекта?
вопрос отпал. спасибо за замечательный скрипт
Спасибо за скрипт. одна проблема – это пытаюсь во второй список вставить что-то вроде selected (чтобы при редактировании записи подгружался список соотв. модели и выставлялась ранее выбранная марка. сейчас покопаюсь в доке, но вдруг кто отпишет до того, как решение найду?:)
Заранее спасибо.
Большое человеческое спасибо, Gennady, за статью!
Скажите, пожалуйста, какой командой в конце можно вытащить (с отображением на экране) результат суммы всех 3-ёх value выбранных option’ов?
Фенкс.
alert($("#country option:selected").text() + ' ' + $("#auto option:selected").text() + ' ' + $("#model option:selected").text());в примере я привел вывод информации в alert, но это непринципиально, можно вставить полученные данные куда-то еще. Главное определиться куда
….
А, вопрос-то невнимательно прочитал – сумма value’ев нужна была? В общем примерно тоже самое:
alert($("#country option:selected").val() + $("#auto option:selected").val() + $("#model option:selected").val());только потом эту строку в число преобразовать…
Gennady, а как передать эту сумму в переменную php, Либо как мне вывести по средствам ajax на экран:
Сумма равна=столько-то. ?
Спасибо за ответы!
Сори, с выводом по средствам ajax понятно. Вопрос снимается:)
«только потом эту строку в число преобразовать…»
Как это делается?
В JS с помощью + объединяют строки и складывают числа. В моем примере, в случае скажем value’в 1,2 и 3 Вы получите не ожидаемые 6, а именно строку 123.
Добавьте в этом примере еще – 0 (минус 0) и JS вернет уже число.
Уважаемый, Gennady!
Не могли бы Вы написать код вывода суммы?
Заранее спасибо.
Ок, чтобы не путаться – делайте так:
var summ= Number($("#country option:selected").val()) + Number($("#auto option:selected").val()) + Number($("#model option:selected").val());проято явно указываем тип данных и в переменной summ искомая сумма…
Извините, комментирование этой статьи завершено.