I have already defined onclick event. I want to add additional call back function, that will be invoked BEFORE already defined callback.
- How to add an event in the head of the queue for concrete event type?
I have already defined onclick event. I want to add additional call back function, that will be invoked BEFORE already defined callback.
If you use attachEvent
for IE you cannot guarantee the order in which events are fired. See http://msdn.microsoft.com/en-us/library/ms536343(VS.85).aspx
If you attach multiple functions to the same event on the same object, the functions are called in random order, immediately after the object's event handler is called.
(I actually have seen that events are called in reverse order, not random). Anyway, libraries generally tend to use attachEvent
deep down, so you're stuck with the same problem.
Having said that, if you can inspect a node for it's 'click' handlers (eg you have an "onclick" attribute setup on your node in your markup), then you can put "yours" ahead of "theirs":
var nodes = document.getElementsByTagName('*'); // collect your nodes however
for(var i=0; i < nodes.length; i++) {
var node = nodes[i];
if(!node.onclick)
continue;
// At this point we have a node with an "onclick" attr.
// Hijack onclick to do something else first.
var original = node.onclick;
node.onclick = function() {
doSomethingElse();
return original.apply(this, arguments);
}
}
See this answer for how to inspect the a node's events in other libraries (if you are using one). You may be able to use it to doSomethingElse()
with those libraries too.
Super. That made me look into jquery doc and I've found that combining crescentfresh's solution with jQuery's unbind() method (an analog of Extjs.removeAll()) will solve my issue.
So, at the end I have this:
this.onclick = function( e )
if ( /*trigger clause*/ true ) {
//cancel all events
$(this).unbind();
return false;
} else {
//continue processing
return original ? original.apply(this, arguments) : true;
}
}
Thanks for advices guys!
PS What the jerks have made this awful reply editor??! It's a headache to paste some code here.
PPS Unfortunatelly I can't vote for two replys and I can't raise useful mark for your reply due to lack of reputation and I can't mark more than one answer acceptable. So, please forgive me. Stupid forum engine, but really cool people here
addEventListener lets you add another event. Note that in IE you will have to use attachEvent.
This will not let you define the order of the events - appearently you can't predict the order the events will be fired in. So if you really want a predictable event queue for an event, you will have to implement it yourself.
You can stop the default action of an event with preventDefault() or stop the propagation of nested event with stopPropagation() to let only your specific event fire.
But pause or delay an event natively without using setTimeout(), stopping, saving his state and re-firing later in the queue is impossible.
Are you working with jquery framework ? I'm currently working with extjs and i found a class you can use or copy
Lets see on http://extjs.com/deploy/dev/docs/ Ext > EventManager > removeAll()
removeAll( String/HTMLElement el ) : void Removes all event handers from an element. Typically you will use Ext.Element.removeAllListeners directly on an Element in favor of calling this version. Parameters: el : String/HTMLElement The id or html element from which to remove the event Returns: void
I think You can set the tag body
as HTMLElement to shut down all events. (not tested sorry)
Download here http://extjs.com/products/extjs/build/ > select jquery adapter if you are working with jquery > extcore will suffice (it contain EventManager.js ).
On the other way, like crescentfresh (answer n°4), i made this sample code to apply to all node events :
var nodes = document.getElementsByTagName('*'); // collect your nodes however
for(var i=0; i < nodes.length; i++) {
var node = nodes[i];
Ext.EventManager.removeAll(node);
}
}
Please let me know if you have trouble using extjs i can help, and vote for me if my answer is useful.
You can simply stop an event listeners by simply load this sample function with correct params :
function removeEvent(obj,type,fn){
if(obj.removeEventListener) obj.removeEventListener(type,fn,false);
else if(obj.detachEvent){
obj.detachEvent("on"+type,obj[type+fn]);
obj[type+fn]=null;
obj["e"+type+fn]=null;
}
}
Also, you can fire à setTimeout within the event that kill other listeners and re-enable listener one by one, externally or with an other setTimeout.
A library to debug events, maybe useful.