Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   Программный вызов обработчика события (https://javascript.ru/forum/events/6731-programmnyjj-vyzov-obrabotchika-sobytiya.html)

TheRoSS 18.12.2009 14:05

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

Есть форма, на отдельные поля которой через addEventListener повешены валидаторы-обработчики "onchange". Причём на каких-то полях обработчики висят, на каких-то нет. Перед отправкой формы требуется дополнительно пройтись по тем элементам, на которых обработчики висят, вызвав их программно.

Я это решаю следующим образом:
В обработчике события отправки формы создаю ивент "onchange" и отправляю его по очереди всем элементам формы. Если на элементе висит валидатор, он будет вызван и возвратит результат проверки.

var h_onsubmit = function(e) {
    var e_onchange = document.createEvent("Event");
    e_onchange.initEvent("change", false, true);

    var res = true;
    var form = e.target.form;
    for(var j = 0; j < form.elements.length; j++) {
        var element = form.elements[j];
        var ret = element.dispatchEvent(e_onchange);
        if(!ret) {
            res = false;
            break;
        }
    }
    if(!res) {
        e.preventDefault();
        e.stopPropagation();
    }
    return res;
}


Работает на ура, если бы не одно "но"...
В форме есть элемент select с набором опций, без валидатора, но со своим обработчиком "onchange".
Так вот, когда такому элементу из обработчика формы приходит событие по dispatchEvent, он сбрасывает своё текущее выбранное значение, что совсем не есть здорово :(

То есть если у меня форма задана так:
<form>
  <select id='select_id' size='1'>
    <option>1</option>
    <option>2</option>
    <option>3</option>
    <option>4</option>
  </select>
  <input id='element_with_validator'/>
  <input type='submit' id='submit_id' value='Submit'/>
</form>


и на сранице была выбрана, например, опция селекта "4", то после вызова
document.getElementById("select_id").dispatchEvent(e_onchange);

в h_onsubmit значение селекта сбросится с "4" в "1".

Код обработчика "onchange" для селекта следующий:
h_select_onchange = function() {
    var value = document.getElementById("select_id").value;
    // ...
};


Как можно решить мою задачу, чтобы опция селекта не сбрасывалась?
Обработчик h_select_onchange желательно не трогать.

P.S. Только что подумал, что в качестве решения моей задачи можно элементам с валидаторами устанавливать какую-нибудь специфическую переменную, в обработчике h_onsubmit проверять у элемента её наличие и отправлять программный "onchange" только элементам с валидаторами. Тогда селекту событие не придёт и сброса не произойдёт. Но хотелось бы всё-таки разобраться, почему происходит сброс и как этого избежать.

P.P.S. Прошу прощения. Ошибка найдена. Была у меня в коде. Это обработчик другого элемента сбрасывал значение. Тему можно удалять.
Мда... утром голова явно работает лучше :)

x-yuri 19.12.2009 07:51

надеюсь в ближайшее время ты столкнешься еще с какими-нибудь проблемами по поводу валидаторов, повешенных на onchange, и тебе прийдется отказаться от этой идеи ;)

Yazla 19.12.2009 19:12

Цитата:

Сообщение от TheRoSS (Сообщение 38338)
Добрый всем день.
Нужна помощь в решении следующей задачи:

Есть форма, на отдельные поля которой через addEventListener повешены валидаторы-обработчики "onchange". Причём на каких-то полях обработчики висят, на каких-то нет. Перед отправкой формы требуется дополнительно пройтись по тем элементам, на которых обработчики висят, вызвав их программно.

Я это решаю следующим образом:
В обработчике события отправки формы создаю ивент "onchange" и отправляю его по очереди всем элементам формы. Если на элементе висит валидатор, он будет вызван и возвратит результат проверки.

var h_onsubmit = function(e) {
    var e_onchange = document.createEvent("Event");
    e_onchange.initEvent("change", false, true);

    var res = true;
    var form = e.target.form;
    for(var j = 0; j < form.elements.length; j++) {
        var element = form.elements[j];
        var ret = element.dispatchEvent(e_onchange);
        if(!ret) {
            res = false;
            break;
        }
    }
    if(!res) {
        e.preventDefault();
        e.stopPropagation();
    }
    return res;
}


