Skip to content

Instantly share code, notes, and snippets.

@sriramrudraraju
Created September 14, 2022 21:19
Show Gist options
  • Save sriramrudraraju/5458f344ba2c37f5ee8a4374e1b1fbd6 to your computer and use it in GitHub Desktop.
Save sriramrudraraju/5458f344ba2c37f5ee8a4374e1b1fbd6 to your computer and use it in GitHub Desktop.
Listening to global only events
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