Feat(config): navigazione tastiera per dialog configurazione
Implementa ordine tabindex personalizzato per inserimento formazioni: - Focus automatico su primo campo all'apertura (Ctrl+M) - Sequenza Tab: nomi squadre → zone 1-6 home → zone 1-6 guest - Navigazione ciclica con Tab/Shift+Tab all'interno del dialog - Bottoni esclusi dalla navigazione (tabindex="-1") - Handler dedicato per gestione focus e prevenzione navigazione esterna
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<section class="homepage">
|
||||
<w-dialog v-model="diaNomi.show" :width="600" @close="abilitaTastiSpeciali()">
|
||||
<w-input v-model="sp.nomi.home" type="text" class="pa3">Nome Home</w-input>
|
||||
<w-input v-model="sp.nomi.guest" type="text" class="pa3">Nome Guest</w-input>
|
||||
<w-dialog v-model="diaNomi.show" :width="600" @close="chiudiDialogConfig()">
|
||||
<w-input v-model="sp.nomi.home" type="text" class="pa3" tabindex="1">Nome Home</w-input>
|
||||
<w-input v-model="sp.nomi.guest" type="text" class="pa3" tabindex="2">Nome Guest</w-input>
|
||||
|
||||
<w-flex justify-center align-center class="pa3">
|
||||
<span class="mr3">Modalità partita:</span>
|
||||
@@ -9,14 +9,16 @@
|
||||
@click="modalitaPartita = '2/3'"
|
||||
:bg-color="modalitaPartita === '2/3' ? 'success' : 'grey-light4'"
|
||||
:dark="modalitaPartita === '2/3'"
|
||||
class="ma1">
|
||||
class="ma1"
|
||||
tabindex="-1">
|
||||
2/3
|
||||
</w-button>
|
||||
<w-button
|
||||
@click="modalitaPartita = '3/5'"
|
||||
:bg-color="modalitaPartita === '3/5' ? 'success' : 'grey-light4'"
|
||||
:dark="modalitaPartita === '3/5'"
|
||||
class="ma1">
|
||||
class="ma1"
|
||||
tabindex="-1">
|
||||
3/5
|
||||
</w-button>
|
||||
</w-flex>
|
||||
@@ -27,17 +29,17 @@
|
||||
<div class="campo-pallavolo">
|
||||
<!-- Fila anteriore - index [3, 2, 1] - VICINO ALLA RETE (prima fila visualizzata) -->
|
||||
<w-flex justify-center class="fila-anteriore">
|
||||
<w-input v-model="sp.form.home[3]" type="text" style="width: 50px; text-align: center;" class="ma1"></w-input>
|
||||
<w-input v-model="sp.form.home[2]" type="text" style="width: 50px; text-align: center;" class="ma1"></w-input>
|
||||
<w-input v-model="sp.form.home[1]" type="text" style="width: 50px; text-align: center;" class="ma1"></w-input>
|
||||
<w-input v-model="sp.form.home[3]" type="text" style="width: 50px; text-align: center;" class="ma1" tabindex="6"></w-input>
|
||||
<w-input v-model="sp.form.home[2]" type="text" style="width: 50px; text-align: center;" class="ma1" tabindex="5"></w-input>
|
||||
<w-input v-model="sp.form.home[1]" type="text" style="width: 50px; text-align: center;" class="ma1" tabindex="4"></w-input>
|
||||
</w-flex>
|
||||
<!-- Linea dei 3 metri -->
|
||||
<div class="linea-tre-metri"></div>
|
||||
<!-- Fila posteriore - index [4, 5, 0] - ZONA DIFESA (seconda fila visualizzata) -->
|
||||
<w-flex justify-center class="fila-posteriore">
|
||||
<w-input v-model="sp.form.home[4]" type="text" style="width: 50px; text-align: center;" class="ma1"></w-input>
|
||||
<w-input v-model="sp.form.home[5]" type="text" style="width: 50px; text-align: center;" class="ma1"></w-input>
|
||||
<w-input v-model="sp.form.home[0]" type="text" style="width: 50px; text-align: center;" class="ma1"></w-input>
|
||||
<w-input v-model="sp.form.home[4]" type="text" style="width: 50px; text-align: center;" class="ma1" tabindex="7"></w-input>
|
||||
<w-input v-model="sp.form.home[5]" type="text" style="width: 50px; text-align: center;" class="ma1" tabindex="8"></w-input>
|
||||
<w-input v-model="sp.form.home[0]" type="text" style="width: 50px; text-align: center;" class="ma1" tabindex="3"></w-input>
|
||||
</w-flex>
|
||||
</div>
|
||||
</div>
|
||||
@@ -47,24 +49,24 @@
|
||||
<div class="campo-pallavolo">
|
||||
<!-- Fila anteriore - index [3, 2, 1] - VICINO ALLA RETE (prima fila visualizzata) -->
|
||||
<w-flex justify-center class="fila-anteriore">
|
||||
<w-input v-model="sp.form.guest[3]" type="text" style="width: 50px; text-align: center;" class="ma1"></w-input>
|
||||
<w-input v-model="sp.form.guest[2]" type="text" style="width: 50px; text-align: center;" class="ma1"></w-input>
|
||||
<w-input v-model="sp.form.guest[1]" type="text" style="width: 50px; text-align: center;" class="ma1"></w-input>
|
||||
<w-input v-model="sp.form.guest[3]" type="text" style="width: 50px; text-align: center;" class="ma1" tabindex="12"></w-input>
|
||||
<w-input v-model="sp.form.guest[2]" type="text" style="width: 50px; text-align: center;" class="ma1" tabindex="11"></w-input>
|
||||
<w-input v-model="sp.form.guest[1]" type="text" style="width: 50px; text-align: center;" class="ma1" tabindex="10"></w-input>
|
||||
</w-flex>
|
||||
<!-- Linea dei 3 metri -->
|
||||
<div class="linea-tre-metri"></div>
|
||||
<!-- Fila posteriore - index [4, 5, 0] - ZONA DIFESA (seconda fila visualizzata) -->
|
||||
<w-flex justify-center class="fila-posteriore">
|
||||
<w-input v-model="sp.form.guest[4]" type="text" style="width: 50px; text-align: center;" class="ma1"></w-input>
|
||||
<w-input v-model="sp.form.guest[5]" type="text" style="width: 50px; text-align: center;" class="ma1"></w-input>
|
||||
<w-input v-model="sp.form.guest[0]" type="text" style="width: 50px; text-align: center;" class="ma1"></w-input>
|
||||
<w-input v-model="sp.form.guest[4]" type="text" style="width: 50px; text-align: center;" class="ma1" tabindex="13"></w-input>
|
||||
<w-input v-model="sp.form.guest[5]" type="text" style="width: 50px; text-align: center;" class="ma1" tabindex="14"></w-input>
|
||||
<w-input v-model="sp.form.guest[0]" type="text" style="width: 50px; text-align: center;" class="ma1" tabindex="9"></w-input>
|
||||
</w-flex>
|
||||
</div>
|
||||
</div>
|
||||
</w-flex>
|
||||
|
||||
<w-button @click="order = !order" class="ma2">Inverti ordine</w-button>
|
||||
<w-button bg-color="success" @click="diaNomi.show = false" class="ma2">
|
||||
<w-button @click="order = !order" class="ma2" tabindex="-1">Inverti ordine</w-button>
|
||||
<w-button bg-color="success" @click="diaNomi.show = false" class="ma2" tabindex="-1">
|
||||
Ok
|
||||
</w-button>
|
||||
</w-dialog>
|
||||
|
||||
@@ -244,6 +244,79 @@ export default {
|
||||
apriDialogConfig() {
|
||||
this.disabilitaTastiSpeciali();
|
||||
this.diaNomi.show = true;
|
||||
|
||||
// Aggiungi gestore Tab per il dialog
|
||||
this.dialogConfigTabHandler = (e) => {
|
||||
if (e.key === 'Tab' && this.diaNomi.show) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const dialog = document.querySelector('.w-dialog');
|
||||
if (!dialog) return;
|
||||
|
||||
const allInputs = Array.from(dialog.querySelectorAll('input[type="text"]'))
|
||||
.sort((a, b) => {
|
||||
const tabA = parseInt(a.closest('[tabindex]')?.getAttribute('tabindex') || '0');
|
||||
const tabB = parseInt(b.closest('[tabindex]')?.getAttribute('tabindex') || '0');
|
||||
return tabA - tabB;
|
||||
});
|
||||
|
||||
if (allInputs.length === 0) return;
|
||||
|
||||
// Verifica se il focus è già dentro il dialog
|
||||
const focusInDialog = dialog.contains(document.activeElement);
|
||||
|
||||
// Se non è nel dialog o non è in un input, vai al primo
|
||||
if (!focusInDialog || !allInputs.includes(document.activeElement)) {
|
||||
allInputs[0].focus();
|
||||
return;
|
||||
}
|
||||
|
||||
// Navigazione normale tra i campi
|
||||
const currentIndex = allInputs.indexOf(document.activeElement);
|
||||
let nextIndex;
|
||||
|
||||
if (e.shiftKey) {
|
||||
nextIndex = currentIndex <= 0 ? allInputs.length - 1 : currentIndex - 1;
|
||||
} else {
|
||||
nextIndex = currentIndex >= allInputs.length - 1 ? 0 : currentIndex + 1;
|
||||
}
|
||||
|
||||
if (allInputs[nextIndex]) {
|
||||
allInputs[nextIndex].focus();
|
||||
}
|
||||
}
|
||||
};
|
||||
window.addEventListener('keydown', this.dialogConfigTabHandler, true);
|
||||
|
||||
// Focus immediato + retry con timeout
|
||||
this.$nextTick(() => {
|
||||
const focusFirst = () => {
|
||||
const dialog = document.querySelector('.w-dialog');
|
||||
if (dialog) {
|
||||
const firstInput = dialog.querySelector('input[type="text"]');
|
||||
if (firstInput) {
|
||||
firstInput.focus();
|
||||
firstInput.select();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// Prova immediatamente
|
||||
if (!focusFirst()) {
|
||||
// Se fallisce, riprova dopo un breve delay
|
||||
setTimeout(focusFirst, 100);
|
||||
}
|
||||
});
|
||||
},
|
||||
chiudiDialogConfig() {
|
||||
if (this.dialogConfigTabHandler) {
|
||||
window.removeEventListener('keydown', this.dialogConfigTabHandler, true);
|
||||
this.dialogConfigTabHandler = null;
|
||||
}
|
||||
this.abilitaTastiSpeciali();
|
||||
},
|
||||
resettaCambi(team) {
|
||||
const teams = team ? [team] : ["home", "guest"];
|
||||
|
||||
Reference in New Issue
Block a user