Содержание


Ajax и XML

Использование Ajax в формах

Создание форм ввода с помощью Ajax

Comments

Серия контента:

Этот контент является частью # из серии # статей: Ajax и XML

Следите за выходом новых статей этой серии.

Этот контент является частью серии:Ajax и XML

Следите за выходом новых статей этой серии.

Первым, что приходит на ум при словах “приложения Web 2.0”, как правило, бывают такие запоминающиеся функции как видео на YouTube, просмотр карт Google Maps с возможностью прокрутки или геолокационные возможности Flickr. За всем этим великолепием, однако, скрываются скромные HTML-формы, которые претерпели масштабные изменения в связи с ростом популярности технологии Ajax.

В этой статье я расскажу, как использовать написанную на JavaScript библиотеку Prototype.js, добавляя вызовы Ajax в HTML-формы для решения типичных проблем, связанных с восприятием приложения пользователями.

Пример использования Ajax в простой форме ввода данных

Начнем с очень простого примера: допустим, есть регистрационная форма, содержащая несколько полей, которую мы хотим отправить на сервер с помощью Ajax, а не обычным для Web способом. Сама страница с формой показана в листинге 1.

Листинг 1. index.html
<html>
<head>
<script src="prototype.js"></script>
</head>
<body>
<form id="myform">
<table>
  <tr><td>First</td><td><input type="text" name="first"></td></tr>
  <tr><td>Last</td><td><input type="text" name="last"></td></tr>
  <tr><td>Email</td><td><input type="text" name="email"></td></tr>
</table>
<input type="button" onclick="dosubmit()" value="Submit">
</form>
<div id="result" style="padding:5px;">
</div>
<script>
function dosubmit( ) {
  new Ajax.Updater( 'result', 'add.php', { method: 'post',
    parameters: $('myform').serialize() } );
  $('myform').reset();
}
</script>
</body>
</html>

В начало страницы я поместил ссылку на файл JavaScript prototype.js, в котором заключены все функции для работы с Ajax. После нее следует стандартная HTML-форма с тремя полями: first, last и email. Под ней находится кнопка, отправляющая содержимое формы на сервер, вызывая функцию JavaScript dosubmit().

Данная функция использует класс Ajax.Updater для отправки данных скрипту add.php. При этом можно задавать различные параметры. В нашем случае указывается, что данные должны передаваться методом post, а параметры формы добавляются с помощью вызова метода serialize() у объекта формы. Данный метод не является стандартным, а предоставляется библиотекой JavaScript.

В качестве первого параметра при вызове Ajax.Updater выступает идентификатор тега <div>, в который помещается фрагмент HTML, возвращаемый скриптом add.php. Это наиболее простой способ оповещения пользователя о результате нажатия на кнопку отправки формы.

Скрипт add.php показан в листинге 2.

Листинг 2. add.php
Thanks <?php echo( $_POST['first'] ) ?> <?php echo( $_POST['last'] ) ?>!

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

При первой загрузке формы в браузере страница будет выглядеть примерно как на рисунке 1.

Рисунок 1. Пример простой формы, созданной с применением Ajax
A simple Ajax form
A simple Ajax form

При нажатии на кнопку Submit данные отправляются серверному скрипту add.php, который возвращает фрагмент HTML, располагая его прямо под Submit (рисунок 2).

Рисунок 2. Отображение результата
The response following the submission
The response following the submission

Вариацией подобных HTML-форм являются формы Ajax с автозаполнением, которые самостоятельно изменяют значения некоторых полей в зависимости от значений определенных ключевых атрибутов. Типичным примером является ввод идентификатора клиента и нажатие на кнопку, в результате чего остальные поля будут автоматически заполнены информацией о данном клиенте.

Пример формы с автозаполнением приведен в листинге 3.

Листинг 3. index.html
<html>
<head>
<script src="prototype.js"></script>
</head>
<body>
<form id="myform">
<table>
  <tr><td>ID</td><td><input 
    type="text" name="id"></td></tr>
  <tr><td>First</td><td><input type="text" 
    name="first" id="elFirst"></td></tr>
  <tr><td>Last</td><td><input type="text" 
    name="last" id="elLast"></td></tr>
  <tr><td>Email</td><td><input type="text" 
    name="email" id="elEmail"></td></tr>
