views:

224

answers:

4

I use this simple working function to add events:

function AppendEvent(html_element, event_name, event_function)
{
   if(html_element)
   {
      if(html_element.attachEvent) //IE
         html_element.attachEvent("on" + event_name, event_function);
      else if(html_element.addEventListener) //FF
            html_element.addEventListener(event_name, event_function, false);
   };
}

While doing this simple test:

AppendEvent(window, 'load', function(){alert('load 1');});
AppendEvent(window, 'load', function(){alert('load 2');});

I noticed that FF3.6 addEventListener appends each new events at the end of the events' queue, therefor in the above example you would get two alerts saying 'load 1' 'load 2'.

On the other side IE7 attachEvent inserts each new events at the begining of the events' queue, therefor in the above example you would get to alerts saying 'load 2' 'load 1'.

Is there a way to fix this and make both to work in the same way?

Thanks!

+1  A: 

You could "queue" up the events then execute them on mass when the event is triggered in a fixed order

var Events = {
    Event: [], 
    appendEvent: function(html_element, event_name, event_function) {
        if (!this.Event[event_name]) {
            this.Event[event_name] = [];
            if (html_element.attachEvent) //IE
            html_element.attachEvent("on" + event_name, function(event) {Events.run(event_name, event)});
        else if (html_element.addEventListener) //FF
            html_element.addEventListener(event_name, function(event) {Events.run(event_name, event)} , false);
        }
        this.Event[event_name].push(event_function)
    },
    run: function(event_name, event) {
        for (var k in this.Event[event_name])
            this.Event[event_name][k](event);
    }
}

Called;

Events.appendEvent(window, 'load', function(){alert('load 1');});
Events.appendEvent(window, 'load', function(){alert('load 2');});

this creates;

Event["load"][0] == function(){alert('load 1');
Event["load"][1] == function(){alert('load 2');

then adds a call to Events.run("load") on the elements onload which iterates and calls everything in Event["load"][].

Alex K.
Makes sense! It works only for one html_element at a time, I mean if I add a load event to an img and to the window, your code would cerate an horrible mess. Anyway +1, for the effort.
Marco Demajo
+1  A: 

According to the MSDN documentation, the order of execution with attachEvent is not specified (the word used is "random"). However it's not surprising that it'd be reverse order of attachment.

You could avoid doing that altogether, and build a chain of handlers based off the "on*event*" attributes of the elements involved. Or you could just use jQuery or something like that, if possible and appropriate.

Pointy
Thanks for pointing out the 'random' spec in MSDN. I gave a try to jQuery, you are right it works and behaves in the same way both on FF and IE. I just did: $(window).load(function () {alert('load 1');}).load(function () {alert('load 2');}) Actually what has always being scaring me about using jQuery is I find it diffcult to read the library source code and I'm afraid some day I find a customer who complain about is website not working for some bug in jQuery and I would not be able to fix it.
Marco Demajo
Well, it is good to be cautious, but you should understand that jQuery is a *very* widely-used library with a very solid and professional release process. It's very solid and, in particular the code in that library that handles browser quirks is likely to be much more solid than anything you or I would write.
Pointy
@Pointy: "solid and professional release process" just to give you an example when I open with IE7 jQuery at the page http://api.jquery.com/category/events/ there is a menu on the left under the title Browse the jQuery API, when I move my mouse over there, the '+' icons go under the menu, guess what happens if on our customers' webistes happen something like this and we don't know how to fix. Anyway I don't want to get into a jQuery yes/no discussion, thanks so much for your help, I really appreciated it.
Marco Demajo
The jQuery documentation site is just about the worst example of jQuery in action that I know of :-) Honestly: look around the web, and you'll find that jQuery is probably the most popular client-side framework in use today. There are many books written about it, and it is in use on many thousands of high-traffic commercial websites.
Pointy
+1  A: 

I solve this problem:

function addEvent(obj,evtype,func,bubble)
{
    try
    {
         obj.addEventListener(evtype,func,bubble);
    }
    catch(err) // for bastard IE
    {
         if(obj["on"+evtype] == null)
              obj["on"+evtype] = func;
         else
         {
          var e = obj["on"+evtype];
          obj["on"+evtype] = function(){e(); func();}
         }
    }
}

work perfectly

Marcelo Disconzi
+1 Hmmm interesting, why then not using the part inside the catch clause for all browsers? I mean why not simply using that part, avoiding using addEventListener totally.
Marco Demajo
A: 

Hello Marco, for performance reasons, so I prefer to use native code for browsers that support the feature.

Marcelo Disconzi