กำหนดลิงค์นี้ จากนั้นมันจะถูกส่งไปยังองค์ประกอบที่มี: อาจเป็นองค์ประกอบ องค์ประกอบและวัตถุ Document เอง บางครั้ง การลงทะเบียนตัวจัดการเหตุการณ์เดียวบนอ็อบเจ็กต์ Document หรือองค์ประกอบคอนเทนเนอร์อื่นๆ จะสะดวกกว่าการลงทะเบียนกับองค์ประกอบทั้งหมดที่น่าสนใจ
หลังจากกำหนดคำศัพท์บางคำแล้ว เราก็สามารถไปยังการสำรวจปัญหาที่เกี่ยวข้องกับเหตุการณ์และการประมวลผลได้
การลงทะเบียนตัวจัดการเหตุการณ์ มีสองวิธีหลักในการลงทะเบียนตัวจัดการเหตุการณ์ สิ่งแรกซึ่งปรากฏในช่วงต้นของการพัฒนาเวิลด์ไวด์เว็บคือการตั้งค่าคุณสมบัติของวัตถุหรือองค์ประกอบเอกสารที่เป็นเป้าหมายของเหตุการณ์ วิธีที่สอง ใหม่กว่าและเป็นสากลมากขึ้น คือการส่งตัวจัดการไปยังเมธอดของอ็อบเจ็กต์หรือองค์ประกอบ
เรื่องนี้มีความซับซ้อนเนื่องจากแต่ละเทคนิคมีสองเวอร์ชัน คุณสมบัติตัวจัดการเหตุการณ์สามารถตั้งค่าในโค้ด JavaScript หรือในองค์ประกอบเอกสารโดยการกำหนดแอตทริบิวต์ที่เหมาะสมโดยตรงในมาร์กอัป HTML การลงทะเบียนตัวจัดการด้วยการเรียกเมธอดสามารถทำได้โดยวิธีมาตรฐานที่เรียกว่า addEventListener() ซึ่งได้รับการสนับสนุนโดยเบราว์เซอร์ทั้งหมดยกเว้น IE เวอร์ชัน 8 และต่ำกว่า และวิธีอื่นที่เรียกว่า attachmentEvent() ซึ่งรองรับโดย IE ทุกเวอร์ชันจนถึง IE9
การตั้งค่าคุณสมบัติตัวจัดการเหตุการณ์ วิธีที่ง่ายที่สุดในการลงทะเบียนตัวจัดการเหตุการณ์คือการตั้งค่าคุณสมบัติบนเป้าหมายเหตุการณ์ให้เป็นฟังก์ชันตัวจัดการที่ต้องการ ตามแบบแผน คุณสมบัติตัวจัดการเหตุการณ์จะมีชื่อที่ประกอบด้วยคำว่า "on" ตามด้วยชื่อเหตุการณ์: onclick, onchange, onload, onmouseover ฯลฯ โปรดทราบว่าชื่อคุณสมบัติเหล่านี้จะคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ และใช้เฉพาะอักขระตัวพิมพ์เล็ก แม้ว่าชื่อประเภทเหตุการณ์จะมีหลายคำ (เช่น "readystatechange") ด้านล่างนี้คือสองตัวอย่างของการลงทะเบียนตัวจัดการเหตุการณ์:
// กำหนดฟังก์ชันให้กับคุณสมบัติ onload ของวัตถุ Window // ฟังก์ชันเป็นตัวจัดการเหตุการณ์: มันถูกเรียกเมื่อมีการโหลดเอกสาร window.onload = function() ( // ค้นหาองค์ประกอบ var elt = document.getElementById("shipping_address"); // ลงทะเบียนตัวจัดการเหตุการณ์ที่จะ ถูกเรียก // โดยตรงก่อนที่จะส่งแบบฟอร์ม elt.onsubmit = function() ( return validate(this); ) )
วิธีการลงทะเบียนตัวจัดการเหตุการณ์นี้ได้รับการสนับสนุนในเบราว์เซอร์ทั้งหมดสำหรับประเภทเหตุการณ์ที่ใช้กันทั่วไปทั้งหมด โดยทั่วไปแล้ว อินเทอร์เฟซแอปพลิเคชันที่ได้รับการสนับสนุนอย่างกว้างขวางทั้งหมดซึ่งกำหนดเหตุการณ์จะทำให้สามารถลงทะเบียนตัวจัดการได้โดยการตั้งค่าคุณสมบัติของตัวจัดการเหตุการณ์
ข้อเสียของการใช้คุณสมบัติตัวจัดการเหตุการณ์คือ คุณสมบัติดังกล่าวได้รับการออกแบบโดยสมมุติว่าเป้าหมายเหตุการณ์จะมีตัวจัดการมากที่สุดหนึ่งตัวต่อชนิดเหตุการณ์ เมื่อสร้างไลบรารีเพื่อใช้ในเอกสารที่กำหนดเอง ควรใช้เทคนิค (เช่น การเรียกเมธอด addEventListener()) เพื่อลงทะเบียนตัวจัดการที่ไม่เปลี่ยนแปลงหรือเขียนทับตัวจัดการที่ลงทะเบียนไว้ก่อนหน้านี้
การตั้งค่าแอ็ตทริบิวต์ตัวจัดการเหตุการณ์ คุณสมบัติของตัวจัดการเหตุการณ์ในองค์ประกอบเอกสารสามารถตั้งค่าได้โดยการกำหนดค่าแอตทริบิวต์ในแท็ก HTML ที่เกี่ยวข้อง ในกรณีนี้ ค่าแอตทริบิวต์จะต้องเป็นสตริงของโค้ด JavaScript โค้ดโปรแกรมนี้ไม่ควรเป็นการประกาศฟังก์ชันตัวจัดการเหตุการณ์โดยสมบูรณ์ แต่เป็นเพียงการประกาศฟังก์ชันตัวจัดการเหตุการณ์เท่านั้น นั่นคือ การใช้งานตัวจัดการเหตุการณ์ในมาร์กอัป HTML ไม่ควรอยู่ในวงเล็บปีกกาและนำหน้าด้วยคีย์เวิร์ดของฟังก์ชัน ตัวอย่างเช่น:
หากค่าแอตทริบิวต์ HTML ของตัวจัดการเหตุการณ์ประกอบด้วยคำสั่ง JavaScript หลายคำสั่ง จะต้องคั่นด้วยเครื่องหมายอัฒภาค หรือค่าแอตทริบิวต์จะต้องปรากฏบนหลายบรรทัด
เหตุการณ์บางประเภทมีไว้สำหรับเบราว์เซอร์โดยรวม ไม่ใช่สำหรับองค์ประกอบเอกสารเฉพาะใดๆ ตัวจัดการสำหรับเหตุการณ์ดังกล่าวใน JavaScript ได้รับการลงทะเบียนในวัตถุ Window ในมาร์กอัป HTML จะต้องวางไว้ในแท็ก แต่เบราว์เซอร์จะลงทะเบียนไว้ในวัตถุ Window ต่อไปนี้เป็นรายการที่สมบูรณ์ของตัวจัดการเหตุการณ์ดังกล่าวซึ่งกำหนดโดยข้อกำหนด HTML5 แบบร่าง:
onafterprint onfocus ononline onresize onbeforeprint onhashchange onpagehide onstorage onbeforeunload onload onpageshow onundo onblur onmessage onpopstate onunload onerror onoffline onredo
เมื่อพัฒนาสคริปต์ฝั่งไคลเอ็นต์ เป็นเรื่องปกติที่จะแยกมาร์กอัป HTML ออกจากโค้ด JavaScript โปรแกรมเมอร์ที่ปฏิบัติตามกฎนี้หลีกเลี่ยง (หรืออย่างน้อยก็พยายามหลีกเลี่ยง) โดยใช้แอตทริบิวต์ตัวจัดการเหตุการณ์ HTML เพื่อหลีกเลี่ยงการผสมโค้ด JavaScript กับมาร์กอัป HTML
addEventListener() ในโมเดลเหตุการณ์มาตรฐาน ซึ่งรองรับโดยเบราว์เซอร์ทั้งหมดยกเว้น IE เวอร์ชัน 8 และต่ำกว่า เป้าหมายของเหตุการณ์สามารถเป็นอ็อบเจ็กต์ใดก็ได้ รวมถึงอ็อบเจ็กต์ Window และ Document และอ็อบเจ็กต์ Elements ทั้งหมดขององค์ประกอบเอกสาร โดยกำหนดวิธีการที่เรียกว่า addEventListener() ด้วยเหตุการณ์ใด ตัวจัดการสามารถลงทะเบียนเพื่อจุดประสงค์นี้ได้
addEventListener() วิธีการรับสามอาร์กิวเมนต์ ประเภทแรกคือประเภทเหตุการณ์ที่ตัวจัดการลงทะเบียนไว้ ประเภทเหตุการณ์ (หรือชื่อ) ต้องเป็นสตริงและต้องไม่มีคำนำหน้า "on" ที่ใช้เมื่อตั้งค่าคุณสมบัติของตัวจัดการเหตุการณ์ อาร์กิวเมนต์ที่สองของเมธอด addEventListener() คือฟังก์ชันที่ควรถูกเรียกใช้เมื่อมีเหตุการณ์ประเภทที่ระบุเกิดขึ้น อาร์กิวเมนต์สุดท้ายถูกส่งผ่านไปยังเมธอด addEventListener() ที่มีค่าบูลีน โดยทั่วไปอาร์กิวเมนต์นี้เป็นเท็จ หากคุณผ่านค่าจริง ฟังก์ชันนี้จะถูกลงทะเบียนเป็นตัวจัดการการสกัดกั้น และจะถูกเรียกใช้ในอีกระยะหนึ่งของการแพร่กระจายเหตุการณ์
ข้อกำหนดอาจมีการเปลี่ยนแปลงในที่สุดเพื่อให้สามารถละเว้นอาร์กิวเมนต์ที่สามได้ แทนที่จะส่งผ่านเป็นเท็จอย่างชัดเจน แต่ในขณะที่เขียนบทความนี้ การละเว้นอาร์กิวเมนต์ที่สามส่งผลให้เกิดข้อผิดพลาดในเบราว์เซอร์ปัจจุบันบางตัว
ตัวอย่างต่อไปนี้จะลงทะเบียนตัวจัดการเหตุการณ์ "คลิก" สองตัวบนองค์ประกอบ สังเกตความแตกต่างระหว่างสองเทคนิคที่ใช้:
คลิกฉัน!
var b = document.getElementById("mybutton"); b.onclick = function() ( alert("ขอบคุณที่คลิกฉัน!"); ); b.addEventListener("คลิก", function() (แจ้งเตือน("ขอบคุณอีกครั้ง!")), false);
การเรียก addEventListener() ด้วยสตริง "click" เนื่องจากอาร์กิวเมนต์แรกไม่มีผลกระทบต่อค่าของคุณสมบัติ onclick ในตัวอย่างด้านบน การคลิกปุ่มจะทำให้กล่องโต้ตอบ alert() สองกล่องปรากฏขึ้น แต่ที่สำคัญกว่านั้นคือ สามารถเรียกเมธอด addEventListener() ได้หลายครั้ง และสามารถใช้เพื่อลงทะเบียนฟังก์ชันตัวจัดการหลายฟังก์ชันสำหรับเหตุการณ์ประเภทเดียวกันในออบเจ็กต์เดียวกันได้ เมื่อเหตุการณ์เกิดขึ้นบนออบเจ็กต์ ตัวจัดการทั้งหมดที่ลงทะเบียนสำหรับประเภทเหตุการณ์นั้นจะถูกเรียกตามลำดับที่ลงทะเบียนไว้
การเรียกเมธอด addEventListener() หลายครั้งบนออบเจ็กต์เดียวกันที่มีอาร์กิวเมนต์เดียวกันจะไม่มีผลใดๆ - ฟังก์ชันตัวจัดการจะถูกลงทะเบียนเพียงครั้งเดียว และการเรียกซ้ำๆ จะไม่ส่งผลต่อลำดับการเรียกตัวจัดการ
Internet Explorer เวอร์ชันเก่ากว่า IE9 ไม่รองรับเมธอด addEventListener() และ RemoveEventListener() IE5 และใหม่กว่ากำหนดวิธีการที่คล้ายกันคือแนบ Event() และ detachEvent() เนื่องจากโมเดลเหตุการณ์ IE ไม่สนับสนุนขั้นตอนการสกัดกั้น วิธีการแนบEvent() และ detachEvent() รับเพียงสองอาร์กิวเมนต์: ประเภทเหตุการณ์และฟังก์ชันตัวจัดการ โดยอาร์กิวเมนต์แรกส่งผ่านชื่อคุณสมบัติตัวจัดการที่นำหน้าด้วย "on" ไปที่ วิธีการใน IE แทนที่จะเป็นประเภทเหตุการณ์ที่ไม่มีคำนำหน้านี้
กำลังเรียกตัวจัดการเหตุการณ์ เมื่อคุณลงทะเบียนตัวจัดการเหตุการณ์ เว็บเบราว์เซอร์จะเรียกมันโดยอัตโนมัติเมื่อมีเหตุการณ์ประเภทที่ระบุเกิดขึ้นบนวัตถุที่ระบุ ส่วนนี้ให้รายละเอียดเกี่ยวกับลำดับของการเรียกตัวจัดการเหตุการณ์ อาร์กิวเมนต์ของตัวจัดการ บริบทของการโทร (ค่าของสิ่งนี้) และวัตถุประสงค์ของค่าที่ส่งคืนของตัวจัดการ ขออภัย รายละเอียดบางส่วนเหล่านี้แตกต่างกันระหว่าง IE เวอร์ชัน 8 และต่ำกว่ากับเบราว์เซอร์อื่นๆ
อาร์กิวเมนต์ตัวจัดการเหตุการณ์ เมื่อตัวจัดการเหตุการณ์ถูกเรียกใช้ โดยปกติ (โดยมีข้อยกเว้นหนึ่งข้อที่กล่าวถึงด้านล่าง) จะส่งผ่านวัตถุเหตุการณ์เป็นอาร์กิวเมนต์เดียว คุณสมบัติของวัตถุเหตุการณ์มีข้อมูลเพิ่มเติมเกี่ยวกับเหตุการณ์ คุณสมบัติประเภท ตัวอย่างเช่น กำหนดประเภทของเหตุการณ์ที่เกิดขึ้น
ใน IE เวอร์ชัน 8 และต่ำกว่า ตัวจัดการเหตุการณ์ที่ลงทะเบียนโดยการตั้งค่าคุณสมบัติจะไม่ส่งผ่านออบเจ็กต์เหตุการณ์เมื่อถูกเรียก แต่วัตถุเหตุการณ์จะถูกเก็บไว้ในตัวแปรส่วนกลาง window.event สำหรับการพกพา ตัวจัดการเหตุการณ์สามารถจัดสไตล์ได้ดังต่อไปนี้ เพื่อให้ใช้ตัวแปร window.event เมื่อถูกเรียกโดยไม่มีอาร์กิวเมนต์:
ออบเจ็กต์เหตุการณ์จะถูกส่งผ่านไปยังตัวจัดการเหตุการณ์ที่ลงทะเบียนด้วยเมธอดแนบEvent() แต่ยังสามารถใช้ตัวแปร window.event ได้ด้วย
เมื่อคุณลงทะเบียนตัวจัดการเหตุการณ์โดยใช้แอตทริบิวต์ HTML เบราว์เซอร์จะแปลงสตริงของโค้ด JavaScript ให้เป็นฟังก์ชัน เบราว์เซอร์อื่นที่ไม่ใช่ IE จะสร้างฟังก์ชันที่มีอาร์กิวเมนต์เหตุการณ์เดียว IE สร้างฟังก์ชันที่ไม่มีการโต้แย้ง หากคุณใช้ตัวระบุเหตุการณ์ในฟังก์ชันดังกล่าว ตัวระบุเหตุการณ์จะอ้างอิงถึง window.event ไม่ว่าในกรณีใด ตัวจัดการเหตุการณ์ที่กำหนดในมาร์กอัป HTML สามารถอ้างอิงอ็อบเจ็กต์เหตุการณ์ได้โดยใช้ตัวระบุเหตุการณ์
บริบทตัวจัดการเหตุการณ์ เมื่อมีการลงทะเบียนตัวจัดการเหตุการณ์โดยการตั้งค่าคุณสมบัติ ดูเหมือนว่าการกำหนดวิธีการองค์ประกอบเอกสารใหม่:
E.onclick = function() ( /* การใช้งานตัวจัดการ */ );
ดังนั้นจึงไม่น่าแปลกใจที่ตัวจัดการเหตุการณ์จะถูกเรียกใช้ (โดยมีข้อยกเว้นประการหนึ่งเกี่ยวกับ IE ซึ่งอธิบายไว้ด้านล่าง) เป็นวิธีการของอ็อบเจ็กต์ที่พวกมันถูกกำหนดไว้ นั่นคือ ในเนื้อความของตัวจัดการเหตุการณ์ คีย์เวิร์ดนี้อ้างอิงถึงเป้าหมายของเหตุการณ์
ในตัวจัดการ คีย์เวิร์ดนี้อ้างอิงถึงออบเจ็กต์เป้าหมาย แม้ว่าจะถูกลงทะเบียนโดยใช้เมธอด addEventListener() ก็ตาม อย่างไรก็ตาม น่าเสียดาย ที่นี่ไม่ใช่กรณีของเมธอดแนบ Event(): ตัวจัดการที่ลงทะเบียนด้วยเมธอดแนบEvent() จะถูกเรียกว่าเป็นฟังก์ชัน และในคำเหล่านั้นคำสำคัญนี้อ้างอิงถึงอ็อบเจ็กต์โกลบอล (หน้าต่าง) ปัญหานี้สามารถแก้ไขได้ด้วยวิธีต่อไปนี้:
/* ลงทะเบียนฟังก์ชันที่ระบุเป็นตัวจัดการเหตุการณ์ประเภทที่ระบุในวัตถุที่ระบุ ตรวจสอบให้แน่ใจว่าตัวจัดการจะถูกเรียกเป็นวิธีการบนวัตถุเป้าหมายเสมอ */ function addEvent(target, type, handler) ( if (target.addEventListener) target.addEventListener(type, handler, false); else target.attachEvent("on" + type, function(event) ( // เรียกตัวจัดการ เป็นวิธีการเป้าหมาย // และส่งผ่านวัตถุเหตุการณ์ return handler.call(target, event ));
โปรดทราบว่าตัวจัดการเหตุการณ์ที่ลงทะเบียนในลักษณะนี้ไม่สามารถลบออกได้ เนื่องจากการอ้างอิงไปยังฟังก์ชัน wrapper ที่ส่งผ่านไปยังเมธอดแนบ Event() จะไม่ถูกเก็บไว้ที่ใดก็ได้เพื่อให้สามารถส่งผ่านไปยังเมธอด detachEvent() ได้
ตัวจัดการส่งคืนค่า ค่าที่ส่งคืนโดยตัวจัดการเหตุการณ์ที่ลงทะเบียนโดยการตั้งค่าคุณสมบัติของวัตถุหรือโดยแอตทริบิวต์ HTML ควรนำมาพิจารณาด้วย โดยทั่วไปแล้ว การส่งคืน false จะบอกเบราว์เซอร์ว่าไม่ควรดำเนินการตามค่าเริ่มต้นสำหรับเหตุการณ์นี้
ตัวอย่างเช่น ตัวจัดการ onclick ของปุ่มส่งแบบฟอร์มอาจคืนค่าเท็จเพื่อป้องกันไม่ให้เบราว์เซอร์ส่งแบบฟอร์ม (ซึ่งอาจมีประโยชน์หากอินพุตของผู้ใช้ล้มเหลวในการตรวจสอบฝั่งไคลเอ็นต์) ในทำนองเดียวกัน ตัวจัดการเหตุการณ์ onkeypress ของฟิลด์อินพุตสามารถกรองอินพุตของแป้นพิมพ์โดยส่งคืนค่าเท็จเมื่อป้อนอักขระที่ไม่ถูกต้อง
สิ่งสำคัญอีกอย่างคือค่าที่ส่งคืนโดยตัวจัดการ onbeforeunload ของวัตถุ Window เหตุการณ์นี้เกิดขึ้นเมื่อเบราว์เซอร์นำทางไปยังหน้าอื่น หากตัวจัดการนี้ส่งคืนสตริง มันจะถูกแสดงในกล่องโต้ตอบโมดอลเพื่อแจ้งให้ผู้ใช้ยืนยันว่าต้องการออกจากเพจ
สิ่งสำคัญคือต้องเข้าใจว่าค่าที่ส่งคืนของตัวจัดการเหตุการณ์จะถูกนับเฉพาะในกรณีที่ตัวจัดการถูกลงทะเบียนโดยการตั้งค่าคุณสมบัติ ตัวจัดการที่ลงทะเบียนกับ addEventListener() หรือแนบEvent() จะต้องเรียกใช้เมธอด PreventDefault() แทน หรือตั้งค่าคุณสมบัติ returnValue ของออบเจ็กต์เหตุการณ์
กำลังยกเลิกกิจกรรม ค่าที่ส่งคืนโดยตัวจัดการเหตุการณ์ที่ลงทะเบียนเป็นคุณสมบัติสามารถใช้เพื่อแทนที่การกระทำเริ่มต้นที่เบราว์เซอร์ทำในกรณีของเหตุการณ์นั้น ในเบราว์เซอร์ที่รองรับเมธอด addEventListener() การกระทำเริ่มต้นยังสามารถแทนที่ได้ด้วยการเรียกเมธอด PreventDefault() ของออบเจ็กต์เหตุการณ์ อย่างไรก็ตาม ใน IE เวอร์ชัน 8 และต่ำกว่า จะได้ผลเช่นเดียวกันโดยการตั้งค่าคุณสมบัติ returnValue ของออบเจ็กต์เหตุการณ์ให้เป็นเท็จ
ตัวอย่างต่อไปนี้สาธิตตัวจัดการเหตุการณ์การคลิกไฮเปอร์ลิงก์ที่ใช้ทั้งสามวิธีในการยกเลิกเหตุการณ์ (บล็อกผู้ใช้จากการติดตามลิงก์):
Window.onload = function() ( // ค้นหาลิงก์ทั้งหมด var a_href = document.getElementsByTagName("a"); // เพิ่มตัวจัดการเหตุการณ์การคลิก (ไม่ใช่สำหรับ IE
โครงการโมดูล DOM Events 3 ปัจจุบันกำหนดคุณสมบัติบนวัตถุเหตุการณ์ที่เรียกว่า defaultPrevented เบราว์เซอร์ทั้งหมดยังไม่รองรับ แต่สิ่งสำคัญคือภายใต้สภาวะปกติ มันจะเป็นเท็จ และจะกลายเป็นจริงก็ต่อเมื่อมีการเรียกใช้เมธอด PreventDefault()
การยกเลิกการดำเนินการเริ่มต้นที่เกี่ยวข้องกับกิจกรรมเป็นเพียงการยกเลิกกิจกรรมประเภทหนึ่งเท่านั้น นอกจากนี้ยังสามารถหยุดเหตุการณ์ไม่ให้แพร่กระจายได้อีกด้วย ในเบราว์เซอร์ที่รองรับเมธอด addEventListener() วัตถุเหตุการณ์จะมีเมธอด stopPropagation() ซึ่งเมื่อถูกเรียกจะหยุดการแพร่กระจายของเหตุการณ์เพิ่มเติม หากตัวจัดการอื่นสำหรับเหตุการณ์นี้ถูกลงทะเบียนบนออบเจ็กต์เป้าหมายเดียวกัน ตัวจัดการที่เหลือจะยังคงถูกเรียกใช้ แต่จะไม่มีการเรียกใช้ตัวจัดการเหตุการณ์อื่นบนออบเจ็กต์อื่นหลังจากเรียกใช้เมธอด stopPropagation()
ใน IE เวอร์ชัน 8 และต่ำกว่า ไม่รองรับเมธอด stopPropagation() วัตถุเหตุการณ์ใน IE มีคุณสมบัติแทน ยกเลิกบับเบิ้ล- การตั้งค่าคุณสมบัตินี้เป็นจริงจะป้องกันไม่ให้เหตุการณ์แพร่กระจาย
แบบร่างปัจจุบันของข้อกำหนด DOM Events 3 กำหนดวิธีการอื่นบนวัตถุเหตุการณ์ วิธีที่เรียกว่า stopImmediatePropagation() เช่นเดียวกับเมธอด stopPropagation() จะป้องกันไม่ให้เหตุการณ์แพร่กระจายไปยังอ็อบเจ็กต์อื่น แต่นอกจากนี้ ยังป้องกันไม่ให้มีการเรียกตัวจัดการเหตุการณ์อื่นที่ลงทะเบียนบนวัตถุเดียวกันอีกด้วย
คุณมีเหตุการณ์ ArrowDown ฟังคีย์บอร์ดต่อไปนี้ (รหัสคีย์คือ 40):
Window.onload = function() ( var itemsContainer = document.getElementById("cities-drop"); document.addEventListener("*****",function(event)( if (event.keyCode == 40 && itemsContainer. style.display=="block") ( event.preventDefault(); for (var i=0;i
ในกรณีนี้ การวางเมาส์เหนือจะไปที่องค์ประกอบสุดท้ายในรายการหลังจากกด ArrowDown
ในกรณีที่ไม่มีเครื่องหมายตัวแบ่ง ตัวแบ่งจะข้ามไปยังองค์ประกอบที่สองและไม่ข้ามอีกต่อไป
เป็นไปไม่ได้ที่จะเข้าใจหลักการที่ว่าผู้ฟังจะฟังอยู่เสมอ...
แก้ไขการสาธิตสดได้ มันเป็นเรื่องของการปิดตัว แต่ฉันไม่แน่ใจ
3 คำตอบ
หลังจากดูโค้ดของคุณและทำความเข้าใจกับสิ่งที่คุณกำลังพยายามทำ ฉันคิดว่าข้อผิดพลาดของคุณคือการใช้ substr โดยที่คุณควรใช้ indexOf นี่คือบรรทัดที่อัปเดต:
If (itemsContainer.getAttribute("class").indexOf("hovered") != -1) รายละเอียดเพิ่มเติม: คุณใช้ substr จริง ๆ กับค่าสตริงสำหรับดัชนีเริ่มต้น ไม่แน่ใจว่าผลลัพธ์จะเป็นอย่างไร แต่เห็นได้ชัดว่าไม่ใช่ -1 เนื่องจากเงื่อนไขคืนค่าเป็นจริงทุกครั้ง ทำให้องค์ประกอบถัดไปต้องขึ้นต่อกันทุกครั้ง ไปจนถึงด้านล่างสุดของรายการ การใช้คำสั่งแบ่ง จะดำเนินการคำสั่ง if บนองค์ประกอบแรก (ทำให้องค์ประกอบที่สองหยุดทำงาน) จากนั้นจึงออก
ฉันจะทิ้งคำสั่ง break ไว้ที่นั่นหลังจากแก้ไขโค้ดของคุณแล้ว เพื่อที่ลูปจะหยุดหลังจากพบว่าตรงกัน และจะไม่วนซ้ำองค์ประกอบที่เหลือโดยไม่จำเป็น
แก้ไข: ฉันพบปัญหาอีกสองสามข้อในโค้ด นี่คือตัวอย่างที่เหมาะกับฉันใน IE และ FF อย่างน้อย (ไม่ได้ทดสอบใน Safari, Opera หรือ Chrome):
รายละเอียด: สำหรับฉันใน IE9 ฟังก์ชันไม่เคยถูกเรียกใช้ แต่ฉันเพิ่งทำให้มันเป็นฟังก์ชันปกติและเพิ่มเหตุการณ์ onkeydown ให้กับแท็กเนื้อหา
ในคำสั่ง if ของคุณ คุณมี itemsContainer.getAttribute("class") ก่อนอื่น คุณต้องใช้ itemsContainer.children[i] ประการที่สอง .getAttribute("class") ใช้งานไม่ได้สำหรับฉันใน IE ดังนั้นฉันจึงเปลี่ยนไปใช้เพียง .className
สุดท้ายนี้ itemsContainer.children[i].nextSibling ไม่ได้ผลสำหรับฉัน แต่มันง่ายพอที่จะเปลี่ยนเป็น itemsContainer.children เพื่อรับพี่น้องคนถัดไป
แทนที่จะใช้การวนซ้ำ คุณสามารถลองใช้วิธีที่ง่ายกว่านี้:
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; if (currentHoveredChoice) ( currentHoveredChoice. className = "hovered"; ) ) )); // โค้ดต่อไปนี้ถูกคัดลอกและวางจากตัวอย่างสด // เพียงเพื่อปิดตัวจัดการฟังก์ชัน onload ในโซลูชันนี้ addEventListener("*****",function(event ) ( if (event.keyCode == 27) ( if (document.getElementById("cities-drop").style.display=="block")( document.getElementById("cities-drop").style.display= " none"; ) )); // สิ้นสุดโค้ดที่คัดลอกแล้ว);
มีบางสิ่งที่ฉันเห็นว่าอาจเป็นปัญหาได้ ก่อนอื่น คุณอัปเดต itemsContainer.children[i].nextSibling ซึ่งเท่ากับ itemsContainer.children ดังนั้นองค์ประกอบสุดท้ายจะถูกเลือกเสมอหากคุณพลาดการหยุดพัก itemsComtainer จะหยุดทำงานเสมอหากมีองค์ประกอบที่ตรงกับคลาส
ปัญหาที่สองคือสิ่งที่ Travesty3 ชี้ให้เห็นในคำตอบของเขา
ฉันยังเปลี่ยนเงื่อนไข if เพื่อตรวจสอบว่าคลาสโฮเวอร์อยู่บนหนึ่งในลูก ๆ แทนที่จะอยู่บนคอนเทนเนอร์เองหรือไม่
ถ้า (itemsContainer.children[i].getAttribute("class").match("hovered"))
ฉันแก้ไขตัวจัดการเหตุการณ์ด้วยบรรทัดโค้ดต่อไปนี้ และดูเหมือนว่าจะทำงานได้ดี:
Document.addEventListener("*****",function(event)( if (event.keyCode === 40 && itemsContainer.style.display==="block") ( event.preventDefault(); for (var i =0,l=itemsContainer.children.length;i
โปรดทราบว่าการสร้างการควบคุมแบบลดขั้นตอนนั้นเป็นงานที่ค่อนข้างหนัก ผู้ใช้คาดหวังที่จะนำทางโดยใช้แป้นพิมพ์ หากต้องการสร้างอินเทอร์เฟซผู้ใช้ที่ยอดเยี่ยม คุณต้องจัดการหลายปุ่ม เช่น ปุ่มลูกศร แท็บเพื่อควบคุมโฟกัส พื้นที่สำหรับเปิดและปิด การป้อนตัวอักษรและตัวเลขเพื่อเน้นไปที่รายการที่ตรงกันรายการแรก เป็นต้น
หากประสบการณ์ผู้ใช้เป็นสิ่งสำคัญ ฉันขอแนะนำให้ใช้เฟรมเวิร์กและปลั๊กอินสำหรับมัน โดยส่วนตัวแล้วฉันชอบ jquery และ jquery ui และมีปลั๊กอินหลายตัวให้เลือกจากแบบเลื่อนลง ข้อดีอีกประการหนึ่งก็คือ หากไคลเอ็นต์ปิดใช้งานจาวาสคริปต์ หรือจาวาสคริปต์ของคุณมีปัญหาด้วยเหตุผลบางประการ ปลั๊กอินส่วนใหญ่จะกลับไปใช้องค์ประกอบการเลือกดั้งเดิมตามปกติ ซึ่งยังคงทำงานได้ดี
ตัวฉันเองได้ใช้ปลั๊กอิน Selectbox นี้เพื่อดรอปดาวน์ง่ายๆ: http://www.abeautifulsite.net/blog/2011/01/jquery-selectbox-plugin/
แก้ไข: ฉันกำลังย้อนกลับคำแนะนำนี้เนื่องจากใช้ไม่ได้หากองค์ประกอบหลายรายการมีชื่อเดียวกัน หากนี่เป็นสิ่งสำคัญ คุณควรตรวจสอบปลั๊กอิน Selectmenu ของ Filament Group: http://filamentgroup.com/lab/jquery_ui_selectmenu_an_aria_accessible_plugin_for_styling_a_html_select/ //Edit
และปลั๊กอินเติมข้อความอัตโนมัติ jquery สำหรับคอมโบบ็อกซ์ที่รองรับอินพุตที่เป็นลายลักษณ์อักษร: http://jqueryui.com/demos/autocomplete/