Created
September 14, 2022 21:19
-
-
Save sriramrudraraju/5458f344ba2c37f5ee8a4374e1b1fbd6 to your computer and use it in GitHub Desktop.
Listening to global only events
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect, useRef } from "react"; | |
interface GlobalScanner { | |
/** | |
* debounce: milliseconds after which keydowns are considered done | |
*/ | |
debounce?: number; | |
/** | |
* disabled: boolean, to disable scanner | |
*/ | |
disabled?: boolean; | |
} | |
/** | |
* | |
* GlobalScanner | |
* | |
* listens to global 'keydown' events and dispatches as new custom 'scanned' event after debounce millisecs | |
* | |
* only listens to events on body target i.e window or document level, inside events are not considered. | |
* | |
* @description | |
* zebra scanners dont publish any special events | |
* instead they trigger 'keypress' with each single char as if entering to input field. | |
* so this component will listen to global keypress events and consider them as barcode scans | |
* | |
*/ | |
export const GlobalScanner = ({ | |
debounce = 1000, | |
disabled = false, | |
}: GlobalScanner) => { | |
const scannedValue = useRef(""); | |
const handleUserKeyPress = (e: KeyboardEvent) => { | |
// only capture if keydown is initiated from document or window level | |
if ((e.target as any).nodeName === "BODY") { | |
scannedValue.current += e.key; | |
} | |
}; | |
const handleDebounce = debounceCallback((e: KeyboardEvent) => { | |
// only capture if keydown is initiated from document or window level | |
if ((e.target as any).nodeName === "BODY" && scannedValue.current) { | |
// dispatching new custom event with value as scannedValue | |
const scanned = new CustomEvent<{value: string}>("scanned", { | |
detail: { value: scannedValue.current }, | |
}); | |
document.dispatchEvent(scanned); | |
scannedValue.current = ""; | |
} | |
}, debounce); | |
useEffect(() => { | |
if (!disabled) { | |
// for listeneing to keydown events | |
document.addEventListener("keydown", handleUserKeyPress); | |
// for trigger debounce handler after waiting debounce seconds | |
document.addEventListener("keydown", handleDebounce); | |
} | |
return () => { | |
document.removeEventListener("keydown", handleUserKeyPress); | |
document.removeEventListener("keydown", handleDebounce); | |
}; | |
}, [handleUserKeyPress, disabled]); | |
return null; | |
}; | |
/** | |
* | |
* @param func Function thats needs to delayed/debounced | |
* @param delay Time in milliseconds | |
* @returns debounced/delayed callback | |
*/ | |
export const debounceCallback = <T extends Function>( | |
func: T, | |
delay: number = 0 | |
) => { | |
let debounceTimer: any; | |
return function () { | |
// @ts-ignore | |
const context = this; | |
const args = arguments; | |
clearTimeout(debounceTimer); | |
debounceTimer = setTimeout(() => func.apply(context, args), delay); | |
}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment