1

I am working on an old application for migrating it to Firefox from IE8/9. It should be compatible on both. As its a very old application, it does not uses jQuery. Client does not want to add jQuery also to this page. I found a strange issue. Here is the example in simple form:

<html>
    <head>
        <script>
            function test(){
                console.log(event);
            }
        </script>
    </head>
    <body >
        <button onclick="test()">Test</button>
    </body>
</html>

When I click on the Test button Firefox show an error that there is no event defined where as IE there is a default event it shows. My application uses this event object a lot. Any one having any idea how I can get this in Firefox?

enter image description here

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Deepak Kumar Padhy
  • 4,128
  • 6
  • 43
  • 79

2 Answers2

4

Your code is dependent on the IE event model, which creates a global window.event object for each event. It is deprecated in favour of the W3C event model (supported by Firefox and others), but still supported in IE for backward compatibility.

You need to pass the event object to the function:

<button onclick="test(event)">Test</button>

then in the function:

function test(event){
    alert(event);
}

If you attach the listener using addEventListner, the event object is passed to the listener as the first argument by default:

document.querySelector('#buttonID').addEventListener('click', test, false);

You can also add listeners directly as properties:

document.querySelector('#buttonID').onclick = test;

which passes the event object as the first parameter in the W3C event model, but not in IE so the function must test and use window.event if event is undefined:

function test(event){
    event = event  || window.event;
    console.log(event);
}

A very simple function to add a listener that works in all browser is:

function addEvent(element, event, fn) {
  if (element.addEventListener) {
    element.addEventListener(event, fn, false);
  } else if (element.attachEvent) {
    element.attachEvent('on' + event, fn);
  }
}

Note that in IE, this will not be set to the element that called the event. If you need to fix that, then the following will do that:

function addEvent(element, evt, fn) {
  if (element.addEventListener) {
    element.addEventListener(evt, fn, false);
  } else if (element.attachEvent) {
    element.attachEvent('on' + evt, function() {
      fn.call(element, event);
    });
  }
}

And use it like:

addEvent(document.getElementById('buttonID', 'click', test);

There are more sophisticated versions, but the above should suffice. It creates unnecessary circular references though, you might want to avoid those. To do that, you need something like:

function addEvent(element, evt, fn) {
  if (element.addEventListener) {
    element.addEventListener(evt, fn, false);
  } else if (element.attachEvent) {
    element.attachEvent('on' + evt, (function(fn, element) {
      return function() {
        fn.call(element, event);
      };
    }(fn, element)));
  }
  // Remove obvious circular reference
  element = null;
}

The bottom line is that in the vast majority of cases, adding listeners as properties is simple, cross browser and sufficient. It only falls down if you need to add more than one listener to an element for the same event, but even that is fairly easily accommodated.

RobG
  • 142,382
  • 31
  • 172
  • 209
3

There is a cross browser difference in implementation. IE used (and still uses) window.event object, while Firefox never implemented it this way. Instead Firefox supported passing event object into event handler. Try this:

function test(event) {
    console.log(event);
}

and in HTML:

<button onclick="test(event)">Test</button>

As the another possibility, since you have to support IE8, you could go with registering event as a property by directly assigning onclick function:

buttonObject.onclick = test;

where buttonObject is a reference to button HTMLElement obtained with some DOM method (document.getElementById, document.querySelector, etc).

Note, that in this case test function needs to use event fallback for window.event object (to make IE8 happy):

function test(event) {
    event = event || window.event;
    console.log(event);
}

|| operator makes sure event will be populated properly: in Firefox and IE9+ event argument will be available, and in IE<9 event parameter will be undefined and window.event will be used.

dfsq
  • 191,768
  • 25
  • 236
  • 258
  • Using that listener code, there is no need for *window.event*, the event object will be passed in both IE and W3C event models, it will not be undefined in IE. – RobG Dec 11 '14 at 14:18
  • @RobG Yes, but not in IE8 and earlier. – dfsq Dec 11 '14 at 14:20
  • In all versions of IE that supported events, back to IE 3 or earlier. – RobG Dec 11 '14 at 14:21
  • @dfsq: My js file contains 3000 lines of code . So for all the cases I need to pass the `event` object for firefox ? – Deepak Kumar Padhy Dec 11 '14 at 14:24
  • 1
    Yes. Or you can attach listeners using *addEventListener* or add them directly as properties. – RobG Dec 11 '14 at 14:27
  • @DeepakKumarPadhy Yes you will have to pass event object, because Firefox doesn't support `window.event`. Or you can use different method like selecting elements and registring `onclick` handler. Are suporting IE8? – dfsq Dec 11 '14 at 14:27
  • @RobG Looks like OP can't use addEventListener, because of IE8. Interesting observation about event object beeing passed in handler by IE. Looks like I confused something. – dfsq Dec 11 '14 at 14:28
  • @dfsq: will do that . Any idea on this http://stackoverflow.com/questions/27420580/attaching-multiple-events-to-a-button-issue-in-ie One more ie issue. – Deepak Kumar Padhy Dec 11 '14 at 14:28
  • @RobG: I know I can not use addEventListner IE8 uses `attachEvent` – Deepak Kumar Padhy Dec 11 '14 at 14:30
  • @DeepakKumarPadhy—there are plenty of solutions for that, e.g. [*addEventListener not working in IE8*](http://stackoverflow.com/questions/9769868/addeventlistener-not-working-in-ie8), which is a trivial solution. There are others but that may be sufficient for you. – RobG Dec 11 '14 at 14:32
  • @RobG: Yes used my own custom function for that which will use either addEventListener or attachevent depending upon browser – Deepak Kumar Padhy Dec 11 '14 at 14:33
  • @RobG Okay, I know what I confused it with. IE8 will **not** pass event object into handler in case of registration like this: `button.onclick = test`. – dfsq Dec 11 '14 at 14:34