Reputation: 98
My problem is quite simple, and I think I know the answer, but if I'm wrong it could be great …
I would like to use an external barcode scanner (work like a physical bluetooth keyboard) to read barcodes but outside any input.
I made a piece of code which works great on android devices but nothing happend on iOS devices …
I'll make it quick, I listen «keyup» events on «window» and when I catch the «Enter» key, I emit the barcode event …
I use RxJS and Observable fromEvent and everithing works great on Android devices.
Is the Safari WebView the problem ?
I remember I already had the same issue on website, Safari does not trigger keyboard events outside elements which don't require keyboard (input, textarea …)
/**
* Outil pour traiter la lecture d'un codebarre par un lecteur physique
* Seuls les évènements claviers hors input sont récupérés
*/
export namespace LecteurCodebarrePhysique {
// L'évènement est-il dans un input ?
const inInput = (event) => {return event.target instanceof Element && event.target.nodeName.toLowerCase() === 'input'};
// La touche relachée est-elle un caractère ?
const isTextKey = (event) => {return !inInput(event) && event.key.length === 1};
// La touche relachée est-elle la touche entrée ?
const isEnter = (event) => {return !inInput(event) && event.keyCode === 13};
/**
* Observable émettant le codebarre lu par un lecteur physique
*/
export function codebarreLu(): Observable<{text: string, format: string}> {
// Observable initiale : évèrement clavier
const keyup: Observable<KeyboardEvent> = fromEvent(window, 'keyup');
return keyup.pipe(
// On ne garde que les touches représentant un caractère
filter(ev => isTextKey(ev)),
// On ne garde que la valeur du caractère
map(ev => ev.key),
// On «bufferise» en attendant la touche entrée
buffer(keyup.pipe(filter(ev => {
const enter = isEnter(ev);
if (enter) {
ev.preventDefault();
ev.stopPropagation();
}
return enter;
}))),
// Quand la touche entrée est relachée, on concatène les caractères
// Et on essaye de déterminer si c'es un EAN13 (13 caractères numériques)
map(chars => {
const codebarre = chars.reduce((code, char) => code + char, '');
const isEan13 = /\d{13}/.test(codebarre);
return {text: codebarre, format: isEan13 ? 'EAN_13' : 'INCONNU'};
})
);
}
}
On Android devices, if I subscribe to the observable and read a barcode outside any inputs, the code inside the subscription is called. On iOS devices, nothing happend …
Upvotes: 1
Views: 577
Reputation: 98
Eureka!
If other guys have the same issue/need of me, I post here the answer! Yes I'm too kind ^^
I've changed the target of the event from «window» to «document» and … wait for it … It works.
Upvotes: 1