Internet Explorer 9, 10 и 11 Конструктор событий не работает

130

Я создаю событие, поэтому используйте конструктор DOM Event:

new Event('change');

Это отлично работает в современных браузерах, но в Internet Explorer 9, 10 и 11 не работает:

Object doesn't support this action

Как исправить Internet Explorer (в идеале через полифилл)? Если я не могу, могу ли я использовать обходной путь?

mikemaccana
источник
56
"как я могу исправить Internet Explorer?" xD
contactmatt 05

Ответы:

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;
})();
mikemaccana
источник
14
Вы, сэр, спасли мне жизнь. Будет ли безопасна полная замена? Я имею в виду, что делаю window.Event= CustomEventна последней строчке.
tfrascaroli 02
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.
Сен Джейкоб,
57

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

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
источник
3
Оно работает! Я просто думаю, что это нужно, return eventчтобы я мог передать его dispatchEvent().
Ноумен
initEventявляется устаревшим и устаревшим , вам нужно хотя бы использовать современный способ и в качестве запасного варианта использовать устаревший способ.
vsync
2
@vsync Это может быть устаревшим, но связанные с вами документы говорят: «Вместо этого используйте определенные конструкторы событий, такие как Event ()», а это именно то , что он пытается полифиллировать, поэтому на самом деле выбора нет.
уменьшено
1
CustomEventпозволяет передавать пользовательские данные через detailопцию и Eventне делает. Я ошибся?
pttsky 02
1
CustomEvent не поддерживается для IE9, 10 или 11, по моему собственному опыту. Единственный хороший ответ кажется принятым.
UndyingJellyfish
5

Этот пакет творит чудеса:

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

Включите пакет и отправьте событие следующим образом:

window.dispatchEvent(new window.CustomEvent('some-event'))
fsavina
источник
95 зависимостей?
Damien Roche
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
3

Есть сервис polyfill, который может исправить это и другие за вас

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

 <script crossorigin="anonymous" src="https://polyfill.io/v3/polyfill.min.js"></script>
frumbert
источник
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
Что плохого в том, чтобы предоставить пользователям множество вариантов?
Liran H
Более общий пакет - 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)));

РЕДАКТИРОВАТЬ: функцию поиска всех Eventинтерфейсов также можно заменить массивом, чтобы изменить только нужные вам интерфейсы событий ( ['Event', 'MouseEvent', 'KeyboardEvent', 'UIEvent' /*, etc... */]).

Кевин Дрост
источник