in javascript, manually controlling order of event listeners

Assuming that FORM contains INPUT, have the following listeners:

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);

desired order of firing

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

nature of problem and attempted solutions

Own code at FORM level, formFirst , formLast and middle , but have no access to INPUT code, inputFirst and inputLast - although could add own listeners on the INPUT.

Attempt 1 modify formFirst() to create and dispatch a new change Event (would be ignored within formFirst ) that would call inputFirst() , but have no way of stopping propagation to prevent inputLast() being called subsequently.

Attempt 2 add middle added as listener to INPUT, but cannot guarantee firing order of two listeners of same type and same useCapture.


Premise of Attempt 2 is incorrect - firing order is determined by declaration order within the target Element.

Here are the rules

  • non-target Element triggers with useCapture=false , starting at the outermost Element and working toward the target Element

    a) if more than one useCapture=true triggers for same element, then order of declaration.

  • at target Element, order of declaration, regardless of useCapture

  • non-target Element triggers with useCapture=false , starting at the innermost Element and working away from the target Element

    a) if more than one useCapture=false triggers for same Element, then order of declaration.


  • I think that this answers just your question. feel free to commentcontact me for more info.

    ----- edit ------

    OK, I just played with it a little as promised, and I found a very simple solution:

    <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>
    

    notice:

  • I put the addEventListener part into an init function, so I can call it after the page is loaded and the element are already exist.
  • I have run this just on chrome. So I don't want to guarantee you things about other browsers.
  • An alternative is writing the event handling on your own. here is an example for that. relaying on this article.

    <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>
    
  • 链接地址: http://www.djcxy.com/p/9362.html

    上一篇: 处理“java.lang.OutOfMemoryError:PermGen空间”错误

    下一篇: 在JavaScript中,手动控制事件侦听器的顺序