в javascript, ручное управление порядком прослушивателей событий

Предположим, что FORM содержит INPUT, имейте следующие слушатели:

JavaScript

function formFirst(e) { ... }
function formLast(e) { ... }
function inputFirst(e) { ... }
function inputLast(e) { ... }
function middle(e) { ... }

document.getElementById('form').addEventListener('change',formFirst,true);
document.getElementById('form').addEventListener('change',formLast,false);
document.getElementById('input').addEventListener('change',inputFirst,true);
document.getElementById('input').addEventListener('change',inputLast,false);

желаемый порядок стрельбы

formFirst()   // normal - outer element, useCapture = true
inputFirst()  // normal - triggering element, declared first
middle()      // -- how to do this?
inputLast()   // normal - triggering element, declared second
formLast()    // normal - outer element, useCapture = false

характер проблемы и попытки решения

Собственный код на уровне FORM, formFirst, formLast и middle, но не имеет доступа к коду INPUT, inputFirst и inputLast, хотя может добавлять собственных слушателей на INPUT.

Попытка 1 изменить formFirst() для создания и отправки нового change Event (будет игнорироваться в formFirst), который будет вызывать inputFirst(), но не имеет возможности остановить распространение, чтобы предотвратить последующий вызов inputLast().

Попытка 2 добавить middle в качестве слушателя к INPUT, но не может гарантировать порядок срабатывания двух слушателей одного типа и одного и того же useCapture.


Предпосылка Попытки 2 неверна - порядок срабатывания определяется порядком объявления в целевом элементе.

Вот правила

  1. нецелевой элемент срабатывает с useCapture=false, начиная с самого внешнего элемента и работая в направлении целевого элемента

    а) если для одного и того же элемента срабатывает более одного useCapture=true, то порядок объявления.

  2. в целевом элементе, порядок объявления, независимо от useCapture

  3. нецелевой элемент срабатывает с useCapture=false, начиная с самого внутреннего элемента и работая дальше от целевого элемента

    а) если для одного и того же Элемента срабатывает более одного useCapture=false, то порядок объявления.


person cc young    schedule 26.09.2011    source источник


Ответы (1)


Я думаю, что это отвечает как раз на ваш вопрос. не стесняйтесь комментировать \ связаться со мной для получения дополнительной информации.

----- редактировать ------

Хорошо, я немного поигрался с этим, как и обещал, и нашел очень простое решение:

<script type="text/javascript">
function formFirst(e) { alert(1); }
function formLast(e) { alert(5); }
function inputFirst(e) { alert(2); }
function inputLast(e) { alert(4); }
function middle(e) { alert(3); }

function init(){
    document.getElementById('form').addEventListener('change',formFirst,true);
    document.getElementById('form').addEventListener('change',formLast,false);
    document.getElementById('input').addEventListener('change',inputFirst,true);
    document.getElementById('input').addEventListener('change',middle,true);
      /*** alternative to last tow lines  
    document.getElementById('input').addEventListener('change',function(){inputFirst();middle();},true);
         **/
    document.getElementById('input').addEventListener('change',inputLast,false);
}

</script>
<body onload="init();">
<form id="form">
<input type="text" id="input" /> <br />
</form>
</body>

уведомление:

  • Я поместил часть addEventListener в функцию инициализации, поэтому я могу вызвать ее после загрузки страницы, когда элемент уже существует.
  • Я запускал это только на хроме. Так что я не хочу гарантировать вам что-то о других браузерах.
  • Альтернативой является написание обработки событий самостоятельно. вот пример для этого. ссылаясь на эту статью.

    <script type="text/javascript">
    
    function formFirst(e) { alert(1); }
    function formLast(e) { alert(5); }
    function inputFirst(e) { alert(2); }
    function inputLast(e) { alert(4); }
    function middle(e) { alert(3); }
    
    function init(){
    
      //create event
      myHandler = new Event();
    
      //add handler
      myHandler.addHandler(formFirst);
      myHandler.addHandler(inputFirst);
      myHandler.addHandler(middle);
      myHandler.addHandler(inputLast);
      myHandler.addHandler(formLast);
    
      //regiser one listener on some object
      document.getElementById('input').addEventListener('change',function(){myHandler.execute();},true);
    }
    
    
    function Event(){
      this.eventHandlers = new Array();
    }
    
    Event.prototype.addHandler = function(eventHandler){
      this.eventHandlers.push(eventHandler);
    }
    
    Event.prototype.execute = function(){
      for(var i = 0; i < this.eventHandlers.length; i++){
        this.eventHandlers[i]();
      }
    }
    
    
    </script>
    <body onload="init();">
    <form id="form">
    <input type="text" id="input" /> <br />
    </form>
    </body>
    
person Ramzi Khahil    schedule 26.09.2011
comment
для вашего конкретного примера просто используйте ture в качестве третьего параметра для всех ваших прослушивателей событий. - person Ramzi Khahil; 26.09.2011
comment
из моего тестирования я думаю, что вы не правы. если бы formLast был добавлен с useCapture = true, то formLast срабатывал бы до срабатывания триггеров INPUT, а не последует за ними, как сейчас. - person cc young; 26.09.2011
comment
Ты прав. Я не думал, что это бросок. Попробуйте эту статью, там вы можете создавать собственные обработчики. А я не пробовал (только нашел). Но я думаю, вы можете прикрепить среднюю функцию к обработчику событий, который запускает функцию inputFirst, чтобы обработчик позже запускал средний метод. Вечером поиграю с этим вариантом. Так что дайте мне знать, если это все еще не работает. - person Ramzi Khahil; 26.09.2011
comment
Извините, что так долго не возвращался - переезд. Вы правы - порядок создания слушателей определяет порядок срабатывания внутри target - хотя имеет смысл, что true триггеры должны срабатывать до false, а на не-цели это не так. - person cc young; 05.10.2011
comment
Привет еще раз. Несколько дней назад я читал кое-что о jQuery. Это не то, что вам нужно, но может помочь. потому что есть вариант callback. это означает, что вы вызываете один метод, а в обратном вызове отправляете следующий (создавая цепочку выполнения). Может быть проблематично, если каким-то образом буксировка таких полей срабатывает одновременно. Но на событии change я в этом сомневаюсь. - person Ramzi Khahil; 18.10.2011