Пишем регистрацию на PHP и JavaScript – Часть 2: JavaScript

Всем привет! Сегодня у нас вторая часть статьи о регистрации, посвященная валидации на клиенте с помощью JavaScript.

Валидация форм на клиенте перед отправкой позволяет снизить нагрузку на сервер (так как некорректные данные не отправляются на сервер) и делает работу с интерфейсом страницы более удобной, так как пользователю не приходится ждать перезагрузки страницы в случае, если отправляемая форма заполнена не верно. Но нельзя рассматривать такую проверку как стопроцентный фильтр некорректных данных. Пользователь может просто отключить JavaScript в браузере, кроме того запрос может исходить не только от браузера, загрузившего страничку с сервера, но и от любой другой программы и содержать данные, которые нельзя было бы отправить используя страничку, загруженную с сервера.

Перейдём к практике

Для того, чтобы сократить код и уберечь нас от лишнего стука по клавишам, напишем вот такую функцию:

1
2
3
function ge(id) {
	return document.getElementById(id);
}


В JavaScript есть обработчик события onsubmit, срабатывающий при попытке отправки формы. Как и любой другой обработчик, если он возвращает false, то браузер не выполняет стандартные действия, связанные с этим событием, в данном случае это отправка формы. В этом обработчике будет производиться вызов функции, которая будет выполнять проверку данных, которые содержит форма. В случае, если данные корректны она вернёт true и форма оправится. Если данные некорректны она вернёт false и форма не отправится. Добавим этот обработчик события к форме:

1
2
3
<form id="reg_form" action="index.php" method="post">
<!—содержимое формы -->
</form>


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

1
2
3
4
5
6
var emptyField = 'Заполните поле!',
	shortLogin = 'Cлишком короткий логин!',
	shortPass = 'Слишком короткий пароль',
	notEqualPass = 'Пароли не совпадают!',
	badMail = 'Плохое мыло!',
	notUniqueLogin = 'Пользователь с таким именем уже зарегестрирован!';


Создадим объект XMLHttpRequest для оправки ajax-запроса. Это нужно для проверки уникальности логина перед отправкой.

var  req = false;
if(window.XMLHttpRequest)
	req = new XMLHttpRequest();
else if(window.ActiveXObject)
	req =  new  ActiveXObject("Microsoft.XMLHTTP");


На нашем сайте при регистрации пользователь должен указать логин, пароль и e-mail. Все поля должны быть заполнены т.е. содержать что-то, кроме пробелов. Напишем функцию, которая будет определять “пуста” ли строка. В дальнейшем под “пустой” строкой будем понимать либо ‘’, либо строку содержащею только пробелы.

function isEmptyStr(str) {
	if(str == "") return true;
	var count = 0;
	for(var i = 0; i &lt; str.length; ++i)
		if(str.charAt(i) == " ") ++count;
	return count == str.length;
}


Думаю, тут всё понятно. Если строка не равна “”, то считаем количество пробелов в ней и, если количество пробелов равно длине строки, то считаем её пустой.

Приступим к написанию тела функции isValidForm(). Все последующие функции будут вложены в неё. Если какое-то поле заполнено некорректно, то будут выполняться схожие операции над ним. Напишем для выполнения этих операций функцию:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
function notValidField(field, str) {
		field.value = str; // Выводим инфу об ошибке в поле
		field.error = true; // Запоминаем, что поле заполнено не верно
		valid = false; // Считаем форму не валидной
		/* Вешаем обработчик события, который будет очищать поле от
			информации об ошибке при фокусе.
			При потере фокуса поля с type="password" меняют type на
			"text", чтобы информация об ошибках не заменялась звёздочками.
			При фокусе на эти поля им необходимо вернуть назад их родной type
		*/
		field.onfocus = function () { 
			if(field.id == 'pass' || field.id == 're_pass') field.type = 'password';
			if(field.error) field.value = '';						
		}
		// Обработчик, который проверяет поле на корректность при потере им фокуса.		
		field.onblur = function () {			
			if(isEmptyStr(field.value)) {
				notValidField(field, emptyField);
				if(field.id == 'pass' || field.id == 're_pass') field.type = 'text';
			} else
				field.error = false;
			switch(field.id) {
				/*Функции checkLogin(), checkMail() и  checkNoXyz()
					выполняют проверку полей по дополнительным параметрам,
					разным для каждого поля.
				*/
				case 'login' : checkLogin(); break;					
				case 'mail' : checkMail();
				case 'no_xyz': checkNoXyz();
			}			
		}		
	}


