Le constructeur d'événements Internet Explorer 9, 10 et 11 ne fonctionne pas


129

Je crée un événement, alors utilisez le constructeur d'événement DOM:

new Event('change');

Cela fonctionne bien dans les navigateurs modernes, mais dans Internet Explorer 9, 10 et 11, cela échoue avec:

Object doesn't support this action

Comment puis-je réparer Internet Explorer (idéalement via un polyfill)? Si je ne peux pas, y a-t-il une solution de contournement que je peux utiliser?


56
"Comment puis-je réparer Internet Explorer?" xD
contactmatt

Réponses:


176

Il existe un polyfill IE pour le constructeur CustomEvent chez MDN . L'ajout de CustomEvent à IE et son utilisation fonctionnent à la place.

(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;
})();

14
Vous monsieur m'a sauvé la vie. Serait-il prudent de faire une substitution complète? Je veux dire, faire window.Event= CustomEventsur la dernière ligne.
tfrascaroli le

7
Dans IE11, il semble être sûr de définir window.Event = CustomEvent, oui.
Corey Alix

10
Pour toute personne intéressée, il semble possible de détecter que vous êtes dans IE (dans ce cas) en vérifiant typeof (Event) qui est «fonction» pour tous sauf IE où c'est «objet». Vous pouvez ensuite polyfill en toute sécurité le constructeur Event en utilisant l'approche ci-dessus.
Euan Smith

J'étudie juste une solution de contournement similaire StorageEventet typeof(StorageEvent)ne fonctionne pas dans MS Edge. Cela fonctionne: try { new StorageEvent(); } catch (e) { /* polyfill */ }.
kamituel

1
Il peut ne pas être sûr de remplacer window.CustomEvent, si vous utilisez des bibliothèques tierces qui utilisent le constructeur CustomEvent défini par IE.
Sen Jacob

55

Je pense que la meilleure solution pour résoudre votre problème et gérer la création d'événements multi-navigateurs est:

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;
}

3
Ça marche! Je pense juste que ça devrait return eventpour que je puisse le transmettre dispatchEvent().
Noumenon

initEventest vieux et obsolète , vous devez au moins utiliser la méthode moderne et comme solution de secours, utilisez la méthode obsolète.
vsync

2
@vsync Cela peut être obsolète, mais les documents que vous avez liés disent "Utilisez plutôt des constructeurs d'événements spécifiques, comme Event ()", ce qui est exactement ce que cela essaie de polyfill, donc il n'y a pas vraiment de choix.
rédigé

1
CustomEventpermet de transmettre des données personnalisées via l' detailoption, et Eventne le fait pas. Ai-je tort?
pttsky

1
CustomEvent n'est pas pris en charge pour IE9, 10 ou 11 selon ma propre expérience. La seule bonne réponse semble être l'acceptation.
UndyingJellyfish

5

Ce package fait la magie:

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

Incluez le colis et envoyez l'événement comme suit:

window.dispatchEvent(new window.CustomEvent('some-event'))

95 dépendances?
Damien Roche

4
@DamienRoche Est-ce que vous avez mal lu "Dependents" comme "Dependencies"? Parce que le paquet a en fait 0 dépendances et (au moment de l'écriture) 102 dépendants (c'est-à-dire des paquets qui en dépendent). Ces 102 paquets dépendants étaient probablement 95 en juillet.
grippe

2
J'ai bien fait! : P
Damien Roche

3

Si vous essayez simplement de distribuer un événement simple comme l'événement de bascule HTML, cela fonctionne dans Internet Explorer 11 ainsi que dans les autres navigateurs:

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);

5
Je ne vois pas pourquoi vous mélangez es6 let(et ne l'utilisez pas var) avec un code censé fonctionner sur l'ancien IE .. cela pourrait dérouter les débutants qui vont copier-coller ceci
vsync

1
@vsync hausser les épaules , je l'ai fait mentionner le numéro de version. Mon site Web personnel ne ciblait IE11 que l'année dernière, il ne m'est donc jamais venu à l'esprit de vérifier le support dans les anciennes versions. (À partir d'aujourd'hui, je sers du HTML brut IE11 sans feuilles de style ni scripts. Les gens doivent passer à autre chose.) Dans tous les cas, la seule version d'Internet Explorer toujours prise en charge par Microsoft à partir d'avril 2017 est la version 11, donc c'est un peu un point discutable. Je n'encourage personne à utiliser un navigateur non compatible en le ciblant. Le Web peut être un endroit dangereux.
Patrick Dark

3
il ne s'agit pas du tout de cela, ni d'essayer de changer le monde ou quoi que ce soit. Par exemple, le titre de la question demande spécifiquement pour IE 9et au-dessus, et peut-être qu'une personne cherchant une réponse qui trouve ce fil, développe une application pour le système bancaire hérité ou un autre système pour les clients commerciaux qui n'ont aucun contrôle sur leurs ordinateurs et sont obligé de travailler avec l'ancien IE. cela n'a rien à voir avec le support Microsoft ..
vsync


2

le custom-eventpackage npm a parfaitement fonctionné pour moi

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);

C'est une bonne réponse, mais il existe déjà un autre package NPM mentionné comme réponse.
mikemaccana

2
Quel est le problème à offrir aux utilisateurs une variété d'options?
Liran H

Un package plus générique est npmjs.com/package/events-polyfill
Markus Jarderot

1

J'utilise personnellement une fonction wrapper pour gérer les événements créés manuellement. Le code suivant ajoutera une méthode statique sur toutes les Eventinterfaces (toutes les variables globales se terminant par Eventsont une interface d'événement) et vous permettra d'appeler des fonctions comme element.dispatchEvent(MouseEvent.create('click'));sur 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: La fonction de recherche de toutes les Eventinterfaces peut également être remplacée par un tableau pour modifier uniquement les interfaces d'événement dont vous avez besoin ( ['Event', 'MouseEvent', 'KeyboardEvent', 'UIEvent' /*, etc... */]).

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.