В тази статия ще се опитам да ви покажа как лесно да направите валидация на форми с HTML5. Не че няма сигурно хиляди модули за всяка възможна библиотека или фреймуърк, обаче те ще ви наложат техния интерфейс и начин на задаване на ограниченията върху полетата, а това може и да не е по вкуса ви. Често пъти за да са съвместими с по-старите браузъри такива модули са доста тежки.
Всъщност като за начало не е необходимо да правите почти нищо, достатъчно е да използвате подходящи типове на полетата, като например type=“email“ за полетата за имейл, type=“numeric“ за числовите полета и т.н. Добавете атрибута required за задължителните полета и готово. Ако имате по-специални изисквания за формата на някое поле, можете да използвате атрибута pattern, в който да зададете подходящ регулярен израз. За телефон например можете да използвате нещо такова: pattern=“(+|00?)?[\d\s-\/()#]+“ – телефонът трябва да започва с + или една или две нули и да съдържа цифри, евентуално интервал, скоби или #. Да видим пример:
<div>
<label for="name">Име*</label>
<input id="name" name="name" required="required" type="text" />
</div>
<div>
<label for="email">Имейл*</label>
<input id="email" name="email" required="required" type="email" />
</div>
<div>
<label for="phone">Телефон*</label>
<input id="phone" name="phone" pattern="(+|00?)?[аs-/()#]+" required="required" type="tel" />
</div>
<div>
<button type="submit">Изпрати</button>
</div>
Тази форма ще работи почти идеално – няма да можете да я изпратите ако данните са невалидни, потребителят ще получи обратна връзка от браузъра с индикация какво не е попълнено правилно… но! Видът на съобщенията може да не е точно желания от Вас, текстът най-вероятно ще е доста лаконичен и при това на език, различен от езика на сайта. И трите проблема са лесно решими със съвсем малко CSS и JavaScript. Нека първо се опитаме да оформим по-добре полетата с малко CSS:
input {
border: 1px solid #999;
border-radius: .25em;
}
input:invalid {
border-color: #900;
box-shadow: none;
}
input:valid {
border-color: #090;
}
Замисълът на този CSS е прост – оформили сме основния вид на полетата и чрез псевдокласовете :invalid и :valid задаваме различен цвят на контура ако полето не е попълнено правилно или ако е. Ако го сложите обаче в сайта си, веднага ще забележите проблем – задължителните полета веднага ще добият червен контур, защото преди да ги попълни потребителя те са невалидни. За да избегнем това ще „активираме“ псевдокласовете след като потребителя вече е взаимодействал с полето. Просто ще добавим един клас на полето когато потребителят го напусне и ще променим стиловете така, че да важат само за комбинацията от този клас и състоянието на полето:
.interacted:invalid {
border-color: #900;
}
.interacted:valid {
border-color: #090;
}
var inputs = document.querySelectorAll('input');
inputs.forEach(function(input, i, array){
input.addEventListener('blur', function(e){
input.classList.add('interacted');
}, true);
});
Една забележка: тук и по-надолу съм използвал forEach върху nodeList, а това е метод на Array, който не е достъпен за nodeList. Най-лесното, но силно недолюбвано решение е:
NodeList.prototype.forEach = Array.prototype.forEach;
В демонстрацията, която подготвих, използвах един не толкова удобен, но по-безопасен вариант:
var forEach = function(ctn, callback){
return Array.prototype.forEach.call(ctn, callback);
}
И така, решихме проблема с вида на полето когато е невалидно и обратно, когато е валидно. Обаче ако езикът на браузъра не е български, и съобщенията, които браузъра показва за невалидните полета, няма да са на български. На мен ми хрумна решение на този проблем (а то се оказа и документирано в MDN). Свойството validity на DOM елемента е обект, чиито свойства показват кои от ограниченията на стойността на полето не са изпълнени. Ако проверим стойностите, можем чрез метода setCustomValidity() да зададем собствен текст на съобщението за грешка. В следващия код съобщението отразява само една от грешките, но за вас няма да е трудно да го промените да показва всички грешки в едно съобщение.
function setValidationMessage(el){
var validity = el.validity;
if( validity.valid ) {
el.setCustomValidity('');
return;
}
if( validity.valueMissing ){
el.setCustomValidity('Полето е задължително, моля, въведете стойност.')
}
if( validity.typeMismatch ){
el.setCustomValidity('Въвели сте невалидна стойност.')
}
if( validity.patternMismatch ){
el.setCustomValidity('Въведената стойност не отговаря на формата на полето.')
}
if( validity.rangeOverflow ){
el.setCustomValidity('Въведената стойност е по-голяма от максималната позволена.')
}
if( validity.rangeUnderflow ){
el.setCustomValidity('Въведената стойност е по-малка от минималната позволена.')
}
if( validity.tooLong ){
el.setCustomValidity('Въведеният текст е твърде дълъг.')
}
}
inputs.forEach(function(input, i, array){
input.addEventListener('blur', function(e){
this.setCustomValidity('');
setValidationMessage(this);
}, true);
});
Сега вече съобщенията са на български и потребителите са доволни, че разбират какъв е проблема. Но какво да направим с вида на съобщенията? Тъй като няма начин да оформим вградените в браузъра балончета, ще ги избегнем изцяло и ще показваме съобщенията сами. За нуждите на тази статия ще сложа текста под полето в един параграф. И когато съобщението е невалидно, в параграфа ще слагам стойността на свойството validationMessage, която след предишната интервенция вече съдържа обяснителен текст на български. А за да не се показват балончетата на браузъра просто ще извикаме метода preventDefault() на събитието invalid.
<div>
<label for="email">Имейл*</label>
<input id="email" name="email" required="required" type="email" />
<p></p>
</div>
inputs.forEach(function(input, i, array){
var p = this.parentNode.getElementsByTagName('p')[0];
input.addEventListener('invalid', function(e){
e.preventDefault();
}, true);
input.addEventListener('blur', function(e){
if(this.checkValidity()){
p.innerHTML = '';
}
else {
p.innerHTML = this.validationMessage;
}
}, true);
});
That’s all, folks! Вече имаме наша си валидация – можем да я оформим както си искаме, да сложим каквито искаме съобщения, но не се налага да измисляме топлата вода по отношение на същинското валидиране на стойностите.
– А к’во пра’им със старите браузъри?
Ами ш’ги китнем малко да запълним дупката, напра’о ш’ги тунинговаме. Първоначално си опитах да използвам H5F на Ryan Seddon, но нещо не сработи добре и като не си намерих грешката реших да опитам нещо друго. След кратко търсене намерих webshims на Alexander Farkas, който китна идеално IE9 и освен това добави и други неща от които имах нужда по-късно, като например URLUtils.
Естествено, за старите браузъри има и друг вариант – да не правите нищо от страна на клиента. Така или иначе валидацията на сървъра ще върне потребителя обратно с подробно обяснение на грешките.
– А к’во пра’им ако няма JavaScript?
Има разни причини, поради които вашия скрипт може да не сработи при някой клиент – може потребителя да е изключил въобще JavaScript, може бъг във вашия скрипт или в браузъра да предизвика грешка, може поради проблеми в мрежата скриптът въобще да не се изтегли или да бъде блокиран от прекалено рестриктивна защитна стена. За да сме сигурни, че ще имаме основна функционалност и без JS можем да използваме пра-стария трик с клас на елемента body или html, който бива подменен от JS, и на базата на него да нагласим стиловете да работят по подходящ начин.
Ако искате да видите горните неща в действие, на тази демонстрационна страница има няколко форми, върху които са приложени отделните стъпки от статията.
Етикети: howto, HTML, HTML5, javascript