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ć?


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

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

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

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

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... */]).


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

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

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.