More generic keyboard event handling
This commit is contained in:
parent
ace8555a09
commit
2e1426e945
@ -50,6 +50,7 @@ import {MutationTypes} from "@/store/mutation-types";
|
||||
import "@/assets/icons/players.svg";
|
||||
import "@/assets/icons/maps.svg";
|
||||
import {nextTick} from "vue";
|
||||
import {handleKeyboardEvent} from "@/util/events";
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@ -113,41 +114,8 @@ export default defineComponent({
|
||||
return;
|
||||
}
|
||||
|
||||
const sectionHeadings: HTMLElement[] = Array.from(this.$el.querySelectorAll('.section__heading button')),
|
||||
position = sectionHeadings.indexOf(e.target as HTMLElement);
|
||||
|
||||
if(position === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
let newPosition;
|
||||
|
||||
switch(e.key) {
|
||||
case 'ArrowDown':
|
||||
newPosition = position + 1;
|
||||
break;
|
||||
case 'ArrowUp':
|
||||
newPosition = position - 1;
|
||||
break;
|
||||
case 'Home':
|
||||
newPosition = 0;
|
||||
break;
|
||||
case 'End':
|
||||
newPosition = sectionHeadings.length - 1;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if(newPosition >= sectionHeadings.length) {
|
||||
newPosition = 0
|
||||
} else if(newPosition < 0) {
|
||||
newPosition = sectionHeadings.length - 1;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
sectionHeadings[newPosition].focus();
|
||||
const sectionHeadings: HTMLElement[] = Array.from(this.$el.querySelectorAll('.section__heading button'));
|
||||
handleKeyboardEvent(e, sectionHeadings);
|
||||
},
|
||||
togglePlayers() {
|
||||
useStore().commit(MutationTypes.TOGGLE_UI_ELEMENT_VISIBILITY, 'players');
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import {defineComponent} from 'vue';
|
||||
import {handleKeyboardEvent} from "@/util/events";
|
||||
|
||||
export default defineComponent({
|
||||
name: 'RadioList',
|
||||
@ -30,36 +31,7 @@ export default defineComponent({
|
||||
|
||||
methods: {
|
||||
onKeydown(e: KeyboardEvent) {
|
||||
if(e.key === 'ArrowUp' || e.key === 'ArrowDown' || e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
|
||||
const fieldset = e.currentTarget as HTMLFieldSetElement,
|
||||
position = Array.from(fieldset.elements).indexOf(e.target as HTMLElement);
|
||||
|
||||
if(position < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let newPosition = (e.key === 'ArrowUp' || e.key === 'ArrowLeft') ? position - 1 : position + 1;
|
||||
|
||||
if(newPosition < 0) {
|
||||
newPosition = fieldset.elements.length - 1;
|
||||
} else if (newPosition >= fieldset.elements.length) {
|
||||
newPosition = 0;
|
||||
}
|
||||
|
||||
(fieldset.elements[newPosition] as HTMLElement).focus();
|
||||
e.preventDefault();
|
||||
} else if(e.key === 'Enter') {
|
||||
if(e.target instanceof HTMLInputElement && e.target.type === 'radio') {
|
||||
const mouseEvent = new MouseEvent('click', {
|
||||
ctrlKey: e.ctrlKey,
|
||||
shiftKey: e.shiftKey,
|
||||
metaKey: e.metaKey,
|
||||
altKey: e.altKey,
|
||||
});
|
||||
|
||||
e.target.dispatchEvent(mouseEvent);
|
||||
}
|
||||
}
|
||||
handleKeyboardEvent(e, Array.from((e.currentTarget as HTMLFieldSetElement).elements) as HTMLElement[])
|
||||
}
|
||||
}
|
||||
});
|
||||
|
64
src/util/events.ts
Normal file
64
src/util/events.ts
Normal file
@ -0,0 +1,64 @@
|
||||
const navigationKeys = new Set<string>([
|
||||
'ArrowUp',
|
||||
'ArrowDown',
|
||||
'ArrowLeft',
|
||||
'ArrowRight',
|
||||
'Home',
|
||||
'End'
|
||||
]);
|
||||
|
||||
export const handleKeyboardEvent = (e: KeyboardEvent, elements: HTMLElement[]) => {
|
||||
if(!e.target) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(navigationKeys.has(e.key)) {
|
||||
const position = elements.indexOf(e.target as HTMLElement);
|
||||
|
||||
if(position < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let newPosition = position;
|
||||
|
||||
switch(e.key) {
|
||||
case 'ArrowUp':
|
||||
case 'ArrowLeft':
|
||||
newPosition = position - 1;
|
||||
break;
|
||||
|
||||
case 'ArrowDown':
|
||||
case 'ArrowRight':
|
||||
newPosition = position + 1;
|
||||
break;
|
||||
|
||||
case 'Home':
|
||||
newPosition = 0;
|
||||
break;
|
||||
|
||||
case 'End':
|
||||
newPosition = elements.length - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(newPosition < 0) {
|
||||
newPosition = elements.length - 1;
|
||||
} else if(newPosition >= elements.length) {
|
||||
newPosition = 0;
|
||||
}
|
||||
|
||||
(elements[newPosition] as HTMLElement).focus();
|
||||
e.preventDefault();
|
||||
} else if(e.key === 'Enter' && e.target) {
|
||||
const mouseEvent = new MouseEvent('click', {
|
||||
ctrlKey: e.ctrlKey,
|
||||
shiftKey: e.shiftKey,
|
||||
metaKey: e.metaKey,
|
||||
altKey: e.altKey,
|
||||
bubbles: true,
|
||||
});
|
||||
|
||||
e.target.dispatchEvent(mouseEvent);
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user