Il costruttore di eventi di Internet Explorer 9, 10 e 11 non funziona


129

Sto creando un evento, quindi usa il costruttore DOM Event:

new Event('change');

Funziona bene nei browser moderni, tuttavia in Internet Explorer 9, 10 e 11, non funziona con:

Object doesn't support this action

Come posso risolvere Internet Explorer (idealmente tramite un polyfill)? Se non posso, c'è una soluzione alternativa che posso usare?


56
"come posso risolvere Internet Explorer?" xD
contactmatt

Risposte:


176

Esiste un polyfill IE per il costruttore CustomEvent presso MDN . Aggiungendo CustomEvent a IE e usando quello invece funziona.

(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
Signore, mi hai salvato la vita. Sarebbe sicuro fare una sostituzione completa? Voglio dire, facendo window.Event= CustomEventsull'ultima riga.
Tfrascaroli,

7
In IE11 sembra sicuro impostare window.Event = CustomEvent, sì.
Corey Alix,

10
Per chiunque sia interessato sembra possibile rilevare che si è in IE (in questo caso) controllando typeof (Event) che è 'funzione' per tutti tranne IE dove è 'object'. È quindi possibile eseguire il polyfill in sicurezza del costruttore di eventi utilizzando l'approccio sopra.
Euan Smith,

Sto solo studiando una soluzione simile per StorageEvente typeof(StorageEvent)non funziona in MS Edge. Questo funziona: try { new StorageEvent(); } catch (e) { /* polyfill */ }.
Kamituel,

1
Potrebbe non essere sicuro sostituire window.CustomEvent, se si utilizzano librerie di terze parti che utilizzano il costruttore CustomEvent definito da IE.
Sen Jacob,

55

Penso che la migliore soluzione per risolvere il tuo problema e gestire la creazione di eventi cross-browser sia:

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
Funziona! Penso solo che dovrebbe, return eventquindi posso passarlo a dispatchEvent().
Noumenon,

initEventè obsoleto e deprecato , è necessario almeno utilizzare il modo moderno e come fallback, utilizzare il modo deprecato.
vsync,

2
@vsync Potrebbe essere deprecato, ma i documenti che hai collegato per dire "Usa invece costruttori di eventi specifici, come Event ()", che è esattamente ciò che sta cercando di eseguire il polyfill, quindi non c'è davvero scelta.
reduckted il

1
CustomEventconsente di trasferire dati personalizzati tramite l' detailopzione e Eventnon lo fa. Ho sbagliato?
pttsky,

1
CustomEvent non è supportato per IE9, 10 o 11 per esperienza personale. L'unica buona risposta sembra essere accettata.
Undying Jellyfish il

5

Questo pacchetto fa la magia:

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

Includi il pacchetto e invia l'evento come segue:

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

95 dipendenze?
Damien Roche,

4
@DamienRoche Potresti essere frainteso "Dipendenti" come "Dipendenze"? Perché il pacchetto in realtà ha 0 dipendenze e (al momento della scrittura) 102 dipendenze (cioè pacchetti che dipendono da esso). Che 102 pacchetti dipendenti probabilmente erano 95 a luglio.
influenza

2
Ho fatto dannatamente bene! : P
Damien Roche,

3

Se stai solo cercando di inviare un semplice evento come l'evento di attivazione / disattivazione HTML, questo funziona in Internet Explorer 11 e in altri browser:

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
non riesco a capire perché stai mescolando es6 let(e non usando var) un codice che dovrebbe essere eseguito sul vecchio IE .. potrebbe confondere i principianti che
copieranno

1
@vsync alzare ho fatto parlare il numero di versione. Il mio sito web personale era destinato esclusivamente a IE11 l'anno scorso, quindi non mi è mai venuto in mente di verificare il supporto nelle versioni precedenti. (Ad oggi, offro HTML IE11 senza fogli di stile o script. Le persone devono andare avanti.) In ogni caso, l'unica versione di Internet Explorer ancora supportata da Microsoft a partire dal 2017 aprile è la versione 11, quindi è un po 'un punto controverso. Non incoraggerei nessuno a utilizzare un browser non supportato scegliendo come target. Il Web può essere un posto pericoloso.
Patrick Dark,

3
non si tratta affatto di questo e non del tentativo di cambiare il mondo o altro. Ad esempio, il titolo della domanda richiede in particolare IE 9e sopra, e forse una persona in cerca di una risposta che trova questo thread, sta sviluppando un'app per il sistema bancario legacy o qualche altro sistema per clienti aziendali che non hanno alcun controllo sui propri computer e sono obbligato a lavorare con IE vecchio. questo non ha nulla a che fare con il supporto Microsoft ..
vsync,


2

il custom-eventpacchetto npm ha funzionato magnificamente per 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);

Questa è una buona risposta, ma c'è già un altro pacchetto NPM menzionato come risposta.
mikemaccana,

2
Cosa c'è di sbagliato nel fornire agli utenti una varietà di opzioni?
Liran H,

Un pacchetto più generico è npmjs.com/package/events-polyfill
Markus Jarderot

1

Personalmente utilizzo una funzione wrapper per gestire eventi creati manualmente. Il codice seguente aggiungerà un metodo statico su tutte le Eventinterfacce (tutte le variabili globali che terminano Eventsono un'interfaccia Event) e ti permetterà di chiamare funzioni come element.dispatchEvent(MouseEvent.create('click'));su 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 funzione per trovare tutte le Eventinterfacce può anche essere sostituita da un array per modificare solo le interfacce Event di cui hai bisogno ( ['Event', 'MouseEvent', 'KeyboardEvent', 'UIEvent' /*, etc... */]).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.