สรุป
<howto-checkbox>
แสดงตัวเลือกบูลีนในแบบฟอร์ม ประเภทที่พบบ่อยที่สุด
ในช่องทำเครื่องหมายเป็นแบบคู่ ซึ่งให้ผู้ใช้สามารถสลับระหว่างช่อง
ทั้งหมด โดยเลือกและยกเลิกการเลือกแล้ว
องค์ประกอบพยายามใช้แอตทริบิวต์ role="checkbox"
ด้วยตนเองและ
tabindex="0"
เมื่อสร้างขึ้นครั้งแรก แอตทริบิวต์ role
ช่วยในการอำนวยความสะดวก
เทคโนโลยีอย่างโปรแกรมอ่านหน้าจอ
จะบอกผู้ใช้ว่าการควบคุมนี้เป็นแบบใด
แอตทริบิวต์ tabindex
ทำให้องค์ประกอบเรียงลำดับแท็บได้ ทำให้เป็นแป้นพิมพ์
โฟกัสและใช้งานได้ ดูข้อมูลเพิ่มเติมเกี่ยวกับทั้ง 2 หัวข้อนี้ได้ที่
ARIA ทำอะไรได้บ้างและการใช้ Tabindex
เมื่อเลือกช่องทำเครื่องหมาย ระบบจะเพิ่มแอตทริบิวต์บูลีน checked
และชุด
พร็อพเพอร์ตี้ checked
ที่เกี่ยวข้องกับ true
นอกจากนี้ องค์ประกอบจะกำหนด
aria-checked
เป็นแอตทริบิวต์ "true"
หรือ "false"
ทั้งนี้ขึ้นอยู่กับ
เมื่อคลิกช่องทำเครื่องหมายด้วยเมาส์หรือแป้นเว้นวรรค จะเป็นการสลับ
รัฐที่ตรวจสอบแล้ว
ช่องทำเครื่องหมายยังรองรับสถานะ disabled
ด้วย หากพร็อพเพอร์ตี้ disabled
ตั้งค่าเป็น "จริง" หรือใช้แอตทริบิวต์ disabled
ชุดช่องทำเครื่องหมาย
aria-disabled="true"
นำแอตทริบิวต์ tabindex
ออกและแสดงผลโฟกัส
ลงในเอกสารหากช่องทำเครื่องหมายคือ activeElement
ปัจจุบัน
ช่องทำเครื่องหมายจะจับคู่กับองค์ประกอบ howto-label
เพื่อให้แน่ใจว่ามีองค์ประกอบ
ชื่อที่เข้าถึงได้
ข้อมูลอ้างอิง
- วิธีการ: คอมโพเนนต์บน GitHub
- รูปแบบช่องทำเครื่องหมายในแนวทางปฏิบัติการเขียน ARIA 1.1
- ARIA ทำอะไรได้บ้าง
- การใช้ Tabindex
สาธิต
ดูการสาธิตการใช้งานจริงใน GitHub
ตัวอย่างการใช้
<style>
howto-checkbox {
vertical-align: middle;
}
howto-label {
vertical-align: middle;
display: inline-block;
font-weight: bold;
font-family: sans-serif;
font-size: 20px;
margin-left: 8px;
}
</style>
<howto-checkbox id="join-checkbox"></howto-checkbox>
<howto-label for="join-checkbox">Join Newsletter</howto-label>
รหัส
(function() {
กำหนดโค้ดคีย์เพื่อช่วยในการจัดการเหตุการณ์ของแป้นพิมพ์
const KEYCODE = {
SPACE: 32,
};
การโคลนเนื้อหาจากเอลิเมนต์ <template>
มีประสิทธิภาพมากกว่าการใช้ teriorHTML เนื่องจากช่วยป้องกันต้นทุนการแยกวิเคราะห์ HTML เพิ่มเติม
const template = document.createElement('template');
template.innerHTML = `
<style>
:host {
display: inline-block;
background: url('../images/unchecked-checkbox.svg') no-repeat;
background-size: contain;
width: 24px;
height: 24px;
}
:host([hidden]) {
display: none;
}
:host([checked]) {
background: url('../images/checked-checkbox.svg') no-repeat;
background-size: contain;
}
:host([disabled]) {
background:
url('../images/unchecked-checkbox-disabled.svg') no-repeat;
background-size: contain;
}
:host([checked][disabled]) {
background:
url('../images/checked-checkbox-disabled.svg') no-repeat;
background-size: contain;
}
</style>
`;
class HowToCheckbox extends HTMLElement {
static get observedAttributes() {
return ['checked', 'disabled'];
}
ตัวสร้างขององค์ประกอบจะทำงานทุกครั้งที่มีการสร้างอินสแตนซ์ใหม่ อินสแตนซ์จะสร้างขึ้นโดยการแยกวิเคราะห์ HTML, เรียก document.createElement('howto-checkbox') หรือเรียกใช้ HowToCheckbox(); เครื่องมือสร้างเป็นพื้นที่ที่ดีในการสร้าง Shadow DOM อย่างไรก็ตาม คุณควรหลีกเลี่ยงการสัมผัสแอตทริบิวต์หรือองค์ประกอบย่อยของ Light DOM เนื่องจากอาจยังไม่พร้อมใช้งาน
constructor() {
super();
this.attachShadow({mode: 'open'});
this.shadowRoot.appendChild(template.content.cloneNode(true));
}
connectedCallback()
เริ่มทำงานเมื่อแทรกองค์ประกอบลงใน DOM ซึ่งเป็นจุดที่เหมาะสมในการตั้งค่า role
, tabindex
, สถานะภายใน, และติดตั้ง Listener เหตุการณ์
connectedCallback() {
if (!this.hasAttribute('role'))
this.setAttribute('role', 'checkbox');
if (!this.hasAttribute('tabindex'))
this.setAttribute('tabindex', 0);
ผู้ใช้อาจตั้งค่าพร็อพเพอร์ตี้บนอินสแตนซ์ขององค์ประกอบ ก่อนที่จะเชื่อมต่อต้นแบบขององค์ประกอบกับคลาสนี้ เมธอด _upgradeProperty()
จะตรวจสอบพร็อพเพอร์ตี้อินสแตนซ์และเรียกใช้ผ่านตัวตั้งค่าคลาสที่เหมาะสม ดูรายละเอียดเพิ่มเติมได้ที่ส่วนพร็อพเพอร์ตี้แบบ Lazy Loading
this._upgradeProperty('checked');
this._upgradeProperty('disabled');
this.addEventListener('keyup', this._onKeyUp);
this.addEventListener('click', this._onClick);
}
_upgradeProperty(prop) {
if (this.hasOwnProperty(prop)) {
let value = this[prop];
delete this[prop];
this[prop] = value;
}
}
disconnectedCallback()
เริ่มทำงานเมื่อนำองค์ประกอบออกจาก DOM จุดนี้เป็นตำแหน่งที่ดีในการจัดการข้อมูล เช่น การเผยแพร่ข้อมูลอ้างอิงและนำ Listener เหตุการณ์ออก
disconnectedCallback() {
this.removeEventListener('keyup', this._onKeyUp);
this.removeEventListener('click', this._onClick);
}
โดยพร็อพเพอร์ตี้และแอตทริบิวต์ที่เกี่ยวข้องควรเหมือนกัน ตัวตั้งค่าพร็อพเพอร์ตี้สำหรับการเลือกจะจัดการกับค่าทรูธี/ค่าที่ไม่เป็นจริง และแสดงค่าเหล่านั้นเป็นสถานะของแอตทริบิวต์ ดูรายละเอียดเพิ่มเติมได้ที่ส่วนหลีกเลี่ยงการซ้ำ
set checked(value) {
const isChecked = Boolean(value);
if (isChecked)
this.setAttribute('checked', '');
else
this.removeAttribute('checked');
}
get checked() {
return this.hasAttribute('checked');
}
set disabled(value) {
const isDisabled = Boolean(value);
if (isDisabled)
this.setAttribute('disabled', '');
else
this.removeAttribute('disabled');
}
get disabled() {
return this.hasAttribute('disabled');
}
ระบบจะเรียก attributeChangedCallback()
เมื่อมีการเปลี่ยนแปลงแอตทริบิวต์ในอาร์เรย์เฝ้าดูแอตทริบิวต์ ซึ่งเป็นตำแหน่งที่ดีในการจัดการผลข้างเคียง เช่น การตั้งค่าแอตทริบิวต์ ARIA
attributeChangedCallback(name, oldValue, newValue) {
const hasValue = newValue !== null;
switch (name) {
case 'checked':
this.setAttribute('aria-checked', hasValue);
break;
case 'disabled':
this.setAttribute('aria-disabled', hasValue);
แอตทริบิวต์ tabindex
ไม่ได้ให้วิธีนำความสามารถในการโฟกัสออกจากองค์ประกอบโดยสมบูรณ์ องค์ประกอบที่มี tabindex=-1
จะยังคงโฟกัสด้วยเมาส์หรือเรียกใช้ focus()
ได้ หากต้องการตรวจสอบว่าองค์ประกอบปิดใช้อยู่และโฟกัสไม่ได้ ให้นำแอตทริบิวต์ tabindex
ออก
if (hasValue) {
this.removeAttribute('tabindex');
หากโฟกัสอยู่ที่องค์ประกอบนี้อยู่ ให้เลิกโฟกัสโดยเรียกใช้เมธอด HTMLElement.blur()
this.blur();
} else {
this.setAttribute('tabindex', '0');
}
break;
}
}
_onKeyUp(event) {
ไม่ต้องจัดการแป้นพิมพ์ลัดแป้นกดร่วมที่เทคโนโลยีความช่วยเหลือพิเศษมักใช้
if (event.altKey)
return;
switch (event.keyCode) {
case KEYCODE.SPACE:
event.preventDefault();
this._toggleChecked();
break;
ระบบจะไม่สนใจการกดแป้นอื่นๆ และระบบจะส่งคืนกลับไปยังเบราว์เซอร์
default:
return;
}
}
_onClick(event) {
this._toggleChecked();
}
_toggleChecked()
เรียกใช้ตัวตั้งค่าที่เลือกไว้และกลับสถานะ เนื่องจาก _toggleChecked()
เกิดจากการดำเนินการของผู้ใช้เท่านั้น จึงจะส่งเหตุการณ์การเปลี่ยนแปลงด้วย กิจกรรมนี้แสดงลูกโป่งเพื่อเลียนแบบลักษณะการทำงานเนทีฟของ <input type=checkbox>
_toggleChecked() {
if (this.disabled)
return;
this.checked = !this.checked;
this.dispatchEvent(new CustomEvent('change', {
detail: {
checked: this.checked,
},
bubbles: true,
}));
}
}
customElements.define('howto-checkbox', HowToCheckbox);
})();