Как стать автором
Обновить

Комментарии 38

НЛО прилетело и опубликовало эту надпись здесь
Ага — забыл (= Со стилями оформления заморочился ((= хехе
Надеюсь, Хабр не дойдёт до того, что на основе анализа длины топика будет выводить самостоятельно: «НЛО прилетело и предложило сделать хабракат» с соответствующим уведомлением на почту. (-:

Мне кажется достаточно было бы делать это всё на уровне заполнения формы, когда топик ещё пишется.
А это НЛО было?? 8-0 ((=
Ну вот это решение уже можно назвать законченным! :)
Раньше, когда интернет был медленнее, часто встречал проблему: форму отправил, а запрос оборвался. Лучший способ — нажать еще раз на кнопку, а она disabled.
Имхо лучше обрабатывать такие проблемы на стороне сервера.
Можно таймер сделать, предотвращающий «дребезг контактов», то есть случайное быстрое нажатие, а то тоже ситуации могут быть, случайно нажал два раза допустим на кнопке «регистрация» а тебе приходит ответ «такой ник уже есть», хотя первую форму сервер обработал нормально и зарегистрировал.
Можно и так сделать. Я бы сделал для каждой формы уникальный ID (например md5(time().rand())) и проверять — отправлялась ли такая форма уже — есть ли такой ID во временной таблице.
Я так пробовал — это то же самое, что дизейблить кнопку. В результате с закэшированной страницы исправленную форму по второму разу не отправишь.
Тогда можно модифицировать этот ID на стороне клиента в событии onunload.
А как об этом узнает сервер?
Тогда этот код может быть хешем данных. Простым crc32 или чем-то подобным. То что хеш не повторялся — гарантия уникальности данных.
Хотя это очень сложно, отправка формы дважды не такая уж и частая ситуация, чтобы с ней так заморачиваться.
uploadForm.setFormLoading(form);

Все ли верно?
Ага, спасибо, поправил (=
Это какой-то бред.

Вам не кажется что вы совсем уж извратились? К тому же ничего не мешает юзеру при тормозах нажать F5 и повторно отправить запрос.

> Если после сабмита формы вновь вернуться на страницу с формой (по кнопке «Назад» в браузере), то сработает кеширование: мы столкнемся с неактивными кнопками и не сможем отправить форму еще раз

Если все сделано правильно (и после обработки действия скрипт редиректит пользователя на GET-страницу) мы вернемся не на предыдущую страницу, а выводжит предупреждение «Вы хотите повторно отправить форму?».

> Кнопки возвращаем в активное состояние до ухода со страницы по событию window.onunload

А в нормальных браузерах работает onunload?
> Вам не кажется что вы совсем уж извратились? К тому же ничего не мешает юзеру при тормозах нажать F5 и повторно отправить запрос.

с аяксом этот фокус не пройдёт.

> Если все сделано правильно…

то мы дадим пользователю возможность отредактировать форму прежде чем отправлять повторно.

> А в нормальных браузерах работает onunload?

да, но не во всех.
> А в нормальных браузерах работает onunload?
Скрипт проверен на Fire Fox, Google Chrome, Opera, Safari, Ie 6, Ie 7
ну ставить disable у кнопок это последнее дело, пользователя вашего сайта это может сильно раздражить, и тогда он может вообще не вернуться на этот сайт. Более понравилось решение с проверкой на стороне сервера. Но это моё мнение, давайте проведем эксперимент по подсчету посетителей до введения такого хака и после)
Ну, может раздражать, а может и не раздражать. Меня бы больше огорчило, если бы из-за случайного двойного нажатия на кнопку случилась какая-нибудь ошибка.

А как вам, автор, вариант с добавлением на страницу полупрозрачного слоя с индикатором загрузки, подобного тем, что используются во всяких thickbox и тому подобных JS modal dialogs? Проблему, на первый взгляд, решает.
Я лично предпочитаю обходить слишком сильную визуализацию. Меня она угнетает (= Но ваш вариант тоже вполне приемлим (= На самом деле, когда мы говорим про disable кнопок, мы скорее все же думаем о том, чтобы сделать для пользователя более очевидными какие-то его действия, чем решаем техническую проблему (=
Ну да, ну да. В этом плане я согласен скорее с вами, чем с комментатором. То есть, лично у меня никаких вопросов не возникает, когда кнопка дизэйблится. Напротив, приходит понимание, что всё окей)))
Еще важно не забывать о CSRF (Cross-Site Request Forgery) атаках:
* isc.sans.org/diary.html?storyid=1750
* en.wikipedia.org/wiki/Cross-site_request_forgery

Решение состоит в том, что:
* при показе формы в сессию и хидден поле кладется ключ
* при отправке формы проверяется ключ из формы с ключом из сессии
* как только получили запрос, из сесии ключ стерли

Пример реализации в Rails api.rubyonrails.org/classes/ActionController/RequestForgeryProtection/ClassMethods.html
Спасибо, раньше разрабатывал лишь интуитивно практикуя правило «изменяет только POST».
Хорошее правило, так и надо делать ;)
Решение с использованием популярного фреймворка jQuery:

(function($) {
    $.enhanceFormsBehaviour = function() {
        $('form').enhanceBehaviour();
    }

    $.fn.enhanceBehaviour = function() {
        return this.each(function() {
            var submits = $(this).find(':submit');
            submits.click(function() {
                var hidden = document.createElement('input');
                hidden.type = 'hidden';
                hidden.name = this.name;
                hidden.value = this.value;
                this.parentNode.insertBefore(hidden, this)
            });
            $(this).submit(function() {
                submits.attr("disabled", "disabled");
            });         
            $(window).unload(function() {
                submits.removeAttr("disabled");
            })
         }); 
    }
})(jQuery);


Вместо formUploader.prepareForm(document.getElementById('the_form')); нужно написать $.enhanceFormsBehaviour()

Скоро оформлю в виде полноценного плагина, с функциями отклика (callback), на которые можно будет повесить показ различных крутилок-вертелок и иных действий, символизирующих работу формы.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Хороший плагин. Универсальный и большой. Предложенный мною код меньше, ориентирован на конкретную проблему/задачу и является просто уменьшенным вариантом описанного в статье кода. Возможно, пригодится кому-нибудь (как минимум, мне самому).
НЛО прилетело и опубликовало эту надпись здесь
Селектор :submit ловит не только инпуты-сабмиты, но и баттоны-сабмиты.

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

На AJAX запросах нужно сбрасывать disable при любом ответе с сервера, в т.ч. и при ответе, сигнализирующем ошибку заполнения формы.

При обычном POST мною был найден именно вариант с window.onunload. Попробуйте найти другой метод, было бы интересно (=

Слой тоже можно вешать, но решалась проблема, связанная именно с disable кнопок.
Да, и еще если будут подобные вопросы.

В макете кода события задаются как form.onsubmit и window.onunload. Это сделано опять же для легкости чтения. По-правильному надо бы добавлять такие обрабтчики через специальные пользовательские функции, типа addEvent(form, 'submit', myFuntion), чтобы не вступить в конфликт с другими возможными функциями, привязанными к тому же событию…
Кстати, использование jQuery решает эту проблему, потому как у ней внутре неонка внутренняя реализация событий в этом фреймворке как раз использует подобное решение.
а о каком именно плагине тут рассказывал НЛО?
// при уходе со страницы — по шлобальному событию onunload

забавно, получается ))
Хорошо еще, что не получилось по жлобальному (=
p.s. спасибо, поправил
Не стал читать весь тред. Может уже было выше.
Сценарий таков:
-Пользователь заполняет форму
-Кликает Submit
-Кнопки лочатся
-Пользователь ошибается при заполнении
-На форме отмечаются ошибки ввода
-Кнопки все еще недоступны, нужно поправить поля с ошибками, чтобы кнопка Submit снова стала доступна

Как такой сценарий? По-мойму отличный ограничитель ограничитель бессмысленных кликов и потеряных нервов.
Я бы при обнаружении ошибки скорее отлочил бы кнопки. Чтобы тот, кто не понял, что произошла ошибка, кликнул бы по кнопке разок и был бы переброшен по этому действию к полю с ошибкой.

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