Riepilogo
Un elemento <howto-checkbox>
rappresenta un'opzione booleana in un modulo. Il tipo più comune di casella di controllo è il doppio, che consente all'utente di alternare tra due opzioni, selezionate e deselezionate.
Quando viene creato per la prima volta, l'elemento tenta di applicare autonomamente gli attributi role="checkbox"
e tabindex="0"
. L'attributo role
aiuta le tecnologie per la disabilità, come uno screen reader, a indicare all'utente il tipo di controllo. L'attributo tabindex
attiva l'elemento nell'ordine delle schede, rendendolo attivabile e utilizzabile dalla tastiera. Per ulteriori informazioni su questi due argomenti, consulta Cosa può fare ARIA? e Utilizzare tabindex.
Quando la casella di controllo è selezionata, viene aggiunto un attributo booleano checked
e viene impostata una proprietà checked
corrispondente su true
. Inoltre, l'elemento imposta un attributo aria-checked
su "true"
o "false"
, a seconda del suo stato. Se fai clic sulla casella di controllo con il mouse o la barra spaziatrice, gli stati selezionati vengono attivati.
La casella di controllo supporta anche uno stato disabled
. Se la proprietà disabled
è impostata su true o viene applicato l'attributo disabled
, la casella di controllo imposta
aria-disabled="true"
, rimuove l'attributo tabindex
e restituisce lo stato attivo
al documento se la casella di controllo è l'attuale activeElement
.
La casella di controllo è abbinata a un elemento howto-label
per garantire che abbia un
nome accessibile.
Riferimento
- Istruzioni: componenti su GitHub
- Pattern casella di controllo nelle pratiche di creazione ARIA 1.1
- Che cosa può fare ARIA?
- Utilizzare tabindex
Demo
Visualizza la demo dal vivo su GitHub
Esempio di utilizzo
<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>
Codice
(function() {
Definisci i codici dei tasti per facilitare la gestione degli eventi della tastiera.
const KEYCODE = {
SPACE: 32,
};
La clonazione dei contenuti di un elemento <template>
è più efficiente rispetto all'uso di innerHTML perché evita costi aggiuntivi di analisi 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'];
}
Il costruttore dell'elemento viene eseguito ogni volta che viene creata una nuova istanza. Le istanze vengono create analizzando l'HTML, richiamando document.createElement('howto-checkbox') o chiamando il nuovo HowToCheckbox(). Il costruttore è ideale per creare un DOM shadow, anche se è consigliabile evitare di toccare attributi o elementi secondari DOM leggeri perché potrebbero non essere ancora disponibili.
constructor() {
super();
this.attachShadow({mode: 'open'});
this.shadowRoot.appendChild(template.content.cloneNode(true));
}
connectedCallback()
si attiva quando l'elemento viene inserito nel DOM. È ideale per impostare i valori iniziali role
e tabindex
, lo stato interno e installare i listener di eventi.
connectedCallback() {
if (!this.hasAttribute('role'))
this.setAttribute('role', 'checkbox');
if (!this.hasAttribute('tabindex'))
this.setAttribute('tabindex', 0);
Un utente può impostare una proprietà su un'istanza di un elemento prima che il relativo prototipo sia stato collegato a questa classe. Il metodo _upgradeProperty()
verifica la presenza di proprietà dell'istanza e le esegue tramite i setter delle classi appropriati. Per ulteriori dettagli, consulta la sezione relativa alle proprietà lente.
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()
si attiva quando l'elemento viene rimosso dal DOM. È un buon posto per eseguire operazioni di pulizia, come il rilascio dei riferimenti e la rimozione dei listener di eventi.
disconnectedCallback() {
this.removeEventListener('keyup', this._onKeyUp);
this.removeEventListener('click', this._onClick);
}
Le proprietà e gli attributi corrispondenti devono essere speculari. L'impostazione delle proprietà per la casella selezionata gestisce i valori veri e propri o falsificati e riflette questi valori nello stato dell'attributo. Per ulteriori dettagli, consulta la sezione Evitare il rientro.
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()
viene chiamato quando viene modificato uno qualsiasi degli attributi nell'array analyzeAttributes. È un buon posto per gestire gli effetti collaterali, come l'impostazione degli attributi 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);
L'attributo tabindex
non offre un modo per rimuovere completamente la messa a fuoco da un elemento. È possibile impostare lo stato attivo sugli elementi con tabindex=-1
comunque con il mouse o richiamando focus()
. Per assicurarti che un elemento sia disattivato e non sia attivabile, rimuovi l'attributo tabindex
.
if (hasValue) {
this.removeAttribute('tabindex');
Se lo stato attivo è attualmente su questo elemento, annulla lo stato attivo chiamando il metodo HTMLElement.blur()
this.blur();
} else {
this.setAttribute('tabindex', '0');
}
break;
}
}
_onKeyUp(event) {
Non gestire le scorciatoie di modifica tipicamente utilizzate dalle tecnologie per la disabilità.
if (event.altKey)
return;
switch (event.keyCode) {
case KEYCODE.SPACE:
event.preventDefault();
this._toggleChecked();
break;
Qualsiasi altra pressione dei tasti viene ignorata e restituita al browser.
default:
return;
}
}
_onClick(event) {
this._toggleChecked();
}
_toggleChecked()
chiama il setter selezionato e cambia lo stato. Poiché _toggleChecked()
è causato solo da un'azione dell'utente, invierà anche un evento di modifica. Questo evento mostra le bolle per riprodurre il comportamento nativo di <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);
})();