</table>
<input type="button" onclick="dofill()" value="Fill Fields">
</form>
<script>
function dofill( ) {
  new Ajax.Updater( 'result', 'getdata.php', 
    { method: 'post', parameters: $('myform').serialize(),
  onSuccess: function( transport ) {
    $('elFirst').value = transport.responseXML.getElementsByTagName('first')
      [0].firstChild.nodeValue;
    $('elLast').value = transport.responseXML.getElementsByTagName('last')
      [0].firstChild.nodeValue;
    $('elEmail').value = transport.responseXML.getElementsByTagName('email')
      [0].firstChild.nodeValue;
  } } );
}
</script>
</body>
</html>

В форму, показанную в листинге 1, я добавил новое поле ID, в которое должен вводиться идентификатор клиента. После ввода вызывается функция dofill(), которая обращается к странице getdata.php и получает от нее документ XML, содержащий имя, фамилию и адрес e-mail указанного клиента.

Обработчик события onSuccess, передаваемый в качестве параметра при вызове Ajax.Updater, использует функции Document Object Model (DOM), поддерживаемые всеми браузерами, для разбора полученного документа XML. Затем он заполняет значения элементов <input> с идентификаторами elFirst, elLast и elEmail <input> данными из XML.

Страница getdata.php показана в листинге 4.

Листинг 4. getdata.php
<?php
header( "content-type: text/xml" );

$first = ' ';
$last = ' ';
$email = ' ';

if ( $_POST['id'] == '1' )
{
  $first = 'Jack';
  $last = 'Herrington';
  $email = 'jherr@pobox.com';
}
?>
<data>
<first><?php echo( $first ) ?></first>
<last><?php echo( $last ) ?></last>
<email><?php echo( $email ) ?></email>
</data>

Эта страница представляет собой не что иное как заглушку вместо обращения к базе данных для получения имени, фамилии и адреса e-mail для данного клиента.

При первом запуске страница должна выглядеть как на рисунке 3.

Рисунок 3. Форма с заполнением
Fill-in form
Fill-in form

Если затем набрать 1 в поле ID и нажать на кнопку Fill Fields, произойдет обращение к странице getdata.php для получения имени, фамилии и адреса e-mail. Далее полученные данные будут помещены в соответствующие поля формы. Результат показан на рисунке 4.

Рисунок 4. Остальные поля формы заполняются в результате работы скрипта, принимающего ID в качестве параметра
The script fills in the fields based       on the ID
The script fills in the fields based on the ID

В качестве следующего фокуса с Ajax я создам обновляемый список незавершенных дел (to-do list).

Обновляемые “по месту” списки

Одним из распространенных примеров, использующихся при демонстрации возможностей Ruby on Rails, являются списки дел, которые обновляются по месту (in-place). Другими словами, представьте себе список вверху страницы и расположенное под ним текстовое поле. Если набрать некоторый текст в этом поле и нажать на кнопку Submit, то в список будет автоматически добавлен новый элемент, причем без перезагрузки страницы. Текстовое поле, в свою очередь, будет очищено, так что можно продолжать с легкостью добавлять элементы.

На самом деле, это весьма непростая задача, поэтому я решил продемонстрировать ее решение на PHP. В листинге 5 показана страница, содержащая список дел.

Листинг 5. index.php
<html>
<head>
<script src="prototype.js"></script>
</head>
<body>

<div id="result" style="padding:5px;">
<?php
$fh = fopen( 'list.txt', 'r' );
while( $str = fgets( $fh ) ) {
?>
<?php echo( $str ); ?><br/>
<?php
}
?>
</div>

<form id="myform">
<input type="text" name="todo">
</form>

<input type="button" onclick="dosubmit()" value="Submit">

<script>
function dosubmit( ) {
  new Ajax.Updater( 'result', 'add.php',
    { method: 'post', parameters: $('myform').serialize() } );
  $('myform').reset();
}
</script>

</body>
</html>

Вместо хранения элементов списка в базе данных я использую простой текстовый файл list.txt, в котором перечислены все записи (по одной на строку). Таким образом, все, что нужно для заполнения списка данными – это открыть файл, прочитать записи и поместить их внутрь элемента <div> с идентификатором result.

