You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
155 lines
4.1 KiB
155 lines
4.1 KiB
import { ref, watch, nextTick, onBeforeUnmount } from 'vue';
|
|
import { state } from "./stateMgr.js";
|
|
|
|
function getNumberFromKeyEvent(event) {
|
|
if (event.keyCode >= 96 && event.keyCode <= 105) {
|
|
return event.keyCode - 96;
|
|
} else if (event.keyCode >= 48 && event.keyCode <= 57) {
|
|
return event.keyCode - 48;
|
|
}
|
|
return null;
|
|
}
|
|
export const ArrowHorizontalKeyHandler = (event) => {
|
|
if (event.key == "ArrowRight") {
|
|
const idx = state.sortedElements.indexOf(String(state.activeIndex));
|
|
state.activeIndex = state.sortedElements[(idx+1)%state.sortedElements.length];
|
|
} else if (event.key == "ArrowLeft") {
|
|
const idx = state.sortedElements.indexOf(String(state.activeIndex))
|
|
state.activeIndex = state.sortedElements[(idx+state.sortedElements.length-1)%state.sortedElements.length];
|
|
}
|
|
}
|
|
export const ArrowVerticalKeyHandler = (event) => {
|
|
if (event.key == "ArrowDown") {
|
|
const idx = state.sortedElements.indexOf(String(state.activeIndex))
|
|
state.activeIndex = state.sortedElements[(idx+1)%state.sortedElements.length];
|
|
event.preventDefault();
|
|
} else if (event.key == "ArrowUp") {
|
|
const idx = state.sortedElements.indexOf(String(state.activeIndex))
|
|
state.activeIndex = state.sortedElements[(idx+state.sortedElements.length-1)%state.sortedElements.length];
|
|
event.preventDefault();
|
|
}
|
|
}
|
|
export const NumberKeyHandler = (event) => {
|
|
let i;
|
|
if ((i = getNumberFromKeyEvent(event)) != null) {
|
|
if (state.elements[i] != undefined) {
|
|
event.stopPropagation();
|
|
event.preventDefault();
|
|
state.activeIndex = i;
|
|
state.elements[i].focus();
|
|
state.elements[i].click();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
export const EnterHandler = (event) => {
|
|
if (event.key == "Enter"){
|
|
if (state.hasOwnProperty("activeElement") && state.activeElement) {
|
|
event.stopPropagation();
|
|
if (state.activeElement.tagName != "BUTTON"){
|
|
event.preventDefault();
|
|
}
|
|
state.activeElement.click();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
export const handleActive = (props, keydownHandlers) => {
|
|
const ownCopy = keydownHandlers.map((f) => (e) => f(e));
|
|
const currActive = ref(1);
|
|
state.activeIndex = 1;
|
|
const handle = () => {
|
|
if (props.active){
|
|
state.activeIndex = currActive.value;
|
|
for (var i = 0; i < keydownHandlers.length; i++) {
|
|
document.addEventListener("keydown", ownCopy[i]);
|
|
}
|
|
} else {
|
|
currActive.value = state.activeIndex;
|
|
for (var i = 0; i < ownCopy.length; i++) {
|
|
document.removeEventListener("keydown", ownCopy[i]);
|
|
}
|
|
}
|
|
}
|
|
onBeforeUnmount(() => {
|
|
// Cleanup
|
|
for (var i = 0; i < ownCopy.length; i++) {
|
|
document.removeEventListener("keydown", ownCopy[i]);
|
|
}
|
|
});
|
|
watch(() => props.active, handle);
|
|
handle();
|
|
}
|
|
|
|
export const vAutofocus = {
|
|
mounted(el, binding, vnode, prevVnode) {
|
|
if (binding.value == undefined || binding.value) {
|
|
state.activeIndex = getId(el);
|
|
}
|
|
}
|
|
}
|
|
|
|
export function getId(el) {
|
|
for (var key in state.elements) {
|
|
if (state.elements[key] == el){
|
|
return key;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const add = (el) => {
|
|
const focus = () => {
|
|
if (state.activeElement !== el) {
|
|
state.activeIndex = val;
|
|
state.activeElement = el;
|
|
}
|
|
}
|
|
|
|
const blur = (e) => {
|
|
if (e.relatedTarget === null) {
|
|
state.activeElement = undefined;
|
|
state.activeIndex = undefined;
|
|
}
|
|
}
|
|
let val;
|
|
if (el.dataset["tabindex"]) {
|
|
val = el.dataset["tabindex"];
|
|
} else {
|
|
val = Object.keys(state.elements).length+1;
|
|
}
|
|
el.tabIndex = val;
|
|
state.elements[val] = el;
|
|
el.addEventListener("focus", focus);
|
|
el.addEventListener("blur", blur);
|
|
el.blurcb = blur;
|
|
el.focuscb = focus;
|
|
};
|
|
|
|
const remove = (el) => {
|
|
delete el.removeAttribute("tabindex");
|
|
delete state.elements[getId(el)]
|
|
// el.removeEventListener("blur", el.blurfn);
|
|
// el.removeEventListener("focus", el.focusfn);
|
|
}
|
|
|
|
export const vIndex = {
|
|
updated(el, binding, vnode, prevVnode) {
|
|
if (binding.oldValue != binding.value){
|
|
if (binding.oldValue) {
|
|
remove(el);
|
|
} else {
|
|
add(el);
|
|
}
|
|
}
|
|
},
|
|
mounted(el, binding, vnode, prevVnode) {
|
|
add(el);
|
|
},
|
|
beforeUnmount(el, binding, vnode, prevVnode) {
|
|
remove(el);
|
|
}
|
|
}
|
|
|