From 336cb39849428feea5e27f2a437ae4c5d1f8ddad Mon Sep 17 00:00:00 2001 From: JonathanMM Date: Mon, 21 Apr 2025 17:25:42 +0200 Subject: [PATCH] =?UTF-8?q?Ajustement=20de=20l=E2=80=99accessibilit=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ts/grille.ts | 82 ++++++++++++++++++++++++++++++++++++++++++---------- ts/input.ts | 62 ++++++++++++++++++++++++++++++++------- 2 files changed, 117 insertions(+), 27 deletions(-) diff --git a/ts/grille.ts b/ts/grille.ts index a7f4604..f9349d9 100644 --- a/ts/grille.ts +++ b/ts/grille.ts @@ -13,7 +13,12 @@ export default class Grille { private _indice: Array; private _motActuel: number; - public constructor(longueurMot: number, maxPropositions: number, indice: string, audioPanel: AudioPanel) { + public constructor( + longueurMot: number, + maxPropositions: number, + indice: string, + audioPanel: AudioPanel + ) { this._grille = document.getElementById("grille") as HTMLElement; this._audioPanel = audioPanel; @@ -30,17 +35,23 @@ export default class Grille { private afficherGrille() { let table = document.createElement("table"); + table.setAttribute("aria-live", "polite"); + table.setAttribute("aria-label", "Grille de jeu"); for (let nbMot = 0; nbMot < this._maxPropositions; nbMot++) { let ligne = document.createElement("tr"); - let mot = this._propositions.length <= nbMot ? "" : this._propositions[nbMot]; + let mot = + this._propositions.length <= nbMot ? "" : this._propositions[nbMot]; if (mot.length > 0) { ligne.setAttribute("role", "group"); - ligne.setAttribute("aria-label", `Mot ${nbMot + 1} sur 6`); + ligne.setAttribute("aria-label", `Mot ${nbMot + 1} sur 6, ${mot}`); } for (let nbLettre = 0; nbLettre < this._longueurMot; nbLettre++) { let cellule = document.createElement("td"); let contenuCellule: string = ""; - if (nbMot < this._motActuel || (nbMot === this._motActuel && mot.length !== 0)) { + if ( + nbMot < this._motActuel || + (nbMot === this._motActuel && mot.length !== 0) + ) { if (mot.length <= nbLettre) { contenuCellule = "."; cellule.classList.add("cellule-lettre-pas-curseur"); @@ -58,24 +69,36 @@ export default class Grille { cellule.classList.add("cellule-lettre-pas-curseur"); } } - if (this._resultats.length > nbMot && this._resultats[nbMot][nbLettre]) { + if ( + this._resultats.length > nbMot && + this._resultats[nbMot][nbLettre] + ) { let resultat = this._resultats[nbMot][nbLettre]; let emoji: string = "🟦"; switch (resultat.statut) { case LettreStatut.BienPlace: emoji = "🟥"; cellule.classList.add("bien-place", "resultat"); - cellule.setAttribute("aria-label", `Lettre ${resultat.lettre} bien placée`); + cellule.setAttribute( + "aria-label", + `Lettre ${resultat.lettre} bien placée` + ); break; case LettreStatut.MalPlace: emoji = "🟡"; cellule.classList.add("mal-place", "resultat"); - cellule.setAttribute("aria-label", `Lettre ${resultat.lettre} mal placée`); + cellule.setAttribute( + "aria-label", + `Lettre ${resultat.lettre} mal placée` + ); break; default: emoji = "🟦"; cellule.classList.add("non-trouve", "resultat"); - cellule.setAttribute("aria-label", `Lettre ${resultat.lettre} non présente`); + cellule.setAttribute( + "aria-label", + `Lettre ${resultat.lettre} non présente` + ); } // console.log(resultat.lettre + " => " + emoji); } @@ -95,7 +118,13 @@ export default class Grille { this.afficherGrille(); } - public validerMot(mot: string, resultats: Array, isBonneReponse: boolean, skipAnimation: boolean = false, endCallback?: () => void): void { + public validerMot( + mot: string, + resultats: Array, + isBonneReponse: boolean, + skipAnimation: boolean = false, + endCallback?: () => void + ): void { this.saisirMot(this._motActuel, mot); this.mettreAJourIndice(resultats); this._resultats.push(resultats); @@ -114,7 +143,10 @@ export default class Grille { } } - private animerResultats(resultats: Array, endCallback?: () => void): void { + private animerResultats( + resultats: Array, + endCallback?: () => void + ): void { let table = this._grille.getElementsByTagName("table").item(0); if (table === null) { this.afficherGrille(); @@ -133,7 +165,12 @@ export default class Grille { this.animerLettre(td, resultats, 0, endCallback); } - private animerLettre(td: HTMLCollectionOf, resultats: Array, numLettre: number, endCallback?: () => void): void { + private animerLettre( + td: HTMLCollectionOf, + resultats: Array, + numLettre: number, + endCallback?: () => void + ): void { if (numLettre >= td.length) { this.afficherGrille(); if (endCallback) endCallback(); @@ -142,21 +179,31 @@ export default class Grille { let cellule = td[numLettre]; let resultat = resultats[numLettre]; cellule.innerHTML = resultat.lettre; - let callback = (() => this.animerLettre(td, resultats, numLettre + 1, endCallback)).bind(this); + let callback = (() => + this.animerLettre(td, resultats, numLettre + 1, endCallback)).bind(this); switch (resultat.statut) { case LettreStatut.BienPlace: cellule.classList.add("bien-place", "resultat"); - cellule.setAttribute("aria-label", `Lettre ${resultat.lettre} bien placée`); + cellule.setAttribute( + "aria-label", + `Lettre ${resultat.lettre} bien placée` + ); this._audioPanel.jouerSonLettreBienPlace(callback); break; case LettreStatut.MalPlace: cellule.classList.add("mal-place", "resultat"); - cellule.setAttribute("aria-label", `Lettre ${resultat.lettre} mal placée`); + cellule.setAttribute( + "aria-label", + `Lettre ${resultat.lettre} mal placée` + ); this._audioPanel.jouerSonLettreMalPlace(callback); break; default: cellule.classList.add("non-trouve", "resultat"); - cellule.setAttribute("aria-label", `Lettre ${resultat.lettre} non présente`); + cellule.setAttribute( + "aria-label", + `Lettre ${resultat.lettre} non présente` + ); this._audioPanel.jouerSonLettreNonTrouve(callback); } } @@ -164,7 +211,10 @@ export default class Grille { private mettreAJourIndice(resultats: Array): void { for (let i = 0; i < this._indice.length; i++) { if (!this._indice[i]) { - this._indice[i] = resultats[i].statut === LettreStatut.BienPlace ? resultats[i].lettre : undefined; + this._indice[i] = + resultats[i].statut === LettreStatut.BienPlace + ? resultats[i].lettre + : undefined; } } } diff --git a/ts/input.ts b/ts/input.ts index e652d12..cbf20a5 100644 --- a/ts/input.ts +++ b/ts/input.ts @@ -23,7 +23,12 @@ export default class Input { private _resultats: Array>; private _haptiqueActive: boolean; - public constructor(gestionnaire: Gestionnaire, configuration: Configuration, longueurMot: number, premiereLettre: string) { + public constructor( + gestionnaire: Gestionnaire, + configuration: Configuration, + longueurMot: number, + premiereLettre: string + ) { this._grille = document.getElementById("grille") as HTMLElement; this._inputArea = document.getElementById("input-area") as HTMLElement; this._premiereLettre = premiereLettre; @@ -32,11 +37,14 @@ export default class Input { this._motSaisi = ""; this._estBloque = new Array(); this._resultats = new Array>(); - this._haptiqueActive = configuration.haptique ?? Configuration.Default.haptique; + this._haptiqueActive = + configuration.haptique ?? Configuration.Default.haptique; this.ajouterEvenementClavierPhysique(); - this.dessinerClavier(configuration.disposition ?? Configuration.Default.disposition); + this.dessinerClavier( + configuration.disposition ?? Configuration.Default.disposition + ); } public dessinerClavier(disposition: ClavierDisposition): void { @@ -55,12 +63,14 @@ export default class Input { lettreDiv.dataset["lettre"] = lettre; lettreDiv.innerText = "⌫"; lettreDiv.classList.add("input-lettre-effacer"); + lettreDiv.setAttribute("aria-label", "Effacer la dernière lettre"); this.ajouterFocus(lettreDiv); break; case "_entree": lettreDiv.innerText = "↲"; lettreDiv.dataset["lettre"] = lettre; lettreDiv.classList.add("input-lettre-entree"); + lettreDiv.setAttribute("aria-label", "Valider le mot"); this.ajouterFocus(lettreDiv); break; case "_vide": @@ -73,6 +83,11 @@ export default class Input { default: lettreDiv.dataset["lettre"] = lettre; lettreDiv.innerText = lettre; + if (lettre === ".") { + lettreDiv.setAttribute("aria-label", "Mettre un blanc"); + } else { + lettreDiv.setAttribute("aria-label", `Lettre ${lettre}`); + } this.ajouterFocus(lettreDiv); } ligneDiv.appendChild(lettreDiv); @@ -80,7 +95,8 @@ export default class Input { this._inputArea.appendChild(ligneDiv); } - this._haptiqueActive = Sauvegardeur.chargerConfig()?.haptique ?? Configuration.Default.haptique; + this._haptiqueActive = + Sauvegardeur.chargerConfig()?.haptique ?? Configuration.Default.haptique; this.ajouterEvenementClavierVirtuel(); this.remettrePropositions(); } @@ -125,7 +141,8 @@ export default class Input { event.stopPropagation(); let div = event.currentTarget; if (!div) return; - if (this._haptiqueActive && window.navigator.vibrate) window.navigator.vibrate(75); + if (this._haptiqueActive && window.navigator.vibrate) + window.navigator.vibrate(75); let lettre = (div as HTMLElement).dataset["lettre"]; if (lettre === undefined) { return; @@ -217,17 +234,25 @@ export default class Input { private siPreremplissageEstReponse(): { preRempli: boolean; mot?: string } { let lettrePrerempli = new Array<{ preRempli: boolean; lettre?: string }>(); - for (let i = 0; i < this._longueurMot; i++) lettrePrerempli.push({ preRempli: false }); + for (let i = 0; i < this._longueurMot; i++) + lettrePrerempli.push({ preRempli: false }); for (let resultat of this._resultats) { for (let positionResultat in resultat) { let lettreResultat = resultat[positionResultat]; - if (lettreResultat.statut === LettreStatut.BienPlace) lettrePrerempli[positionResultat] = { preRempli: true, lettre: lettreResultat.lettre }; + if (lettreResultat.statut === LettreStatut.BienPlace) + lettrePrerempli[positionResultat] = { + preRempli: true, + lettre: lettreResultat.lettre, + }; } } if (lettrePrerempli.every((lettre) => lettre.preRempli)) { - return { preRempli: true, mot: lettrePrerempli.reduce((mot, lettre) => mot + lettre.lettre, "") }; + return { + preRempli: true, + mot: lettrePrerempli.reduce((mot, lettre) => mot + lettre.lettre, ""), + }; } return { preRempli: false }; @@ -236,7 +261,11 @@ export default class Input { private saisirLettre(lettre: string): void { if (this.estBloque()) return; if (this._motSaisi.length >= this._longueurMot) return; - if (this._motSaisi.length === 0 && lettre.toUpperCase() !== this._premiereLettre) this._motSaisi += this._premiereLettre; + if ( + this._motSaisi.length === 0 && + lettre.toUpperCase() !== this._premiereLettre + ) + this._motSaisi += this._premiereLettre; this._motSaisi += lettre; this._gestionnaire.actualiserAffichage(this._motSaisi); } @@ -246,7 +275,8 @@ export default class Input { } public debloquer(contexte: ContexteBloquage): void { - if (this._estBloque.includes(contexte)) this._estBloque.splice(this._estBloque.indexOf(contexte), 1); + if (this._estBloque.includes(contexte)) + this._estBloque.splice(this._estBloque.indexOf(contexte), 1); } private estBloque(): boolean { @@ -268,7 +298,8 @@ export default class Input { let statutLettres: { [lettre: string]: LettreStatut } = {}; // console.log(statutLettres); for (let resultat of resultats) { - if (!statutLettres[resultat.lettre]) statutLettres[resultat.lettre] = resultat.statut; + if (!statutLettres[resultat.lettre]) + statutLettres[resultat.lettre] = resultat.statut; else { switch (resultat.statut) { case LettreStatut.BienPlace: @@ -300,12 +331,17 @@ export default class Input { touche.className = ""; touche.classList.add("input-lettre"); touche.classList.add("lettre-bien-place"); + touche.setAttribute( + "aria-label", + `Lettre ${lettre}, bien placée` + ); break; case LettreStatut.MalPlace: if (touche.classList.contains("lettre-bien-place")) break; touche.className = ""; touche.classList.add("input-lettre"); touche.classList.add("lettre-mal-place"); + touche.setAttribute("aria-label", `Lettre ${lettre}, mal placée`); break; default: if (touche.classList.contains("lettre-bien-place")) break; @@ -313,6 +349,10 @@ export default class Input { touche.className = ""; touche.classList.add("input-lettre"); touche.classList.add("lettre-non-trouve"); + touche.setAttribute( + "aria-label", + `Lettre ${lettre}, non présente` + ); break; } }