|
Статьи.
AJAX — реализация связанных списков
Связанные списки это два или более списка. Выбор значения в одном из них влияет на содержание остальных. Такие списки очень удобны, если вам надо выбрать некий объект с определенными характеристиками.
Пример: Вы заходите на сайт автосалона и хотите выбрать машину и вы уже знаете какая модель и какого цвета вам нужна. Естественно, что не все сочетания моделей и цветов есть в наличии. Поэтому, будет гораздо удобнее, выбрав модель машины в одном списке, сразу же посмотреть имеющиеся в наличии цвета данной модели.
Самым простым было бы показывать пользователю два списка. В первом — все модели машин, во втором —все цвета, независимо от их наличия.
Здесь есть две проблемы. Первая проблема заключается в том, что несколько раз выбрав отсутствующие в наличии комбинации модели и цвета, пользователь очень быстро устанет и пойдет на другой сайт. Вторая проблема — паразитивная нагрузка на сервер при выборе несуществующих комбинаций.
Рассмотрим три варианта реализации связанных списков. Для написания примеров мы будем использовать XHTML, JavaScript и PHP.
Классическая реализация
Заходя на страницу, пользователь видит два списка: с названиями моделей и названиями всех возможных цветов. При выборе конкретной модели и цвета происходит запрос к серверу, затем создается выборка из базы данных имеющихся цветов выбранной модели и генерация новой страницы.
Вместо базы данных мы будем использовать PHP массивы c набором цветов для каждой модели.
Пример кода:
<body>
<?php
// Проверка, пришли ли данные из формы
if ( $_GET["models"] ) {
// Как бы выборка из базы данных
$colorsArray = array(
"BentleyAzure"=>array("red"=>"Красный", "green"=>"Зеленый"),
"ChevroletCorvette"=>array("black"=>"Черный", "blue"=>"Синий"),
"FerrariEnzo"=>array("green"=>"Зеленый", "black"=>"Черный", "yellow"=>"Желтый")
);
$colors = $colorsArray[$_GET["models"]];
// Проверка на доступность модели этого цвета
if ( array_key_exists($_GET["colors"], $colors) ) {
echo '<p style="color:#090">Модель такого цвета есть в наличии</p>';
} else {
echo '<p style="color:#900">Модель такого цвета отсутствует</p>';
}
}
?>
<form action="#" method="GET">
Модели
<select id="models" name="models">
<option value="BentleyAzure">Bentley Azure</option>
<option value="ChevroletCorvette">Chevrolet Corvette</option>
<option value="FerrariEnzo">Ferrari Enzo</option>
</select>
<br/>
Цвета
<select id="colors" name="colors">
<option value="red">Красный</option>
<option value="black">Черный</option>
<option value="green">Зеленый</option>
<option value="blue">Синий</option>
<option value="yellow">Желтый</option>
</select>
<br/>
<input type="submit" value="Выбрать" />
</form>
</body>
Недостатки такого подхода:
- Пересылка клиенту всего HTML кода страницы вместо списка цветов имеющихся в наличии.
- Пользователю придется ждать некоторое время, пока данные придут с сервера и отрендерятся в браузере.
JavaScript реализация
Естественно, хотелось бы, не заставляя пользователя долго ждать, менять содержимое списка с цветами динамически.
Для этого, сделав выборку из базы данных, на сервере следует создать JavaScript массив с имеющимися в наличии цветами для каждой модели. И написать функцию, меняющую содержание списка цветов в зависимости от выбранной модели.
Пример кода:
<head>
<title>Связанные списки</title>
<script type="text/javascript">
// Данные, как бы из базы, сформированные на стороне сервера.
// Обычно находятся в подключаемом JavaScript файле.
var colorsArray = {
BentleyAzure : {red:"Красный",green:"Зеленый"},
ChevroletCorvette : {black:"Черный",blue:"Синий"},
FerrariEnzo : {green:"Зеленый",black:"Черный",yellow:"Желтый"}
}
// Функция, заполняющая список цветами доступными для выбранной модели.
function getColors(_this){
var colors = colorsArray[_this.value];
var _select = document.getElementById("colors");
_select.innerHTML = ""; // Удаляем всех потомков.
for(var i in colors){ // Добавляем доступные цвета.
var option = document.createElement("option");
var optionText = document.createTextNode(colors[i]);
option.appendChild(optionText);
option.setAttribute("value",i);
_select.appendChild(option);
}
// Делаем список цветов видимым.
_select.style.display="inline";
}
</script>
</head>
<body>
<form action="#" method="get">
Модели
<select id="models" name="models" onchange="getColors(this)">
<option value="BentleyAzure">Bentley Azure</option>
<option value="ChevroletCorvette">Chevrolet Corvette</option>
<option value="FerrariEnzo">Ferrari Enzo</option>
</select>
<br/>
Цвета
<select id="colors" name="colors"></select>
<br/>
<input type="submit" value="Выбрать" />
</form>
</body>
Недостатки такого подхода:
- Объем такого массива может быть очень большим и не все данные могут понадобиться пользователю.
- С момента создания массива до момента, когда пользователь выберет подходящую ему по цвету модель, может пройти значительное время и данные на сервере могут измениться. В результате пользователь может выбрать комбинацию модель-цвет, которой уже нет в наличии.
AJAX реализация
С точки зрения usability и минимизации количества данных передаваемых от сервера клиенту, наилучшей будет AJAX реализация.
Для этого мы напишем небольшое JavaScript приложение, которое в ответ на выбор определенной модели, будет динамически менять содержание списка с цветами, загружая данные о цветах с сервера, используя AJAX. Но, сначала, сделаем так, чтобы все цвета присутствовали в списке и напишем проверку с помощью PHP - на случай, если пользователь выберет несуществующую комбинацию. Это нужно для того, чтобы пользователь в любом случае имел возможность выбора, даже если его браузер не поддерживает JavaScript или AJAX.
Пример кода:
<body>
<?php
// Проверка, пришли ли данные из формы
if ( $_GET["models"] ) {
// Как бы выборка из базы данных
$colorsArray = array(
"BentleyAzure"=>array("red"=>"Красный", "green"=>"Зеленый"),
"ChevroletCorvette"=>array("black"=>"Черный", "blue"=>"Синий"),
"FerrariEnzo"=>array("green"=>"Зеленый", "black"=>"Черный", "yellow"=>"Желтый")
);
$colors = $colorsArray[$_GET["models"]];
// Проверка на доступность модели этого цвета
if ( array_key_exists($_GET["colors"], $colors) ) {
echo '<p style="color:#090">Модель такого цвета есть в наличии</p>';
} else {
echo '<p style="color:#900">Модель такого цвета отсутствует</p>';
}
}
?>
<form action="#" method="GET">
Модели
<select id="models" name="models">
<option value="BentleyAzure">Bentley Azure</option>
<option value="ChevroletCorvette">Chevrolet Corvette</option>
<option value="FerrariEnzo">Ferrari Enzo</option>
</select>
<br/>
Цвета
<select id="colors" name="colors">
<option value="red">Красный</option>
<option value="black">Черный</option>
<option value="green">Зеленый</option>
<option value="blue">Синий</option>
<option value="yellow">Желтый</option>
</select>
<br/>
<input type="submit" value="Выбрать" />
</form>
</body>
Теперь мы обеспечили доступность нашего интерфейса пользователям тех браузеров, где отключен JavaScript или не поддерживается AJAX.
Напишем небольшой PHP скрипт, отдающий по AJAX запросу доступные цвета машин в формате XML.
Пример кода:
<?php
header('Content-Type: text/xml; charset=windows-1251');
$request = $_GET["models"];
if($request) echo loadData($request);
function loadData($request){
// Функция, как бы делающая выборку из базы.
if($request == "BentleyAzure") {
$result = '<color value="red">Красный</color><color value="green">Зеленый</color>';
} elseif ($request == "ChevroletCorvette"){
$result = '<color value="black">Черный</color><color value="blue">Синий</color>';
} elseif ($request == "FerrariEnzo") {
$result = '<color value="green">Зеленый</color>
<color value="black">Черный</color>
<color value="yellow">Желтый</color>';
}
if($result) return $result = '<?xml version="1.0" encoding="windows-1251"?>
<colors>'.$result.'</colors>';
}
?>
И теперь, собственно, AJAX. Наше AJAX приложение будет состоять из двух частей: первая часть будет выполнять AJAX запрос к написанному ранее скрипту ajax.php, а вторая часть обрабатывать полученные данные и записывать их в список цветов.
Для получения данных от сервера мы используем объект XMLHttpRequest . Проблема в том, что его синтаксис и название в разных браузерах неодинаковы. Поэтому мы воспользуемся готовой функцией, предоставляющей кроссбраузерное решение работы с этим объектом.
Пример кода:
// Функция, осуществляющая AJAX запросfunction loadXMLDoc(method, url) {
if(window.XMLHttpRequest) {
req = new XMLHttpRequest();
req.onreadystatechange = processReqChange;
req.open(method, url, true);
req.send(null);
} else if (window.ActiveXObject) {
req = new ActiveXObject("Microsoft.XMLHTTP");
if(req) {
req.onreadystatechange = processReqChange;
req.open(method, url, true);
req.send( );
}
}
}
// Функция, выполняемая при изменении статуса
// запроса, если статус равен 200, данные получены
function processReqChange() {
if(req.readyState == 4) {
if(req.status == 200) {
getColors(req.responseXML.documentElement);
} else {
alert("There was a problem retrieving the XML data:\n" + req.statusText);
}
}
}
Не будем вдаваться в подробности реализации AJAX запроса. Укажем лишь, что функция loadXMLDoc осуществляет запрос HTTP методом, переданным ей в качестве параметра по указанному URL. Функция processReqChange выполняется как только придет ответ от сервера. В случае, если данные пришли и HTTP статус равен 200 т.е. «OK», данные передаются в виде XML в функцию getColors .
Осталось только распарсить XML данные с сервера, и вписать их в список доступных цветов.
Пример кода:
<head>
<title>Связанные списки</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
<style type="text/css">
fieldset{width:10em;display:block;padding:.5em}
select{width:10em}
</style>
<script type="text/javascript">
// Функция, осуществляющая AJAX запрос.
function loadXMLDoc( method, url ){
if ( window.XMLHttpRequest ) {
req = new XMLHttpRequest();
req.onreadystatechange = processReqChange;
req.open(method, url, true);
req.send( null );
} else if ( window.ActiveXObject ) {
req = new ActiveXObject( "Microsoft.XMLHTTP" );
if ( req ) {
req.onreadystatechange = processReqChange;
req.open( method, url, true );
req.send( );
}
}
}
// Функция, выполняемая при изменении статуса
// запроса, если статус равен 200, данные получены.
function processReqChange() {
if ( req.readyState == 4 ) {
if ( req.status == 200 )
getColors(req.responseXML.documentElement);
else
alert("There was a problem retrieving the XML data:\n" + req.statusText);
}
}
function onChange( _this ) {
var url = "ajax.php?models=" + _this.value;
loadXMLDoc( "get", url );
}
function getColors( xml ) {
var colors = xml.getElementsByTagName( "color" );
var _select = document.getElementById( "colors" );
_select.innerHTML = ""; // Удаляем всех потомков.
// Создаем список с доступными цветами.
for ( i=0; i<colors.length; i++ ) {
var option = document.createElement( "option" );
var optionText = document.createTextNode( colors[i].firstChild.data );
option.appendChild( optionText );
option.setAttribute( "value",colors[i].getAttribute("value") );
_select.appendChild( option );
}
}
</script>
</head>
<body>
<?php
// Проверка, пришли ли данные из формы.
if ( $_GET["models"] ) {
// Как бы выборка из базы данных
$colorsArray = array (
"BentleyAzure" => array( "red"=>"Красный", "green"=>"Зеленый" ),
"ChevroletCorvette"=>array( "black"=>"Черный", "blue"=>"Синий" ),
"FerrariEnzo"=>array( "green"=>"Зеленый", "black"=>"Черный", "yellow"=>"Желтый" )
);
$colors = $colorsArray[$_GET["models"]];
// Проверка на доступность модели этого цвета.
if ( array_key_exists($_GET["colors"], $colors) )
echo '<h3 style="color:#090">Модель такого цвета есть в наличии</h3>';
else
echo '<h3 style="color:#900">Модель такого цвета отсутствует</h3>';
}
?>
<form action="#" method="GET">
Модели
<select id="models" name="models" onchange="onChange(this);">
<option value="BentleyAzure">Bentley Azure</option>
<option value="ChevroletCorvette">Chevrolet Corvette</option>
<option value="FerrariEnzo">Ferrari Enzo</option>
</select>
Цвета
<select id="colors" name="colors">
<option value="red">Красный</option>
<option value="black">Черный</option>
<option value="green">Зеленый</option>
<option value="blue">Синий</option>
<option value="yellow">Желтый</option>
</select>
<input type="submit" value="Выбрать" />
</form>
</body>
Источник: http://www.freeartists.ru
|
|