Под списком находится форма с текстовым полем для ввода новых записей. А еще ниже расположена кнопка, вызывающая функцию JavaScript dosubmit() при нажатии. Данная функция использует класс Ajax.Updater для обращения к странице add.php, которая добавляет элемент и возвращает обновленный список, содержащий новую запись.

Скрипт add.php показан в листинге 6.

Листинг 6. add.php
<?php
$total = '';

$fh = fopen( 'list.txt', 'r' );
while( $str = fgets( $fh ) ) {
?>
<?php echo( $str ); ?><br/>
<?php
  $total .= $str;
}

if ( array_key_exists( 'todo', $_POST ) )
{
?>
<?php echo( $_POST['todo'] ); ?><br/>
<?php
  $fh = fopen( 'list.txt', 'w' );
  fwrite( $fh, $total."\n".$_POST['todo'] );
  fclose( $fh );
}
?>

Мой незатейливый список дел показан в листинг 7.

Листинг 7. list.txt
Get swim goggles (Купить очки для плавания)
Practice swimming (Тренироваться)
Swim in race (Участвовать в соревнованиях по плаванию)

При первой загрузке страница выглядит как на рисунке 5.

Рисунок 5. Добавление элемента в список дел
Preparing to add a to-do item
Preparing to add a to-do item

Затем, если набрать "Finish in record time!" (побить рекорд) и нажать Submit, то список обновится без перезагрузки страницы. Результат показан на рисунке 6.

Рисунок 6. Страница после добавления нового элемента
The page after inserting a record
The page after inserting a record

Разумеется, демонстрации возможностей Rails не ограничиваются только списками дел. Но они являются одними из факторов успеха Web 2.0. Кстати говоря, если вам не приходилось работать с Rails, то я настоятельно рекомендую вам (как и любому Web-программисту) попробовать его в деле. Даже если вы решите не использовать его в своих проектах, вам будет полезно посмотреть, как выстраивается архитектура приложений, как используется механизм MVC (модель-представление-контроллер) и насколько легко работать с моделью хранения данных.

Еще одним примером часто встречающейся в Web ситуации являются списки полей с возможностью добавления новых. Я называю их расширяющимися списками (expando lists).

Расширяющиеся списки

Как реализовать возможность добавления неограниченного количества ключевых слов к некоторой записи? В качестве одного из способов можно предложить использовать список слов, разделяемых запятыми. Или можно создать кнопку, с помощью которой пользователи могут добавлять произвольное количество ключевых слов. В листинге 8 показан пример реализации второго подхода.

Листинг 8. index.html
<html>
<head>
<script src="prototype.js"></script>
</head>
<body>
<form id="myform">
<table id="keytable">
  <tr><td>Keyword</td><td><input type="text" 
    name="keyword_1"></td></tr>
</table>
</form>

<input type="button" onclick="addkeyword()" value="Add Keyword">
<input type="button" onclick="dosubmit()" value="Submit">

<div id="result" style="padding:5px;">
</div>

<script>
var nextkeyid = 2;
function addkeyword()
{
  var elTR = $('keytable').insertRow( -1 );

  var elTitleTD = elTR.insertCell( -1 );
  elTitleTD.appendChild( document.createTextNode( 'Keyword' ) );

  var elInput = document.createElement( 'input' );
  elInput.type = 'text';
  elInput.name = 'keyword_'+nextkeyid;
  nextkeyid++;

  var elInputTD = elTR.insertCell( -1 );
  elInputTD.appendChild( elInput );
}
function dosubmit( ) {
  new Ajax.Updater( 'result', 'add.php', 
    { method: 'post', parameters: $('myform').serialize() } );
}
</script>
</body>
</html>

Центральное место здесь занимает функция addkeyword(), которая использует вызовы insertRow и insertCell для создания новой строки в таблице ключевых слов. Затем с помощью метода document.createElement она создает новое поле ввода для хранения слова. При нажатии на кнопку Submit класс Ajax.Updater вызовет скрипт add.php, который просто возвращает список ключевых слов, полученных от формы. Скрипт показан в листинге 9.

