Обработка форм на JavaScript

Octane, 09.09.2008

В этой статье разберем наиболее эффективную модель построения обработчиков элементов веб-интерфейсов на примере HTML-форм. Для понимания материала, изложенного в этой статье, от Вас потребуется знание объектной модели JavaScript.

Обычно встречаются 2 ситуации неправильно организованного алгоритма обработки веб-форм:

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

Если со второй ситуацией все ясно, со временем, такие программисты могут начать писать более грамотный код, то на первом случае остановимся поподробнее.

Почему же не стоит пытаться реализовать полноценный шаблон MVC на JavaScript? Потому что в большинстве случаев работа с объектом требует обновления внешнего вида, а межкомпонентные связи «View» и «Model» добавляют много лишнего, ничем не оправданного кода, который к тому же снижает производительность.

Controller пусть остается отдельно, а Model от View отделять не надо. Особенности Javascript/DOM/CSS позволяют успешно реализовывать аспекты Model средствами View

javascript.ru

Если Вы активно применяете принципы MVC в своей практике, то на время прочтения этой статьи постарайтесь их забыть вообще.

Обработка форм

Итак, в начале статьи говорилось, что мы будем рассматривать модель обработчика элемента веб-интерфейса на примере HTML-форм.

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

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

function $(id) {
  return document.getElementById(id);
}

Всего лишь сокращаем запись получения ссылки на DOM-узел по идентификатору. Эта функция обычно уже есть в Вашем наборе частоиспользуемых методов или входит в состав используемого в проекте фреймворка.

Воспользуемся функцией-конструктором, для создания объекта — обработчика формы:

function Form(id) {
  this.form = $(id);
}

Функция «Form» создает объект, с атрибутом «form», содержащим ссылку на HTML-форму, полученную по идентификатору. Для чего функция, если можно сразу записать объект, спросите Вы? Для того, чтобы было возможно использовать «prototype».

Добавим в «prototype» функции «Form» набор методов, которые будут использоваться в каждой форме нашего проекта:

Form.prototype = {

  // функция init принимает 3 входных параметра;
  // submit - функция, срабатывющая по событию формы onsubmit;
  // success - функция вызываемая в результате
  // успешной обработки формы;
  // error - функция вызываемая при ошибке.
  init: function(submit, success, error) {

    // добавляем принятые функции, как методы текущего объекта
    this.submit = submit;
    this.success = success;
    this.error = error;

    // создаем атрибут, отвечающий за состояние формы
    this.enabled = true; // включена

    // создаем функцию, которая будет вызвана
    // по событию формы onsubmit
    var _this = this, listener = function() {

      // функция process находится в прототипе функции Form
      // и служит для выполнения дополнительных операций
      // при вызове переданной пользователем функции submit
      _this.process();

      // предотвращаем стандартное действие отправки данных
      // формы на сервер по событию onsubmit
      var ev = arguments[0] || window.event;
      ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
    };

    // добавляем созданный выше обработчик listener
    // к событию формы onsubmit
    // для нормальных браузеров
    if(this.form.addEventListener)
      this.form.addEventListener('submit', listener, false);
    // для IE
    //@cc_on this.form.attachEvent('onsubmit', listener);
  },

  // функция process выполняет дополнительные действия
  // при вызове указанной пользователем функции submit
  process: function() {
    if(this.enabled) { // если форма включена
      this.enabled = false; // отключаем форму
      this.submit(); // вызываем функцию submit
    }
  },

  // функция message управляет отображением сообщений
  // об ошибках и удачной отправке данных
  message: function(text) {
    // здесь должен находиться код, отвечающий
    // за способ отображения сообщений форм
    // конкретного проекта
    alert(text);
  }
};

Таким образом, мы создали конструктор объекта — обработчик формы, в списке методов которого есть 3 функции:

  1. «init» — функция, с которой будет начинаться работа с каждой формой. Она расширяет каждый новый объект, функциями, указанными программистом. Создает атрибут «enabled», отвечающий за состояние формы (влючена/выключена), для предотвращения повторной отправки данных, а так же отключает стандартное поведение формы по событию «onsubmit».
  2. «process» — выполняет дополнительные операции, присущие всем формам конкретного проекта, перед запуском указанной программистом функции «submit».
  3. «message» — управляет отображением информации об ошибках и успешной отправке. Должна быть тесно связана с версткой и оформлением форм в рамках конкретного проекта.

Как же теперь все это использовать? Да очень просто, а главное удобно:

// создаем новую копию объекта Form
// для HTML-формы с идентификатором "my-form"
var myForm = new Form('my-form');

// вызываем метод init и передаем ему 3 функции
myForm.init(

  // submit
  function() {
    // здесь должен находится код, отвечающий 
    // за обработку конкретной формы, например,
    // здесь мы проверяем, не пусты ли поля ввода
    // с идентифкаторами "log" и "pwd"?
    $('log').value && $('pwd').value ? this.success() : this.error();
  },

  // success
  function() {
    // показываем пользователю сообщение об
    // успешной передаче данных
    this.message('Успешно');
  },

  // error
  function() {
    // показываем сообщение об ошибке
    this.message('Ошибка');
    // включаем форму для того,
    // чтобы пользователь имел возможность
    // повторить попытку снова
    this.enabled = true;
  }
);

Функция «submit» должна содержать код, проверяющий правильность ввода данных, выполняющий отправку данных формы на сервер через AJAX и вызывающий функции успешного выполнения операции (success) или ошибки (error) отправки или некорректного ввода данных пользователем.

В некоторых проектах функции «success» и «error» можно разместить в «prototype» функции-конструктора «Form», если способ отображения сообщений совершенно ничем не будет отличаться во всех формах проекта.

Чтобы добавить что-то еще, не предусмотренное функционалом метода «init», но необходимое для работы конкретной формы, можно использовать созданную ссылку на новую копию объекта «Form», например:

myForm.form.getElementsByTagName('input')[0].onfocus = function() {
  // какой-то код…
};

Вывод

Таким образом, мы создали обработчик HTML-форм в рамках одного конкретного проекта. Самым главным достоинством такого подхода является то, что написав подобный обработчик, при создании каждой новой формы Вам не придется задумываться о коде, отвечающем за ее оформление, которое в большинстве случаем в рамках одного проекта для всех форм одинаковое.

Этот же принцип можно применять и для других элементов веб-интерфейса.

Полезно почитать

Отвлекитесь от программирования и уделите внимание оформлению форм. Советую прочесть статью «Кроссбраузерное выравнивание кнопок-изображений в формах», сэкономите себе много времени в итоге.

Подписаться на обновления блога

Вам понравился наш блог, хотите следить за обновлениями? Подпишитесь на RSS рассылку или рассылку по электронной почте. Так же вы можете следить за нами в Twitter.

Категории: JavaScript | Комментировать

Комментарии

  1. ponedilok / 09.09.2008 в 12:36

    Я хоть и отношусь к категории 2, но описанное оказалось ново и полезно :)

  2. Snail / 21.05.2009 в 11:01

    Тоже не первый год работаю с ОО языками, в особенности с js и php, и описание интересно, структурировано и полезно..
    Автору ++!!;))

  3. edsfd / 15.01.2010 в 04:53

    ssd

  4. Ярослав / 30.01.2010 в 15:20

    Добрый день! Подскажите, где найти информацию о разработке на JavaScript форм для пересчета цифр?

Оставить комментарий

480×60
480×60