In javascript, manually controlling the order of event listeners

Assuming FORM contains INPUT, there are 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 shooting order

 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 the problem and attempts to solve

Native code at the FORM level, formFirst , formLast and middle , but does not have access to the INPUT, inputFirst and inputLast - although it can add its own listeners to INPUT.

Attempt 1 to modify formFirst() to create and send a new change Event (will be ignored in formFirst ), which will call inputFirst() but have no way to stop the distribution to prevent inputLast() being called later.

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


The premise of attempt 2 is incorrect β€” the order of fire is determined by the order of the announcement in the target element.

Here are the rules

  • Element useCapture=false triggers with useCapture=false , starting at the outer element and working on the target element

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

  • in the target element, the declaration order, regardless of useCapture

  • Element out-of- useCapture=false triggers with useCapture=false , starting from the innermost element and working from the target element

    a) if more than one useCapture=false starts the same element, then the declaration order.

+7
source share
1 answer

I think this only answers your question. Feel free to comment \ contact me for more information.

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

Well, I just played around with it a bit, as I promised, and 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> 

Note:

  • I put the addEventListener part in the init function, so I can call it after the page loads, and the element already exists.
  • I only run this on chrome. Therefore, I do not want to guarantee you anything in relation to other browsers.
  • An alternative is to record event processing yourself. here is an example of this. relay to 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> 
+3
source

All Articles