Увольнение и сбор пользовательских событий

Представьте себе этот сценарий (это действительно просто сценарий):

  • У меня есть глобальный счетчик, который увеличивается с каждым щелчком мыши.
  • когда я достигну 50 щелчков, я хочу запустить пользовательское событие с именем "достигаемое количество"
  • Я хочу зарегистрировать мой объект окна, чтобы захватить это событие с чем-то вроде
     window.addEventListener('reachedCount', function(args){alert(args.count);}, false)

Итак, мои проблемы в том, что я не знаю и нигде не могу найти, как передать аргументы моему eventHandler. Кроме того, я попробовал опубликованный метод Rikudo, но он не работает в IE lt 9.

Это возможно? Как?

Ответ 1

Используя ответ Rikudo Sennin, вы можете передавать параметры своему обработчику событий, помещая их внутри самого события, как это делают обработчики DOM!

function fireEvent(name, target, param1, param2) {
    //Ready: create a generic event
    var evt = document.createEvent("Events")
    //Aim: initialize it to be the event we want
    evt.initEvent(name, true, true); //true for can bubble, true for cancelable
    evt.param1 = param1;
    evt.param2 = param2;
    //FIRE!
    target.dispatchEvent(evt);
}

function foobar(ev) {
    alert("foobar" + ' ' + ev.param1 + ' ' + event.param2);
}

function testEvents(param1) {
    window.addEventListener("foobar", foobar, false); //false to get it in bubble not capture.
    fireEvent("foobar", document, 'test', param1);
}

Ответ 2

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

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

Для ваших собственных аргументов в некоторых случаях вы можете повторно использовать существующие поля (или, возможно, даже добавить новые собственные поля):

var newEvent = ...
newEvent['scrollX'] = your-own-custom-value;

Именно то, как они будут устанавливаться, будет отличаться в зависимости от того, сможете ли вы использовать новый стандартизованный способ HTML5 или должны вернуться к более старой поддержке браузера. (Различные "прокладки", которые добавляют поддержку пользовательских событий даже старым браузерам, которые ничего не предоставляют, здесь не рассматриваются - многие из них предоставят свой собственный довольно уникальный способ установки аргументов.)

В способе HTML5 используется параметр "словарь" (второй) для конструктора объектов, что-то вроде этого:

var newEvent = new CustomEvent('customname', { propertyname : propertyvalue,
                                            anotherpropname : anotherpropvalue,
                                              thirdpropname : thirdpropvalue,
                                                etcpropname : etcpropvalue }   );

Соответствующий старый метод будет выглядеть примерно так:

var newEvent = document.createEvent();
newEvent.initEvent('customname', true, true);
newEvent['propertyname'] = propertyvalue;
newEvent['anotherpropname'] = anotherpropvalue;
newEvent['thirdpropname'] = thirdpropvalue;
newEvent['etcpropname'] = etcprovalue;

(В приведенном выше примере также может быть понятнее, что фактически делает конструктор CustomEvent HTML5.)

Использование существующих имен свойств, подобных этому (или создания ваших собственных свойств:-), обычно не рекомендуется, поскольку проблемы с кросс-браузером и проблемы отладки могут быть довольно серьезными. Время от времени это будет необходимо, и оно будет работать, но не полагаться на него как на общую технику. Хотя некоторые типы объектов событий включают определенное именованное свойство, подобные типы объектов событий могут и не быть. Некоторые свойства события могут быть "только для чтения". Объекты событий очень сильно изменяются из одного браузера в другой и даже между версиями браузера. И создание ваших собственных новых свойств может смутить реализацию браузера Javascript.

Вместо этого используйте одно конкретное свойство, которое "зарезервировано" для вашего использования в пользовательских событиях, и ничего больше: detail.

Часто у вас будет несколько аргументов, но для вашего использования есть только одно свойство. Таким образом, обычный подход заключается в том, чтобы всегда приводить все ваши аргументы в один "объект" , что-то вроде этого:

var myargs = { my : 1,
              own : getElementById('foo');
             args : { X : 32, Y : 53 }    };

Способ настройки этой переменной HTML5 будет выглядеть примерно так:

