, mentakrifkan pautan ini. Ia kemudiannya akan dihantar kepada elemen yang mengandungi: mungkin elemen Elemen dan objek Dokumen itu sendiri. Kadangkala adalah lebih mudah untuk mendaftarkan pengendali acara tunggal pada objek Dokumen atau elemen kontena lain daripada mendaftar pada semua elemen yang diminati.
Setelah mentakrifkan beberapa istilah, kita boleh meneruskan untuk meneroka isu yang berkaitan dengan acara dan pemprosesannya.
Mendaftarkan Pengendali Acara Terdapat dua cara utama untuk mendaftar pengendali acara. Yang pertama, yang muncul pada awal pembangunan World Wide Web, adalah untuk menetapkan sifat objek atau elemen dokumen yang menjadi sasaran acara tersebut. Kaedah kedua, lebih baru dan lebih universal, adalah untuk menghantar pengendali kepada kaedah objek atau elemen.
Perkara ini rumit oleh fakta bahawa setiap teknik mempunyai dua versi. Anda boleh menetapkan sifat pengendali acara dalam kod JavaScript atau dalam elemen dokumen dengan mentakrifkan atribut yang sepadan secara langsung dalam penanda HTML. Mendaftarkan pengendali dengan panggilan kaedah boleh dilakukan dengan kaedah standard yang dipanggil addEventListener(), yang disokong oleh semua pelayar kecuali IE versi 8 dan ke bawah, dan kaedah lain yang dipanggil attachEvent(), disokong oleh semua versi IE sehingga IE9.
Menetapkan sifat pengendali acara Cara paling mudah untuk mendaftar pengendali acara ialah menetapkan sifat sasaran acara kepada fungsi pengendali yang dikehendaki. Mengikut konvensyen, sifat pengendali acara mempunyai nama yang terdiri daripada perkataan "on" diikuti dengan nama acara: onclick, onchange, onload, onmouseover, dsb. Harap maklum bahawa nama sifat ini sensitif huruf besar dan hanya menggunakan aksara kecil, walaupun nama jenis acara ialah berbilang perkataan (contohnya, "readystatechange"). Di bawah ialah dua contoh pendaftaran pengendali acara:
// Berikan fungsi kepada sifat onload objek Window. // Fungsi ialah pengendali acara: ia dipanggil apabila dokumen dimuatkan window.onload = function() ( // Cari elemen var elt = document.getElementById("shipping_address"); // Daftarkan pengendali acara yang akan dipanggil // terus sebelum menyerahkan borang elt.onsubmit = function() ( return validate(this); ) )
Kaedah mendaftar pengendali acara ini disokong dalam semua penyemak imbas untuk semua jenis acara yang biasa digunakan. Secara umum, semua antara muka aplikasi yang disokong secara meluas yang mentakrifkan acara mereka membenarkan pengendali didaftarkan dengan menetapkan sifat pengendali acara.
Kelemahan menggunakan sifat pengendali acara ialah ia direka bentuk dengan andaian bahawa sasaran acara akan mempunyai paling banyak satu pengendali bagi setiap jenis acara. Apabila mencipta pustaka untuk digunakan dalam dokumen sewenang-wenangnya, lebih baik menggunakan teknik (seperti memanggil kaedah addEventListener()) untuk mendaftarkan pengendali yang tidak mengubah atau menimpa pengendali yang didaftarkan sebelum ini.
Menetapkan atribut pengendali acara Sifat pengendali acara pada elemen dokumen juga boleh ditetapkan dengan mentakrifkan nilai atribut dalam teg HTML yang sepadan. Dalam kes ini, nilai atribut mestilah rentetan kod JavaScript. Kod program ini tidak sepatutnya menjadi pengisytiharan lengkap fungsi pengendali acara, tetapi hanya badannya. Iaitu, pelaksanaan pengendali acara dalam penanda HTML tidak harus disertakan dalam pendakap kerinting dan didahului oleh kata kunci fungsi. Sebagai contoh:
Jika nilai atribut HTML pengendali acara terdiri daripada berbilang penyataan JavaScript, ia mesti dipisahkan dengan koma bertitik atau nilai atribut mesti muncul pada berbilang baris.
Sesetengah jenis acara ditujukan untuk penyemak imbas secara keseluruhan, bukannya untuk sebarang elemen dokumen tertentu. Pengendali untuk acara sedemikian dalam JavaScript didaftarkan dalam objek Window. Dalam penanda HTML ia mesti diletakkan dalam teg, tetapi pelayar akan mendaftarkannya dalam objek Window. Berikut ialah senarai lengkap pengendali acara sedemikian yang ditakrifkan oleh draf spesifikasi HTML5:
onafterprint onfocus ononline onresize onsebelumeprint onhashtukar pada halamansembunyikan pada storan padasebelum muatkan onload pada halamantunjukkan semula onkabur pada mesej padapopstate onloaderrorrar onoffline onredo
Apabila membangunkan skrip sebelah pelanggan, adalah amalan biasa untuk memisahkan penanda HTML daripada kod JavaScript. Pengaturcara yang mengikuti peraturan ini mengelakkan (atau sekurang-kurangnya cuba mengelak) menggunakan atribut pengendali acara HTML untuk mengelakkan pencampuran kod JavaScript dengan penanda HTML.
addEventListener() Dalam model acara standard, disokong oleh semua penyemak imbas kecuali IE versi 8 dan ke bawah, sasaran acara boleh menjadi sebarang objek - termasuk objek Tetingkap dan Dokumen dan semua objek Elemen elemen dokumen - mentakrifkan kaedah yang dipanggil addEventListener() dengan acara yang mana. pengendali boleh didaftarkan untuk tujuan ini.
Kaedah addEventListener() mengambil tiga hujah. Yang pertama ialah jenis acara yang pengendali didaftarkan. Jenis acara (atau nama) mestilah rentetan dan tidak boleh memasukkan awalan "hidup" yang digunakan semasa menetapkan sifat pengendali acara. Argumen kedua kepada kaedah addEventListener() ialah fungsi yang harus dipanggil apabila peristiwa jenis yang ditentukan berlaku. Argumen terakhir dihantar ke kaedah addEventListener() dengan nilai boolean. Biasanya hujah ini adalah palsu. Jika anda menghantarnya benar, fungsi tersebut akan didaftarkan sebagai pengendali pemintasan dan akan dipanggil dalam fasa penyebaran acara yang lain.
Spesifikasi akhirnya mungkin berubah supaya boleh diterima untuk meninggalkan hujah ketiga dan bukannya memberikannya palsu secara eksplisit, tetapi sehingga penulisan ini, peninggalan hujah ketiga mengakibatkan ralat dalam beberapa penyemak imbas semasa.
Coretan berikut mendaftarkan dua pengendali acara "klik" pada elemen. Perhatikan perbezaan antara dua teknik yang digunakan:
Klik saya! var b = document.getElementById("button saya"); b.onclick = function() ( alert("Terima kasih kerana mengklik pada saya!"); ); b.addEventListener("klik", function() (alert("Terima kasih sekali lagi!")), false);
Memanggil kaedah addEventListener() dengan rentetan "klik" sebagai hujah pertama tidak menjejaskan nilai sifat onclick. Dalam coretan di atas, mengklik butang akan memaparkan dua kotak dialog makluman(). Tetapi yang lebih penting, kaedah addEventListener() boleh dipanggil berbilang kali dan boleh digunakan untuk mendaftarkan berbilang fungsi pengendali untuk jenis acara yang sama dalam objek yang sama. Apabila peristiwa berlaku pada objek, semua pengendali yang didaftarkan untuk jenis acara itu akan dipanggil, mengikut urutan di mana mereka didaftarkan.
Memanggil kaedah addEventListener() beberapa kali pada objek yang sama dengan hujah yang sama tidak mempunyai kesan - fungsi pengendali didaftarkan sekali sahaja dan panggilan berulang tidak menjejaskan susunan pengendali dipanggil.
Dipasangkan dengan kaedah addEventListener() ialah kaedah removeEventListener(), yang mengambil tiga hujah yang sama, tetapi bukannya menambah, ia mengalih keluar fungsi pengendali daripada objek. Ini selalunya berguna apabila anda perlu mendaftar pengendali acara sementara dan kemudian mengeluarkannya pada satu ketika.
Versi Internet Explorer lebih awal daripada IE9 tidak menyokong kaedah addEventListener() dan removeEventListener(). IE5 dan kemudiannya mentakrifkan kaedah yang serupa, attachEvent() dan detachEvent() . Oleh kerana model peristiwa IE tidak menyokong fasa pemintasan, kaedah attachEvent() dan detachEvent() hanya mengambil dua argumen: jenis acara dan fungsi pengendali, dengan argumen pertama menghantar nama sifat pengendali yang diawali dengan "on" ke kaedah dalam IE dan bukannya acara jenis tanpa awalan ini.
Memanggil pengendali acara Sebaik sahaja anda mendaftar pengendali acara, pelayar web akan memanggilnya secara automatik apabila acara jenis yang ditentukan berlaku pada objek yang ditentukan. Bahagian ini memperincikan susunan pengendali peristiwa dipanggil, hujah kepada pengendali, konteks panggilan (nilai ini) dan tujuan nilai pulangan pengendali. Malangnya, beberapa butiran ini berbeza antara IE versi 8 dan ke bawah dan pelayar lain.
Hujah Pengendali Acara Apabila pengendali acara dipanggil, ia biasanya (dengan satu pengecualian, dibincangkan di bawah) meluluskan objek acara sebagai hujah tunggal. Sifat objek acara mengandungi maklumat tambahan tentang acara tersebut. Sifat jenis, sebagai contoh, menentukan jenis peristiwa yang berlaku.
Dalam IE versi 8 dan ke bawah, pengendali acara yang didaftarkan dengan menetapkan sifat tidak diluluskan objek acara apabila dipanggil. Sebaliknya, objek acara disimpan dalam tetingkap pembolehubah global.event. Untuk kemudahalihan, pengendali acara boleh digayakan seperti berikut supaya mereka menggunakan pembolehubah window.event apabila dipanggil tanpa hujah:
Objek acara dihantar kepada pengendali acara yang didaftarkan dengan kaedah attachEvent(), tetapi mereka juga boleh menggunakan pembolehubah window.event.
Apabila anda mendaftar pengendali acara menggunakan atribut HTML, penyemak imbas menukar rentetan kod JavaScript kepada fungsi. Pelayar selain daripada IE mencipta fungsi dengan satu hujah, peristiwa. IE mencipta fungsi yang tidak memerlukan hujah. Jika anda menggunakan pengecam acara dalam fungsi sedemikian, ia akan merujuk kepada window.event. Dalam kedua-dua kes, pengendali acara yang ditakrifkan dalam penanda HTML boleh merujuk objek acara menggunakan pengecam acara.
Konteks Pengendali Acara Apabila pengendali acara didaftarkan dengan menetapkan sifat, ia kelihatan seperti mentakrifkan kaedah elemen dokumen baharu:
E.onclick = function() ( /* pelaksanaan pengendali */ );
Oleh itu, tidak menghairankan bahawa pengendali acara dipanggil (dengan satu pengecualian mengenai IE, yang diterangkan di bawah) sebagai kaedah objek di mana ia ditakrifkan. Iaitu, dalam badan pengendali acara, kata kunci ini merujuk kepada sasaran acara.
Dalam pengendali, kata kunci ini merujuk kepada objek sasaran, walaupun semasa mereka didaftarkan menggunakan kaedah addEventListener(). Walau bagaimanapun, malangnya, ini tidak berlaku untuk kaedah attachEvent(): pengendali yang berdaftar dengan kaedah attachEvent() dipanggil sebagai fungsi, dan di dalamnya kata kunci ini merujuk kepada objek global (Tetingkap). Masalah ini boleh diselesaikan dengan cara berikut:
/* Mendaftarkan fungsi yang ditentukan sebagai pengendali acara jenis yang ditentukan dalam objek yang ditentukan. Memastikan bahawa pengendali akan sentiasa dipanggil sebagai kaedah pada objek sasaran. */ function addEvent(target, type, handler) ( if (target.addEventListener) target.addEventListener(type, handler, false); else target.attachEvent("on" + type, function(event) ( // Panggil pengendali sebagai kaedah sasaran, // dan berikannya pengendali pengembalian objek acara.panggilan(sasaran, acara); )); )
Ambil perhatian bahawa pengendali acara yang didaftarkan dengan cara ini tidak boleh dialih keluar kerana rujukan kepada fungsi pembalut yang dihantar kepada kaedah attachEvent() tidak disimpan di mana-mana supaya ia boleh dihantar ke kaedah detachEvent().
Nilai pulangan pengendali Nilai yang dikembalikan oleh pengendali acara yang didaftarkan dengan menetapkan sifat objek atau oleh atribut HTML harus diambil kira. Biasanya, mengembalikan palsu memberitahu penyemak imbas bahawa ia tidak sepatutnya melakukan tindakan lalai untuk acara ini.
Sebagai contoh, pengendali onclick butang hantar borang mungkin kembali palsu untuk menghalang penyemak imbas daripada menyerahkan borang. (Ini boleh berguna jika input pengguna gagal pengesahan pihak klien.) Begitu juga, pengendali acara onkeypress medan input boleh menapis input papan kekunci dengan mengembalikan palsu apabila aksara tidak sah dimasukkan.
Juga penting ialah nilai yang dikembalikan oleh pengendali onbeforeunload objek Window. Peristiwa ini dijana apabila penyemak imbas menavigasi ke halaman lain. Jika pengendali ini mengembalikan rentetan, ia akan dipaparkan dalam kotak dialog modal yang menggesa pengguna mengesahkan bahawa mereka mahu meninggalkan halaman.
Adalah penting untuk memahami bahawa nilai pulangan pengendali acara hanya dikira jika pengendali didaftarkan dengan menetapkan sifat. Pengendali yang berdaftar dengan addEventListener() atau attachEvent() mesti memanggil kaedah preventDefault() atau menetapkan sifat returnValue objek acara.
Membatalkan acara Nilai yang dikembalikan oleh pengendali acara yang didaftarkan sebagai harta boleh digunakan untuk mengatasi tindakan lalai yang diambil oleh penyemak imbas sekiranya peristiwa itu berlaku. Dalam penyemak imbas yang menyokong kaedah addEventListener(), tindakan lalai juga boleh ditindih dengan memanggil kaedah preventDefault() objek acara. Walau bagaimanapun, dalam IE versi 8 dan ke bawah, kesan yang sama dicapai dengan menetapkan sifat returnValue objek acara kepada palsu.
Coretan berikut menunjukkan pengendali acara klik hiperpautan yang menggunakan ketiga-tiga kaedah untuk membatalkan acara (menyekat pengguna daripada mengikuti pautan):
Window.onload = function() ( // Cari semua pautan var a_href = document.getElementsByTagName("a"); // Tambah pengendali acara klik (bukan untuk IE
Projek modul DOM Events 3 semasa mentakrifkan sifat pada objek Event yang dipanggil defaultPrevented . Ia belum lagi disokong oleh semua pelayar, tetapi intipatinya ialah dalam keadaan biasa ia adalah palsu dan hanya menjadi benar jika kaedah preventDefault() dipanggil.
Membatalkan tindakan lalai yang dikaitkan dengan acara hanyalah satu jenis membatalkan acara. Ia juga mungkin untuk menghentikan acara daripada merebak. Dalam penyemak imbas yang menyokong kaedah addEventListener(), objek acara mempunyai kaedah stopPropagation(), yang apabila dipanggil menghentikan penyebaran acara selanjutnya. Jika pengendali lain untuk acara ini didaftarkan pada objek sasaran yang sama, maka pengendali yang tinggal masih akan dipanggil, tetapi tiada pengendali peristiwa lain pada objek lain akan dipanggil selepas kaedah stopPropagation() dipanggil.
Dalam IE versi 8 dan ke bawah, kaedah stopPropagation() tidak disokong. Sebaliknya, objek acara dalam IE mempunyai sifat cancelBubble. Menetapkan sifat ini kepada benar menghalang acara daripada disebarkan.
Draf semasa spesifikasi DOM Events 3 mentakrifkan kaedah lain pada objek Event, kaedah yang dipanggil stopImmediatePropagation(). Seperti kaedah stopPropagation(), ia menghalang acara daripada menyebar ke mana-mana objek lain. Tetapi sebagai tambahan, ia juga menghalang mana-mana pengendali acara lain yang didaftarkan pada objek yang sama daripada dipanggil.
Anda mempunyai acara ArrowDown pendengar papan kekunci berikut (kod kuncinya ialah 40):
Window.onload = function() ( var itemsContainer = document.getElementById("cities-drop"); document.addEventListener("*****",function(event)( if (event.keyCode == 40 && itemsContainer. style.display=="block") ( event.preventDefault(); untuk (var i=0;i
dalam kes ini, melayang pergi ke elemen terakhir dalam senarai selepas ArrowDown ditekan.
Sekiranya break tidak diulas, ia melompat ke elemen kedua dan tidak melompat lagi.
Adalah mustahil untuk mendapatkan prinsip bagaimana untuk melakukan ini, bahawa pendengar sentiasa mendengar...
EDIT demo langsung boleh dilakukan, ini soal penutupan tetapi saya tidak pasti
3 jawapan
Selepas melihat kod anda dan memahami perkara yang anda cuba lakukan, saya rasa ralat anda menggunakan substr di mana anda sepatutnya menggunakan indexOf . Berikut ialah baris yang dikemas kini:
If (itemsContainer.getAttribute("class").indexOf("hovered") != -1) Butiran lanjut: Anda sebenarnya menggunakan substr dengan nilai rentetan untuk indeks permulaan. Tidak pasti apakah keputusan ini, tetapi nampaknya ia bukan -1 kerana keadaan kembali benar setiap kali, menyebabkan elemen seterusnya bergantung SETIAP kali, sehingga ke bahagian bawah senarai. Menggunakan pernyataan break, ia melaksanakan pernyataan if pada elemen pertama (menyebabkan elemen kedua tergantung) dan kemudian keluar.
Saya akan meninggalkan penyataan rehat di sana selepas membetulkan kod anda, supaya gelung itu akan berhenti selepas ia menemui padanannya dan tidak akan berulang tanpa perlu melalui elemen yang lain.
EDIT: Saya menemui beberapa lagi masalah dalam kod. Berikut ialah contoh yang berfungsi untuk saya dalam IE dan FF sekurang-kurangnya (tidak diuji dalam Safari, Opera atau Chrome):
Butiran: Bagi saya dalam IE9 fungsi itu tidak pernah dipanggil. Sebaliknya, saya hanya menjadikannya fungsi biasa dan menambahkan acara onkeydown pada teg badan.
Dalam pernyataan if anda anda mempunyai itemsContainer.getAttribute("class") . Pertama, anda perlu menggunakan itemsContainer.children[i] . Kedua, .getAttribute("class") tidak berfungsi untuk saya dalam IE, jadi saya menukarnya kepada .className sahaja.
Akhir sekali, itemsContainer.children[i].nextSibling tidak berfungsi untuk saya, tetapi cukup mudah untuk menukarnya kepada itemsContainer.children untuk mendapatkan adik beradik seterusnya.
Daripada menggunakan gelung, anda boleh mencuba pendekatan yang lebih mudah:
Window.onload = function() ( var itemsContainer = document.getElementById("cities-drop"); document.addEventListener("*****",function(event) ( if (event.keyCode == 40 && itemsContainer. style.display=="block") ( event.preventDefault(); var previousHoveredChoice = itemsContainer.querySelector(".hovered"); previousHoveredChoice.className = ""; var currentHoveredChoice = previousHoveredChoice.nextSibling; jika (currentHoveredChoice) (.HoveredChoice) (. className = "berlegar"; ) ) )); //kod berikut disalin-tampal daripada contoh langsung //hanya untuk menutup pengendali fungsi beban dalam dokumen penyelesaian ini.addEventListener("*****",function(event )( if (event.keyCode == 27) ( if (document.getElementById("cities-drop").style.display=="block")( document.getElementById("cities-drop").style.display= "tiada"; ) ) )); //akhir kod salin-tampal );
Terdapat beberapa perkara yang saya lihat boleh menjadi masalah. Pertama sekali, anda mengemas kini itemsContainer.children[i].nextSibling yang sama dengan itemsContainer.children . Oleh itu, elemen terakhir sentiasa dipilih jika anda terlepas rehat. itemsComtainer akan sentiasa digantung jika terdapat elemen yang sepadan dengan kelas.
Masalah kedua ialah apa yang Travesty3 tunjukkan dalam jawapannya.
Saya juga menukar syarat if untuk memeriksa sama ada kelas berlegar berada pada salah seorang kanak-kanak dan bukannya pada bekas itu sendiri.
Jika (itemsContainer.children[i].getAttribute("class").match("legar"))
Saya mengubah suai pengendali acara dengan baris kod berikut dan nampaknya berfungsi dengan baik:
Document.addEventListener("*****",function(event)( if (event.keyCode === 40 && itemsContainer.style.display==="block") ( event.preventDefault(); for (var i =0,l=itemContainer.children.length;i
Perlu diingat bahawa membuat kawalan langkah turun sedemikian adalah kerja yang banyak. Pengguna mengharapkan untuk menavigasi melaluinya menggunakan papan kekunci. Untuk mencipta antara muka pengguna yang hebat, anda mesti mengendalikan berbilang kekunci seperti kekunci anak panah, tab untuk mengawal fokus, ruang untuk membuka dan menutupnya, input abjad angka untuk memfokus pada item padanan pertama, dsb.
Jika pengalaman pengguna adalah penting, saya akan mengesyorkan menggunakan rangka kerja dan pemalam untuknya. Saya secara peribadi lebih suka jquery dan jquery ui dan terdapat beberapa pemalam untuk dipilih daripada drop down. Faedah lain ialah jika javascript dilumpuhkan oleh pelanggan atau javascript anda bermasalah atas sebab tertentu, kebanyakan pemalam akan kembali kepada elemen pilih asli biasa yang masih berfungsi dengan baik.
Saya sendiri telah menggunakan pemalam kotak pilihan ini untuk dropdown mudah: http://www.abeautifulsite.net/blog/2011/01/jquery-selectbox-plugin/
Edit: Saya membalikkan cadangan ini kerana ia tidak berfungsi jika berbilang elemen mempunyai nama yang sama. Jika ini penting, anda harus menyemak pemalam pilih menu Kumpulan Filamen: http://filamentgroup.com/lab/jquery_ui_selectmenu_an_aria_accessible_plugin_for_styling_a_html_select/ //Edit
Dan pemalam autolengkap jquery untuk kotak kombo yang turut menyokong input bertulis: http://jqueryui.com/demos/autocomplete/