Internet Explorer 9, 10 & 11 Pembuat acara tidak berfungsi

129

Saya membuat acara, jadi gunakan konstruktor DOM Event:

new Event('change');

Ini berfungsi baik di browser modern, namun di Internet Explorer 9, 10 & 11, gagal dengan:

Object doesn't support this action

Bagaimana saya bisa memperbaiki Internet Explorer (idealnya melalui polyfill)? Jika saya tidak bisa, apakah ada solusi yang dapat saya gunakan?

mikemaccana
sumber
56
"bagaimana saya bisa memperbaiki Internet Explorer?" xD
contactmatt

Jawaban:

176

Ada polyfill IE untuk konstruktor CustomEvent di MDN . Menambahkan CustomEvent ke IE dan menggunakannya malah berfungsi.

(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
sumber
14
Anda Tuan menyelamatkan hidup saya. Apakah aman untuk membuat pengganti yang lengkap? Maksudku, lakukan window.Event= CustomEventdi baris terakhir.
tfrascaroli
7
Di IE11 tampaknya aman untuk mengatur window.Event = CustomEvent, ya.
Corey Alix
10
Bagi siapa pun yang tertarik tampaknya mungkin untuk mendeteksi Anda berada di IE (untuk kasus ini) dengan memeriksa typeof (Event) yang merupakan 'fungsi' untuk semua kecuali IE di mana itu adalah 'objek'. Anda kemudian dapat dengan aman polyfill konstruktor acara menggunakan pendekatan di atas.
Euan Smith
Saya baru saja menyelidiki penyelesaian yang serupa untuk StorageEventdan typeof(StorageEvent)tidak bekerja di MS Edge. Ini bekerja: try { new StorageEvent(); } catch (e) { /* polyfill */ }.
kamituel
1
Mungkin tidak aman untuk mengganti jendela. CustomEvent, jika Anda menggunakan perpustakaan pihak ketiga yang menggunakan konstruktor CustomEvent yang ditentukan IE.
Sen Jacob
55

Saya pikir solusi terbaik untuk menyelesaikan masalah Anda dan menangani pembuatan acara lintas-browser adalah:

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
sumber
3
Berhasil! Saya hanya berpikir itu harus return eventjadi saya bisa meneruskannya dispatchEvent().
Noumenon
initEventsudah tua dan usang , Anda harus setidaknya menggunakan cara modern dan sebagai cadangan, gunakan cara usang.
vsync
2
@vsync Mungkin sudah tidak digunakan lagi, tetapi dokumen yang Anda tautkan mengatakan "Alih-alih menggunakan konstruktor peristiwa tertentu, seperti Event ()", yang persis seperti ini yang coba di-polyfill, jadi tidak ada pilihan lain.
Reduckted
1
CustomEventmemungkinkan untuk melewatkan data khusus melalui detailopsi, dan Eventtidak. Apakah aku salah?
pttsky
1
CustomEvent tidak didukung untuk IE9, 10 atau 11 baik per pengalaman saya sendiri. Satu-satunya jawaban yang baik tampaknya adalah yang diterima.
UndyingJellyfish
5

Paket ini melakukan keajaiban:

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

Sertakan paket dan kirim acara sebagai berikut:

window.dispatchEvent(new window.CustomEvent('some-event'))
fsavina
sumber
95 dependensi?
Damien Roche
4
@DamienRoche Mungkinkah Anda salah membaca "Tanggungan" sebagai "Tanggungan"? Karena paket tersebut sebenarnya memiliki 0 dependensi dan (pada saat penulisan) 102 tanggungan (yaitu, paket yang bergantung padanya). Itu 102 paket tergantung mungkin 95 kembali pada bulan Juli.
Flu
2
Aku benar-benar berdarah! : P
Damien Roche
3

Jika Anda hanya mencoba mengirim acara sederhana seperti acara beralih HTML, ini berfungsi di Internet Explorer 11 serta browser lainnya:

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
sumber
5
tidak dapat melihat mengapa Anda mencampurkan es6 let(dan tidak menggunakan var) dengan kode yang seharusnya dijalankan pada IE lama .. ini mungkin membingungkan pemula yang akan menyalin-menempelkan ini
vsync
1
@ vsync mengangkat bahu Saya memang menyebutkan nomor versi. Situs web pribadi saya hanya menargetkan IE11 tahun lalu, jadi tidak pernah terpikir oleh saya untuk memeriksa dukungan dalam versi yang lebih lama. (Sampai hari ini, saya menyajikan IE11 HTML biasa tanpa stylesheet atau skrip. Orang-orang perlu melanjutkan.) Dalam hal apa pun, satu-satunya versi Internet Explorer yang masih didukung oleh Microsoft pada 2017 April adalah versi 11, jadi ini sedikit titik diperdebatkan. Saya tidak akan mendorong siapa pun untuk menggunakan browser yang tidak didukung dengan menargetkannya. Web bisa menjadi tempat yang berbahaya.
Patrick Dark
3
ini sama sekali bukan tentang itu, dan bukan tentang mencoba mengubah dunia atau apa pun. Misalnya, judul untuk pertanyaan yang secara spesifik menanyakan IE 9dan di atas, dan mungkin seseorang yang mencari jawaban yang menemukan utas ini, sedang mengembangkan aplikasi untuk sistem perbankan warisan atau sistem lain untuk klien bisnis yang tidak memiliki kendali atas komputer mereka dan wajib bekerja dengan IE lama. ini tidak ada hubungannya dengan Dukungan Microsoft ..
vsync
3

Ada layanan polyfill yang dapat menambal ini dan lainnya untuk Anda

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

 <script crossorigin="anonymous" src="https://polyfill.io/v3/polyfill.min.js"></script>
frumbert
sumber
2

yang custom-eventpaket NPM bekerja dengan indah bagi saya

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
sumber
Ini adalah jawaban yang bagus, tetapi sudah ada paket NPM lain yang disebutkan sebagai jawaban.
mikemaccana
2
Apa yang salah dengan memberi pengguna berbagai opsi?
Liran H
Paket yang lebih umum adalah npmjs.com/package/events-polyfill
Markus Jarderot
1

Saya pribadi menggunakan fungsi pembungkus untuk menangani acara yang dibuat secara manual. Kode berikut akan menambahkan metode statis pada semua Eventantarmuka (semua variabel global yang diakhiri Eventadalah antarmuka Acara) dan memungkinkan Anda untuk memanggil fungsi seperti element.dispatchEvent(MouseEvent.create('click'));pada 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: Fungsi untuk menemukan semua Eventantarmuka juga dapat diganti dengan array untuk mengubah hanya antarmuka Acara yang Anda butuhkan ( ['Event', 'MouseEvent', 'KeyboardEvent', 'UIEvent' /*, etc... */]).

Kevin Drost
sumber