Листинг 9. add.php
Post Result:<br/>
<?php var_export( $_POST ) ?>

Сначала в моем браузере страница выглядит так, как показано на рисунке 7.

Рисунок 7. Форма ввода, содержащая одно ключевое слово
The keyword form with a single keyword
The keyword form with a single keyword

Затем, после того как с помощью кнопки Add Keyword я создал несколько новых полей и нажал на Submit, страница приняла вид как на рисунке 8.

Рисунок 8. Форма ввода после добавления ключевых слов и нажатия на кнопку Submit
The keyword form after adding keywords and clicking Submit
The keyword form after adding keywords and clicking Submit

Это наилучший способ дать пользователям возможность добавлять несколько значений к одной и той же записи. Это удобно использовать для таких вещей как телефонные номера, ключевые слова или адреса. А еще одним типичным примером использования Ajax являются формы авторизации.

Формы авторизации

Формы авторизации особенно хороши в Ajax потому, что они, во-первых, сразу показывают, была ли попытка входа удачной или нет, а во-вторых, позволяют производить авторизацию “по месту”. Представьте, что вы читаете статью и хотите оставить свои замечания, но это требует авторизации. Благодаря Ajax вы можете авторизоваться, не покидая страницу со статьей. Если у вас достаточно прав доступа, то вам сразу будет показана форма для ввода комментария. Это гораздо проще, чем отслеживать, на какой странице находился пользователь, чтобы перенаправить его на эту страницу после успешной авторизации.

Пример простой формы авторизации, использующей Ajax, показан в листинге 10.

Листинг 10. index.html
<html>
<head>
<script src="prototype.js"></script>
</head>
<body>
<form id="logform">
User: <input type="text" name="user"><br/>
Password: <input type="password" name="password"><br/>
<input type="button" onclick="login()" value="Login">
</form>
<div id="noway" style="display:none;">
  No way!
</div>
<script>
function login() {
  new Ajax.Request( 'login.php',
  {
    method: 'post',
    postBody: $('logform').serialize(),
    onSuccess: function( transport ) {
      if( transport.responseText.match( /\<ok\/\>/ ) )
        window.location = 'home.html';
      else
        $('noway').style.display='block';
    }
  } );
}
</script>
</body>
</html>

Форма, находящаяся вверху страницы, содержит поля User и Password. Под ними расположен элемент <div> с идентификатором noway, который показывается в случае отрицательного результата авторизации. Попытка авторизации осуществляется с помощью метода login() в JavaScript, который использует класс Ajax.Request. В случае, если скрипт login.php возвращает XML-фрагмент <ok />, то форма перенаправляет пользователя на домашнюю страницу. В противном случае на экран выводится содержимое элемента noway.

Скрипт login.php представлен в листинге 11.

Листинг 11. login.php
<?php
header( 'Content-type: text/xml' );
if ( $_POST['user'] == 'jack' && $_POST['password'] == 'password' )
  echo( "<ok/>" );
else
  echo( "<bad/>" );
?>

Этот код просто использует жестко заданные значения имени пользователя и пароля и возвращает ok в случае совпадения. В ином случае возвращается bad.

Для полноты картины код домашней страницы показан в листинге 12.

Листинг 12. home.html
<html>
<body>
  You are logged in and this is your home page.
</body>
</html>

Для начала загрузите форму в браузер, введите неправильное имя и пароль и нажмите Login. Результат должен быть как на рисунке 9.

Рисунок 9. Страница авторизации после ввода неправильного пароля
The login page after typing an       incorrect password
The login page after typing an incorrect password

Если же изменить имя пользователя и пароль на корректные значения и вновь нажать Login, то вы будете перенаправлены на домашнюю страницу, которая показана на рисунке 10.

Рисунок 10. Страница авторизации после ввода правильного имени пользователя и пароля
The login page after typing the       correct user name and password
The login page after typing the correct user name and password

В качестве последнего примера рассмотрим использование Ajax совместно с XForms.

Ajax и XForms

Я не считаю себя экспертом в XForms, но мне нравится этот стандарт. Далее я покажу, как можно совместно использовать клиентские формы XForms с Prototype.js и Ajax.

Несложный код примера с использованием XForms показан в листинге 13.

