Конструктор подій Internet Explorer 9, 10 та 11 не працює


129

Я створюю подію, тому використовуйте конструктор подій DOM:

new Event('change');

Це добре працює в сучасних браузерах, проте в Internet Explorer 9, 10 та 11 він не вдається:

Object doesn't support this action

Як я можу виправити Internet Explorer (в ідеалі за допомогою поліфункції)? Якщо я не можу, чи можна вирішити спосіб вирішення?


55
"як я можу виправити Internet Explorer?" xD
contactmatt

Відповіді:


176

На MDN є поліфункція IE для конструктора CustomEvent . Додавання CustomEvent до IE та використання цього натомість працює.

(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
Ви, сер, врятували мені життя. Чи було б безпечно зробити повну заміну? Я маю на увазі, роблю window.Event= CustomEventна останньому рядку.
tfrascaroli

7
В IE11 здається, що безпечно встановити window.Event = CustomEvent, так.
Корі Алікс

10
Для всіх, хто цікавиться, можливо, можна виявити, що ви перебуваєте в IE (для цього випадку), перевіривши typeof (Event), який є "функцією" для всіх, крім IE, де він є "об'єктом". Потім можна безпечно заповнити конструктор подій, використовуючи вищезазначений підхід.
Юан Сміт

Я просто досліджую подібне рішення StorageEventі typeof(StorageEvent)не працює в MS Edge. Це працює: try { new StorageEvent(); } catch (e) { /* polyfill */ }.
kamituel

1
Замінити window.CustomEvent може не безпечно, якщо ви використовуєте сторонні бібліотеки, які використовують конструктор CustomEvent, визначений IE.
Сена Якова

55

Я думаю, що найкраще рішення для вирішення вашої проблеми та вирішення проблем із створенням крос-браузерних подій:

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
Це працює! Я просто думаю, що це повинно, return eventщоб я міг передати це dispatchEvent().
Номенон

initEventє старим і застарілим , вам потрібно принаймні використовувати сучасний спосіб і як запасний спосіб використовувати застарілий спосіб.
vsync

2
@vsync Це може бути застарілим, але документи, з якими ви посилаєтесь, говорять "Натомість використовуйте конкретні конструктори подій, як, наприклад, Event ()". Це саме те , що це намагається заповнити, тому вибору насправді немає.
скорочено

1
CustomEventдозволяє передавати власні дані через detailопцію, а Eventні. Я помиляюся?
птцький

1
CustomEvent не підтримується для IE9, 10 або 11, на мій власний досвід. Єдиною хорошою відповіддю, здається, є прийнята.
UndyingJellyfish

5

Цей пакет робить магію:

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

Включіть пакет і відправте подію наступним чином:

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

95 залежностей?
Дамієн Рош

4
@DamienRoche Чи могли б ви неправильно прочитати "Залежних" як "Залежності"? Тому що пакет фактично має 0 залежностей і (до моменту написання) 102 залежних (тобто пакетів, які залежать від нього). Ці 102 залежні пакети, ймовірно, повернулися 95 в липні.
грип

2
Я криваво добре зробив! : P
Дамієн Рош

3

Якщо ви просто намагаєтесь відправити таку просту подію, як подія перемикання HTML, це працює в Internet Explorer 11, а також інших браузерах:

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
не можу зрозуміти, чому ви змішуєте es6 let(а не використовуєте var) з кодом, який повинен працювати на старому IE .. це може заплутати початківців, які
скопіюють

1
@vsync знизують я зробив згадати номер версії. Мій особистий веб-сайт був орієнтований лише на IE11 минулого року, тому мені ніколи не спадало на думку перевіряти підтримку в старих версіях. (На сьогоднішній день я обслуговую звичайний HTML IE11 без таблиць стилів чи сценаріїв. Людям потрібно рухатись далі.) У будь-якому випадку, єдиною версією Internet Explorer, яка все ще підтримується Microsoft станом на квітень 2017 року, є версія 11, тому це трохи точка суперечки. Я б не закликав когось використовувати непідтримуваний браузер, націлюючи його. Мережа може бути небезпечним місцем.
Патрік Темний

3
справа зовсім не в тому, а не в спробі змінити світ чи що-небудь. Наприклад, заголовок на запитання конкретно запитує IE 9і вище, і, можливо, людина, яка шукає відповідь, яка знайде цю тему, розробляє додаток для застарілої банківської системи або іншу систему для бізнес-клієнтів, які не мають контролю над своїми комп’ютерами і є зобов’язаний працювати зі старим IE. це не має нічого спільного з підтримкою Microsoft ..
vsync


2

custom-eventпакет NPM працював прекрасно для мене

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

Це хороша відповідь, але вже є ще один пакет NPM, який згадується як відповідь.
mikemaccana

2
Що не так у наданні користувачам різноманітних варіантів?
Ліран Н

Більш загальний пакет - npmjs.com/package/events-polyfill
Маркус Джардеро,

1

Я особисто використовую функцію обгортки для обробки подій, створених вручну. Наступний код додасть статичний метод для всіх Eventінтерфейсів (усі глобальні змінні, що закінчуються Event, є інтерфейсом події) і дозволить викликати функції, як element.dispatchEvent(MouseEvent.create('click'));на 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: Функція пошуку всіх Eventінтерфейсів також може бути замінена масивом, щоб змінити лише потрібні інтерфейси Event ( ['Event', 'MouseEvent', 'KeyboardEvent', 'UIEvent' /*, etc... */]).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.