Ringkasan
<howto-checkbox>
mewakili opsi boolean dalam formulir. Jenis yang paling umum
adalah jenis ganda yang memungkinkan
pengguna untuk beralih di antara dua
pilihan -- dicentang dan tidak dicentang.
Elemen mencoba menerapkan sendiri atribut role="checkbox"
dan
tabindex="0"
saat pertama kali dibuat. Atribut role
membantu asistif
teknologi seperti {i>screen reader<i} memberi tahu
pengguna seperti apa kontrolnya.
Atribut tabindex
mengikutsertakan elemen ke dalam urutan tab, sehingga menjadikannya keyboard
dapat difokuskan dan dioperasikan. Untuk mempelajari lebih lanjut
tentang kedua topik ini, lihat
Apa yang dapat dilakukan ARIA? dan Menggunakan tabindex.
Jika kotak dicentang, kotak akan menambahkan atribut boolean checked
, dan menetapkan
properti checked
yang sesuai dengan true
. Selain itu, elemen ini menetapkan
aria-checked
ke "true"
atau "false"
, bergantung pada
status. Mengeklik kotak centang dengan mouse, atau bilah spasi, akan mengaktifkan atau menonaktifkan
status yang dicentang.
Kotak centang juga mendukung status disabled
. Jika properti disabled
ditetapkan ke true atau atribut disabled
diterapkan, kotak centang akan disetel
aria-disabled="true"
, menghapus atribut tabindex
, dan menampilkan fokus
ke dokumen jika kotak centang adalah activeElement
saat ini.
Kotak centang disambungkan dengan elemen howto-label
untuk memastikannya memiliki
nama yang dapat diakses.
Referensi
- HowTo: Komponen di GitHub
- Pola Kotak Centang dalam Praktik Penulisan ARIA 1.1
- Apa yang dapat dilakukan ARIA?
- Menggunakan tabindex
Demo
Contoh penggunaan
<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>
Kode
(function() {
Menentukan kode tombol untuk membantu menangani peristiwa keyboard.
const KEYCODE = {
SPACE: 32,
};
Meng-clone konten dari elemen <template>
memiliki performa yang lebih baik daripada menggunakan innerHTML karena menghindari biaya penguraian HTML tambahan.
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'];
}
Konstruktor elemen dijalankan setiap kali instance baru dibuat. Instance dibuat dengan mengurai HTML, memanggil document.createElement('howto-checkbox'), atau memanggil HowToCheckbox() baru; Konstruktor adalah tempat yang bagus untuk membuat shadow DOM, meskipun Anda harus menghindari menyentuh atribut atau turunan light DOM apa pun karena mungkin belum tersedia.
constructor() {
super();
this.attachShadow({mode: 'open'});
this.shadowRoot.appendChild(template.content.cloneNode(true));
}
connectedCallback()
diaktifkan saat elemen disisipkan ke dalam DOM. Ini adalah tempat yang baik untuk menetapkan role
, tabindex
, status internal, dan pemroses peristiwa penginstalan awal.
connectedCallback() {
if (!this.hasAttribute('role'))
this.setAttribute('role', 'checkbox');
if (!this.hasAttribute('tabindex'))
this.setAttribute('tabindex', 0);
Pengguna dapat menetapkan properti pada instance elemen, sebelum prototipenya terhubung ke class ini. Metode _upgradeProperty()
akan memeriksa properti instance dan menjalankannya melalui penyetel class yang tepat. Lihat bagian properti lambat untuk detail selengkapnya.
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()
diaktifkan saat elemen dihapus dari DOM. Ini adalah tempat yang baik untuk melakukan pekerjaan pembersihan seperti merilis referensi dan menghapus pemroses peristiwa.
disconnectedCallback() {
this.removeEventListener('keyup', this._onKeyUp);
this.removeEventListener('click', this._onClick);
}
Properti dan atributnya yang sesuai harus saling mencerminkan. Penyetel properti untuk yang dicentang menangani nilai benar/salah dan mencerminkan nilai tersebut ke status atribut. Lihat bagian jangan masuk kerja lagi untuk mengetahui detail selengkapnya.
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()
dipanggil saat salah satu atribut dalam arrayobservableAttributes diubah. Ini adalah tempat yang baik untuk menangani efek samping, seperti menetapkan atribut 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);
Atribut tabindex
tidak menyediakan cara untuk sepenuhnya menghapus kemampuan fokus dari suatu elemen. Elemen dengan tabindex=-1
masih dapat difokuskan dengan mouse atau dengan memanggil focus()
. Untuk memastikan elemen dinonaktifkan dan tidak dapat difokuskan, hapus atribut tabindex
.
if (hasValue) {
this.removeAttribute('tabindex');
Jika fokus saat ini berada pada elemen ini, batalkan fokus dengan memanggil metode HTMLElement.blur()
this.blur();
} else {
this.setAttribute('tabindex', '0');
}
break;
}
}
_onKeyUp(event) {
Tidak menangani pintasan pengubah yang biasanya digunakan oleh teknologi pendukung.
if (event.altKey)
return;
switch (event.keyCode) {
case KEYCODE.SPACE:
event.preventDefault();
this._toggleChecked();
break;
Penekanan tombol lainnya akan diabaikan dan diteruskan kembali ke browser.
default:
return;
}
}
_onClick(event) {
this._toggleChecked();
}
_toggleChecked()
memanggil penyetel yang dicentang dan membalik statusnya. Karena _toggleChecked()
hanya disebabkan oleh tindakan pengguna, peristiwa tersebut juga akan mengirim peristiwa perubahan. Balon peristiwa ini dibuat untuk meniru perilaku native <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);
})();