Сегодня мы создадим красивую форму, которая также прекрасно будет работать при отключенном JS. То есть первым делом мы сделаем так, чтобы форма работала без JS и без подержки CSS3, а далее уже будем накладывать слоями разные фишки, AJAX и jQuery.
В данной форме также есть пользовательские всплывающие подсказки для валидации.
Шаг 1 - XHTML
Первый шаг заключается в создании скелета нашей формы. Она должна быть простой и очень юзабильной :)
<div id="carbonForm">
<h1>Signup</h1>
<form action="submit.php" method="post" id="signupForm">
<div class="fieldContainer">
<div class="formRow"></div>
<!-- Two more formRow divs -->
</div>
<div class="signupButton">
<input type="submit" name="submit" id="submit" value="Signup" />
</div>
</form>
</div>
div carbonForm - главный контейнер формы. Он центрирован на странице с помощью CSS свойства margin, а по вертикали с помощью jQuery.
Внутри у на заголовок и форма с div fieldContainer. Внутри него три div formRow, у которых следующая разметка:
<div class="formRow">
<div class="label">
<label for="name">Name:</label>
</div>
<div class="field">
<input type="text" name="name" id="name" />
</div>
</div>
Каждая пара элементов label и input размещена внутри оберток, которые выровнены по левому краю. Важно, чтобы название текстовых полей были такими же как и id, так как это используется при отображении всплывающих ошибок.
Шаг 2 - CSS
Форма сильно зависит от CSS для достижения такого красивого эффекта. Целая череда CSS3 свойств используется тут. Ранее такого эффекта можно было добиться только с помощью Photoshop. Здесь представлена только наиболее интересные стили:
#carbonForm{
/* Главный контейнер */
background-color:#1C1C1C;
border:1px solid #080808;
margin:20px auto;
padding:20px;
width:500px;
-moz-box-shadow:0 0 1px #444 inset;
-webkit-box-shadow:0 0 1px #444 inset;
box-shadow:0 0 1px #444 inset;
}
.fieldContainer{
/* Светлая закругленная секция, которая содержит поля */
background-color:#1E1E1E;
border:1px solid #0E0E0E;
padding:30px 10px;
/* CSS3 тени, используется для внутреннего свечения */
-moz-box-shadow:0 0 20px #292929 inset;
-webkit-box-shadow:0 0 20px #292929 inset;
box-shadow:0 0 20px #292929 inset;
}
#carbonForm,.fieldContainer,.errorTip{
/* Закругления div */
-moz-border-radius:12px;
-webkit-border-radius:12px;
border-radius:12px;
}
.formRow{
height:35px;
padding:10px;
position:relative;
}
.label{
float:left;
padding:0 20px 0 0;
text-align:right;
width:70px;
}
label{
font-family:Century Gothic,Myriad Pro,Arial,Helvetica,sans-serif;
font-size:11px;
letter-spacing:1px;
line-height:35px; /* Neat line height trick */
}
.field{
float:left;
}
.field input{
/* Текстовый ячейки */
border:1px solid white;
color:#666666;
font-family:Arial,Helvetica,sans-serif;
font-size:22px;
padding:4px 5px;
background:url("img/box_bg.png") repeat-x scroll left top #FFFFFF;
outline:none;
}
#submit{
/* Кнопка отправки */
border:1px solid #f4f4f4;
cursor:pointer;
height:40px;
text-indent:-9999px;
text-transform:uppercase;
width:110px;
background:url("img/submit.png") no-repeat center center #d0ecfd;
-moz-border-radius:6px;
-webkit-border-radius:6px;
border-radius:6px;
}
#submit.active{
/* Добавляем прелоадер после нажатия на кнопку */
background-image:url("img/preloader.gif");
}
input:hover,
input:focus{
/* CSS3 эффект свечения */
-moz-box-shadow:0 0 8px lightblue;
-webkit-box-shadow:0 0 8px lightblue;
box-shadow:0 0 8px lightblue;
}
Большинство из этих стилей понятны с первого взгляда. Возможно для Вас будет интересен момент с использованием кнопки отправки.
Для того, чтобы спрятать текст (в нашем случае "Signup") мы можем использовать трюк с отрицательным text-indent, но в IE это работает только, если мы укажем правило text-transform:uppercase. Мы также добавляем прозрачный фон состоящий из текста "Submit", который сменяется вращающимся gif прелоадером, если кнопке присвоен класс "active".
Шаг 3 - jQuery
После подключения библиотеки у нас идет файл script.js.
script.js
$(document).ready(function(){
// $(document).ready() выполняется после загрузки страницы
// Привязываем слежение за отправкой формы:
$('#signupForm').submit(function(e){
// Если прошлая отправка еще не завершилась:
if($('#submit').hasClass('active')) return false;
// Добавляем класс active dyjgrt. Будем отображать gif прелоадер:
$('#submit').addClass('active');
// Убираем текущие сообщения об ошибках
$('.errorTip').remove();
// Выдаем запрос POST ajax для submit.php:
$.post($('#signupForm').attr('action'),
$('#signupForm').serialize()+'&fromAjax=1',function(response){
if(!response.status)
{
// Если случилась ошибка
// Проходим через все текстовые ячейки,
// и проверяем где именно ошибка
$('input[type!=submit]').each(function(){
var elem = $(this);
var id = elem.attr('id');
if(response[id])
showTooltip(elem,response[id]);
});
}
else location.replace(response.redirectURL);
$('#submit').removeClass('active');
},'json');
e.preventDefault();
});
$(window).resize();
});
// Центрируем вертикально форму при каждом изменении размеров браузера:
$(window).resize(function(){
var cf = $('#carbonForm');
$('#carbonForm').css('margin-top',($(window).height()-cf.outerHeight())/2)
});
// Вспомогательная функция, которая отвечает за всплывающие ошибки:
function showTooltip(elem,txt)
{
// elem - текстовая ячейка, txt - текст ошибки
$('<div class="errorTip">').html(txt).appendTo(elem.closest('.formRow'));
}
Нажатие на кнопку отправки (или же нажатие кнопки Enter после заполнения полей) отправляет форму. Функция, которая привязана к отправке предотвращает форму от e.preventDefault() и выдает запрос для submit.php.
Возвращенный ответ расценивается как код JSON (объект JavaScript), который содержит специально свойство status. В зависимости от его значения, скрипт или же показывает ошибки при заполнении или же перенаправляет браузер на указанную страницу.
Текст сообщений об ошибках
{
"status" : 0, // Обозначает, что возникла ошибка
"email" : "Please fill in a valid email!", // Сообщение об ошибке
"pass" : "Please fill in a valid password!" // Сообщение об ошибке
}
Всплывающий ошибки генерируются скриптом при прохождении по всем текстовым ячейкам и при проверки существования их id в качестве свойств. Если они существуют - создается ошибка с помощью функции showTooltip().
Также обратите внимание как мы используем метод serialize() на строке 18 для отправки всех полей за один раз. Также на этой же строке мы устанавливаем fromAjax=1, что сообщит PHP о необходимости возврата ответа как JSON.
Шаг 4 - PHP
Эта форма хороша тем, что прекрасно работает даже без JavaScript. Она работает потому, что атрибут action имеет также значение submit.php. Это означает, что нам необходимо только внедрить проверку.
submit.php
// Сообщения об ошибках:
error_reporting(E_ALL^E_NOTICE);
// По этому УРЛу переходит пользователь
// после удачного заполнения и отправки формы:
$redirectURL = 'http://demo.tutorialzine.com/2010/04/carbon-signup-form/demo.html';
$errors = array();
// Проверяем введенные данные, и, если есть ошибки, добавляем их в массив $errors:
if(!$_POST['name'] || strlen($_POST['name'])<3 || strlen($_POST['name'])>50)
{
$errors['name']='Please fill in a valid name!<br />Must be between 3 and 50 characters.';
}
if(!$_POST['email'] || !preg_match("/^[\.A-z0-9_\-\+]+[@][A-z0-9_\-]+([.][A-z0-9_\-]+)+[A-z]{1,4}$/", $_POST['email']))
{
$errors['email']='Please fill in a valid email!';
}
if(!$_POST['pass'] || strlen($_POST['pass'])<5)
{
$errors['pass']='Please fill in a valid password!<br />Must be at least 5 characters long.';
}
// Проверяем был ли запрос с помощью AJAX
if($_POST['fromAjax'])
{
if(count($errors))
{
$errString = array();
foreach($errors as $k=>$v)
{
// The name of the field that caused the error, and the
// error text are grouped as key/value pair for the JSON response:
$errString[]='"'.$k.'":"'.$v.'"';
}
// JSON ответ об ошибке:
die ('{"status":0,'.join(',',$errString).'}');
}
// JSON удачный ответ. Возвращает УРЛ для редиректа:
echo '{"status":1,"redirectURL":"'.$redirectURL.'"}';
exit;
}
// Если запрос был не AJAX (из за отключенного JS скорее всего):
if(count($errors))
{
echo '<h2>'.join('<br /><br />',$errors).'</h2>';
exit;
}
// Переправляем пользователей вручную после удачной отправки:
header("Location: ".$redirectURL);
Все полученные ошибки добавляются в массив $errors. И они потом отображаются на экране.
Вот и все готово! Пользуйтесь!