В моем последнем посте мы узнали, как проверить, были ли изменены отдельные элементы формы пользователем. Сегодня мы будем использовать эту информацию для написания кода JavaScript, который может обнаруживать обновления в любой форме.
Вот примеры и ссылки на код:
Наши предпосылки
Поскольку мы все хорошие разработчики, мы определим наши требования перед тем, как вырезать любой код:
- Мы напишем функцию FormChanges (), которая принимает один перегруженный аргумент формы — либо узел DOM формы, либо идентификатор строки.
- Функция вернет массив узлов элемента формы, которые пользователь изменил. Это позволяет нам определить, какие поля были изменены или, если массив пуст, то никакие поля не изменились.
- Функция вернет NULL, если форма не найдена.
- Мы не будем зависеть от какой-либо конкретной библиотеки JavaScript, поэтому функция остается совместимой со всеми из них.
- Он должен работать во всех современных браузерах — и IE6 или IE7.
Функция FormChanges ()
Чтобы облегчить вам жизнь, вот начало нашей функции:
function FormChanges(form) {
Мы перегружаем аргумент формы — это может быть элемент DOM, но, если это строка идентификатора, нам нужно найти этот элемент в DOM:
if (typeof form == "string") form = document.getElementById(form);
Если у нас нет узла формы, функция вернет ноль без дальнейшей работы:
if (!form || !form.nodeName || form.nodeName.toLowerCase() != "form") return null;
Теперь мы объявим переменные, которые будем использовать в функции:
- «Изменено» — это возвращенный массив элементов формы, которые были обновлены пользователем.
- ‘n’ — это узел элемента формы
- ‘c’ устанавливается в true, если элемент был изменен
- ‘def’ — опция по умолчанию для блоков выбора
- «o», «ol» и «opt» — временные переменные, используемые в циклах
var changed = [], n, c, def, o, ol, opt;
Теперь мы можем запустить наш основной цикл, который проверяет каждый элемент формы по очереди. Первоначально для параметра c установлено значение false, указывающее, что в проверяемом элементе не было никаких изменений:
for (var e = 0, el = form.elements.length; e < el; e++) { n = form.elements[e]; c = false;
Далее мы извлечем имя узла (input, textarea, select) и рассмотрим его в операторе switch. Мы ищем только узлы select и not-select, поэтому оператор switch не является строго обязательным. Тем не менее, он легче для чтения и позволяет нам добавлять дополнительные типы узлов при их представлении.
Обратите внимание, что большинство браузеров возвращают имя узла в верхнем регистре, но мы играем его безопасно и всегда конвертируем строку в нижний регистр.
switch (n.nodeName.toLowerCase()) {
Первый оператор case оценивает выпадающие списки. Это самая сложная проверка, так как мы должны пройти через все дочерние элементы option
чтобы сравнить свойства selected и defaultSelected.
Цикл также устанавливает def для последней опции с атрибутом selected. Если у нас есть блок с одним выбором, тогда def сравнивается со свойством selectedIndex этого узла, чтобы убедиться, что мы обрабатываем ситуации, когда ни у одного option
или у нескольких элементов option
нет атрибута selected ( полное объяснение см. В предыдущей статье). ).
// select boxes case "select": def = 0; for (o = 0, ol = n.options.length; o < ol; o++) { opt = n.options[o]; c = c || (opt.selected != opt.defaultSelected); if (opt.defaultSelected) def = o; } if (c && !n.multiple) c = (def != n.selectedIndex); break;
Теперь нам нужно обработать элементы input
и textarea
. Обратите внимание, что наш case "textarea":
не использует разрыв, поэтому он попадает в case "input":
code.
Флажки и радиоэлементы имеют свои свойства selected и defaultChecked по сравнению, в то время как все другие типы имеют свое значение по сравнению с defaultValue
// input / textarea case "textarea": case "input": switch (n.type.toLowerCase()) { case "checkbox": case "radio": // checkbox / radio c = (n.checked != n.defaultChecked); break; default: // standard values c = (n.value != n.defaultValue); break; } break; }
Если значение c равно true, элемент изменился, поэтому мы добавляем его в измененный массив. Цикл завершен:
if (c) changed.push(n); }
Нам просто нужно вернуть измененный массив и завершить функцию:
return changed; }
Пример использования
Предположим, мы создали следующую форму:
<form id="myform" action="index.html" method="post"> <fieldset> <legend>Your profile</legend> <input type="hidden" id="changed" name="changed" value="yes" /> <div> <label for="name">name:</label> <input type="text" id="name" name="name" value="Jonny Dough" /> </div> <div> <label for="job">job title:</label> <select id="job" name="job"> <option>web designer</option> <option selected="selected">web developer</option> <option>graphic artist</option> <option>IT professional</option> <option>other</option> </select> </div> <div> <button type="submit">Update Profile</button> </div> </fieldset> </form>
Мы можем проверить, изменил ли пользователь какие-либо поля формы, используя такой код, как:
var changed = FormChanges("myform"); alert(changed.length + " field(s) have been updated.");
Или, если никаких изменений не произошло, мы можем изменить скрытое значение «изменено» на «нет» при отправке формы. Это позволило бы коду на стороне сервера пропускать проверку полей и обновления базы данных:
var form = document.getElementById("myform"); form.onsubmit = function() { if (FormChanges(form).length == 0) { document.getElementById("changed").value = "no"; } return true; }
(Примечание: изменение «да» на «нет» изящно ухудшается, поскольку, если JavaScript не доступен, сервер всегда будет обрабатывать входящие данные.)
Я надеюсь, что вы найдете это полезным.