Как это реализовано
Для начала нам нужна база городов. Скачать базу в формате SQL можно здесь.
Клиентская часть
Посмотреть клиентский код можно здесь.
AJAX у меня реализован через известную библиотеку jQuery. При выборе страны (или региона) отсылаем серверному скрипту 2 параметра методом POST:
id – id объекта (страны или региона)
type – тип списка, который нужно получить (города или регионы)
<script type="text/javascript">
function getList(type, obj) {
$("#loading_" + type).show(); // запускаем крутящееся колесико
$.post("/ajax/city.php", {type: type, id: $("#"+obj).val()}, onAjaxSuccess);
function onAjaxSuccess(data) {
out = document.getElementById(type);
for (var i = out.length - 1; i >= 0; i--) {
out.options[i] = null;
}
eval(data);
$("#loading_" + type).hide(); // скрываем крутящееся колесико
}
}
</script>
Во время обращения к серверному скрипту следует оповестить пользователя о том, что идет какой-либо обмен данными (показываем крутящееся колесико загрузки). Индикация во время обмена данными в Web 2.0 играет очень важную роль: посетители могли еще не привыкнуть к таким способам обновления страницы.
Серверная часть
Как только на сервер пришел запрос от клиента (параметры id и type), мы формируем либо список регионов, либо список городов и отправляем его клиенту. Список формируется в виде js-объекта Option а затем, когда ответ пришел клиенту, то этот ответ (текстовая строка) выполняется через eval и получается полноценный html-код из option. Изначально я сразу формировал html-код из option, но в одном из браузеров (по-моему, IE6) он не хотел вставляться в select, поэтому пришлось использовать извращение eval().
<?php
include($_SERVER['DOCUMENT_ROOT'].'/include/config.php');
include($_SERVER['DOCUMENT_ROOT'].'/include/db.php');
$id = (int)$_POST['id']; // id объекта (страна или регион)
$type = $_POST['type']; // тип списка, который нужно получить (города или регионы)
sleep(1); // спешить нам некуда
if ($type == 'city') {
// выбираем города в данном регионе
$cities = $DB->select('SELECT *
FROM city
WHERE region_id = ?d
ORDER BY name', $id);
if (!empty($cities)) {
echo "out.options[out.options.length] = new Option('выберите город...','none');\n";
foreach ($cities as $city) {
echo "out.options[out.options.length] = new Option('".$city['name']."','".$city['city_id']."');\n";
}
}
else {
echo "out.options[out.options.length] = new Option('нет городов','none');\n";
}
}
if ($type == 'region') {
// выбираем регионы в данной стране
$regions = $DB->select('SELECT *
FROM region
WHERE country_id = ?d
ORDER BY name', $id);
if (!empty($regions)) {
echo "out.options[out.options.length] = new Option('выберите регион...','none');\n";
foreach ($regions as $region) {
echo "out.options[out.options.length] = new Option('".$region['name']."','".$region['region_id']."');\n";
}
}
else {
echo "out.options[out.options.length] = new Option('нет регионов','none');\n";
}
}
?>
Для выборки данных из базы я использую библиотеку DBSimple (в коде объект $DB). Вы можете легко переделать работу с базой данных под свой код. Запросы элементарные, так что разберетесь.
sleep(1) – замораживает выполнение скрипта на 1 секунду. Я это сделал специально, чтобы можно было увидеть крутящееся колесико при загрузке.
Загрузка...

имели ли опыт с JSON ?
используя json, в этом примере код можно сделать менее избыточным
Да, с JSON имел опыт. Но этот код писался в 2008 году, поэтому переделывать его влом:)
Кстати, JSON активно используется в Контакте.
Вконтакте не очень :)
на такие запросы они выдают готовый html, как я понимаю, закешированный в nginx
Поиск людей, список друзей в Контакте сделан через JSON. По-моему даже API у них выдает списки в виде json.
Спасибо, Серёж!
Полезный у тебя сайт.
Последнее время часто натыкаюсь.
А нельзя выложить готовые скрипты в архиве как это было сделано с sql базой городов?
Да, где конфиг, где db.php
Что такое out.options[out.options.length] и где функция Option ? В каком виде должен содержаться ответ от city.php ?
в нем должен быть уже html список ?
Разобрался. Но така как не было библиотеки DB то воспользовался штатными средствами cms для запросов. потом еще были проблемы с кодировкой, т.к. сайт в windows-1251, но помог $id=iconv("UTF-8", "windows-1251", $id); в city.php
http://blog.wel.org.ua/index.php/2010/08/есть-где-взять-названия-городов-насел/
Для выборки данных из базы я использовал PDO, у автора пример с DBSimple.
Жду предложений