概要
<howto-checkbox>
は、フォーム内のブール値オプションを表します。最も一般的なタイプのチェックボックスは、ユーザーが 2 つの選択肢(オンとオフ)を切り替えることができるデュアルタイプです。
要素は、最初に作成されたときに、属性 role="checkbox"
と tabindex="0"
のセルフ適用を試みます。role
属性は、スクリーン リーダーなどの支援技術が、これがどのようなコントロールであるかをユーザーに伝えるのに役立ちます。tabindex
属性は、要素をタブ順序に含め、キーボードでフォーカスして操作できるようにします。これらの 2 つのトピックの詳細については、ARIA の機能と tabindex の使用をご覧ください。
チェックボックスがオンの場合、checked
ブール属性が追加され、対応する checked
プロパティが true
に設定されます。また、この要素は、状態に応じて aria-checked
属性を "true"
または "false"
に設定します。マウスまたは Space キーでチェックボックスをクリックすると、これらのチェック状態が切り替わります。
チェックボックスは disabled
状態もサポートしています。disabled
プロパティが true に設定されているか、disabled
属性が適用されている場合、チェックボックスは aria-disabled="true"
を設定し、tabindex
属性を削除します。チェックボックスが現在の activeElement
である場合は、ドキュメントにフォーカスを戻します。
チェックボックスは howto-label
要素とペアになっていて、ユーザー補助機能用の名前が設定されています。
リファレンス
デモ
使用例
<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>
要素からコンテンツをクローンすると、HTML の解析コストが追加されないため、innerHTML を使用するよりもパフォーマンスが向上します。
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') を呼び出すか、new HowToCheckbox() を呼び出すことで作成します。コンストラクタは Shadow DOM を作成するのに適していますが、属性や Light DOM の子要素は使用できない可能性があるため、触らないでください。
constructor() {
super();
this.attachShadow({mode: 'open'});
this.shadowRoot.appendChild(template.content.cloneNode(true));
}
connectedCallback()
は、要素が DOM に挿入されたときに発生します。初期の role
、tabindex
、内部状態を設定し、イベント リスナーをインストールするのに適した場所です。
connectedCallback() {
if (!this.hasAttribute('role'))
this.setAttribute('role', 'checkbox');
if (!this.hasAttribute('tabindex'))
this.setAttribute('tabindex', 0);
ユーザーは、プロトタイプがこのクラスに接続される前に、要素のインスタンスにプロパティを設定できます。_upgradeProperty()
メソッドは、インスタンス プロパティをチェックし、適切なクラス セッターを通じて実行します。詳しくは、遅延プロパティのセクションをご覧ください。
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 から削除されたときに発生します。参照の解放やイベント リスナーの削除などのクリーンアップ作業を行うのに適しています。
disconnectedCallback() {
this.removeEventListener('keyup', this._onKeyUp);
this.removeEventListener('click', this._onClick);
}
プロパティと対応する属性は互いにミラーリングする必要があります。checked のプロパティ セッターは、真偽値を処理し、それらを属性の状態に反映します。詳しくは、再入を回避するをご覧ください。
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()
は、observedAttributes 配列内のいずれかの属性が変更されたときに呼び出されます。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);
})();