Выше было сказано, что регулируемая передача данных может про водиться в зависимости от определенных действий пользователя. П работе с формами иногда удобно отправлять данные по мере запол ния формы. Обычно передача данных производится с целью их верки, чтобы не ждать, пока форма будет заполнена до конца. В под ных случаях для определения момента отправки данных, как пр ло, применяется обработчик события onchange для каждого из элем тов формы.Событие onchange возникает в элементах выбора , когда выби¬рается какой-либо из вариантов списка. В других элементах оно воз¬никает, если значение было изменено и элемент терял фокуса ввода. Так, если ввести несколько символов в текстовое поле ввода и щелк¬нуть мышью за его пределами (чтобы заставить поле потерять фокус ввода), возникает событие onchange и вызывается его обработчик. Если снова щелкнуть мышью по полю ввода, а потом за его пределами (или нажать клавишу Tab), текстовое поле снова потеряет фокус ввода, но на этот раз событие onchange не возникнет, поскольку никаких изменений в поле произведено не было. Применение обработчика именно этого со¬бытия для регулирования поможет сократить случаи неоправданной передачи данных.
Обычно правильность заполнения формы проверяют перед ее отправ¬кой на сервер. Кнопка отправки формы изначально находится в запре¬щенном состоянии и переходит в разрешенное только тогда, когда все поля формы проверены сервером. Допустим, что на некотором сайте пользователь сначала должен зарегистрироваться, прежде чем полу¬чит возможность что-то делать на нем. Это может быть интернет-мага¬зин, работающий только с зарегистрированными пользователями, или сайт, доступ к доске объявлений которого открыт только для членов некоторого сообщества. Обычно в таких случаях для создания новой учетной записи требуется получить от пользователя следующую ин¬формацию, в правильности которой необходимо убедиться:
• Имя пользователя (должно быть уникальным).
• Адрес электронной почты.
• Дата рождения.
Разумеется, объем и характер данных, требуемых от пользователя, сильно зависит от ваших требований, но вышеперечисленные данные чаще всего фигурируют в большинстве веб-приложений.
На первом шаге следует описать форму HTML, которая будет зани¬маться сбором информации. Эта форма должна быть автономной, со¬храняющей работоспособность, даже если функциональность Ajax бу¬дет недоступна броузеру:
По поводу этой формы следует сделать несколько замечаний, первых, не все поля надо проверять. Имя и фамилия пользоват также его пол (который выбирается из выпадающего списка) не ют выполнения проверки. Остальные поля - адрес электронной ты, имя пользователя (логин) и дата рождения - будут прове~ средствами Ajax. Во-вторых, обратите внимание на скрытые жения, расположенные рядом с этими полями ввода. Эти изоб~ ния будут видны, только если содержимое поля нельзя признать вильным. Изначально изображения не видны, поскольку в бро> не имеющих поддержки механизмов Ajax, они не должны быть \ В этой форме полностью отсутствует код JavaScript - все необхо,; функции и обработчики событий описываются в отдельном файле.
Проверка содержимого каждого поля формы выполняется с пом единственной функции, validateField(). Это возможно благодаря что для каждого поля задействуется один и тот же алгоритм про (обращение к серверу и ожидание ответа). Эти поля отличаются типами данных, подлежащих проверке, а также тем, что каждо лю соответствует свое изображение, которое надо сделать в в случае, если содержимое поля не прошло проверку на правил
Сценарий, исполняемый на стороне сервера, находится в файле Valida-tsForm. php. Этому сценарию в строке запроса передается параметр в ви-ж пары имя-значение. В качестве имени должно передаваться имя ааемента управления, содержимое которого проверяется, а в качестве его значения -
содержимое поля. В зависимости от имени параметра сценарий выполняет соответствующую проверку. Затем он выводит «кую строку:
11<сообщение_об_ошибке>
Be первая часть говорит о том, прошло ли значение проверку (t rue - да, *5lse - нет). Вторая часть строки, расположенная за двумя символами • !'»,- это сообщение об ошибке. Она присутствует только в том слу¬чае, если значение признано неправильным. Ниже приводится пара примеров строк, возвращаемых сценарием:
true||
false||Неверная дата.
Первая строка означает, что данные признаны корректными, а вторая говорит о том, что была указана неверная дата.
Эти сообщения представлены в простом текстовом формате. Позже в этой книге вы узнаете о применении для тех же целей других форматов представления данных, таких какХЖ и JSON.
Код сценария, выполняющего проверку:
Этот сценарий сначала определяет, какое поле подвергается провер Для этого применяется функция isset (), проверяющая значение м сива $_GET. Если в массиве присутствует значение конкретного по начинается его проверка. Имя пользователя проверяется на прису вие в массиве имен уже зарегистрированных пользователей, после го проверяется длина имени (не менее восьми символов). Дата рож ния передается прямо во встроенную функцию PHP strtotime(), ко рая преобразует строку с датой в число секунд, прошедших от 1 ян ря 1970 г. Если строка с датой содержит ошибку, функция вернет -Формат адреса электронной почты проверяется с помощью регуляр го выражения. Это регулярное выражение было приведено Джон Коггсхоллом (John Coggeshall) в статье «Е-mail validation with PHP (Проверка корректности адресов электронной почты в РНР4), котор можно найти по адресу www.zend.com/zend/spotlight/evl2apr.php.
Обратите внимание, что имена пользователей в этом примере храня в виде простого массива и жестко зашиты в текст сценария. В раба реализации имена пользователей должны храниться в базе данных, средством запросов к которой и проверяется уникальность имени по зователя.
Переменные $valid и Smessage инициализируются значениями по ум чанию - false и "Неизвестная ошибка". Таким образом, сценарий, званный с некорректными параметрами (например, с неверным и нем поля ввода), всегда будет возвращать признак ошибки. Однако ли проверяемое значение признается правильным, то в обе перем ные записываются соответствующие значения (в переменную $valid значение true, а в переменную Smessage - пустая строка). Если же п ввода опознано, но его содержимое не может быть признано прави ным, изменяется значение только переменной $message, т. к. перемен¬ная $valid уже имеет значение false. В самом конце сценарий выводит строку ответа в том формате, о котором мы уже говорили.
Далее необходимо добавить код JavaScript, который будет выполнять проверку. Корректность заполнения всех полей будет проверять един¬ственная функция, validateFieldQ. В самом начале она выполняет действия, обеспечивающие ее работоспособность в разных броузерах:
function validateField(oEvent) { oEvent = oEvent || window,event; var txtField = oEvent.target || oEvent.srcElement;
// далее следует остальной код функции
}
Первые две строки функции нивелируют различия между моделями событий в IE и в DOM-совместимых броузерах (таких как Mozilla Fire-fox, Opera и Safari). DOM-совместимые броузеры передают всем обра¬ботчикам событий объект event, который хранит информацию об эле¬менте управления, породившем событие в свойстве target. В IE объект event является свойством объекта window, таким образом, первая стро¬ка функции выбирает корректную ссылку и записывает ее в перемен¬ную oEvent. Логическая операция OR (| |) возвращает непустое значе¬ние, если хотя бы один из аргументов не равен null. При работе в IE ар¬гумент функции oEvent будет содержать значение null, вследствие чего в него будет записана ссылка на window, event. В случае DOM-совмести¬мого броузера значение аргумента oEvent будет просто записано само в себя. Вторая строка выполняет аналогичные действия относительно элемента управления, породившего событие, ссылка на который хра¬нится в свойстве srcElement в броузере IE. В результате после выполне¬ния этих двух строк мы получаем ссылку на элемент управления, в ко¬тором возникло событие, в переменной txtField. Следующий шаг - соз¬дание запроса HTTP с помощью объекта XMLHttp:
function validateField(oEvent) { oEvent = oEvent || window.event; var txtField = oEvent.target || oEvent.srcElement;
var oXmlHttp = zXmlHttp.createRequest(); oXmlHttpsopen(':get"r«"ValidateForiii.php?+ txtField.name + "=" + encodeURIComponent(txtField.value), true); . : oXmlHttp.onreadystatechange = function () {
// далее следует остальной код функции
oXmlHttp send(null);
}
Для обеспечения поддержки объекта XMLHttp в разных броузерах вы¬брана библиотека zXml. Объект XMLHttp создается и сохраняется в пере¬менной oXMLHttp. Затем с помощью метода ореп() инициализируется за¬прос GET. Обратите внимание, что строка запроса для сценария Vali-j dateForm. php создается как комбинация имени поля, знака равенства! содержимого поля (которое проходит кодирование URI с помощи функции encodeURIComponent()). Также следует обратить внимание на тц| что запрос выполняется асинхронно. Это очень важно, поскольку вряа| ли целесообразно мешать пользователю, заполняющему форму в то ври мя, когда вы выполняете проверку. Помните, что на время выполни ния синхронных запросов пользовательский интерфейс «замораживи ется» (включая ввод символов и щелчки мышью). Заключительна! часть функции обрабатывает ответ сервера:
function validateField(oEvent) { oEvent = oEvent || window.event; var txtField = oEvent.target || oEvent.srcElement; var oXmlHttp = zXmlHttp.createftequest(); oXmlHttp.open("get", "ValidateForm.php? " + txtField.name + "="
+ encodeURIComponent(txtField.value), true); oXmlHttp.onreadystatechange = function () {
if (oXmlHttp. readyState == 4) { j
if (oXmlHttp.status == 200) { j
var arrlnfo = oXmlHttp.responseText.split("|I"); fvv :: : var imgError = document. getElementByldC'img"
+ txtField. id. substring^) + "Error"); var btnSignllp = document.getElementByldC'btnSlgnup");
if (!eval(arrlnfo[0])) {
imgError.title = arrInfo[1];
imgError.style.display = "";
txtField.valid = false; } else {
imgError.style.display = "none"; txtField.valid = true;
btnSignUp.disabled = !isFormValid(); } else {
alert("flpM попытке соединения с сервером возникла ошибка."
}
После проверки значений свойств readyState и status содержимое сво ства responseText разбивается на массив строк (arrlnfo) с помощью : тода JavaScript split (). В первом элементе массива окажется значев переменной PHP $valid, во втором - значение переменной $message. тем функция получает ссылки на изображение, сообщающее об оши ке, и на кнопку «Зарегистрироваться!». Идентификатор изображен! сообщающего об ошибке, получается из имени поля ввода, из котор удаляется подстрока "txt" (с помощью функции substring()), затем в на¬чало имени подставляется строка img, а в конец добавляется строка Ег-'ог (например, из имени поля txtBirthday получается имя изображения mgBirthdayError).
Для того чтобы получить из строки логическое значение, элемент агг-lnfo[0] передается функции eval(). (Не забывайте, что в массиве хра¬нится всего лишь строка: либо true, либо false.) Если это false, то в за¬головок изображения записывается текст сообщения об ошибке из агг-Info[1], само изображение делается видимым, а в дополнительное свойство valid текстового поля записывается значение false (позднее нам это пригодится). Если введенное значение будет признано невер¬ным, то, наведя указатель мыши на изображение, появившееся рядом с полем ввода, можно будет прочитать текст сообщения об ошибке (рис. 3.3). В противном случае изображение скрывается, а в дополни¬тельное свойство valid текстового поля записывается значение true.
Вы наверняка заметили, что в этой функции фигурирует кнопка «За¬регистрироваться!». Она должна быть запрещена, если в форме еще ос¬таются поля с некорректными данными. Это проверяется с помощью функции isFormValid(). Если она возвращает значение false, то в свой¬ство кнопки disabled записывается значение true. Функция isFormVa-l:d() обходит в цикле поля формы и проверяет значения свойства valid для каждого из них:Функция проверяет наличие свойства valid в каждом элементе фор: Делается это с помощью оператора typeof, который вернет строку "Ь lean", если свойство существует и хранит логическое значение. 1 скольку в форме имеются поля, значения которых не проверяю (и соответственно не имеют свойства valid), такая проверка гаран рует, что учитываться будут только те поля, значения которых по жат проверке.
Заключительная часть сценария устанавливает обработчики собы в поля ввода. Это надлежит делать по завершении загрузки фор и при условии наличия поддержки объекта XMLHttp (т. к. именно с помощью выполняются проверки):
// Если броузер поддерживает механизмы Ajax, запретить кнопку // «Зарегистрироваться!» и установить обработчики событий window.onload = function () { if (zXmlHttp.isSupportedO) { : - var btnSignUp = document.getElementById("btnSignUp");
var txtUsername = document.getElementById("txtUsername"); var txtBirthday = document.getElementByldC'txtBirthday");: var txtEmail = document.getElementByldC'txtEmail");
btnSignUp.disabled = true; ' txtUsername.onchange = validateField; txtBirthday.onchange = validateField; * txtEmail.onchange = validateField; txtUsername.valid = false; txtBirthday.valid = false; txtEmail.valid = false;
Этот обработчик события onload устанавливает обработчик события change для каждого текстового поля, а также инициализирует доп нительное свойство valid значением false. Кроме того, с самого нач блокируется кнопка «Зарегистрироваться!», чтобы исключить отп ку заведомо неверных данных. Обратите внимание: кнопка будет блокирована только в том случае, если объект XMLHttp поддержива броузером, иначе форма будет вести себя как обычная веб-форма, верка которой будет полностью производиться на стороне сервера после ее отправки.
Когда вы загрузите этот пример, каждое из трех полей, требую проверки, будет отсылать запросы серверу каждый раз, когда вы б те менять значение текущего поля и переходить в другое. Примене шаблона с регулируемой передачей данных улучшает ощущения п
эователя. Но форма не теряет свою функциональность даже при от¬ключенном JavaScript или при отсутствии поддержки XMLHttp.
Такие проверки не исключают необходимости окончательной проверки всех данных формы после того, как она будет отослана на сервер. Помни¬те, что пользователь может отключить у себя поддержку JavaScript, но вы все равно обязаны лишний разубедиться в корректности данных, преж¬де чем использовать их.