You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
besure_app/src/hooks/useScannerInput.js

204 lines
4.9 KiB
JavaScript

import { onHide, onShow, onUnload } from '@dcloudio/uni-app'
const androidKeyCodeMap = {
7: '0',
8: '1',
9: '2',
10: '3',
11: '4',
12: '5',
13: '6',
14: '7',
15: '8',
16: '9',
29: 'A',
30: 'B',
31: 'C',
32: 'D',
33: 'E',
34: 'F',
35: 'G',
36: 'H',
37: 'I',
38: 'J',
39: 'K',
40: 'L',
41: 'M',
42: 'N',
43: 'O',
44: 'P',
45: 'Q',
46: 'R',
47: 'S',
48: 'T',
49: 'U',
50: 'V',
51: 'W',
52: 'X',
53: 'Y',
54: 'Z',
55: ',',
56: '.',
69: '-',
70: '=',
71: '[',
72: ']',
73: '\\',
74: ';',
75: "'",
76: '/',
81: '+'
}
export function useScannerInput(options = {}) {
const minLength = Number(options.minLength ?? 3)
const commitDelay = Number(options.commitDelay ?? 120)
const uppercase = options.uppercase !== false
const ignoreInputTarget = options.ignoreInputTarget !== false
const hideKeyboardOnScan = options.hideKeyboardOnScan !== false
const hideKeyboardOnLeave = options.hideKeyboardOnLeave !== false
const onScan = typeof options.onScan === 'function' ? options.onScan : () => {}
let scannerBuffer = ''
let scannerTimer = null
let scannerListening = false
let plusKeyListening = false
function getScannerEventTarget() {
if (typeof document !== 'undefined') return document
if (typeof window !== 'undefined') return window
return null
}
function registerScannerListener() {
if (scannerListening) return
const target = getScannerEventTarget()
if (target?.addEventListener) {
target.addEventListener('keydown', handleScannerKeydown)
scannerListening = true
}
registerPlusKeyListener()
}
function unregisterScannerListener() {
const target = getScannerEventTarget()
if (scannerListening && target?.removeEventListener) {
target.removeEventListener('keydown', handleScannerKeydown)
}
scannerListening = false
unregisterPlusKeyListener()
clearScannerBuffer()
if (hideKeyboardOnLeave) hideSoftKeyboard()
}
function registerPlusKeyListener() {
if (plusKeyListening) return
if (typeof plus === 'undefined' || !plus?.key?.addEventListener) return
plus.key.addEventListener('keydown', handlePlusScannerKeydown)
plusKeyListening = true
}
function unregisterPlusKeyListener() {
if (!plusKeyListening) return
if (typeof plus !== 'undefined' && plus?.key?.removeEventListener) {
plus.key.removeEventListener('keydown', handlePlusScannerKeydown)
}
plusKeyListening = false
}
function handlePlusScannerKeydown(event) {
handleScannerKeydown({ ...event, isPlusKeyEvent: true })
}
function handleScannerKeydown(event) {
if (ignoreInputTarget) {
const targetTag = String(event?.target?.tagName || '').toLowerCase()
if (targetTag === 'input' || targetTag === 'textarea') return
}
const key = normalizeScannerKey(event)
if (!key) return
if (key === 'Enter') {
commitScannerBuffer()
return
}
scannerBuffer += key
if (scannerTimer) clearTimeout(scannerTimer)
scannerTimer = setTimeout(() => {
commitScannerBuffer()
}, commitDelay)
}
function normalizeScannerKey(event) {
if (event?.ctrlKey || event?.altKey || event?.metaKey) return ''
if (isAndroidPlusKeyEvent(event)) return normalizeAndroidKeyCode(event)
const key = event?.key
if (key === 'Enter' || key === 'Tab') return 'Enter'
if (typeof key === 'string' && key.length === 1) return uppercase ? key.toUpperCase() : key
const code = Number(event?.keyCode || event?.which || 0)
if (code === 13 || code === 9) return 'Enter'
if (code >= 48 && code <= 90) {
const value = String.fromCharCode(code)
return uppercase ? value.toUpperCase() : value
}
if (code >= 96 && code <= 105) return String(code - 96)
if (code === 189 || code === 109) return '-'
if (code === 190 || code === 110) return '.'
return ''
}
function isAndroidPlusKeyEvent(event) {
return Boolean(event?.isPlusKeyEvent)
}
function normalizeAndroidKeyCode(event) {
const code = Number(event?.keyCode || event?.which || 0)
if (code === 66 || code === 61 || code === 160) return 'Enter'
const value = androidKeyCodeMap[code] || ''
return uppercase ? value.toUpperCase() : value.toLowerCase()
}
function clearScannerBuffer() {
scannerBuffer = ''
if (scannerTimer) {
clearTimeout(scannerTimer)
scannerTimer = null
}
}
async function commitScannerBuffer() {
const value = scannerBuffer.trim()
clearScannerBuffer()
if (value.length < minLength) return
if (hideKeyboardOnScan) hideSoftKeyboard()
await onScan(value)
}
function hideSoftKeyboard() {
try {
uni.hideKeyboard()
} catch (e) {}
}
onShow(() => {
registerScannerListener()
})
onHide(() => {
unregisterScannerListener()
})
onUnload(() => {
unregisterScannerListener()
})
return {
clearScannerBuffer,
registerScannerListener,
unregisterScannerListener
}
}