Konstruktor zdarzeń programu Internet Explorer 9, 10 i 11 nie działa

134

Tworzę wydarzenie, więc użyj konstruktora DOM Event:

new Event('change');

Działa to dobrze w nowoczesnych przeglądarkach, jednak w Internet Explorer 9, 10 i 11 kończy się niepowodzeniem z:

Object doesn't support this action

Jak mogę naprawić Internet Explorera (najlepiej za pomocą polyfill)? Jeśli nie mogę, czy istnieje obejście, którego mogę użyć?

mikemaccana
źródło
57
„Jak mogę naprawić Internet Explorera?” xD
contactmatt

Odpowiedzi:

177

Istnieje wypełnienie IE dla konstruktora CustomEvent w MDN . Dodanie CustomEvent do IE i używanie go zamiast tego działa.

(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
źródło
14
Pan uratował mi życie. Czy pełne zastąpienie byłoby bezpieczne? Mam na myśli, robiąc window.Event= CustomEventw ostatniej linii.
tfrascaroli
7
W IE11 wydaje się być bezpieczne ustawienie window.Event = CustomEvent, tak.
Corey Alix
10
Dla każdego zainteresowanego wydaje się, że można wykryć, że jesteś w IE (w tym przypadku), sprawdzając typeof (Event), który jest „funkcją” dla wszystkich z wyjątkiem IE, gdzie jest to „obiekt”. Następnie możesz bezpiecznie wypełnić konstruktor Event, korzystając z powyższego podejścia.
Euan Smith
Właśnie badam podobne obejście StorageEventi typeof(StorageEvent)nie działa w MS Edge. Działa to: try { new StorageEvent(); } catch (e) { /* polyfill */ }.
kamituel
1
Zastąpienie window.CustomEvent może nie być bezpieczne, jeśli używasz bibliotek innych firm, które używają konstruktora CustomEvent zdefiniowanego w IE.
Sen Jacob
60

Myślę, że najlepszym rozwiązaniem do rozwiązania Twojego problemu i radzenia sobie z tworzeniem wydarzeń w różnych przeglądarkach jest:

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
źródło
3
To działa! Po prostu uważam, że powinno, return eventwięc mogę to przekazać dispatchEvent().
Noumenon,
initEventjest stary i przestarzały , musisz przynajmniej użyć nowoczesnego sposobu i jako rozwiązania zastępczego użyć przestarzałego sposobu.
vsync
3
@vsync To może być przestarzałe, ale dokumenty, do których utworzyłeś łącze, mówią „Zamiast tego użyj określonych konstruktorów zdarzeń, takich jak Event ()”, co jest dokładnie tym , co próbuje wypełnić, więc tak naprawdę nie ma wyboru.
zmniejszono
1
CustomEventpozwala na przekazywanie niestandardowych danych przez detailopcję, a Eventnie. Czy się mylę?
pttsky
1
CustomEvent nie jest obsługiwane w IE9, 10 lub 11, według mojego własnego doświadczenia. Wydaje się, że jedyną dobrą odpowiedzią jest akceptacja.
UndyingJellyfish
5

Ten pakiet robi magię:

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

Dołącz paczkę i wyślij zdarzenie w następujący sposób:

window.dispatchEvent(new window.CustomEvent('some-event'))
fsavina
źródło
95 zależności?
Damien Roche,
6
@DamienRoche Czy to możliwe, że przegapiłeś „Dependents” jako „Dependencies”? Ponieważ pakiet faktycznie ma 0 zależności i (do czasu pisania) 102 zależności (tj. Pakiety, które od niego zależą). W lipcu tych 102 pakietów zależnych prawdopodobnie było 95.
grypa
3
Cholernie dobrze! : P
Damien Roche
3

Jeśli próbujesz tylko wywołać proste zdarzenie, takie jak zdarzenie przełączania HTML, działa to w programie Internet Explorer 11, a także w innych przeglądarkach:

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
źródło
5
nie rozumiem, dlaczego mieszasz es6 let(i nie używasz var) z kodem, który ma działać na starym IE .. może to zmylić początkujących, którzy to skopiują i
wkleją
1
@vsync wzruszyć ja nie wspominając o numer wersji. Moja prywatna witryna była skierowana tylko do IE11 w zeszłym roku, więc nigdy nie przyszło mi do głowy, aby sprawdzić obsługę starszych wersji. (Na dzień dzisiejszy obsługuję zwykły HTML IE11 bez arkuszy stylów i skryptów. Ludzie muszą przejść dalej.) W każdym razie jedyną wersją Internet Explorera wciąż obsługiwaną przez firmę Microsoft od kwietnia 2017 r. Jest wersja 11, więc jest to trochę sprawa dyskusyjna. Nie zachęcałbym nikogo do korzystania z nieobsługiwanej przeglądarki, kierując ją na nią. Internet może być niebezpiecznym miejscem.
Patrick Dark,
4
w ogóle nie chodzi o to i nie chodzi o próbę zmiany świata czy cokolwiek. Na przykład w tytule pytania, o które chodzi konkretnie IE 9i powyżej, a być może osoba szukająca odpowiedzi, która znajdzie ten wątek, tworzy aplikację dla starszego systemu bankowego lub innego systemu dla klientów biznesowych, którzy nie mają kontroli nad swoimi komputerami i są zobowiązany do pracy ze starym IE. nie ma to nic wspólnego z pomocą techniczną firmy Microsoft ..
vsync
2

Osobiście używam funkcji opakowującej do obsługi ręcznie utworzonych zdarzeń. Poniższy kod doda statyczną metodę do wszystkich Eventinterfejsów (wszystkie zmienne globalne kończące się na Eventsą interfejsem Event) i umożliwi wywoływanie funkcji takich jak element.dispatchEvent(MouseEvent.create('click'));w 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)));

EDYCJA: Funkcję znajdującą wszystkie Eventinterfejsy można również zastąpić tablicą, aby zmienić tylko potrzebne interfejsy zdarzeń ( ['Event', 'MouseEvent', 'KeyboardEvent', 'UIEvent' /*, etc... */]).

Kevin Drost
źródło
2

the custom-eventpakiet npm pięknie pracował dla mnie

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.
źródło
To dobra odpowiedź, ale jako odpowiedź wymieniono już inny pakiet NPM.
mikemaccana
2
Co jest złego w oferowaniu użytkownikom różnorodnych opcji?
Liran H
Bardziej ogólny pakiet to npmjs.com/package/events-polyfill
Markus Jarderot