var newEvent = new CustomEvent('customname', { bubbles : true,
                                            cancelable : true,
                                                detail : myargs } );

Более старый интерфейс для выполнения той же самой вещи будет выглядеть примерно так:

var newEvent = document.createEvent();
newEvent.initEvent('customname', true, true);
newEvent['detail'] = myargs;

(Конечно, если вы сильно используете Javasript "литеральный объект" для фигурного скобки, чтобы свести к минимуму вашу типизацию, ваш код может выглядеть немного иначе, чем приведенные выше примеры, которые определяют приоритетность.)

(Два существующих свойства событий, "пузырьки" и "отменяемые" всегда должны быть установлены для каждого события независимо от установки возможных пользовательских аргументов. Если используется новый способ HTML5, они всегда будут отображаться как две дополнительные строки в объект, который является вторым параметром для конструктора CustomEvent. Если используется более старый способ, они будут вторым и третьим параметрами для вызова initEvent (...).

Также предлагаются два разных способа запуска пользовательского события. В новом способе HTML5 используется object.dispatchEvent(newEvent). В более старом способе используется object.fireEvent('customname', newEvent, false). Здесь "объект" означает DOMObject/Element; точно, что (если что-либо) происходит, если "объект" - это нечто, кроме элемента DOM, даже больше зависит от браузера, чем остальная часть этой темы. (Смешивание HTML5-способа и старого способа обычно работает, но может быть запутанным. Еще одним частым источником путаницы является системная функция с именем fireEvent (...), а также определение вашей собственной функции с тем же именем.)

(Существует несколько тайных различий между двумя способами запуска настраиваемого события. Более старый метод fireEvent (...) требует повторного указания имени события, даже если вы уже указали его в initEvent (...), а более старый метод fireEvent (...) не вызывает "действие по умолчанию" [что бы это ни значило].)

С другой стороны, пользовательские аргументы получают доступ одинаково, независимо от того, использовался ли HTML5 или старый метод настройки события. Он будет выглядеть примерно так:

function customhandler(evt) {
        alert(evt.detail.own);

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

function customhandler(evt) {
        alert(evt.detail.args.X);

Похоже, что некоторые из них могут работать несколько иначе в IE 9 и ниже. Надеемся, что проблемы просто обычные, пытаясь повторно использовать или даже создать свойства объекта события. Если проблемы более распространены, вы можете отправить сообщение "извините:-(" на своем веб-сайте, или вы можете дождаться, когда IE6/7/8/9 умрет, или вы можете попробовать перекрестный браузер, взломать его самостоятельно, или вы может использовать какую-то прокладку/резервную копию. Мне не понятно, лучше ли найти прокладку, которая "выглядит точно так же", как обычный интерфейс, или использовать альтернативный интерфейс, предоставляемый прокладкой для всего (даже если обычный интерфейс доступно).

(Отказ от ответственности: Конечно, я мог ошибаться в отношении некоторых из вышеперечисленных...: -)

Ответ 3

function fireEvent(name, target) {
    //Ready: create a generic event
    var evt = document.createEvent("Events")
    //Aim: initialize it to be the event we want
    evt.initEvent(name, true, true); //true for can bubble, true for cancelable
    //FIRE!
    target.dispatchEvent(evt);
}

function foobar() {
    alert("foobar");
}

function testEvents() {
    window.addEventListener("foobar", foobar, false); //false to get it in bubble not capture.
    fireEvent("foobar", document);
}

Нашел этот код с 1 минутой поиска Google. http://the.unwashedmeme.com/blog/2004/10/04/custom-javascript-events/

Ответ 4

Ответы выше кажутся устаревшими.

Создайте новый CustomEvent.

var data = { x:20, y:30, rotationY: 60 },
    end = new CustomEvent('MOTION_FINISHED', { detail: data });
    this.dispatchEvent(end);

Похоже, что только свойство "detail" может передавать параметры. Я также читал, что доступны свойства "пузыри" и "отменяемые", но вы не упомянули их в своем вопросе.

Чтобы получить ваши параметры:

function _handler(e){
    var x = (e.detail && e.detail.x) || 0;
}