forked from vikunja/frontend
chore: remove old shortkey implementation
This commit is contained in:
parent
e40b0a04be
commit
c79a22661f
|
@ -31,8 +31,6 @@ import Notifications from '@kyvg/vue3-notification'
|
||||||
// PWA
|
// PWA
|
||||||
import './registerServiceWorker'
|
import './registerServiceWorker'
|
||||||
|
|
||||||
// Shortcuts
|
|
||||||
import shortkey from '@/plugins/shortkey'
|
|
||||||
// Vuex
|
// Vuex
|
||||||
import {store} from './store'
|
import {store} from './store'
|
||||||
// i18n
|
// i18n
|
||||||
|
@ -55,8 +53,6 @@ const app = createApp(App)
|
||||||
|
|
||||||
app.use(Notifications)
|
app.use(Notifications)
|
||||||
|
|
||||||
app.use(shortkey, {prevent: ['input', 'textarea', '.input', '[contenteditable]']})
|
|
||||||
|
|
||||||
// directives
|
// directives
|
||||||
import focus from './directives/focus'
|
import focus from './directives/focus'
|
||||||
import tooltip from './directives/tooltip'
|
import tooltip from './directives/tooltip'
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
function capitalizeFirstLetter(string) {
|
|
||||||
return string.charAt(0).toUpperCase() + string.slice(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
const MODIFIER_KEYS = ['shift', 'ctrl', 'meta', 'alt']
|
|
||||||
|
|
||||||
const SHORT_CUT_INDEX = [
|
|
||||||
{ key: 'ArrowUp', value: 'arrowup' },
|
|
||||||
{ key: 'ArrowLeft', value: 'arrowlef' },
|
|
||||||
{ key: 'ArrowRight', value: 'arrowright' },
|
|
||||||
{ key: 'ArrowDown', value: 'arrowdown' },
|
|
||||||
{ key: 'AltGraph', value: 'altgraph' },
|
|
||||||
{ key: 'Escape', value: 'esc' },
|
|
||||||
{ key: 'Enter', value: 'enter' },
|
|
||||||
{ key: 'Tab', value: 'tab' },
|
|
||||||
{ key: ' ', value: 'space' },
|
|
||||||
{ key: 'PageUp', value: 'pagup' },
|
|
||||||
{ key: 'PageDown', value: 'pagedow' },
|
|
||||||
{ key: 'Home', value: 'home' },
|
|
||||||
{ key: 'End', value: 'end' },
|
|
||||||
{ key: 'Delete', value: 'del' },
|
|
||||||
{ key: 'Backspace', value: 'bacspace' },
|
|
||||||
{ key: 'Insert', value: 'insert' },
|
|
||||||
{ key: 'NumLock', value: 'numlock' },
|
|
||||||
{ key: 'CapsLock', value: 'capslock' },
|
|
||||||
{ key: 'Pause', value: 'pause' },
|
|
||||||
{ key: 'ContextMenu', value: 'cotextmenu' },
|
|
||||||
{ key: 'ScrollLock', value: 'scrolllock' },
|
|
||||||
{ key: 'BrowserHome', value: 'browserhome' },
|
|
||||||
{ key: 'MediaSelect', value: 'mediaselect' },
|
|
||||||
]
|
|
||||||
|
|
||||||
export function encodeKey(pKey) {
|
|
||||||
const shortKey = {}
|
|
||||||
|
|
||||||
MODIFIER_KEYS.forEach((key) => {
|
|
||||||
shortKey[`${key}Key`] = pKey.includes(key)
|
|
||||||
})
|
|
||||||
|
|
||||||
let indexedKeys = createShortcutIndex(shortKey)
|
|
||||||
const vKey = pKey.filter(
|
|
||||||
(item) => !MODIFIER_KEYS.includes(item),
|
|
||||||
)
|
|
||||||
indexedKeys += vKey.join('')
|
|
||||||
return indexedKeys
|
|
||||||
}
|
|
||||||
|
|
||||||
function createShortcutIndex(pKey) {
|
|
||||||
let k = ''
|
|
||||||
|
|
||||||
MODIFIER_KEYS.forEach((key) => {
|
|
||||||
if (pKey.key === capitalizeFirstLetter(key) || pKey[`${key}Key`]) {
|
|
||||||
k += key
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
SHORT_CUT_INDEX.forEach(({ key, value }) => {
|
|
||||||
if (pKey.key === key) {
|
|
||||||
k += value
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (
|
|
||||||
(pKey.key && pKey.key !== ' ' && pKey.key.length === 1) ||
|
|
||||||
/F\d{1,2}|\//g.test(pKey.key)
|
|
||||||
) {
|
|
||||||
k += pKey.key.toLowerCase()
|
|
||||||
}
|
|
||||||
|
|
||||||
return k
|
|
||||||
}
|
|
||||||
export { createShortcutIndex as decodeKey }
|
|
||||||
|
|
||||||
export function parseValue(value) {
|
|
||||||
value = typeof value === 'string' ? JSON.parse(value.replace(/'/gi, '"')) : value
|
|
||||||
|
|
||||||
return value instanceof Array ? { '': value } : value
|
|
||||||
}
|
|
|
@ -1,186 +0,0 @@
|
||||||
import { parseValue, decodeKey, encodeKey } from './helpers'
|
|
||||||
|
|
||||||
let mapFunctions = {}
|
|
||||||
let objAvoided = []
|
|
||||||
let elementAvoided = []
|
|
||||||
let keyPressed = false
|
|
||||||
|
|
||||||
function dispatchShortkeyEvent(pKey) {
|
|
||||||
const e = new CustomEvent('shortkey', { bubbles: false })
|
|
||||||
|
|
||||||
if (mapFunctions[pKey].key) {
|
|
||||||
e.srcKey = mapFunctions[pKey].key
|
|
||||||
}
|
|
||||||
|
|
||||||
const elm = mapFunctions[pKey].el
|
|
||||||
|
|
||||||
if (!mapFunctions[pKey].propagte) {
|
|
||||||
elm[elm.length - 1].dispatchEvent(e)
|
|
||||||
} else {
|
|
||||||
elm.forEach((elmItem) => elmItem.dispatchEvent(e))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function keyDown(pKey) {
|
|
||||||
if (
|
|
||||||
(!mapFunctions[pKey].once && !mapFunctions[pKey].push) ||
|
|
||||||
(mapFunctions[pKey].push && !keyPressed)
|
|
||||||
) {
|
|
||||||
dispatchShortkeyEvent(pKey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function fillMappingFunctions(
|
|
||||||
mappingFunctions,
|
|
||||||
{ b, push, once, focus, propagte, el },
|
|
||||||
) {
|
|
||||||
for (let key in b) {
|
|
||||||
const k = encodeKey(b[key])
|
|
||||||
const propagated = mappingFunctions[k] && mappingFunctions[k].propagte
|
|
||||||
const elm =
|
|
||||||
mappingFunctions[k] && mappingFunctions[k].el
|
|
||||||
? mappingFunctions[k].el
|
|
||||||
: []
|
|
||||||
|
|
||||||
elm.push(el)
|
|
||||||
|
|
||||||
mappingFunctions[k] = {
|
|
||||||
push,
|
|
||||||
once,
|
|
||||||
focus,
|
|
||||||
key,
|
|
||||||
propagte: propagated || propagte,
|
|
||||||
el: elm,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function bindValue(value, el, binding, vnode) {
|
|
||||||
const { modifiers } = binding
|
|
||||||
const push = !!modifiers.push
|
|
||||||
const avoid = !!modifiers.avoid
|
|
||||||
const focus = !modifiers.focus
|
|
||||||
const once = !!modifiers.once
|
|
||||||
const propagte = !!modifiers.propagte
|
|
||||||
|
|
||||||
if (avoid) {
|
|
||||||
objAvoided = objAvoided.filter((itm) => !itm === el)
|
|
||||||
objAvoided.push(el)
|
|
||||||
} else {
|
|
||||||
fillMappingFunctions(mapFunctions, {
|
|
||||||
b: value,
|
|
||||||
push,
|
|
||||||
once,
|
|
||||||
focus,
|
|
||||||
propagte,
|
|
||||||
el: vnode.el,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function unbindValue(value, el) {
|
|
||||||
for (let key in value) {
|
|
||||||
const k = encodeKey(value[key])
|
|
||||||
const idxElm = mapFunctions[k].el.indexOf(el)
|
|
||||||
|
|
||||||
if (mapFunctions[k].el.length > 1 && idxElm > -1) {
|
|
||||||
mapFunctions[k].el.splice(idxElm, 1)
|
|
||||||
} else {
|
|
||||||
delete mapFunctions[k]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function availableElement(decodedKey) {
|
|
||||||
const objectIsAvoided = !!objAvoided.find(
|
|
||||||
(r) => r === document.activeElement,
|
|
||||||
)
|
|
||||||
const filterAvoided = !!elementAvoided.find(
|
|
||||||
(selector) =>
|
|
||||||
document.activeElement && document.activeElement.matches(selector),
|
|
||||||
)
|
|
||||||
return !!mapFunctions[decodedKey] && !(objectIsAvoided || filterAvoided)
|
|
||||||
}
|
|
||||||
|
|
||||||
function keyDownListener(pKey) {
|
|
||||||
const decodedKey = decodeKey(pKey)
|
|
||||||
|
|
||||||
// Check avoidable elements
|
|
||||||
if (!availableElement(decodedKey)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mapFunctions[decodedKey].propagte) {
|
|
||||||
pKey.preventDefault()
|
|
||||||
pKey.stopPropagation()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mapFunctions[decodedKey].focus) {
|
|
||||||
keyDown(decodedKey)
|
|
||||||
keyPressed = true
|
|
||||||
} else if (!keyPressed) {
|
|
||||||
const elm = mapFunctions[decodedKey].el
|
|
||||||
elm[elm.length - 1].focus()
|
|
||||||
keyPressed = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function keyUpListener(pKey) {
|
|
||||||
const decodedKey = decodeKey(pKey)
|
|
||||||
|
|
||||||
if (!availableElement(decodedKey)) {
|
|
||||||
keyPressed = false
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mapFunctions[decodedKey].propagte) {
|
|
||||||
pKey.preventDefault()
|
|
||||||
pKey.stopPropagation()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mapFunctions[decodedKey].once || mapFunctions[decodedKey].push) {
|
|
||||||
dispatchShortkeyEvent(decodedKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
keyPressed = false
|
|
||||||
}
|
|
||||||
|
|
||||||
// register key presses that happen before mounting of directive
|
|
||||||
// if (process?.env?.NODE_ENV !== 'test') {
|
|
||||||
// (() => {
|
|
||||||
document.addEventListener('keydown', keyDownListener, true)
|
|
||||||
document.addEventListener('keyup', keyUpListener, true)
|
|
||||||
// })()
|
|
||||||
// }
|
|
||||||
|
|
||||||
function install(app, options) {
|
|
||||||
elementAvoided = [...(options && options.prevent ? options.prevent : [])]
|
|
||||||
|
|
||||||
app.directive('shortkey', {
|
|
||||||
beforeMount(el, binding, vnode) {
|
|
||||||
// Mapping the commands
|
|
||||||
const value = parseValue(binding.value)
|
|
||||||
bindValue(value, el, binding, vnode)
|
|
||||||
},
|
|
||||||
|
|
||||||
updated(el, binding, vnode) {
|
|
||||||
const oldValue = parseValue(binding.oldValue)
|
|
||||||
unbindValue(oldValue, el)
|
|
||||||
|
|
||||||
const newValue = parseValue(binding.value)
|
|
||||||
bindValue(newValue, el, binding, vnode)
|
|
||||||
},
|
|
||||||
|
|
||||||
unmounted(el, binding) {
|
|
||||||
const value = parseValue(binding.value)
|
|
||||||
unbindValue(value, el)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
install,
|
|
||||||
encodeKey,
|
|
||||||
decodeKey,
|
|
||||||
keyDown,
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user