Рубрика «JavaScript»

Проверка правильности заполнения формы

Проверка правильности заполнения полей формы на стороне клиента очень удобна для пользователей: это позволяет обнаружить и исправить ошибки еще до того, как форма будет отправлена на сервер. Однако наличие проверки на стороне клиента не гарантирует, что на сервер всегда будут отправляться корректные данные, потому что некоторые пользователи отключают JavaScript в своих браузерах. Кроме того, проверка правильности на стороне клиента не представляет защиты от злонамеренного пользователя. Поэтому проверка на стороне клиента никогда не сможет заменить проверку на стороне сервера.

JavaScript, представленный немного ниже, позволяет выполнять автоматическую проверку на стороне клиента. Чтобы воспользоваться этим кодом, достаточно просто подключить его к HTML-странице, определить CSS-стили для выделения полей, содержащих некорректную информацию, и добавить дополнительные атрибуты к элементам формы. Чтобы сделать поле обязательным к заполнению, достаточно просто добавить к нему атрибут required. Чтобы выполнить проверку правильности с помощью регулярного выражения, следует добавить атрибут pattern и присвоить ему текст регулярного выражения.

<script src="validate.js"></script> <!-- Подключить модуль проверки -->
<style type="text/css">
/*
Validate.js требует, чтобы были определены стили класса "invalid"
для отображения полей с некорректными данными, давая тем самым
пользователю отличать их визуально.
Для полей с корректными данными можно также определить необязательные стили.
*/
input.invalid { background: #faa } /* Красноватый фон для полей с ошибками */
input.valid { background: #afa } /* Зеленовытый фон для полей, заполненных правильно */
</style>
<!--
Теперь, чтобы включить проверку полей формы, нужно просто
установить атрибут required или pattern.
-->

<form>
<!-- Это поле должно быть заполнено -->
Имя: <input type="text" name="name" required /><br/>
<!--
\s* - означает необязательный пробел
\w+ - один или более алфавитно-цифровых символов
-->

Электронная почта: <input type="text" name="email" pattern="^\s*\w+@\w+\.\w+\s*" /><br/>
<!-- \d{6} означает, что должно быть введено ровно шесть цифр -->
Почтовый индекс: <input type="text" name="zip" pattern="^\s*\d{6}\s*" /><br/>
<!-- Следующее поле не проверяется -->
Непроверяемое поле: <input type="text" /><br/>
<input type="submit" value="Отправить" />
</form>

Обратите внимание: при подключении файла validate.js к HTML-файлу в глобальное пространство имен не добавляется ни одного имени, кроме того, скрипт автоматически регистрирует обработчик события onload, который выполняет обход всех форм документа, отыскивает поля с атрибутами required и pattern и в случае необходимости добавляет обработчики событий onchange и onsubmit. Эти обработчики устанавливают значение свойства className каждого элемента формы, который подвергается проверке, в значение “invalid” или “valid”, поэтому необходимо предусмотреть определение хотя бы “неправильного” (invalid) CSS-класса, чтобы обеспечить визуальное отличие полей с корректными и некорректными данными.

/**
validate.js: ненавязчивая проверка HTML-форм.

После загрузки документа данный скрипт сканирует документ в поисках
HTML-форм и текстовых полей в формах. Если обнаруживаются элементы
с атрибутами "required" или "pattern", к ним добавляются соответствующие
обработчики событий, выполняющие проверку данных формы.

Если атрибут формы имеет атрибут "pattern", значение этого атрибута
используется регулярное JavaScript-выражение, а элементу назначается
обработчик события onchange, который проверяет ввод пользователя с помощью
этого шаблона. Если данные не соответствуют шаблону, цвет фона элемента
ввода изменяется, чтобы привлечь внимание пользователя.

По умолчанию текстовое поле должно содержать некоторую подстроку, которая
соответствует шаблону. Если требуется указать более строгое соответствие,
используйте якорные элементы ^ и $ в начале и конце шаблона.

Элемент формы с атрибутом "required" должен содержать какое-либо значение.
Если быть более точным, атрибут "reqiured" является краткой формой атрибута
pattern="\S". То есть этот атрибут требует, чтобы поле содержало хотя бы
один символ, отличный от пробела.

Если элемент формы прошел проверку, в атрибут "class" этого элемента
записывается значение "valid". В противном случае - значение "invalid".
Для коррекной работы validate.js необходимо вместе с ним использовать
таблицу CSS-стилей, где определяются стили для "неправильного" класса.
Например

<!-- Для привлечения внимания окрасить фон элементов формы,
     содержащих ошибки, в оранжевый цвет -->
<style type="text/css">input.invalid {background: #fa0; }</style>

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

Этот код не может использоваться для проверки форм или полей, в которых
вы определили собственный обработчик событий onchange или onsubmit,
а также полей, для которых вы определили свое значение атрибута class.

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


(function() { // Все, что требуется, выполняется внутри анонимной функции
    // По окончании загрузки документа вызвать функцию init()
    if (window.addEventListener)
        window.addEventListener("load", init, false);
    else if (window.attachEvent)
        window.attachEvent("onload", init);

    // Устанавливает обработчики событий для форм и элементов форм,
    // где это необходимо
    function init() {
        // Цикл по всем формам в документе
        for(var i = 0; i < document.forms.length; i++) {
            var f = document.forms[i]// текущая форма

            // Предположить, что форма не требует проверки
            var needsValidation = false;

            // Цикл по всем элементам текущей формы
            for(j = 0; j < f.elements.length; j++) {
                var e = f.elements[j]// текущий элемент

                // Интерес представляют только поля <input type="text">
                if (e.type != "text") continue;

                // Проверить, имеются ли атрибуты, требующие проверки
                var pattern = e.getAttribute("pattern");
                // Можно было бы использовать e.hasAttribute()
                // но MS IE не поддерживает его
                var required = e.getAttribute("required") != null;

                // Атрибут required - это лишь краткая форма записи
                // атрибута pattern
                if (required && !pattern) {
                    pattern = "\\S";
                    e.setAttribute("pattern", pattern);
                }

                // Если элемент требует проверки,
                if (pattern) {
                    // проверять при каждом изменении содержимого элемента
                    e.onchange = validateOnChange;
                    // Запомнить, чтобы потом добавить обработчик onsubmit
                    needsValidation = true;
                }
            }

            // Если хотя бы один элемент формы требует проверки,
            // то необходимо установить обработчик события onsubmit формы
            if (needsValidation) f.onsubmit = validateOnSubmit;
        }
    }
         
    // Эта функция - обработчик события onchange для текстового поля, которое
    // требует проверки. Не забывайте, что в функции init() мы преобразовали
    // атрибут required в pattern
    function validateOnChange() {
        var textfield = this;                            // текстовое поле
        var pattern = textfield.getAttribute("pattern"); // шаблон
        var value = this.value;                          // данные, введенные пользователем

        // Если значение не соответствует шаблону, установить
        // значение атрибута сдфыы равным "invalid"
        if (value.search(pattern) == -1) textfield.className = "invalid";
        else textfield.className = "valid";
    }

    // Эта функция - обработчик события onsubmit для любой формы,
    // требующей проверки
    function validateOnSubmit() {
        // Перед отправкой формы выполнить проверку всех полей в форме
        // и установить их свойства className в соответствующее значение.
        // Если хотя бы одно из этих полей содержит ошибку, вывести диалоговое
        // окно и заблокировать отправку данных формы.
        var invalid = false// Предполагаем, что все правильно
        // Цикл по всем элементам формы
        for(var i = 0; i < this.elements.length; i++) {
            var e = this.elements[i];
            // Если элемент - это текстовое поле, для которого установлен
            // наш обработчик события onchange
            if (e.type == "text" && e.onchange == validateOnChange) {
                e.onchange(); // Вызвать обработчик для повторной проверки
                // Если проверка не пройдена - значит вся форма не прошла проверку
                if (e.className == "invalid") invalid = true;
            }
        }

        // Если форма не прошла проверку, вывести диалоговое окно
        // и заблокировать отправку формы
        if (invalid) {
            alert("Форма заполнена не полностью или были введены некорректные данные.\n" +
                  "Пожалуйста, проверьте правильность выделенных полей и повторите попытку.");
            return false;
        }
    }
})();

Корзина для Интернет-магазина средствами JavaScript

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

Учитывая, что многие Интернет-магазины предлагают лишь ограниченное число товаров (менее 100), все товары в этом случае могут быть отображены в одной большой таблице.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<html>
<title>Интернет-магазин</title>
<meta http-equiv="content-type" content="text/html; windows-1251" />
<script type="text/javascript">
var goods = new Array();
goods = [  
  ["M005","Монитор Acer AL1916CS","Описание Acer AL1916CS",6000],
  ["M006","Монитор Acer AL2216WSD","Описание Acer AL2216WSD",8900],
  ["M007","Монитор Acer AL2416WBSD","Описание Acer AL2416WBSD",15000],
  ["M009","Монитор BenQ G700","Описание BenQ G700",4800],
  ["M008","Монитор BenQ G900W","Описание BenQ G900W",5000],
  ["M003","Монитор Samsung 2043NW","Описание Samsung 2043NW",7000],
  ["M001","Монитор Samsung 740N","Описание Samsung 740N",5700],
  ["M002","Монитор Samsung 943N","Описание Samsung 943N",6430],
  ["M004","Монитор Samsung SM2232BW","Описание Samsung SM2232BW",11500],
  ["N001","Ноутбук Acer Aspire 5315","Описание Acer Aspire 5315",14500],
  ["N002","Ноутбук Acer Extensa 5220","Описание Acer Extensa 5220",15500],
  ["N003","Ноутбук Samsung R20","Описание Samsung R20",15800],
  ["N004","Ноутбук Samsung R60","Описание Samsung R60",20100],
  ["N006","Ноутбук Toshiba A210-199","Описание Toshiba A210-199",17000],
  ["N005","Ноутбук Toshiba A210-19A","Описание Toshiba A210-19A",24700],
  ["P001","Принтер EPSON PictureMate 290","Описание EPSON PictureMate 29",7300],
  ["P002","Принтер EPSON Stylus Photo R270","Описание EPSON Stylus Photo R270",3650],
  ["P003","Принтер EPSON Stylus Photo R390","Описание EPSON Stylus Photo R390",6200]
];
 
var count = goods.length;
var orders = new Array();
for( var i = 0; i < count; i++ ) orders[i] = 0;

var param = getCookie( "basket" );
for( var i = 0; i < count; i++ ) {
  pos = param.indexOf( ',' );
  if( pos == -1 ) break;
  orders[i] = parseInt( param.substring ( -1, pos ) );
  param = param.substring ( pos+1 );
}

window.onload = function() {
  var table = createTable(goods);   
  document.getElementById("shop").appendChild(table);
}
 
function updateTable()
{
  var totalGoods = 0;
  var totalCosts = 0;
  var basket = "";
  for ( var i = 0; i < count; i++ ) {
    var item = document.getElementById( "item"+i );
    var cnt = parseInt( item.value );
    if ( isNaN(cnt) || cnt < 0 ) {
      cnt = 0;
      item.value = "0";
    }
    if ( cnt > 0 )
      item.parentNode.parentNode.setAttribute("bgcolor", "lightblue");
    else
      item.parentNode.parentNode.removeAttribute("bgcolor")
    orders[i] = cnt;
    basket = basket + cnt + ",";
    totalGoods = totalGoods + cnt;
    totalCosts = totalCosts + cnt*goods[i][3];
  }
  var span = document.getElementById("totalGoods");
  var newTextNode = document.createTextNode(totalGoods);
  span.replaceChild(newTextNode, span.firstChild);
  var span = document.getElementById("totalCosts");
  var newTextNode = document.createTextNode(totalCosts);
  span.replaceChild(newTextNode, span.firstChild);
 
  setCookie("basket", basket);
}

function createTable(data) {
  var table = document.createElement("table");
  table.setAttribute("border", "1");
  table.setAttribute("cellspacing", "0");
  table.setAttribute("cellpadding", "2");
  var thead = document.createElement("thead");
  var tr = document.createElement("tr");
  tr.setAttribute("bgcolor", "lightgrey");
  var head = new Array("Код","Наименование","Описание","Стоимость","Количество");
  for (var i = 0; i < head.length; i++) {
    var th = document.createElement("th");
    var newText = document.createTextNode(head[i]);
    th.appendChild(newText);
    tr.appendChild(th);
  }
  thead.appendChild(tr);
  table.appendChild(thead);

  var totalGoods = 0;
  var totalCosts = 0.0;
 
  var tbody = document.createElement("tbody");
  for (var i = 0; i < data.length; i++) {
    var tr = document.createElement("tr");
    if ( orders[i] > 0 ) tr.setAttribute("bgcolor", "lightblue");
    for (var j=0; j < data[i].length; j++) {
      var td = document.createElement("td");
      var newText = document.createTextNode(data[i][j]);
      td.appendChild(newText);
      tr.appendChild(td);
    }
    var td = document.createElement("td");
    var newInput = document.createElement("input");
    newInput.setAttribute("type", "text");
    newInput.setAttribute("id", "item"+i);
    newInput.setAttribute("value", orders[i]);
    newInput.setAttribute("size", "3");
    newInput.onblur = updateTable;
    td.appendChild(newInput);
    tr.appendChild(td);
    tbody.appendChild(tr);

    totalGoods = totalGoods + orders[i];
    totalCosts = totalCosts + orders[i]*goods[i][3];
  }
  var tr = document.createElement("tr");
  var td = document.createElement("td");
  td.setAttribute("colspan", "3");
  td.setAttribute("align", "right");
  var textNode = document.createTextNode("Итого:");
  td.appendChild(textNode);
  tr.appendChild(td);
  var td = document.createElement("td");
  var span = document.createElement("span");
  span.setAttribute("id", "totalCosts");
  var textNode = document.createTextNode(totalCosts);
  span.appendChild(textNode);
  td.appendChild(span);
  tr.appendChild(td);
  var td = document.createElement("td");
  var span = document.createElement("span");
  span.setAttribute("id", "totalGoods");
  var textNode = document.createTextNode(totalGoods);
  span.appendChild(textNode);
  td.appendChild(span);
  tr.appendChild(td);
  tbody.appendChild(tr);

  table.appendChild(tbody);
  return table;
}

function setCookie(name,value)
{
  document.cookie = name + '=' + value;
}   

function getCookie(name)
{
  var arg = name + "=";
  startpos = document.cookie.indexOf(arg, 0);
  if (startpos == -1)
    return "";
  else
    startpos += arg.length;
  endpos = document.cookie.indexOf(';', startpos);
  if (endpos == -1) endpos = document.cookie.length;
  return document.cookie.substring(startpos, endpos);
}
</script>


</head>
<body>

<div id="shop"></div>

</body>
</html>

В приведенном выше листинге все имеющиеся товары выводятся в виде таблицы. Строка со списком количества всех заказанных товаров для всех наименований сохраняется в cookie (переменная basket).

Количество товаров содержится в переменной count. В массиве orders хранится количаство заказанных товаров соответствующего наименования. Заказанные единицы товара всех наименований перечисляются через запятую, даже если заказано нулевое количество любого товара. При построении таблицы ведется расчет общего количества заказанных товаров (переменная totalGoods) и суммарной стоимости заказанных товаров (переменная totalCosts). Финальные значения переменных totalGoods и totalCosts выводятся в последней строке таблицы.

Ссылки по теме:

Ограничение количества вводимых символов для textarea

Для элементов input доступно такое свойство, как maxlength, которое позволяет ограничить количество вводимых в эти поля символов. Однако для textarea такой атрибут не существует, и поэтому для ограничения ввода нужно использовать JavaScript.

<script type="text/javascript">
function limitText(limitField, limitCount, limitNum) {
    if (limitField.value.length > limitNum) {
        limitField.value = limitField.value.substring(0, limitNum);
    } else {
        limitCount.value = limitNum - limitField.value.length;
    }
}
</script>

Пример использования функции:

<form name="myform">
<textarea name="message" onKeyDown="limitText(this,this.form.count,20);"
onKeyUp="limitText(this,this.form.count,20);">

</textarea><br />
<span style="font-size:smaller">(не более 20 символов)</span><br/>
<input readonly type="text" name="count" size="3" value="20"/> символов осталось.
</form>

Так можно поступить и с обычной строкой ввода (type=”text”).