В качестве параметров она принимает некорректно заполненное поле и текст, который будет в нём отображатся. Эта функция будет вложена в isValidForm().

Напишем функции для проверки полей по дополнительным параметрам. Для проверки поля логин:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function checkLogin() {
		/*Логин не может быть короче 5 символов.
			Выводим инфу о том, что логин слишком короткий только если поле
			было заполнено ранее (!login.error).			
		*/
		if(login.value.length &lt; 5 &amp;&amp; !login.error) {
			notValidField(login, shortLogin);
		} else if(!login.error) {
		/* Если логин достаточно длинный, то отправляем асинхронный запрос
			для проверки его уникальности.
		*/
			req.open('GET', 'index.php?isset_login=' + encodeURIComponent(login.value), false);			
			console.log('index.php?isset_login=' + encodeURIComponent(login.value));
			if(req.readyState == 4  &amp;&amp; req.status  ==  200) {
				/*Если пользователь с таким логином уже есть, то
					выводим инфу об этом в поле.
				*/
				if(req.responseText == '1')
					notValidField(login, notUniqueLogin);
			}
		}			
	}


Хочу обратить внимание, что здесь используется асинхронный ajax-запрос, то есть выполнения кода останавливается до получения ответа от сервера, так как нам необходимо проверить уникальность логина до отправки формы на сервер.
Функция для проверки полей для ввода пароля и его подтверждения:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function checkPass() {
		if(!pass.error &amp;&amp; !rePass.error) {
			//Проверяем пароли на длинну и совпадают ли они.
			if(pass.value.length &lt; 5 &amp;&amp; pass.value == rePass.value) {
				notValidField(pass, shortPass);
				notValidField(rePass, shortPass);
				/*Меняем type на text, чтобы не отображаль звёздочки,
					как при вводе пароля.
				*/
				pass.type = 'text';
				rePass.type = 'text';
			//Аналогично, если пароли не совпадают.
			} else if(pass.value != rePass.value) {
				notValidField(pass, notEqualPass);
				notValidField(rePass, notEqualPass);
				pass.type = 'text';
				rePass.type = 'text';
			}
		}
	}


И функции для проверки e-mail и чекбокса. Тут всё просто: проверяем мыло на соответствие регекспу (регулярному выражению), чекбокс – на наличие галочки (checked=”true”). Регексп длинный и ужасный. Не будем вдаваться в подробности его работы.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function checkMail() {
		if(!mail.error &amp;&amp; !/^([a-z0-9])(\w|[.]|-|_)+([a-z0-9])@([a-z0-9])([a-z0-9.-]*)([a-z0-9])([.]{1})([a-z]{2,4})$/i.test(mail.value))
			notValidField(mail, 'Плохое мыло!');
	}
 
	function checkNoXyz() {
		var el = ge('no_xyz');
		if(!el.checked) {
			ge('text_no_xyz').innerHTML = 'Галочку поставь, блять!';
			valid = false;
			el.onchange = function () {
				if(el.checked) ge('text_no_xyz').innerHTML = 'Обязуюсь не творить хуйни!'
			}
		}
	}

Теперь отбираем все нужные нам элементы по id, проверяем “заполненность” полей с type=”password” и type=”text” (не забываем, что в форме есть чекбокс) и вызываем все предыдущие функции для проверки логина, паролей, мыла и чекбокса. Всё это делаем в функции isValidForm().

var elements = ge('reg_form').elements,
		login = ge('login'),
		pass = ge('pass'),
		rePass = ge('re_pass'),
		mail = ge('mail'),
		valid = true;
	//Проверяем поля с type="password" и type="text" на "заполненность"
	for(var i = 0; i &lt; elements.length; ++i) {
		if(elements[i].error) valid = false;
		if((elements[i].type == 'text' || elements[i].type == 'password') &amp;&amp; isEmptyStr(elements[i].value)) {
			notValidField(elements[i], emptyField);
			elements[i].type = 'text';
		}
	}
	/*Выполняем дополнительную проверку полей по параметрам,
		разным для каждого поля
	*/
	checkLogin();	
	checkPass();
	checkMail();
	checkNoXyz();	
	return valid;


Это всё! Регистрация работает красиво и быстро. На этом с ней покончено 🙂
Чтобы не пропустить следующие статьи в рубрике «Сайт с нуля», подпишитесь на RSS.
У нас на очереди статья о авторизации на сайте. До встречи!

Пишем регистрацию на PHP и JavaScript – Часть 1: PHP