Search code examples
javascriptdom-events

JavaScript and Passing Event instance to function


I am facing a cross browser issue while trying to pass an event object from an onclick event.

Currently, I am doing the following

for (var i = 0; i < list.length; i++)
{
  var link= list[i];     
  link.onclick = function(el) {  return function () {LinkManager.HandleOnClick(window.event, el); }}(link);
 }

Firefox doesn't respect window.event. However, how else can I pass it?

I resorted to a "not" clean solution:

for (var i = 0; i < list.length; i++)
{
  var link= list[i];     
  link.onclick =  SomeClickHandler;
 }

function SomeClickHandler(e)
{
  e = e || window.event;
  if (typeof (e) !== 'undefined')
  {
    var element = e.target || e.srcElement;
    LinkManager.HandleOnClick(e, element);
  }
}

Can anyone recommend a better way of solving it? I really didn't like the workaround that I did.


Solution

  • If I understand correctly, you want your handler to have access to the el variable and the event object when it's called. That's possible and not that hard, but you might want to read up on closures:

    link.onclick = (function(el)
    {
        return function (e)//this function will receive the event object
        {
            e = e || window.event;//for ie
            LinkManager.HandleOnClick(e, el);
        }
    })(link);
    

    but, to be honest, this is overkill, try this (pun intended):

    link.onclick = function(e)
    {//this refers to `link`, the clicked element
        e = e || window.event;//for ie
        LinkManager.HandleOnClick(e, this);
    };
    

    or even less code:

    link.onclick = function(e)
    {//this refers to `link`, the clicked element
        e = e || window.event;//for ie
        LinkManager.HandleOnClick.apply(this,[e]);
        //LinkManager.HandleOnClick will receive 1 argument, the event object, and 'this' will point to 'link'
    };
    

    and even less:

    link.onclick = LinkManager.HandleOnClick;//this === link, 1 argument: the event object
    

    That said, you're iterating a list, and attaching an event listener to each individual child element. I'd strongly advise you to use delegaion:

    if (list.addEventListener)
    {
        list.addEventListener('click',LinkManager.HandleOnClick,false);
    }
    else if (list.attachEvent)
    {
        list.attachEvent('onclick',LinkManager.HandleOnClick);
    }
    else
    {
        //use the loop you have now as a last resort
    }
    
    //LinkManager.HandleOnClick should start like so:
    LinkManager.HandleOnClick = function(e)
    {
        e = e || window.event;//<- you have the event object here
        var target = e.target || e.srcElement;//=== list item: your link variables, your element
        console.log(this);//<-should reference the list element (<ul> || <ol>)
    };
    

    Anyway, that's how I'd tackle this