Работает на ура, если бы не одно "но"...
В форме есть элемент select с набором опций, без валидатора, но со своим обработчиком "onchange".
Так вот, когда такому элементу из обработчика формы приходит событие по dispatchEvent, он сбрасывает своё текущее выбранное значение, что совсем не есть здорово :(

То есть если у меня форма задана так:
<form>
  <select id='select_id' size='1'>
    <option>1</option>
    <option>2</option>
    <option>3</option>
    <option>4</option>
  </select>
  <input id='element_with_validator'/>
  <input type='submit' id='submit_id' value='Submit'/>
</form>


и на сранице была выбрана, например, опция селекта "4", то после вызова
document.getElementById("select_id").dispatchEvent(e_onchange);

в h_onsubmit значение селекта сбросится с "4" в "1".

Код обработчика "onchange" для селекта следующий:
h_select_onchange = function() {
    var value = document.getElementById("select_id").value;
    // ...
};


Как можно решить мою задачу, чтобы опция селекта не сбрасывалась?
Обработчик h_select_onchange желательно не трогать.

P.S. Только что подумал, что в качестве решения моей задачи можно элементам с валидаторами устанавливать какую-нибудь специфическую переменную, в обработчике h_onsubmit проверять у элемента её наличие и отправлять программный "onchange" только элементам с валидаторами. Тогда селекту событие не придёт и сброса не произойдёт. Но хотелось бы всё-таки разобраться, почему происходит сброс и как этого избежать.

P.P.S. Прошу прощения. Ошибка найдена. Была у меня в коде. Это обработчик другого элемента сбрасывал значение. Тему можно удалять.
Мда... утром голова явно работает лучше :)

Если честно, то подход немножко неправельный, мягко говоря. Имхо.
Почему бы тебе просто не зделать метод validate у каждого елемента и вызывать его тогда когда надо?!.

TheRoSS 19.12.2009 19:40

Цитата:

Сообщение от x-yuri (Сообщение 38477)
надеюсь в ближайшее время ты столкнешься еще с какими-нибудь проблемами по поводу валидаторов, повешенных на onchange, и тебе прийдется отказаться от этой идеи ;)


Пока плавание проходит нормально, подводных камней не обнаружено :)
Но вообще, в вэбе у меня опыта не много, я больше серверный программист. Чего стоит опастаться?

Цитата:

Сообщение от Yazla (Сообщение 38544)
Если честно, то подход немножко неправельный, мягко говоря. Имхо.
Почему бы тебе просто не зделать метод validate у каждого елемента и вызывать его тогда когда надо?!


При моём подходе в тексте HTML элелемент с валидацией может быть задан так:
<script type="text/javascript" src="validate.js"></script>
...
<input class="validateUnsignedInteger"
         required="Необходимо задать номер счёта."
         invalid="Номер счёта должен состоять только из цифр."/>

<input class="validateString"
         required="У царевны-лягушки должно быть имя!!!"/>

<input class="validateUnsignedInteger"
         invalid="Количество танков в гараже Ивана-царевича должно быть целым числом."/>

Всё, больше никаких манипуляций с HTML не требуется. Особенно полезно, если есть много страниц с большим количеством элементов, которые нуждаются в валидации. Код полностью отделён от вёрстки и не зависит от конкретного элемента. Причём валидация будет проводится как при изменении поля, так и непосредственно перед отправкой формы (вешается на onclick, не на onsubmit кнопки sumbit)

x-yuri 20.12.2009 10:53

Цитата:

Сообщение от TheRoSS
Пока плавание проходит нормально, подводных камней не обнаружено
Но вообще, в вэбе у меня опыта не много, я больше серверный программист. Чего стоит опастаться?

я не очень корректно выразился. То что валидация происходит по onchange - это нормально, но onchange - не только для валидации. И когда ты отправляешь события элементам, ты примерно это и говоришь. Почему бы просто не вызвать все валидаторы по порядку (а не обработчики события onchange)?

TheRoSS 20.12.2009 13:55

Да, согласен.
Для других событий "onchange" в их обработчиках приходится проверять, действительно ли было изменение в элементе, что чревато.
Только другого способа, кроме как через генерацию события, вызвать функцию-обработчик, установленную по addEventListener, я не нашёл.

Значит, получается, более правильный способ - это создавать в элементе вспомогательную переменную, на которую вешать функции-валидаторы (помимо события), при отправке формы проверять, была ли установлена эта переменная, и вызывать валидаторы через неё?

Да, при таком подходе "лишних" "onchange" не будет. Единственное, не хотелось бы вводить новых символов в пространство имён элемента.

x-yuri 21.12.2009 14:28

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

Как сделать правильно? Ну, например, почему бы просто не сделать функцию валидации элемента, которую вызывать из обработчика onchange и из onsubmit формы? По поводу onchange, естественно, не обязательно создавать промежуточную функцию

p.s. причем обработчик можно ставить не только через AddEventListener


Часовой пояс GMT +3, время: 05:16.