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

Статьи.

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>

Недостатки такого подхода:

  1. Пересылка клиенту всего HTML кода страницы вместо списка цветов имеющихся в наличии.
  2. Пользователю придется ждать некоторое время, пока данные придут с сервера и отрендерятся в браузере.

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>

Недостатки такого подхода:

  1. Объем такого массива может быть очень большим и не все данные могут понадобиться пользователю.
  2. С момента создания массива до момента, когда пользователь выберет подходящую ему по цвету модель, может пройти значительное время и данные на сервере могут измениться. В результате пользователь может выбрать комбинацию модель-цвет, которой уже нет в наличии.

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