Page 1 of 2 12 LastLast
Results 1 to 10 of 19

Thread: order of event execution in IE

  1. #1
    Join Date
    May 2007
    Location
    Canada
    Posts
    85
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default order of event execution in IE

    Hi,

    I think this is one of the issues, on which IE decided to be unique. Here's my problem.

    I already have an object that has a click event to do something. I'm using that object in another work of mine, where I needed to do some calculation, when that object was clicked.

    So, I added another click event to that object. Now, the object has two click events. Both Firefox and Opera executes the click events in the order they were added. So, the first click event, which was the original event created by the object itself, gets called first and then the second click event, that I needed to add for this particular work, gets called first. This is working fine for me.

    But in IE, it's working in LIFO order (last event added gets called first). Because of this I'm getting a totally wrong calculated value.

    I don't know if there's any way to fix it, as I couldn't find it while googling. I really hope I'm wrong and may be someone could show me how to get around this. Thank you so much for helping.

  2. #2
    Join Date
    May 2007
    Location
    USA
    Posts
    373
    Thanks
    2
    Thanked 4 Times in 4 Posts

    Default

    If you are adding the events all in one sitting, you could try something like this:
    Code:
    if(window.addEventListener) {
    	el.addEventListener("click", func1, false);
    	el.addEventListener("click", func2, false);
    	}
    else{
    	el.attachEvent("onclick", func2);
    	el.attachEvent("onclick", func1);
    	}
    But I would guess that this is less than ideal. I can try think tanking a function that adds events and automatically does this for you when adding events later in the code.

    Oh, and you are not mistaken. I just tested it too, confirming your worst NIGHTMARE!
    Last edited by Trinithis; 06-04-2007 at 01:06 AM. Reason: drama

  3. #3
    Join Date
    May 2007
    Location
    USA
    Posts
    373
    Thanks
    2
    Thanked 4 Times in 4 Posts

    Default

    This works in FF and IE:
    Code:
    //type has no "on" in it, and bool is optional
    function addEvent(el, type, func, bool) {
    	if(window.addEventListener) el.addEventListener(type, func, !!bool);
    	else {
    		type = "on" + type;
    		if(el.events===undefined) el.events = [];
    		for(var e=el.events, i=e.length-1; i!=-1; --i) {
    			el.detachEvent(e[i][0], e[i][1]);
    			}
    		el.events.push([type, func]);
    		for(var e=el.events, i=e.length-1; i!=-1; --i) {
    			el.attachEvent(e[i][0], e[i][1]);
    			}
    		}
    	}

  4. #4
    Join Date
    May 2007
    Location
    Canada
    Posts
    85
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default

    Oh, and you are not mistaken. I just tested it too, confirming your worst NIGHTMARE!
    LOL... Tell me about it . I did knew about this before, but never thought I would need to use multiple events of the same type on the same object.

    Thanks for the last post though. Could you explain the code a little? Not sure why you have a detach event inside an addEvent function. The for loop looks wired too.

    Thanks again.

  5. #5
    Join Date
    May 2007
    Location
    USA
    Posts
    373
    Thanks
    2
    Thanked 4 Times in 4 Posts

    Default

    First, the usage syntax of the code is something like this:
    Code:
    var element = document.getElementById("myID");
    function ABCs() {
    	alert("Now I know my ABC's!!!");
    	}
    addEvent(element, "click", ABCs)
    //Or if you want to capture the event with non-IE browsers: addEvent(element, "click", ABCs, true);
    As for the code itself, I'll try walking you through it with comments:
    Code:
    function addEvent(el, type, func, bool) {
    	if(window.addEventListener) el.addEventListener(type, func, !!bool);
    	//Checks to see if the method of adding events is through addEventListener or attachEvent.
    	//The !!bool is to turn bool into false if undefined or false, or into true if set to true.
    	//Note that I don't have to do fancy legwork with reordering events here, as it is already FIFO.
    	else {
    	//IE way of adding events and making LIFO into FIFO
    		type = "on" + type;
    		//IE wants an argument like "onclick" vs "click"
    		if(el.events===undefined) el.events = [];
    		//Gives the element a property to record what events have been assigned to it because you can't tell otherwise (or at least I don't think so).
    		for(var e=el.events, i=e.length-1; i!=-1; --i) {
    		//Looks through the element's event property that I had created and sets a loop to get rid of all its events.
    		//Note that this loop could easily look like for(var i=0, e=el.events; i<e.length; i++) and do the same thing.
    		//Also, if this is element currently has no events, this is bypassed.
    			el.detachEvent(e[i][0], e[i][1]);
    			//(Remember e=el.event.) e is an array that has length equal to the number of events the element has. e[i] stores the event type (e[i][0]) and the function (e[i][1]), so el.detachEvent() can remove the event.
    			//The event is removed in the first place to restack the event pile later in the code by readding them in the "correct" order.
    			}
    		el.events.push([type, func]);
    		//Records the new event into el.events
    		for(var e=el.events, i=e.length-1; i!=-1; --i) {
    		//With the previous loop it did not matter whether it incremented or decremented. In this case, it has to decrement because we have to reverse LIFO into FIFO
    			el.attachEvent(e[i][0], e[i][1]);
    			//Adds the events in "reverse" order to make it FIFO
    			}
    		}
    	}
    Last edited by Trinithis; 06-04-2007 at 04:43 AM.

  6. #6
    Join Date
    May 2007
    Location
    USA
    Posts
    373
    Thanks
    2
    Thanked 4 Times in 4 Posts

    Default

    I have an edit to make with my addEvent to make it mimic addEventListener even better.
    Code:
    function addEvent(el, type, func, bool) {
    	if(window.addEventListener) el.addEventListener(type, func, !!bool);
    	else {
    		type = "on" + type;
    		var hasEvent = false;
    		if(el.events===undefined) el.events = [];
    		for(var e=el.events, i=e.length-1; i!=-1; --i) {
    			el.detachEvent(e[i][0], e[i][1]);
    			if(e[i][0]==type && e[i][1]==func) hasEvent = true;
    			}
    		if(!hasEvent) el.events.push([type, func]);
    		for(var e=el.events, i=e.length-1; i!=-1; --i) {
    			el.attachEvent(e[i][0], e[i][1]);
    			}
    		}
    	}
    Oh, and you will need this to remove events in a fashion so that addEvent won't provide bugs.
    Code:
    function removeEvent(el, type, func, bool) {
    	if(window.addEventListener) el.removeEventListener(type, func, !!bool);
    	else if(el.events) {
    		type = "on" + type;
    		for(var e=el.events, i=e.length-1; i!=-1; --i) {
    			if(e[i][0]==type && e[i][1]==func) {
    				el.detachEvent(type, func);
    				el.events.splice(i, 1);
    				break;
    				}
    			}
    		}
    	}
    Last edited by Trinithis; 06-04-2007 at 04:48 AM.

  7. #7
    Join Date
    May 2007
    Location
    Canada
    Posts
    85
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default

    Hey Trinithis,

    I just tried the last addEvent function that you posted, but it still seems to be doing the same thing in IE. Executing events in LIFO order

  8. #8
    Join Date
    May 2007
    Location
    Canada
    Posts
    85
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default

    Okay. Never mind. It's working now. It didn't work before because I wasn't using the actual "addEvent" function. doh...

    Anyways... In the mean time while I didn't realize why that code wasn't working, I started to write my own, which was following the exact same algorithm and this one is working too. There's not much difference between mine and Trinithis except that I'm revarsing the array of events and then re-adding them. Here's mine:

    HTML Code:
    	this.addEvent = function(eventTarget, eventType, eventHandler, eventBubble)
    	{
    		if(eventTarget.addEventListener)
    		{
    			//for true web browsers
    			eventTarget.addEventListener(eventType, eventHandler, eventBubble) ;
    		}
    		else
    		{
    			//for IE
    			
    			eventType = "on" + eventType ;
    			
    			if(!eventTarget.events)
    			{
    				/**
    				 * No events was registered for this object.
    				 * Create an array to store the events
    				 */
    				eventTarget.events = new Array() ;
    			}
    			else
    			{
    				/**
    				 * Events were registered on this object before.
    				 * Detach them now, so that we can sort the event
    				 * order after registereing the new event.
    				 */
    				for(var i = 0 ; i < eventTarget.events.length ; i++)
    				{
    					eventTarget.detachEvent(eventTarget.events[i][0], eventTarget.events[i][1]) ;
    				}
    			}
    			
    			//store the new event in the array
    			eventTarget.events.push([eventType, eventHandler]) ;
    			
    			//Copy the event array and revarse the order
    			var tempEventList ;
    			tempEventList = eventTarget.events ;
    			tempEventList.reverse() ;
    			
    			//Register the events from the reversed order array
    			for(var i = 0 ; i < tempEventList.length ; i++)
    			{
    				eventTarget.attachEvent(tempEventList[i][0], tempEventList[i][1]) ;
    			}
    		}
    		
    	}
    I know mine is working too, but do you see anything wrong with mine in terms of the performance? Thanks again for your code Trinithis.

  9. #9
    Join Date
    May 2007
    Location
    USA
    Posts
    373
    Thanks
    2
    Thanked 4 Times in 4 Posts

    Default

    eventBubble would be more aptly named eventCapture. But then again, it might be best removing that whole paramater and default it to false because I don't know how to mimic it in IE, meaning that if you wanted to capture the event, things would behave differently for IE users. That is, unless right after you add the event, you have a condition check for (window.addEvent) and do your magic there.

    Unless you have a special reason to, I would use
    Code:
    function addEvent()
    over
    Code:
    this.addEvent = function() //or window.addEvent = function()
    As for your performance specs it adds a miniscule (though negligible) time to execution. My code runs neglibly faster than yours (without checking to see if the event is already attached. I check because the code would otherwise fail if you attach a duplicate event in IE. I think yours would fail too. FF handles it automatically.), and I revamped it to make it even more neglibly faster just for you

    Code:
    function addEvent(el, type, func, bool) {
    	if(el.addEventListener) el.addEventListener(type, func, bool);
    	else {
    		type = "on" + type;
    		if(!el.events) el.events = [];
    		var i = 0, e = el.events, len = e.length, unique = true;
    		while(i<len) {
    			el.detachEvent(e[i][0], e[i][1]);
    			if(e[i][0]===type && e[i][1]===func) {
    				unique = false;
    				break;
    				}
    			++i;
    			} 
    		if(unique) e.push([type, func]);
    		do {
    			el.attachEvent(e[i][0], e[i][1]);
    			} while(i--)
    		}
    	}
    
    
    function removeEvent(el, type, func, bool) {
    	if(el.addEventListener) el.removeEventListener(type, func, bool);
    	else if(el.events) {
    		type = "on" + type;
    		var e = el.events, i = e.length - 1;
    		do {
    			if(e[i][0]===type && e[i][1]===func) {
    				el.detachEvent(type, func);
    				e.splice(i, 1);
    				break;
    				}
    			} while(i--)
    		}
    	}
    Oh, and btw, I noticed when not using reverse() you say "revarse". Is that the Canadian way of saying it?
    Last edited by Trinithis; 06-05-2007 at 06:27 AM.

  10. #10
    Join Date
    May 2007
    Location
    Canada
    Posts
    85
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Default

    Unless you have a special reason to, I would use
    Code:

    function addEvent()

    over
    Code:

    this.addEvent = function() //or window.addEvent = function()
    Actually I was writing this addEvent function for an object / class. That's why I had this.addEvent . I should probably make it public instead of privileged. Will work on it later.
    Oh, and btw, I noticed when not using reverse() you say "revarse". Is that the Canadian way of saying it?
    Nope, not that I know of. But for some reason, when typing I always type "revarse". I guess that make more sense. lol... now we're getting into grammer from javascript.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •