Internet Explorer 9, 10 & 11 Event constructor doesn't work
N

7

141

I am creating an event, so use the DOM Event constructor:

new Event('change');

This works fine in modern browsers, however in Internet Explorer 9, 10 & 11, it fails with:

Object doesn't support this action

How can I fix Internet Explorer (ideally via a polyfill)? If I can't, is there a workaround I can use?

Neckcloth answered 27/10, 2014 at 20:19 Comment(1)
"how can I fix Internet Explorer?" xDPearsall
N
187

There's an IE polyfill for the CustomEvent constructor at MDN. Adding CustomEvent to IE and using that instead works.

(function () {
  if ( typeof window.CustomEvent === "function" ) return false; //If not IE

  function CustomEvent ( event, params ) {
    params = params || { bubbles: false, cancelable: false, detail: undefined };
    var evt = document.createEvent( 'CustomEvent' );
    evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
    return evt;
   }

  CustomEvent.prototype = window.Event.prototype;

  window.CustomEvent = CustomEvent;
})();
Neckcloth answered 27/10, 2014 at 20:32 Comment(9)
You sir saved my life. Would it be safe to make a complete substitution? I mean, doing window.Event= CustomEvent on the last line.Endocarp
In IE11 it seems to be safe to set window.Event = CustomEvent, yes.Salazar
For anybody interested it seems to be possible to detect you are in IE (for this case) by checking typeof(Event) which is 'function' for all except IE where it is 'object'. You can then safely polyfill the Event constructor using the approach above.Enwind
I'm just investigating similar workaround for StorageEvent and typeof(StorageEvent) doesn't work in MS Edge. This works: try { new StorageEvent(); } catch (e) { /* polyfill */ }.Dissension
It might not be safe to substitute window.CustomEvent, if you are using third party libraries which uses IE defined CustomEvent constructor.Dibranchiate
In IE you need to place this block of code at the very top before it is needed for instantiation.Plutonium
Refer here developer.mozilla.org/en-US/docs/Web/API/CustomEvent/…Derrickderriey
I had to to some adjustments, but this is definitely the solution. Saved my day. Thanks.Anuradhapura
I noticed the polyfill on MDN doesn't have this line: CustomEvent.prototype = window.Event.prototype; -- what's the purpose of adding this line?Accentual
C
68

I think that the best solution to solve your problem and deal with cross-browser event creation is:

function createNewEvent(eventName) {
    var event;
    if (typeof(Event) === 'function') {
        event = new Event(eventName);
    } else {
        event = document.createEvent('Event');
        event.initEvent(eventName, true, true);
    }
    return event;
}
Concepcion answered 7/2, 2017 at 12:6 Comment(5)
It works! I just think it should return event so I can pass it to dispatchEvent().Zwart
initEvent is old and deprecated, you need to at least use the modern way and as a fallback, use the deprecated way.Omniscient
@Omniscient It might be deprecated, but the docs you linked to say "Instead use specific event constructors, like Event()", which is exactly what this is trying to polyfill, so there's no choice really.Likeminded
CustomEvent allows to pass custom data through detail option, and Event doesn't. Am I wrong?Wolverhampton
CustomEvent is not supported for IE9, 10 or 11 either per my own experience. The only good answer seems to be the accepted.Meandrous
C
4

This package does the magic:

https://www.npmjs.com/package/custom-event-polyfill

Include the package and dispatch the event as following:

window.dispatchEvent(new window.CustomEvent('some-event'))
Confraternity answered 16/2, 2017 at 17:44 Comment(3)
95 dependencies?Sterlingsterlitamak
@DamienRoche Could it be you missread "Dependents" as "Dependencies"? Because the package actually has 0 dependencies and (by the time of writing) 102 dependents (i.e., packages that depend on it). That 102 dependent packages probably were 95 back in july.Delrio
I bloody well did! :PSterlingsterlitamak
S
3

If you're just trying to dispatch a simple event like the HTML toggle event, this works in Internet Explorer 11 as well as the other browsers:

let toggle_event = null;
try {
    toggle_event = new Event("toggle");
}
catch (error) {
    toggle_event = document.createEvent("Event");
    let doesnt_bubble = false;
    let isnt_cancelable = false;
    toggle_event.initEvent("toggle", doesnt_bubble, isnt_cancelable);
}
// disclosure_control is a details element.
disclosure_control.dispatchEvent(toggle_event);
Sacha answered 15/9, 2016 at 13:21 Comment(3)
can't see why you are mixing es6 let (and not use var) with a code supposed to run on old IE.. it might confuse beginners who will copy-paste thisOmniscient
@Omniscient shrug I did mention the version number. My personal website was only targeting IE11 last year, so it never occurred to me to check support in older versions. (As of today, I serve IE11 plain HTML without stylesheets or scripts. People need to move on.) In any case, the only version of Internet Explorer still supported by Microsoft as of 2017 April is version 11, so it's a bit of a moot point. I’d not encourage anyone to use an unsupported browser by targeting it. The Web can be a dangerous place.Sacha
it's not about that at all, and not about trying to change the world or anything. For example, the title for the question specifically asks for IE 9 and above, and perhaps a person seeking an answer who finds this thread, is developing an app for legacy banking system or some other system for business clients which have no control over their computers and are obliged to work with old IE. this has nothing to do with Microsoft Support..Omniscient
C
3

the custom-event npm package worked beautifully for me

https://www.npmjs.com/package/custom-event

var CustomEvent = require('custom-event');

// add an appropriate event listener
target.addEventListener('cat', function(e) { process(e.detail) });

// create and dispatch the event
var event = new CustomEvent('cat', {
  detail: {
    hazcheeseburger: true
  }
});
target.dispatchEvent(event);
Clash answered 15/6, 2018 at 11:4 Comment(3)
This is a good answer, but there's already another NPM package mentioned as an answer.Neckcloth
What's wrong with giving users a variety of options?Clash
A more generic package is npmjs.com/package/events-polyfillSapindaceous
K
3

There's a polyfill service which can patch this and others for you

https://polyfill.io/v3/url-builder/

 <script crossorigin="anonymous" src="https://polyfill.io/v3/polyfill.min.js"></script>
Khajeh answered 14/3, 2019 at 0:28 Comment(0)
S
2

I personally use a wrapper function to handle manually created events. The following code will add a static method on all Event interfaces (all global variables ending in Event are an Event interface) and allow you to call functions like element.dispatchEvent(MouseEvent.create('click')); on IE9+.

(function eventCreatorWrapper(eventClassNames){
    eventClassNames.forEach(function(eventClassName){
        window[eventClassName].createEvent = function(type,bubbles,cancelable){
            var evt
            try{
                evt = new window[eventClassName](type,{
                    bubbles: bubbles,
                    cancelable: cancelable
                });
            } catch (e){
                evt = document.createEvent(eventClassName);
                evt.initEvent(type,bubbles,cancelable);
            } finally {
                return evt;
            }
        }
    });
}(function(root){
    return Object.getOwnPropertyNames(root).filter(function(propertyName){
        return /Event$/.test(propertyName)
    });
}(window)));

EDIT: The function to find all Event interfaces can also be replaced by an array to alter only the Event interfaces you need (['Event', 'MouseEvent', 'KeyboardEvent', 'UIEvent' /*, etc... */]).

Somato answered 9/2, 2018 at 11:57 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.