Internet Explorer 9, 10 & 11 Der Ereigniskonstruktor funktioniert nicht

129

Ich erstelle ein Ereignis. Verwenden Sie daher den DOM-Ereigniskonstruktor:

new Event('change');

Dies funktioniert in modernen Browsern einwandfrei, schlägt jedoch in Internet Explorer 9, 10 und 11 fehl mit:

Object doesn't support this action

Wie kann ich den Internet Explorer reparieren (idealerweise über eine Polyfüllung)? Wenn ich nicht kann, gibt es eine Problemumgehung, die ich verwenden kann?

Mikemaccana
quelle
55
"Wie kann ich den Internet Explorer reparieren?" xD
contactmatt

Antworten:

176

Es gibt eine IE-Polyfüllung für den CustomEvent-Konstruktor bei MDN . Das Hinzufügen von CustomEvent zum IE und dessen Verwendung funktioniert stattdessen.

(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;
})();
Mikemaccana
quelle
14
Sie, mein Herr, haben mir das Leben gerettet. Wäre es sicher, eine vollständige Substitution vorzunehmen? Ich meine, window.Event= CustomEventin der letzten Zeile.
Tfrascaroli
7
In IE11 scheint es sicher zu sein, window.Event = CustomEvent zu setzen, ja.
Corey Alix
10
Für alle Interessierten scheint es möglich zu sein, zu erkennen, dass Sie sich im IE befinden (in diesem Fall), indem Sie typeof (Event) überprüfen, das für alle außer dem IE, bei dem es sich um ein Objekt handelt, "Funktion" ist. Anschließend können Sie den Ereigniskonstruktor mithilfe des obigen Ansatzes sicher mehrfach füllen.
Euan Smith
Ich untersuche nur eine ähnliche Problemumgehung StorageEventund typeof(StorageEvent)arbeite nicht in MS Edge. Das funktioniert : try { new StorageEvent(); } catch (e) { /* polyfill */ }.
Kamituel
1
Es ist möglicherweise nicht sicher, window.CustomEvent zu ersetzen, wenn Sie Bibliotheken von Drittanbietern verwenden, die den vom IE definierten CustomEvent-Konstruktor verwenden.
Sen Jacob
55

Ich denke, dass die beste Lösung, um Ihr Problem zu lösen und sich mit der Erstellung browserübergreifender Ereignisse zu befassen, Folgendes ist:

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;
}
michalduda
quelle
3
Es klappt! Ich denke nur, dass es return eventso sein sollte, damit ich es weitergeben kann dispatchEvent().
Noumenon
initEventIst alt und veraltet , müssen Sie zumindest die moderne Methode verwenden und als Fallback die veraltete Methode verwenden.
vsync
2
@vsync Es ist möglicherweise veraltet, aber in den von Ihnen verlinkten Dokumenten steht "Verwenden Sie stattdessen bestimmte Ereigniskonstruktoren wie Event ()". Genau das versucht dies zu polyfillieren, sodass es wirklich keine Wahl gibt.
Reduziert
1
CustomEventErmöglicht die Weitergabe benutzerdefinierter Daten durch die detailOption und Eventnicht. Liege ich falsch?
Pttsky
1
CustomEvent wird meiner Erfahrung nach auch nicht für IE9, 10 oder 11 unterstützt. Die einzig gute Antwort scheint die akzeptierte zu sein.
UndyingJellyfish
5

Dieses Paket macht die Magie:

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

Fügen Sie das Paket hinzu und senden Sie die Veranstaltung wie folgt aus:

window.dispatchEvent(new window.CustomEvent('some-event'))
fsavina
quelle
95 Abhängigkeiten?
Damien Roche
4
@DamienRoche Könnte es sein, dass Sie "Abhängige" als "Abhängigkeiten" falsch verstanden haben? Weil das Paket tatsächlich 0 Abhängigkeiten und (zum Zeitpunkt des Schreibens) 102 Abhängigkeiten hat (dh Pakete, die davon abhängen). Diese 102 abhängigen Pakete waren wahrscheinlich im Juli 95.
Grippe
2
Ich habe es verdammt gut gemacht! : P
Damien Roche
3

Wenn Sie nur versuchen, ein einfaches Ereignis wie das HTML-Umschaltereignis auszulösen, funktioniert dies sowohl in Internet Explorer 11 als auch in den anderen Browsern:

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);
Patrick Dark
quelle
5
es6 letvar
Ich
1
@vsync Achselzucken Ich habe die Versionsnummer erwähnt. Meine persönliche Website war letztes Jahr nur auf IE11 ausgerichtet, daher kam ich nie auf den Gedanken, den Support in älteren Versionen zu überprüfen. (Ab heute verwende ich einfaches IE11-HTML ohne Stylesheets oder Skripte. Die Benutzer müssen weitermachen.) Auf jeden Fall ist die einzige Version von Internet Explorer, die von Microsoft ab April 2017 noch unterstützt wird, Version 11, also eine Art von strittiger Punkt. Ich würde niemanden ermutigen, einen nicht unterstützten Browser zu verwenden, indem er darauf abzielt. Das Web kann ein gefährlicher Ort sein.
Patrick Dark
3
Es geht überhaupt nicht darum und nicht darum, die Welt oder irgendetwas zu verändern. Zum Beispiel entwickelt der Titel für die Frage, nach der speziell gefragt wird IE 9, und möglicherweise eine Person, die nach einer Antwort sucht und diesen Thread findet, eine App für ein altes Bankensystem oder ein anderes System für Geschäftskunden, die keine Kontrolle über ihre Computer haben und dies sind verpflichtet, mit alten IE zu arbeiten. Dies hat nichts mit Microsoft Support zu tun ..
vsync
3

Es gibt einen Polyfill-Service, der dieses und andere für Sie patchen kann

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

 <script crossorigin="anonymous" src="https://polyfill.io/v3/polyfill.min.js"></script>
Frumbert
quelle
2

Das custom-eventnpm-Paket hat bei mir wunderbar funktioniert

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);
Liran H.
quelle
Dies ist eine gute Antwort, aber es gibt bereits ein anderes NPM-Paket, das als Antwort erwähnt wird.
Mikemaccana
2
Was ist falsch daran, Benutzern eine Vielzahl von Optionen anzubieten?
Liran H
Ein allgemeineres Paket ist npmjs.com/package/events-polyfill
Markus Jarderot
1

Ich persönlich verwende eine Wrapper-Funktion, um manuell erstellte Ereignisse zu verarbeiten. Der folgende Code fügt eine statische Methode für alle EventSchnittstellen hinzu (alle globalen Variablen, die mit enden, Eventsind eine Ereignisschnittstelle) und ermöglicht es Ihnen, Funktionen wie element.dispatchEvent(MouseEvent.create('click'));unter IE9 + aufzurufen .

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

BEARBEITEN: Die Funktion zum Auffinden aller EventSchnittstellen kann auch durch ein Array ersetzt werden, um nur die von Ihnen benötigten Ereignisschnittstellen zu ändern ( ['Event', 'MouseEvent', 'KeyboardEvent', 'UIEvent' /*, etc... */]).

Kevin Drost
quelle