Листинг 13. index.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:xforms="http://www.w3.org/2002/xforms">
<head>
<title>XForms AJAX Example</title>
<xforms:model id="modelData">
 <xforms:instance xmlns="">
  <Data>
   <First>First</First>
   <Last>Last</Last>
   <Email>email@email.com</Email>
  </Data>
 </xforms:instance>
</xforms:model>
<script src="prototype.js"></script>
</head>
<body>
<xforms:input ref="/Data/First">
<xforms:label>First: </xforms:label>
</xforms:input><br/>
<xforms:input ref="/Data/Last">
<xforms:label>Last: </xforms:label>
</xforms:input><br/>
<xforms:input ref="/Data/Email">
<xforms:label>Email: </xforms:label>
</xforms:input><br/><br/>

<button onclick="submit()">Submit</button>
<script>
function submit()
{
 var m = $('modelData');
 var base = m.getElementsByTagName('Data')[0];
 var s = new XMLSerializer();
 var data = ( s.serializeToString( base ) ).toString();
 new Ajax.Updater( 'result', 'params.php', 
   { method: 'post', parameters: 'data='+escape( data ) } );
}
</script>

<br/><br/>
<div id="result">
</div>

</body></html>

В начале файла находится XML-описание модели XForm. Затем следует набор меток и полей XForms, составляющих саму форму ввода. При нажатии на кнопку Submit происходит вызов функции JavaScript submit(). Данная функция использует JavaScript-объект XMLSerializer для сериализации данных модели XForms в XML-строку, которая затем передается скрипту params.php. Этот скрипт, показанный в листинге 14, трансформирует XML в HTML, который затем выводится на страницу.

Листинг 14. params.php
<?php
echo( htmlentities( $_POST['data'] ) );
?>

Если открыть данную страницу в браузере с установленным плагином XForms, то она будет выглядеть как на рисунке 11.

Рисунок 11. Страница XForms, использующая Ajax
An Ajax-enabled XForms page
An Ajax-enabled XForms page

Заполнив форму данными и нажав Submit, вы увидите результат, показанный на рисунке 12.

Рисунок 12. Страница после нажатия на Submit
The page after clicking Submit
The page after clicking Submit

Как видите, страница содержит данные модели, которые были сериализованы в XML-строку, переданы скрипту params.php, а затем отправлены обратно на страницу, внутрь тега <div> с идентификатором result.

Заключение

Использование Ajax в формах HTML открывает широкие возможности, лишь малая часть которых затронута в данной статье. Тем не менее, в ней содержатся несколько реалистичных примеров, которые могут натолкнуть вас на мысли о том, чего можно добиться в ваших собственных приложениях, избежав серьезных изменений на страницах.


Ресурсы для скачивания


Похожие темы

  • Оригинал статьи: “Ajax and XML: Ajax for forms” (Джек Д. Херрингтон, developerWorks, январь 2008 г.). (EN)
  • Зайдите на домашнюю страницу PHP, содержащую бесценные материалы для PHP-программистов. (EN)
  • Библиотека Prototype: прочитайте о возможностях этой инфраструктуры JavaScript, созданной для упрощения разработки динамических Web-приложений. (EN)
  • JavaScript-библиотека Scriptaculous: в ней вы найдете средства для добавления к вашему Web-сайту различных эффектов, отлично дополняющих инфраструктуру на основе Prototype. (EN)
  • Установите модуль XForms для Firefox, который необходим для запуска примеров к данной статье. (EN)
  • Обратитесь к документации по Prototype.js documentation page за дополнительной информацией о библиотеке Prototype. Кроме того, на этой странице вы найдете ссылки на официальный блог Prototype и многие другие материалы. (EN)
  • Прочитайте о jQuery – еще одной библиотеке JavaScript, обладающей схожими с Prototype.js возможностями. (EN)
  • Ознакомьтесь с Yahoo! User Interface Library – инструментарием Ajax, разработанным Yahoo! (EN)
  • Посетите раздел по XML на сайте developerWorks, содержащий обширную коллекцию материалов по XML.

Комментарии

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

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=XML
ArticleID=407309
ArticleTitle=Ajax и XML: Использование Ajax в формах
publish-date=07082009