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 Elementa) 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 Elementa) if more than one
useCapture=false
triggers for same Element, then order of declaration.
Advertisement
Answer
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>