1

I have the following function:

function toggleContent()
{
    var parent = this.parentElement;

    toggleClass(parent,"detailsAreVisible");
}

This function is being called when a user clicks on a certain button. The binding happens in plain javascript like this:

var allTogglingButtons = document.querySelectorAll("[unhideicon],[hideicon]");
crossBrowserAddClickEvent(allTogglingButtons, toggleContent);

The crossBrowserAddClickEvent function is necessary to fix another IE problem:

function crossBrowserAddClickEvent(array, functionName)
{   
    for(var i=0; i < array.length; i++)
    {
        if (array[i].addEventListener)
        {
            aray[i].addEventListener('click', functionName); 
        }
        else if (array[i].attachEvent)
        {
            array[i].attachEvent('onclick', functionName);
        }   
    }
}

This works fine in chrome and firefox, because the "this" variable is set to the button I'm clicking on inside the toggleContent function. However, in IE "this" is equal to the (default) global window / document object and of course calling .parentElement on that yields null. Why is "this" not the clicked button?

For reference, the "button" i'm clickingon is actually an svg element:

<svg unhideicon class="svgIcon">    ....    </svg>
CupawnTae
  • 14,192
  • 3
  • 29
  • 60
user1884155
  • 3,616
  • 4
  • 55
  • 108
  • 2
    Why you need `.attachEvent`? [IE8 doesn't support svg at all](http://caniuse.com/#feat=svg) and that is the last version which does not support [`.addEventListener`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Browser_compatibility) – Andreas Jul 23 '15 at 09:14
  • Well we're gonna replace svg with img soon because of this, but first things first :) – user1884155 Jul 23 '15 at 09:44
  • I'm still curious... As already written, SVG is only supported by IE since version 9. Then why you need to use `.attachEvent`? IE9+ supports `.addEventListener` – Andreas Jul 23 '15 at 09:51

2 Answers2

3

this is a well-known Exlorer problem You have to use EVENT object to obtain your caller

function toggleContent(e)
{
    var event = e || window.event;
    var parent = (event.target || event.srcElement).parentElement;

    toggleClass(parent,"detailsAreVisible");
}
Matteo Rubini
  • 831
  • 5
  • 9
2

The actual issue is not because of IE, it is because of how attachEvent differs from addEventListener. You should notice your code works fine in IE9+ because it will use addEventListener like Chrome and Firefox. Where as IE8 uses attachEvent so needs to be handled a bit differently.

What I suggest is that you use call to call the function, that way you can define what this is, in this case you can tell it to be the element that you are attaching the event to:

// other code.
else if (array[i].attachEvent)
{
    var element = array[i];
    (function (el){
        el.attachEvent('onclick', function () {
            functionName.call(el);
        });
    })(element);
}

Using this method means you don't have to change your toggleContent function code

Here is a working example


Note that I have used a closure to avoid issues with your loop. Because the click event function runs when it's clicked, it means it will use the current value of i (not the value that was set when the event was attached). So regardless of which element you click, i will always be equal to array.length. Which is not only the wrong number, but is out of bounds anyway.

musefan
  • 47,875
  • 21
  • 135
  • 185
  • `array[i]` will be `undefined` when the `click` event is triggered, because `i` will be out of bounds – Andreas Jul 23 '15 at 09:35
  • pay attention with "i" variables and script fragment, variable may change after declaration and, when called, i=last value – Matteo Rubini Jul 23 '15 at 09:35
  • I'm confused. I thought javacript would put in the correct array[i] object when the "addClickEvent" function is called, why would it try to evaluate array[i] at the time I actually click? – user1884155 Jul 23 '15 at 09:46
  • Musefan, your solution would also need to be put in the other part of the if/else (the part with addEventListener instead of AttachEvent), because of IE 9+ – user1884155 Jul 23 '15 at 09:48
  • @user1884155 [Javascript infamous Loop issue?](http://stackoverflow.com/questions/1451009/javascript-infamous-loop-issue) – Andreas Jul 23 '15 at 09:52
  • @Andreas: Sorry, got a bit distracted. I wrapped in a closure which should resolve the issue – musefan Jul 23 '15 at 09:57
  • @user1884155: You don't need to add this code for `addEventListener`, the current issue is not with IE. It is with using `attachEvent` which is what IE 8 uses. IE 9+ will use `addEventListener`the same way other browsers do so don't need to fix that part – musefan Jul 23 '15 at 10:03