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.
204 lines
4.9 KiB
JavaScript
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
|
|
}
|
|
}
|