Bladeren bron

init

master
Anna Ho 3 jaren geleden
bovenliggende
commit
04c9014058
20 gewijzigde bestanden met toevoegingen van 1883 en 1 verwijderingen
  1. +0
    -1
      .gitignore
  2. BIN
      gradle/wrapper/gradle-wrapper.jar
  3. +12
    -0
      node_modules/.package-lock.json
  4. +10
    -0
      node_modules/onscan/.github/main.workflow
  5. +17
    -0
      node_modules/onscan/.project
  6. +6
    -0
      node_modules/onscan/.settings/.jsdtscope
  7. +1
    -0
      node_modules/onscan/.settings/org.eclipse.wst.jsdt.ui.superType.container
  8. +1
    -0
      node_modules/onscan/.settings/org.eclipse.wst.jsdt.ui.superType.name
  9. +55
    -0
      node_modules/onscan/HISTORY.md
  10. +20
    -0
      node_modules/onscan/LICENSE
  11. +201
    -0
      node_modules/onscan/README.md
  12. +20
    -0
      node_modules/onscan/bower.json
  13. +428
    -0
      node_modules/onscan/index.html
  14. +526
    -0
      node_modules/onscan/onscan.js
  15. +5
    -0
      node_modules/onscan/onscan.min.js
  16. +21
    -0
      node_modules/onscan/package.json
  17. +24
    -0
      package-lock.json
  18. +5
    -0
      package.json
  19. +526
    -0
      src/main/webapp/resources/js/onscan.js
  20. +5
    -0
      src/main/webapp/resources/js/onscan.min.js

+ 0
- 1
.gitignore Bestand weergeven

@@ -12,7 +12,6 @@
.mtj.tmp/

# Package Files #
*.jar
*.war
*.nar
*.ear


BIN
gradle/wrapper/gradle-wrapper.jar Bestand weergeven


+ 12
- 0
node_modules/.package-lock.json Bestand weergeven

@@ -0,0 +1,12 @@
{
"name": "TBMS",
"lockfileVersion": 2,
"requires": true,
"packages": {
"node_modules/onscan.js": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/onscan.js/-/onscan.js-1.5.2.tgz",
"integrity": "sha512-9oGYy2gXYRjvXO9GYqqVca0VuCTAmWhbmX3egBSBP13rXiMNb+dKPJzKFEeECGqPBpf0m40Zoo+GUQ7eCackdw=="
}
}
}

+ 10
- 0
node_modules/onscan/.github/main.workflow Bestand weergeven

@@ -0,0 +1,10 @@
workflow "publish on release" {
on = "push"
resolves = ["publish"]
}

action "publish" {
uses = "actions/npm@master"
args = "publish"
secrets = ["77cd6a03-5851-4997-ba04-a529eb3a7629"]
}

+ 17
- 0
node_modules/onscan/.project Bestand weergeven

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>onScan.js</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
</natures>
</projectDescription>

+ 6
- 0
node_modules/onscan/.settings/.jsdtscope Bestand weergeven

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry excluding="**/bower_components/*|**/node_modules/*|**/*.min.js" kind="src" path=""/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
<classpathentry kind="output" path=""/>
</classpath>

+ 1
- 0
node_modules/onscan/.settings/org.eclipse.wst.jsdt.ui.superType.container Bestand weergeven

@@ -0,0 +1 @@
org.eclipse.wst.jsdt.launching.JRE_CONTAINER

+ 1
- 0
node_modules/onscan/.settings/org.eclipse.wst.jsdt.ui.superType.name Bestand weergeven

@@ -0,0 +1 @@
Global

+ 55
- 0
node_modules/onscan/HISTORY.md Bestand weergeven

@@ -0,0 +1,55 @@
# onScan.js - version history

### 1.5.2

- FIX undefined variable oOptions when in paste-mode

### 1.5.1

- NEW utility method `onScan.isAttachedTo()`.
- FIX improvements in documentation

## 1.5

- NEW method `onScan.isScanInProgressFor()` to test if a potential keyboard scan is in progress
- NEW option `captureEvents` to make sure onScan gets events before any other listerer below in the DOM

### 1.4.3

- NEW `onScan.simulate()` now accepts arrays of key codes or event properties
- FIX shiftKey detection was not working

### 1.4.2

- FIX missing update of min-version for 1.4.1
- FIX further improvements for key code normalization

### 1.4.1

- FIX default keyboard event decoder

## 1.4

- Improved default key code decoder: ignore non-alphanumeric characters, case sensitive now, etc.
- Wrapped onScan as a JS module
- Fixed JS errors in browsers, that do not allow overriding KeyboardEvent.which

### 1.3.2

- FIX option `ignoreIfFocusOn` not working

## 1.3

- Added option `reactToKeydown` to disable keyboard-mode if favor of clipboard-mode only
- Cleaned up API
- Improved README
- Added LICENSE and HISTORY.md

## 1.2

- Added support for NPM

## 1.0

- Initial release


+ 20
- 0
node_modules/onscan/LICENSE Bestand weergeven

@@ -0,0 +1,20 @@
The MIT License (MIT)

Copyright (c) 2014-2015 almasaeed2010

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 201
- 0
node_modules/onscan/README.md Bestand weergeven

@@ -0,0 +1,201 @@
# onScan.js

Framework-agnostic JavaScript scan-events for hardware barcode scanners.

## Quick start

1. Install via `npm install onscan.js` or `bower install onscan-js`
2. Include `onscan.min.js` in your script
3. Add the following initilization script to run on page/view load.

```javascript
// Enable scan events for the entire document
onScan.attachTo(document);
// Register event listener
document.addEventListener('scan', function(sScancode, iQuantity) {
alert(iQuantity + 'x ' + sScancode);
});
```

## Demo & Playground

[Online demo](https://a.kabachnik.info/onscan-js-playground.html)

A similar demo is available within the
package: just load `index.html` from the lib's folder to play around with the settings on your own server.

## Requirements

1) A hardware barcode scanner, that
- acts as a keyboard (often called keyboard-wedge-mode), or
- pastes the scanned codes (clipboard-mode)
2) A more-or-less modern browser (IE9+)

## How it works

onScan.js attempts to distinguish between regular input and scan input by measuring input spead,
looking for certain prefix and suffix characters, etc. If a scan is detected, it triggers a custom
JavaScript event called `scan` for the DOM element specified during initialization.

There are lot's of options to fine-tune detection of specific scanner models.

There are also a couple of usefull extras (some requiring specifc hardware):

- Passing a counter along with the scanned code
- Adding a secondary action to the hardware button of built-in scanners, if it is long pressed
## Some examples

```javascript
// Initialize with options
onScan.attachTo(document, {
suffixKeyCodes: [13], // enter-key expected at the end of a scan
reactToPaste: true, // Compatibility to built-in scanners in paste-mode (as opposed to keyboard-mode)
onScan: function(sCode, iQty) { // Alternative to document.addEventListener('scan')
console.log('Scanned: ' + iQty + 'x ' + sCode);
},
onKeyDetect: function(iKeyCode){ // output all potentially relevant key events - great for debugging!
console.log('Pressed: ' + iKeyCode);
}
});

// Simulate a scan programmatically - e.g. to test event handlers
onScan.simulate(document, '1234567890123');

// Simulate raw keyCodes
onScan.simulate(document, [48,49,50]);

// Simulate keydown events
onScan.simulate(document, [ {keyCode:80, key:'P', shiftKey:true}, {keyCode:49,key:'1'} ]);

// Change options on-the-fly
onScan.setOptions(document, {
singleScanQty: 5 // change the quantity to 5 for every scan
});

// Remove onScan.js from a DOM element completely
onScan.detachFrom(document);
```

## Options

The following options can be set when initializing onScan.js:

| Option | Default | Description |
| ------ | ------- | ----------- |
| onScan | function(sScanned, iQty){} | Callback after successful scan. <br><br>Arguments: <br> - `sScanned` - [string] scanned code <br> - `iQty` - [integer] quantity |
| onScanButtonLongPress | function(){} | Callback after the scan button was pressed and held down for a time defined in `scanButtonLongPressThreshold`. This can only be used if the scan button behaves as a key itself and the `scanButtonKeyCode` option is set. |
| onScanError | function(oDebug){} | Callback after a scanned string being dropped due to restrictions. <br><br>Arguments: <br> - `oDebug` - [object] plain object with various debug data|
| onKeyDetect | function(iKeyCode, oEvent){} | Callback after every detected key event. Further event processing can be canceled by returning `false` from this callback - e.g. to exclude certain key events completely. <br><br>Arguments: <br> - `iKeyCode` - [integer] detected key code <br> - `oEvent` [KeyboardEvent] complete event instance |
| onKeyProcess | function(sChar, oEvent){} | Callback after a key event was decoded and found to be part of a potential scan code. Keep in mind, that a this point it is not yet known, whether it's a scan or not - it's just a valid character being processed and decoded. <br><br>Arguments: <br> - `sChar` - [string] decoded character<br> - `oEvent` [KeyboardEvent] complete event instance |
| onPaste | function(sPasted, oEvent){} | Callback after detecting a paste. Only fired if `reactToPaste` is set to `true`. <br><br>Arguments: <br> - `sPasted` - [string] pasted string <br> - `oEvent` - [Event] complete event instance |
| keyCodeMapper | onScan.decodeKeyEvent() | A function to extract the character from a `keydown` event. The event will be ignored if the function returns `null`. See chapter "Decoding key codes" below for more information. |
| timeBeforeScanTest | 100 | Wait duration (ms) after keypress event to check if scanning finished |
| avgTimeByChar | 30 | Average time (ms) between 2 chars. If a scan is detected, but it took more time that [code length] * `avgTimeByChar`, a `scanError` will be triggered. |
| minLength | 6 | Minimum length for a scanned code. If the scan ends before reaching this length, it will trigger a `scanError` event. |
| suffixKeyCodes | [9,13] | An array with possible suffix codes sent by the scanner after the actual data. Detecting one of them means end of scanning, but they can never be part of the scanned code. Many scanners will send key code `13` (enter) as suffix by default. This can be changed in the configuration in most cases. <br><br>NOTE: KeyboardEvents with these key codes will be silenced via `event.stopImmediatePropagation()` and `event.preventDefault()`. |
| prefixKeyCodes | [] | An array with possible prefix codes sent by the scanner before the actual data. Detecting one of them means start of scanning, but they can never be part of the scanned code. Many scanners support prefix characters in their configuration.<br><br>NOTE: KeyboardEvents with these key codes will be silenced via `event.stopImmediatePropagation()` and `event.preventDefault()`. |
| ignoreIfFocusOn | false | Ignore scans if the currently focused element matches this selector. For example, if you set this option to `'input'`, scan events will not be fired if an input field is focused. You can either pass an DOMElement, a CSS selector or an array containing multiple besaid objects. |
| scanButtonKeyCode | false | Key code of the scanner hardware button (i.e. if the scanner button a acts as a key itself). Knowing this key code is important, because it is not part of the scanned code and must be ignored. |
| scanButtonLongPressTime | 500 | Time (ms) to hold the scan button before `onScanButtonLongPress` is triggered. Only works if `scanButtonKeyCode` is set. |
| stopPropagation | false | Stop immediate propagation of events, that are processed successfully.<br><br><b>WARNING:</b> If `reactToKeyDown` is true, every keyboard event, that could potentially be part of a scancode will be stopped! |
| preventDefault | false | Prevent default action of events, that are processed successfully.<br><br><b>WARNING:</b> If `reactToKeyDown` is true, the default of every keyboard event, that could potentially be part of a scancode will be prevented - in particular you won't be able to use the keyboard for typing!!! |
| captureEvents | false | Set to `true` to force all relevant events to be dispatched to onScan _before_ being dispatched to any `EventTarget` beneath it in the DOM tree. Use this if you need to cancel certain events in onScan callbacks. Technically this option is used as the third parameter in `.addEventListener(type, listener [, useCapture])` calls. The exact behavior is documented [here](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener). |
| singleScanQty | 1 | This is the quantity of items which gets returned on a single successful scan. |
| reactToKeydown | true | Look for scan input among `keydown` events (i.e. if the scanner works in keyboard-mode). |
| reactToPaste | false | Look for scan input among `paste` events (i.e. if the scanner works in clipboard-mode). |


## Events

| Event name | Parameters passed to listener | Description |
| ------ | ------- | ----------- |
| scan | sScanned, iQty | Triggered after successful scan. Handler arguments: <br> - `sScanned` - [string] scanned code <br> - `iQty` - [integer] quantity |
| scanButtonLongPress | | Triggered after the scan button was pressed and held down for a time defined in `scanButtonLongPressThreshold`. This can only be used if the scan button behaves as a key itself and the `scanButtonKeyCode` option is set. No arguments are passed to the handler. |
| scanError | oDebug | Triggered after a scanned string being dropped due to restrictions. Handler arguments: <br> - `oDebug` - [object] plain object with various debug data |

You can register regular event listeners on the DOM element, onScan was initialized for:

```javascript
document
.addEventListener('scan', function(sScanned, iQty){ ... });
.addEventListener('scanError', function(oDebug){ ... });
.addEventListener('scanButtonLongPressed', function(){ ... });
```

You can also define callback directly in the options, when initializing onScan:

```javascript
onScan.attachTo(document, {
onScan: function(sScanned, iQty) { ... },
onScanError: function(oDebug) { ... },
onScanButtonLongPress: function() { ... },
onKeyDetect: function(iKeyCode, oEvent){ ... }
onKeyProcess: function(sChar, oEvent){ ... }
onPaste: function(sPasted){ ... }
});
```

Note: there are more callbacks in the options, than event types. The non-event callbacks are primarily usefull for testing and finding the right configuration for a specific scanner - see playgournd for examples.

## Methods

| Method | Arguments | Description |
| ------ | --------- | ----------- |
| attachTo | DOMElement, oOptions | Initializes listening for scan events for given DOM element. Only events fired for this DOM element will be processed. Use `document` to process all possible events. This is the best pick in most cases. <br><br>NOTE: onScan.js can be attached to a DOM element only once. If you, for some reason, need to call `attachTo()` for a single element multiple times, you must call `detachFrom()` first. |
| detachFrom | DOMElement | Removes all scanner detection logic from the given DOM element. |
| simulate | DOMElement, mStringOrArray | Fires the `scan` event for the given scan code - usefull to trigger listeners manually (e.g. for testing). Accepts either an already decoded string or an array with key codes or event property objects - see below for details. |
| setOptions | DOMElement, oOptions | Replaces only the newly sent options. |
| getOptions | DOMElement | Retrieves entire oOptions object. |
| decodeKeyEvent | Event | Extracts the scanned string character from a keyboard event (i.e. `keydown`) |
| isAttachedTo | DOMElement | Returns `true` if onScan is attached to the given DOM element and `false` otherwise |
| isScanInProgressFor | DOMElement | Returns `true` the scanner is currently in the middle of a scan sequence and `false` otherwise. Technically, this means, that the scan sequence started (e.g. via prefix character) and has not ended yet (e.g. via suffix or timeout). This method is usefull inside event handlers. |

## Decoding key codes

By default, onScan.js ignores any key codes other than those matching letters and numbers. The latter are transformed into characters using built-in browser logic (i.e. the `event.key`). These [key codes](https://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes) are converted to characters:

- `48`-`90` (letters and regular numbers)
- `96`-`105` (numeric keypad numbers)
- `106`-`111` (numeric keypad operations)

This should work for the vast majority of cases. However, if you encounter strange extra characters in the codes read or miss some characters (like hypens), you can override the default decoding algorithm by specifying a custom `keyCodeMapper` like this:

```javascript
onScan.attachTo(document, {
onScan: function(sScanned, iQty) { ... },
keyCodeMapper: function(oEvent) {
// Look for special keycodes or other event properties specific to
// your scanner
if (oEvent.which = 'your_special_key_code') {
return 'xxx';
}
// Fall back to the default decoder in all other cases
return onScan.decodeKeyEvent(oEvent);
}
});
```

Background: Barcode scanners operating in keyboard-mode (as opposed to clipboard-mode) work by simulating pressing keyboard keys. They send numeric key codes and the browser interprets them as input. This works great for letters and numbers. However, many barcode scanners also send additional characters depending on their configuration: e.g. the trailing enter (key code `13`), prefix or suffix codes, delimiters, and even their own "virtual" key codes. There are also cases, when key codes are used in a non-standard way. All these cases can be easily treated using a custom `keyCodeMapper` as shown above.

### Simulating key codes

If you do not have your scanner at hand, you can simulate keyboard events programmatically via `onScan.simulate()`. You can pass the desired scan code in the following formats:

- a string - in this case no keyCode decoding is done and the code is merely validated against constraints like minLenght, etc.
- an array of keyCodes (e.g. `[70,71,80]`) - will produce `keydown` events with corresponding `keyCode` properties. NOTE: these events will have empty `key` properties, so decoding may yield different results than with native events.
- an array of objects (e.g. `[{keyCode: 70, key: "F", shiftKey: true}, {keyCode: 71, key: "g"}]`) - this way almost any event can be simulated exactly, but it's a lot of work to do.

Hint: use the `onKeyDetect` checkbox in the playground to get a full dump of each keyboard event an just paste them in your simulation code.

## Credits

This library was inspired by the jQuery plugin [jQuery ScannerDetection](https://github.com/iuyes/jQuery-Scanner-Detection) by Julien Maurel.

## History

See [HISTORY.md](https://github.com/axenox/onscan.js/blob/master/HISTORY.md).

## License

onScan.js is an open source project licensed under MIT.

+ 20
- 0
node_modules/onscan/bower.json Bestand weergeven

@@ -0,0 +1,20 @@
{
"name": "onscan-js",
"homepage": "https://github.com/axenox/onscan.js/issues",
"description": "Framework agnostic onScan event fired when using hardware barcode scanners",
"main": "onscan.js",
"license": "MIT",
"authors": [
"Andrej Kabachnik",
"Thomas Michael"
],
"keywords": ["barcode", "RFID", "scanner", "scan"],
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
]
}

+ 428
- 0
node_modules/onscan/index.html Bestand weergeven

@@ -0,0 +1,428 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="onscan.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-dark bg-dark" style="margin-bottom: 20px">
<span class="navbar-brand mb-0 h1">onScan.js Playground</span>
</nav>
<div class="container">
<form id="playground" class="form-horizontal">
<div class="row">
<div class="col-12 col-xs-12">
<textarea style="margin: 5px 5px 0 5px" id="consoleTextField" readonly="readonly" class="form-control" rows="10"></textarea>
</div>
</div>
<div class="row">
<div class="col-12 col-xs-12">
<input style="margin: 5px 5px 0 5px" type="button" id="clearTextArea" class="btn btn-light btn-default" onclick="javascript:document.getElementById('consoleTextField').value = '';" value="Clear Console Log" />
</div>
</div>
<div class="row">
<div class="col-12 col-xs-12">
<h3>Methods</h3>
</div>
</div>
<div class="row">
<div class="col-12 col-xs-12 col-md-5">
<div style="margin: 5px 5px 0 5px" class="input-group mb-3">
<input id="iTestInput" class="form-control" placeholder="Enter scan code or [key,key,...]" title="Scan code as string or [keyCode,keyCode,...]" />
<div class="input-group-append input-group-btn">
<input type="button" class="btn btn-primary" id="bFireTestInput" onclick="fireTestInput()" value="simulate()">
</div>
</div>
</div>
<div class="col-12 col-xs-12 col-md-7">
<input style="margin: 5px 5px 0 5px" type="button" id="bGenerateonScan" class="btn btn-primary" onclick="initOnScan()" value="attachTo(document)" />
<input style="margin: 5px 5px 0 5px" type="button" id="bDestroyonScan" class="btn btn-primary" onclick="destroyOnScan()" value="detachFrom(document)" />
<input style="margin: 5px 5px 0 5px" type="button" id="bGgetonScanSettings" class="btn btn-primary" onclick="getonScanSettings()" value="getOptions()" />
</div>
</div>
<div class="row">
<div class="col-12 col-xs-12 col-md-6">
<h3>Mode</h3>
<div class="form-group row">
<label class="control-label col-9 col-xs-9 col-sm-7 col-lg-6">reactToKeydown:</label>
<div class="col-3 col-xs-3 col-sm-5 checkbox form-check">
<input id="iAcceptKeyInput" type="checkbox" checked="checked"/>
</div>
</div>
<div class="form-group row">
<label class="control-label col-9 col-xs-9 col-sm-7 col-lg-6">reactToPaste:</label>
<div class="col-3 col-xs-3 col-sm-5 checkbox form-check">
<input id="iAcceptPasteInput" type="checkbox" checked="checked"/>
</div>
</div>
<h3>Events / Callbacks</h3>
<div class="form-group row">
<label class="control-label col-9 col-xs-9 col-sm-7 col-lg-6">onScan:</label>
<div class="col-3 col-xs-3 col-sm-5 checkbox form-check">
<input id="iOnComplete" type="checkbox" checked="checked"/>
</div>
</div>
<div class="form-group row">
<label class="control-label col-9 col-xs-9 col-sm-7 col-lg-6">onScanButtonLongPress:</label>
<div class="col-3 col-xs-3 col-sm-5 checkbox form-check">
<input id="iOnScanButtonLongPressed" type="checkbox" />
</div>
</div>
<div class="form-group row">
<label class="control-label col-9 col-xs-9 col-sm-7 col-lg-6">onScanError:</label>
<div class="col-3 col-xs-3 col-sm-5 checkbox form-check">
<input id="iOnError" type="checkbox" />
</div>
</div>
<div class="form-group row">
<label class="control-label col-9 col-xs-9 col-sm-7 col-lg-6">onKeyDetect:</label>
<div class="col-3 col-xs-3 col-sm-5 checkbox form-check">
<input id="iOnKeyDetect" type="checkbox" />
</div>
</div>
<div class="form-group row">
<label class="control-label col-9 col-xs-9 col-sm-7 col-lg-6">onKeyProcess:</label>
<div class="col-3 col-xs-3 col-sm-5 checkbox form-check">
<input id="iOnKeyProcessed" type="checkbox" />
</div>
</div>
<div class="form-group row">
<label class="control-label col-9 col-xs-9 col-sm-7 col-lg-6">onPaste:</label>
<div class="col-3 col-xs-3 col-sm-5 checkbox form-check">
<input id="iOnPaste" type="checkbox" />
</div>
</div>
<div class="form-group row">
<label class="control-label col-9 col-xs-9 col-sm-7 col-lg-6">Use event handlers, not callbacks:</label>
<div class="col-3 col-xs-3 col-sm-5 checkbox form-check">
<input id="iCompleteHandler" type="checkbox" />
</div>
</div>
</div>
<div class="col-12 col-xs-12 col-md-6">
<h3>Options</h3>
<div class="form-group row">
<label class="control-label col-12 col-xs-12 col-sm-7 col-lg-6">timeBeforeScanTest:</label>
<div class="col-12 col-xs-12 col-sm-5">
<input id="iTimeBeforeScanTest" class="form-control" value="100" />
</div>
</div>
<div class="form-group row">
<label class="control-label col-12 col-xs-12 col-sm-7 col-lg-6">avgTimeByChar:</label>
<div class="col-12 col-xs-12 col-sm-5">
<input id="iAvgTimeByChar" class="form-control" value="30" />
</div>
</div>
<div class="form-group row">
<label class="control-label col-12 col-xs-12 col-sm-7 col-lg-6">minLength:</label>
<div class="col-12 col-xs-12 col-sm-5">
<input id="iMinLength" class="form-control" value="6" />
</div>
</div>
<div class="form-group row">
<label class="control-label col-12 col-xs-12 col-sm-7 col-lg-6">suffixKeyCodes:</label>
<div class="col-12 col-xs-12 col-sm-5">
<input id="iEndChar" class="form-control" value="9,13" />
</div>
</div>
<div class="form-group row">
<label class="control-label col-12 col-xs-12 col-sm-7 col-lg-6">prefixKeyCodes:</label>
<div class="col-12 col-xs-12 col-sm-5">
<input id="iStartChar" class="form-control" value="" />
</div>
</div>
<div class="form-group row">
<label class="control-label col-9 col-xs-9 col-sm-7 col-lg-6">ignoreIfFocusOn:</label>
<div class="col-12 col-xs-12 col-sm-5">
<div class="input-group">
<div class="input-group-prepend input-group-addon">
<div class="input-group-text">
<input id="iIgnoreIfFocusOn" type="checkbox" />
</div>
</div>
<input id="iIgnoreIfFocusOnSelector" class="form-control" value="input" />
</div>
</div>
</div>
<div class="form-group row">
<label class="control-label col-12 col-xs-12 col-sm-7 col-lg-6">scanButtonKeyCode:</label>
<div class="col-12 col-xs-12 col-sm-5">
<input id="iScanButtonKeyCode" class="form-control" value="" />
</div>
</div>
<div class="form-group row">
<label class="control-label col-12 col-xs-12 col-sm-7 col-lg-6">scanButtonLongPressTime:</label>
<div class="col-12 col-xs-12 col-sm-5">
<input id="iScanButtonLongPressThreshold" class="form-control" value="500" />
</div>
</div>
<div class="form-group row">
<label class="control-label col-12 col-xs-12 col-sm-7 col-lg-6">singleScanQty:</label>
<div class="col-12 col-xs-12 col-sm-5">
<input id="iSingleScanQty" class="form-control" value="1" />
</div>
</div>
<div class="form-group row">
<label class="control-label col-9 col-xs-9 col-sm-7 col-lg-6">keyCodeMapper:</label>
<div class="col-3 col-xs-3 col-sm-5 checkbox form-check">
<input id="ikeyCodeMapper" type="checkbox" />
</div>
</div>
<div class="form-group row">
<label class="control-label col-9 col-xs-9 col-sm-7 col-lg-6">stopPropagation:</label>
<div class="col-3 col-xs-3 col-sm-5 checkbox form-check">
<input id="iStopPropagation" type="checkbox" />
</div>
</div>
<div class="form-group row">
<label class="control-label col-9 col-xs-9 col-sm-7 col-lg-6">preventDefault:</label>
<div class="col-3 col-xs-3 col-sm-5 checkbox form-check">
<input id="iPreventDefault" type="checkbox" />
</div>
</div>
</div>
</div>
</form>
</div>
<script type="text/javascript">

if (typeof console != "undefined")
if (typeof console.log != 'undefined')
console.olog = console.log;
else
console.olog = function() {};

console.log = function(message, error) {
console.olog(message);
var oOutput = document.getElementById('consoleTextField');
if (error){
oOutput.value += "ERROR: " + message + '\n';
} else {
oOutput.value += ('> ' + message + '\n');
}
oOutput.scrollTop = oOutput.scrollHeight;
};
console.error = console.debug = console.info = console.log;

window.onerror = function(msg){
console.log(msg, true);
}
function initOnScan(){
var prop;
var array;
var suffixKeyCodes = [];
var prefixKeyCodes = [];
if (document.getElementById("iEndChar").value){
array = document.getElementById("iEndChar").value.split(",");
for (prop in array)
suffixKeyCodes.push(parseInt(array[prop]));
// suffixKeyCodes.push(parseInt(prop));
}
if (document.getElementById("iStartChar").value){
array = document.getElementById("iStartChar").value.split(",")
for (prop in document.getElementById("iStartChar").value.split(","))
prefixKeyCodes.push(parseInt(array[prop]));
}
var options = {
timeBeforeScanTest: parseInt(document.getElementById("iTimeBeforeScanTest").value),
avgTimeByChar: parseInt(document.getElementById("iAvgTimeByChar").value),
minLength: parseInt(document.getElementById("iMinLength").value),
suffixKeyCodes: suffixKeyCodes,
prefixKeyCodes: prefixKeyCodes,
scanButtonLongPressTime: parseInt(document.getElementById("iScanButtonLongPressThreshold").value),
stopPropagation: document.getElementById("iStopPropagation").checked,
preventDefault: document.getElementById("iPreventDefault").checked,
reactToPaste: document.getElementById("iAcceptPasteInput").checked,
reactToKeyDown: document.getElementById("iAcceptKeyInput").checked,
singleScanQty: parseInt(document.getElementById("iSingleScanQty").value)
}
if (document.getElementById("iOnComplete").checked){
options.onScan = function(barcode, qty){
console.log("[onScan]: Code: " + barcode + " Quantity: " + qty);
};
} else {
options.onScan = function(){};
}
if (document.getElementById("iOnError").checked){
options.onScanError = function(err){
var sFormatedErrorString = "Error Details: {\n";
for (var i in err){
sFormatedErrorString += ' ' + i + ': ' + err[i] + ",\n";
}
sFormatedErrorString = sFormatedErrorString.trim().replace(/,$/, '') + "\n}";
console.log("[onScanError]: " + sFormatedErrorString);
};
} else {
options.onScanError = function(){};
}
if (document.getElementById("iOnKeyProcessed").checked){
options.onKeyProcess = function(sChar, oEvent){
console.log('[onKeyProcess]: Processed character "' + sChar + '"');
};
} else {
options.onKeyProcess = function(){};
}
if (document.getElementById("iOnKeyDetect").checked){
options.onKeyDetect = function(iKey, oEvent){
var oEventProps = ''
+ 'key:"' + oEvent.key + '", '
+ 'ctrlKey:' + oEvent.ctrlKey + ', '
+ 'altKey:' + oEvent.altKey + ', '
+ 'shiftKey:' + oEvent.shiftKey + ', '
+ 'metaKey:' + oEvent.metaKey + ', '
+ 'keyCode:' + oEvent.keyCode + ', '
+ 'charCode:' + oEvent.charCode + ', ';
console.log('[onKeyDetect]: Detected key code "' + iKey + '". Event dump: ' + oEventProps);
};
} else {
options.onKeyDetect = function(){};
}
if (document.getElementById("iIgnoreIfFocusOn").checked){
document.getElementById("iIgnoreIfFocusOnSelector").removeAttribute("disabled");
options.ignoreIfFocusOn = document.getElementById("iIgnoreIfFocusOnSelector").value;
} else {
options.ignoreIfFocusOn = false;
document.getElementById("iIgnoreIfFocusOnSelector").disabled = "disabled";
}
if (document.getElementById("iScanButtonKeyCode").value){
options.scanButtonKeyCode = parseInt(document.getElementById("iScanButtonKeyCode").value);
} else {
options.scanButtonKeyCode = false;
}
if (document.getElementById("iOnScanButtonLongPressed").checked){
options.onScanButtonLongPress = function(){
console.log("[onScanButtonLongPress]: ScanButton has been long-pressed");
};
} else {
options.onScanButtonLongPress = function(){};
}
if (document.getElementById("iOnPaste").checked){
options.onPaste = function(sPasteString){
console.log("[onPaste]: Data has been pasted: " + sPasteString);
}
} else {
options.onPaste = function(){};
}
if (document.getElementById("iCompleteHandler").checked){
document.addEventListener('scan', scanHandler);
} else {
document.removeEventListener('scan', scanHandler);
}
if (document.getElementById("iCompleteHandler").checked){
document.addEventListener('scanError', scanErrorHandler);
} else {
document.removeEventListener('scanError', scanErrorHandler);
}
if (document.getElementById("ikeyCodeMapper").checked){
options.keyCodeMapper = function (e) {
var iKeyCode = e.which;
var sChar = onScan.decodeKeyEvent(e);
console.log('[keyCodeMapper]: Decoding key code "' + iKeyCode + '" to "' + sChar + '"')
return sChar;
}
}
try {
onScan.attachTo(document, options);
console.log("onScan Started!");
} catch(e) {
onScan.setOptions(document, options);
console.log("onScansettings changed!");
}

}
function destroyOnScan(){
console.log("onScan destroyed!");
onScan.detachFrom(document);
}
function clearTextArea(){
document.getElementById('consoleTextField').value = "";
}
function scanHandler(e){
console.log("[scanHandler]: Code: " + e.detail.code);
}
function scanErrorHandler(e){
var sFormatedErrorString = "Error Details: {\n";
for (var i in e.detail){
sFormatedErrorString += ' ' + i + ': ' + e.detail[i] + ",\n";
}
sFormatedErrorString = sFormatedErrorString.trim().replace(/,$/, '') + "\n}";
console.log("[scanErrorHandler]: " + sFormatedErrorString);
}
function getonScanSettings(){
var sFormatedErrorString = "Scanner Settings: \n";
var aJSONArray = JSON.stringify(onScan.getOptions(document)).split(",");
for (prop = 0; prop < aJSONArray.length - 1; prop++){
if (aJSONArray[prop+1][0] == '\"'){
sFormatedErrorString += aJSONArray[prop] + "," + "\n";
} else {
sFormatedErrorString += aJSONArray[prop] + ",";
}
}
sFormatedErrorString += aJSONArray[aJSONArray.length - 1];
console.log(sFormatedErrorString);
}
function fireTestInput(){
var sInput = (document.getElementById("iTestInput").value || '').trim();
if (sInput.startsWith('[') && sInput.endsWith(']')) {
onScan.simulate(document, JSON.parse(sInput));
} else {
onScan.simulate(document, sInput);
}
}
(function(){
initOnScan();
document.querySelectorAll("#playground input").forEach(function(oInput){
if (oInput.type == 'button' || oInput.readonly) {
return;
}
oInput.addEventListener('change', function(){
console.log('onScan configuration updated');
onScan.detachFrom(document);
initOnScan();
});
});
})();
</script>


</body>
</html>

+ 526
- 0
node_modules/onscan/onscan.js Bestand weergeven

@@ -0,0 +1,526 @@
/*
* onScan.js - scan-events for hardware barcodes scanners in javascript
*/
;(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory()) :
global.onScan = factory()
}(this, (function () {
var onScan = {
/**
*
* @param DomElement oDomElement
* @param Object oOptions
* @return self
*/
attachTo: function(oDomElement, oOptions) {
if(oDomElement.scannerDetectionData !== undefined){
throw new Error("onScan.js is already initialized for DOM element " + oDomElement);
}
var oDefaults = {
onScan: function(sScanned, iQty){}, // Callback after detection of a successfull scanning: function(){sScancode, iCount)}()
onScanError: function(oDebug){}, // Callback after detection of a unsuccessfull scanning (scanned string in parameter)
onKeyProcess: function(sChar, oEvent){}, // Callback after receiving and processing a char (scanned char in parameter)
onKeyDetect: function(iKeyCode, oEvent){}, // Callback after detecting a keyDown (key char in parameter) - in contrast to onKeyProcess, this fires for non-character keys like tab, arrows, etc. too!
onPaste: function(sPasted, oEvent){}, // Callback after receiving a value on paste, no matter if it is a valid code or not
keyCodeMapper: function(oEvent) {return onScan.decodeKeyEvent(oEvent)}, // Custom function to decode a keydown event into a character. Must return decoded character or NULL if the given event should not be processed.
onScanButtonLongPress: function(){}, // Callback after detection of a successfull scan while the scan button was pressed and held down
scanButtonKeyCode:false, // Key code of the scanner hardware button (if the scanner button a acts as a key itself)
scanButtonLongPressTime:500, // How long (ms) the hardware button should be pressed, until a callback gets executed
timeBeforeScanTest:100, // Wait duration (ms) after keypress event to check if scanning is finished
avgTimeByChar:30, // Average time (ms) between 2 chars. Used to do difference between keyboard typing and scanning
minLength:6, // Minimum length for a scanning
suffixKeyCodes:[9,13], // Chars to remove and means end of scanning
prefixKeyCodes:[], // Chars to remove and means start of scanning
ignoreIfFocusOn:false, // do not handle scans if the currently focused element matches this selector or object
stopPropagation:false, // Stop immediate propagation on keypress event
preventDefault:false, // Prevent default action on keypress event
captureEvents:false, // Get the events before any listeners deeper in the DOM
reactToKeydown:true, // look for scan input in keyboard events
reactToPaste:false, // look for scan input in paste events
singleScanQty: 1, // Quantity of Items put out to onScan in a single scan
}
oOptions = this._mergeOptions(oDefaults, oOptions);
// initializing options and variables on DomElement
oDomElement.scannerDetectionData = {
options: oOptions,
vars:{
firstCharTime: 0,
lastCharTime: 0,
accumulatedString: '',
testTimer: false,
longPressTimeStart: 0,
longPressed: false
}
};
// initializing handlers (based on settings)
if (oOptions.reactToPaste === true){
oDomElement.addEventListener("paste", this._handlePaste, oOptions.captureEvents);
}
if (oOptions.scanButtonKeyCode !== false){
oDomElement.addEventListener("keyup", this._handleKeyUp, oOptions.captureEvents);
}
if (oOptions.reactToKeydown === true || oOptions.scanButtonKeyCode !== false){
oDomElement.addEventListener("keydown", this._handleKeyDown, oOptions.captureEvents);
}
return this;
},
/**
*
* @param DomElement oDomElement
* @return void
*/
detachFrom: function(oDomElement) {
// detaching all used events
if (oDomElement.scannerDetectionData.options.reactToPaste){
oDomElement.removeEventListener("paste", this._handlePaste);
}
if (oDomElement.scannerDetectionData.options.scanButtonKeyCode !== false){
oDomElement.removeEventListener("keyup", this._handleKeyUp);
}
oDomElement.removeEventListener("keydown", this._handleKeyDown);
// clearing data off DomElement
oDomElement.scannerDetectionData = undefined;
return;
},
/**
*
* @param DomElement oDomElement
* @return Object
*/
getOptions: function(oDomElement){
return oDomElement.scannerDetectionData.options;
},
/**
*
* @param DomElement oDomElement
* @param Object oOptions
* @return self
*/
setOptions: function(oDomElement, oOptions){
// check if some handlers need to be changed based on possible option changes
switch (oDomElement.scannerDetectionData.options.reactToPaste){
case true:
if (oOptions.reactToPaste === false){
oDomElement.removeEventListener("paste", this._handlePaste);
}
break;
case false:
if (oOptions.reactToPaste === true){
oDomElement.addEventListener("paste", this._handlePaste);
}
break;
}
switch (oDomElement.scannerDetectionData.options.scanButtonKeyCode){
case false:
if (oOptions.scanButtonKeyCode !== false){
oDomElement.addEventListener("keyup", this._handleKeyUp);
}
break;
default:
if (oOptions.scanButtonKeyCode === false){
oDomElement.removeEventListener("keyup", this._handleKeyUp);
}
break;
}
// merge old and new options
oDomElement.scannerDetectionData.options = this._mergeOptions(oDomElement.scannerDetectionData.options, oOptions);
// reinitiallize
this._reinitialize(oDomElement);
return this;
},
/**
* Transforms key codes into characters.
*
* By default, only the follwing key codes are taken into account
* - 48-90 (letters and regular numbers)
* - 96-105 (numeric keypad numbers)
* - 106-111 (numeric keypad operations)
*
* All other keys will yield empty strings!
*
* The above keycodes will be decoded using the KeyboardEvent.key property on modern
* browsers. On older browsers the method will fall back to String.fromCharCode()
* putting the result to upper/lower case depending on KeyboardEvent.shiftKey if
* it is set.
*
* @param KeyboardEvent oEvent
* @return string
*/
decodeKeyEvent : function (oEvent) {
var iCode = this._getNormalizedKeyNum(oEvent);
switch (true) {
case iCode >= 48 && iCode <= 90: // numbers and letters
case iCode >= 106 && iCode <= 111: // operations on numeric keypad (+, -, etc.)
if (oEvent.key !== undefined && oEvent.key !== '') {
return oEvent.key;
}
var sDecoded = String.fromCharCode(iCode);
switch (oEvent.shiftKey) {
case false: sDecoded = sDecoded.toLowerCase(); break;
case true: sDecoded = sDecoded.toUpperCase(); break;
}
return sDecoded;
case iCode >= 96 && iCode <= 105: // numbers on numeric keypad
return 0+(iCode-96);
}
return '';
},
/**
* Simulates a scan of the provided code.
*
* The scan code can be defined as
* - a string - in this case no keyCode decoding is done and the code is merely validated
* against constraints like minLenght, etc.
* - an array of keyCodes (e.g. `[70,71,80]`) - will produce `keydown` events with corresponding
* `keyCode` properties. NOTE: these events will have empty `key` properties, so decoding may
* yield different results than with native events.
* - an array of objects (e.g. `[{keyCode: 70, key: "F", shiftKey: true}, {keyCode: 71, key: "g"}]`) -
* this way almost any event can be simulated, but it's a lot of work to do.
*
* @param DomElement oDomElement
* @param string|array mStringOrArray
* @return self
*/
simulate: function(oDomElement, mStringOrArray){
this._reinitialize(oDomElement);
if (Array.isArray(mStringOrArray)){
mStringOrArray.forEach(function(mKey){
var oEventProps = {};
if( (typeof mKey === "object" || typeof mKey === 'function') && (mKey !== null) ) {
oEventProps = mKey;
} else {
oEventProps.keyCode = parseInt(mKey);
}
var oEvent = new KeyboardEvent('keydown', oEventProps);
document.dispatchEvent(oEvent);
})
} else {
this._validateScanCode(oDomElement, mStringOrArray);
}
return this;
},
/**
* @private
* @param DomElement oDomElement
* @return void
*/
_reinitialize: function(oDomElement){
var oVars = oDomElement.scannerDetectionData.vars;
oVars.firstCharTime = 0;
oVars.lastCharTime = 0;
oVars.accumulatedString = '';
return;
},
/**
* @private
* @param DomElement oDomElement
* @return boolean
*/
_isFocusOnIgnoredElement: function(oDomElement){
var ignoreSelectors = oDomElement.scannerDetectionData.options.ignoreIfFocusOn;
if(!ignoreSelectors){
return false;
}
var oFocused = document.activeElement;
// checks if ignored element is an array, and if so it checks if one of the elements of it is an active one
if (Array.isArray(ignoreSelectors)){
for(var i=0; i<ignoreSelectors.length; i++){
if(oFocused.matches(ignoreSelectors[i]) === true){
return true;
}
}
// if the option consists of an single element, it only checks this one
} else if (oFocused.matches(ignoreSelectors)){
return true;
}
// if the active element is not listed in the ignoreIfFocusOn option, return false
return false;
},
/**
* Validates the scan code accumulated by the given DOM element and fires the respective events.
*
* @private
* @param DomElement oDomElement
* @return boolean
*/
_validateScanCode: function(oDomElement, sScanCode){
var oScannerData = oDomElement.scannerDetectionData;
var oOptions = oScannerData.options;
var iSingleScanQty = oScannerData.options.singleScanQty;
var iFirstCharTime = oScannerData.vars.firstCharTime;
var iLastCharTime = oScannerData.vars.lastCharTime;
var oScanError = {};
var oEvent;
switch(true){
// detect codes that are too short
case (sScanCode.length < oOptions.minLength):
oScanError = {
message: "Receieved code is shorter then minimal length"
};
break;
// detect codes that were entered too slow
case ((iLastCharTime - iFirstCharTime) > (sScanCode.length * oOptions.avgTimeByChar)):
oScanError = {
message: "Receieved code was not entered in time"
};
break;
// if a code was not filtered out earlier it is valid
default:
oOptions.onScan.call(oDomElement, sScanCode, iSingleScanQty);
oEvent = new CustomEvent(
'scan',
{
detail: {
scanCode: sScanCode,
qty: iSingleScanQty
}
}
);
oDomElement.dispatchEvent(oEvent);
onScan._reinitialize(oDomElement);
return true;
}
// If an error occurred (otherwise the method would return earlier) create an object for errordetection
oScanError.scanCode = sScanCode;
oScanError.scanDuration = iLastCharTime - iFirstCharTime;
oScanError.avgTimeByChar = oOptions.avgTimeByChar;
oScanError.minLength = oOptions.minLength;
oOptions.onScanError.call(oDomElement, oScanError);
oEvent = new CustomEvent(
'scanError',
{detail: oScanError}
);
oDomElement.dispatchEvent(oEvent);
onScan._reinitialize(oDomElement);
return false;
},
/**
* @private
* @param Object oDefaults
* @param Object oOptions
* @return Object
*/
_mergeOptions: function(oDefaults, oOptions){
var oExtended = {};
var prop;
for (prop in oDefaults){
if (Object.prototype.hasOwnProperty.call(oDefaults, prop)){
oExtended[prop] = oDefaults[prop];
}
}
for (prop in oOptions){
if (Object.prototype.hasOwnProperty.call(oOptions, prop)){
oExtended[prop] = oOptions[prop];
}
}
return oExtended;
},
/**
* @private
* @param KeyboardEvent e
* @return int
* @see https://www.w3schools.com/jsref/event_key_keycode.asp
*/
_getNormalizedKeyNum: function(e){
return e.which || e.keyCode;
},
/**
* @private
* @param KeyboardEvent e
* @return void
*/
_handleKeyDown: function(e){
var iKeyCode = onScan._getNormalizedKeyNum(e);
var oOptions = this.scannerDetectionData.options;
var oVars = this.scannerDetectionData.vars;
var bScanFinished = false;
if (oOptions.onKeyDetect.call(this, iKeyCode, e) === false) {
return;
}
if (onScan._isFocusOnIgnoredElement(this)){
return;
}
// If it's just the button of the scanner, ignore it and wait for the real input
if(oOptions.scanButtonKeyCode !== false && iKeyCode==oOptions.scanButtonKeyCode) {
// if the button was first pressed, start a timeout for the callback, which gets interrupted if the scanbutton gets released
if (!oVars.longPressed){
oVars.longPressTimer = setTimeout( oOptions.onScanButtonLongPress, oOptions.scanButtonLongPressTime, this);
oVars.longPressed = true;
}
return;
}
switch(true){
// If it's not the first character and we encounter a terminating character, trigger scan process
case (oVars.firstCharTime && oOptions.suffixKeyCodes.indexOf(iKeyCode)!==-1):
e.preventDefault();
e.stopImmediatePropagation();
bScanFinished=true;
break;
// If it's the first character and we encountered one of the starting characters, don't process the scan
case (!oVars.firstCharTime && oOptions.prefixKeyCodes.indexOf(iKeyCode)!==-1):
e.preventDefault();
e.stopImmediatePropagation();
bScanFinished=false;
break;
// Otherwise, just add the character to the scan string we're building
default:
var character = oOptions.keyCodeMapper.call(this, e);
if (character === null){
return;
}
oVars.accumulatedString += character;
if (oOptions.preventDefault) {
e.preventDefault();
}
if (oOptions.stopPropagation) {
e.stopImmediatePropagation();
}
bScanFinished=false;
break;
}
if(!oVars.firstCharTime){
oVars.firstCharTime=Date.now();
}
oVars.lastCharTime=Date.now();
if(oVars.testTimer){
clearTimeout(oVars.testTimer);
}
if(bScanFinished){
onScan._validateScanCode(this, oVars.accumulatedString);
oVars.testTimer=false;
} else {
oVars.testTimer=setTimeout(onScan._validateScanCode, oOptions.timeBeforeScanTest, this, oVars.accumulatedString);
}
oOptions.onKeyProcess.call(this, character, e);
return;
},
/**
* @private
* @param Event e
* @return void
*/
_handlePaste: function(e){
var oOptions = this.scannerDetectionData.options;
var oVars = this.scannerDetectionData.vars;
var sPasteString = (event.clipboardData || window.clipboardData).getData('text');
// if the focus is on an ignored element, abort
if (onScan._isFocusOnIgnoredElement(this)){
return;
}
e.preventDefault();

if (oOptions.stopPropagation) {
e.stopImmediatePropagation();
}
oOptions.onPaste.call(this, sPasteString, event);
oVars.firstCharTime = 0;
oVars.lastCharTime = 0;
// validate the string
onScan._validateScanCode(this, sPasteString);
return;
},
/**
* @private
* @param KeyboardEvent e
* @return void
*/
_handleKeyUp: function(e){
// if the focus is on an ignored element, abort
if (onScan._isFocusOnIgnoredElement(this)){
return;
}
var iKeyCode = onScan._getNormalizedKeyNum(e);
// if hardware key is not being pressed anymore stop the timeout and reset
if (iKeyCode == this.scannerDetectionData.options.scanButtonKeyCode){
clearTimeout(this.scannerDetectionData.vars.longPressTimer);
this.scannerDetectionData.vars.longPressed = false;
}
return;
},
/**
* Returns TRUE the scanner is currently in the middle of a scan sequence.
*
* @param DomElement
* @return boolean
*/
isScanInProgressFor: function(oDomElement) {
return oDomElement.scannerDetectionData.vars.firstCharTime > 0;
},
/**
* Returns TRUE if onScan is attached to the given DOM element and FALSE otherwise.
*
* @param DomElement
* @return boolean
*/
isAttachedTo: function(oDomElement) {
return (oDomElement.scannerDetectionData !== undefined);
}
};
return onScan;
})));

+ 5
- 0
node_modules/onscan/onscan.min.js
Diff onderdrukt omdat het te groot bestand
Bestand weergeven


+ 21
- 0
node_modules/onscan/package.json Bestand weergeven

@@ -0,0 +1,21 @@
{
"name": "onscan.js",
"version": "1.5.2",
"description": "Framework agnostic onScan event fired when using hardware barcode scanners",
"main": "onscan.js",
"repository": {
"type": "git",
"url": "https://github.com/axenox/onscan.js.git"
},
"keywords": ["barcode", "RFID", "scanner", "scan"],
"author": "Andrej Kabachnik",
"contributors": [
"Andrej Kabachnik",
"Thomas Michael"
],
"license": "MIT",
"bugs": {
"url": "https://github.com/axenox/onscan.js/issues"
},
"homepage": "https://github.com/axenox/onscan.js/"
}

+ 24
- 0
package-lock.json Bestand weergeven

@@ -0,0 +1,24 @@
{
"name": "TBMS",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"dependencies": {
"onscan.js": "^1.5.2"
}
},
"node_modules/onscan.js": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/onscan.js/-/onscan.js-1.5.2.tgz",
"integrity": "sha512-9oGYy2gXYRjvXO9GYqqVca0VuCTAmWhbmX3egBSBP13rXiMNb+dKPJzKFEeECGqPBpf0m40Zoo+GUQ7eCackdw=="
}
},
"dependencies": {
"onscan.js": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/onscan.js/-/onscan.js-1.5.2.tgz",
"integrity": "sha512-9oGYy2gXYRjvXO9GYqqVca0VuCTAmWhbmX3egBSBP13rXiMNb+dKPJzKFEeECGqPBpf0m40Zoo+GUQ7eCackdw=="
}
}
}

+ 5
- 0
package.json Bestand weergeven

@@ -0,0 +1,5 @@
{
"dependencies": {
"onscan.js": "^1.5.2"
}
}

+ 526
- 0
src/main/webapp/resources/js/onscan.js Bestand weergeven

@@ -0,0 +1,526 @@
/*
* onScan.js - scan-events for hardware barcodes scanners in javascript
*/
;(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory()) :
global.onScan = factory()
}(this, (function () {
var onScan = {
/**
*
* @param DomElement oDomElement
* @param Object oOptions
* @return self
*/
attachTo: function(oDomElement, oOptions) {
if(oDomElement.scannerDetectionData !== undefined){
throw new Error("onScan.js is already initialized for DOM element " + oDomElement);
}
var oDefaults = {
onScan: function(sScanned, iQty){}, // Callback after detection of a successfull scanning: function(){sScancode, iCount)}()
onScanError: function(oDebug){}, // Callback after detection of a unsuccessfull scanning (scanned string in parameter)
onKeyProcess: function(sChar, oEvent){}, // Callback after receiving and processing a char (scanned char in parameter)
onKeyDetect: function(iKeyCode, oEvent){}, // Callback after detecting a keyDown (key char in parameter) - in contrast to onKeyProcess, this fires for non-character keys like tab, arrows, etc. too!
onPaste: function(sPasted, oEvent){}, // Callback after receiving a value on paste, no matter if it is a valid code or not
keyCodeMapper: function(oEvent) {return onScan.decodeKeyEvent(oEvent)}, // Custom function to decode a keydown event into a character. Must return decoded character or NULL if the given event should not be processed.
onScanButtonLongPress: function(){}, // Callback after detection of a successfull scan while the scan button was pressed and held down
scanButtonKeyCode:false, // Key code of the scanner hardware button (if the scanner button a acts as a key itself)
scanButtonLongPressTime:500, // How long (ms) the hardware button should be pressed, until a callback gets executed
timeBeforeScanTest:100, // Wait duration (ms) after keypress event to check if scanning is finished
avgTimeByChar:30, // Average time (ms) between 2 chars. Used to do difference between keyboard typing and scanning
minLength:6, // Minimum length for a scanning
suffixKeyCodes:[9,13], // Chars to remove and means end of scanning
prefixKeyCodes:[], // Chars to remove and means start of scanning
ignoreIfFocusOn:false, // do not handle scans if the currently focused element matches this selector or object
stopPropagation:false, // Stop immediate propagation on keypress event
preventDefault:false, // Prevent default action on keypress event
captureEvents:false, // Get the events before any listeners deeper in the DOM
reactToKeydown:true, // look for scan input in keyboard events
reactToPaste:false, // look for scan input in paste events
singleScanQty: 1, // Quantity of Items put out to onScan in a single scan
}
oOptions = this._mergeOptions(oDefaults, oOptions);
// initializing options and variables on DomElement
oDomElement.scannerDetectionData = {
options: oOptions,
vars:{
firstCharTime: 0,
lastCharTime: 0,
accumulatedString: '',
testTimer: false,
longPressTimeStart: 0,
longPressed: false
}
};
// initializing handlers (based on settings)
if (oOptions.reactToPaste === true){
oDomElement.addEventListener("paste", this._handlePaste, oOptions.captureEvents);
}
if (oOptions.scanButtonKeyCode !== false){
oDomElement.addEventListener("keyup", this._handleKeyUp, oOptions.captureEvents);
}
if (oOptions.reactToKeydown === true || oOptions.scanButtonKeyCode !== false){
oDomElement.addEventListener("keydown", this._handleKeyDown, oOptions.captureEvents);
}
return this;
},
/**
*
* @param DomElement oDomElement
* @return void
*/
detachFrom: function(oDomElement) {
// detaching all used events
if (oDomElement.scannerDetectionData.options.reactToPaste){
oDomElement.removeEventListener("paste", this._handlePaste);
}
if (oDomElement.scannerDetectionData.options.scanButtonKeyCode !== false){
oDomElement.removeEventListener("keyup", this._handleKeyUp);
}
oDomElement.removeEventListener("keydown", this._handleKeyDown);
// clearing data off DomElement
oDomElement.scannerDetectionData = undefined;
return;
},
/**
*
* @param DomElement oDomElement
* @return Object
*/
getOptions: function(oDomElement){
return oDomElement.scannerDetectionData.options;
},
/**
*
* @param DomElement oDomElement
* @param Object oOptions
* @return self
*/
setOptions: function(oDomElement, oOptions){
// check if some handlers need to be changed based on possible option changes
switch (oDomElement.scannerDetectionData.options.reactToPaste){
case true:
if (oOptions.reactToPaste === false){
oDomElement.removeEventListener("paste", this._handlePaste);
}
break;
case false:
if (oOptions.reactToPaste === true){
oDomElement.addEventListener("paste", this._handlePaste);
}
break;
}
switch (oDomElement.scannerDetectionData.options.scanButtonKeyCode){
case false:
if (oOptions.scanButtonKeyCode !== false){
oDomElement.addEventListener("keyup", this._handleKeyUp);
}
break;
default:
if (oOptions.scanButtonKeyCode === false){
oDomElement.removeEventListener("keyup", this._handleKeyUp);
}
break;
}
// merge old and new options
oDomElement.scannerDetectionData.options = this._mergeOptions(oDomElement.scannerDetectionData.options, oOptions);
// reinitiallize
this._reinitialize(oDomElement);
return this;
},
/**
* Transforms key codes into characters.
*
* By default, only the follwing key codes are taken into account
* - 48-90 (letters and regular numbers)
* - 96-105 (numeric keypad numbers)
* - 106-111 (numeric keypad operations)
*
* All other keys will yield empty strings!
*
* The above keycodes will be decoded using the KeyboardEvent.key property on modern
* browsers. On older browsers the method will fall back to String.fromCharCode()
* putting the result to upper/lower case depending on KeyboardEvent.shiftKey if
* it is set.
*
* @param KeyboardEvent oEvent
* @return string
*/
decodeKeyEvent : function (oEvent) {
var iCode = this._getNormalizedKeyNum(oEvent);
switch (true) {
case iCode >= 48 && iCode <= 90: // numbers and letters
case iCode >= 106 && iCode <= 111: // operations on numeric keypad (+, -, etc.)
if (oEvent.key !== undefined && oEvent.key !== '') {
return oEvent.key;
}
var sDecoded = String.fromCharCode(iCode);
switch (oEvent.shiftKey) {
case false: sDecoded = sDecoded.toLowerCase(); break;
case true: sDecoded = sDecoded.toUpperCase(); break;
}
return sDecoded;
case iCode >= 96 && iCode <= 105: // numbers on numeric keypad
return 0+(iCode-96);
}
return '';
},
/**
* Simulates a scan of the provided code.
*
* The scan code can be defined as
* - a string - in this case no keyCode decoding is done and the code is merely validated
* against constraints like minLenght, etc.
* - an array of keyCodes (e.g. `[70,71,80]`) - will produce `keydown` events with corresponding
* `keyCode` properties. NOTE: these events will have empty `key` properties, so decoding may
* yield different results than with native events.
* - an array of objects (e.g. `[{keyCode: 70, key: "F", shiftKey: true}, {keyCode: 71, key: "g"}]`) -
* this way almost any event can be simulated, but it's a lot of work to do.
*
* @param DomElement oDomElement
* @param string|array mStringOrArray
* @return self
*/
simulate: function(oDomElement, mStringOrArray){
this._reinitialize(oDomElement);
if (Array.isArray(mStringOrArray)){
mStringOrArray.forEach(function(mKey){
var oEventProps = {};
if( (typeof mKey === "object" || typeof mKey === 'function') && (mKey !== null) ) {
oEventProps = mKey;
} else {
oEventProps.keyCode = parseInt(mKey);
}
var oEvent = new KeyboardEvent('keydown', oEventProps);
document.dispatchEvent(oEvent);
})
} else {
this._validateScanCode(oDomElement, mStringOrArray);
}
return this;
},
/**
* @private
* @param DomElement oDomElement
* @return void
*/
_reinitialize: function(oDomElement){
var oVars = oDomElement.scannerDetectionData.vars;
oVars.firstCharTime = 0;
oVars.lastCharTime = 0;
oVars.accumulatedString = '';
return;
},
/**
* @private
* @param DomElement oDomElement
* @return boolean
*/
_isFocusOnIgnoredElement: function(oDomElement){
var ignoreSelectors = oDomElement.scannerDetectionData.options.ignoreIfFocusOn;
if(!ignoreSelectors){
return false;
}
var oFocused = document.activeElement;
// checks if ignored element is an array, and if so it checks if one of the elements of it is an active one
if (Array.isArray(ignoreSelectors)){
for(var i=0; i<ignoreSelectors.length; i++){
if(oFocused.matches(ignoreSelectors[i]) === true){
return true;
}
}
// if the option consists of an single element, it only checks this one
} else if (oFocused.matches(ignoreSelectors)){
return true;
}
// if the active element is not listed in the ignoreIfFocusOn option, return false
return false;
},
/**
* Validates the scan code accumulated by the given DOM element and fires the respective events.
*
* @private
* @param DomElement oDomElement
* @return boolean
*/
_validateScanCode: function(oDomElement, sScanCode){
var oScannerData = oDomElement.scannerDetectionData;
var oOptions = oScannerData.options;
var iSingleScanQty = oScannerData.options.singleScanQty;
var iFirstCharTime = oScannerData.vars.firstCharTime;
var iLastCharTime = oScannerData.vars.lastCharTime;
var oScanError = {};
var oEvent;
switch(true){
// detect codes that are too short
case (sScanCode.length < oOptions.minLength):
oScanError = {
message: "Receieved code is shorter then minimal length"
};
break;
// detect codes that were entered too slow
case ((iLastCharTime - iFirstCharTime) > (sScanCode.length * oOptions.avgTimeByChar)):
oScanError = {
message: "Receieved code was not entered in time"
};
break;
// if a code was not filtered out earlier it is valid
default:
oOptions.onScan.call(oDomElement, sScanCode, iSingleScanQty);
oEvent = new CustomEvent(
'scan',
{
detail: {
scanCode: sScanCode,
qty: iSingleScanQty
}
}
);
oDomElement.dispatchEvent(oEvent);
onScan._reinitialize(oDomElement);
return true;
}
// If an error occurred (otherwise the method would return earlier) create an object for errordetection
oScanError.scanCode = sScanCode;
oScanError.scanDuration = iLastCharTime - iFirstCharTime;
oScanError.avgTimeByChar = oOptions.avgTimeByChar;
oScanError.minLength = oOptions.minLength;
oOptions.onScanError.call(oDomElement, oScanError);
oEvent = new CustomEvent(
'scanError',
{detail: oScanError}
);
oDomElement.dispatchEvent(oEvent);
onScan._reinitialize(oDomElement);
return false;
},
/**
* @private
* @param Object oDefaults
* @param Object oOptions
* @return Object
*/
_mergeOptions: function(oDefaults, oOptions){
var oExtended = {};
var prop;
for (prop in oDefaults){
if (Object.prototype.hasOwnProperty.call(oDefaults, prop)){
oExtended[prop] = oDefaults[prop];
}
}
for (prop in oOptions){
if (Object.prototype.hasOwnProperty.call(oOptions, prop)){
oExtended[prop] = oOptions[prop];
}
}
return oExtended;
},
/**
* @private
* @param KeyboardEvent e
* @return int
* @see https://www.w3schools.com/jsref/event_key_keycode.asp
*/
_getNormalizedKeyNum: function(e){
return e.which || e.keyCode;
},
/**
* @private
* @param KeyboardEvent e
* @return void
*/
_handleKeyDown: function(e){
var iKeyCode = onScan._getNormalizedKeyNum(e);
var oOptions = this.scannerDetectionData.options;
var oVars = this.scannerDetectionData.vars;
var bScanFinished = false;
if (oOptions.onKeyDetect.call(this, iKeyCode, e) === false) {
return;
}
if (onScan._isFocusOnIgnoredElement(this)){
return;
}
// If it's just the button of the scanner, ignore it and wait for the real input
if(oOptions.scanButtonKeyCode !== false && iKeyCode==oOptions.scanButtonKeyCode) {
// if the button was first pressed, start a timeout for the callback, which gets interrupted if the scanbutton gets released
if (!oVars.longPressed){
oVars.longPressTimer = setTimeout( oOptions.onScanButtonLongPress, oOptions.scanButtonLongPressTime, this);
oVars.longPressed = true;
}
return;
}
switch(true){
// If it's not the first character and we encounter a terminating character, trigger scan process
case (oVars.firstCharTime && oOptions.suffixKeyCodes.indexOf(iKeyCode)!==-1):
e.preventDefault();
e.stopImmediatePropagation();
bScanFinished=true;
break;
// If it's the first character and we encountered one of the starting characters, don't process the scan
case (!oVars.firstCharTime && oOptions.prefixKeyCodes.indexOf(iKeyCode)!==-1):
e.preventDefault();
e.stopImmediatePropagation();
bScanFinished=false;
break;
// Otherwise, just add the character to the scan string we're building
default:
var character = oOptions.keyCodeMapper.call(this, e);
if (character === null){
return;
}
oVars.accumulatedString += character;
if (oOptions.preventDefault) {
e.preventDefault();
}
if (oOptions.stopPropagation) {
e.stopImmediatePropagation();
}
bScanFinished=false;
break;
}
if(!oVars.firstCharTime){
oVars.firstCharTime=Date.now();
}
oVars.lastCharTime=Date.now();
if(oVars.testTimer){
clearTimeout(oVars.testTimer);
}
if(bScanFinished){
onScan._validateScanCode(this, oVars.accumulatedString);
oVars.testTimer=false;
} else {
oVars.testTimer=setTimeout(onScan._validateScanCode, oOptions.timeBeforeScanTest, this, oVars.accumulatedString);
}
oOptions.onKeyProcess.call(this, character, e);
return;
},
/**
* @private
* @param Event e
* @return void
*/
_handlePaste: function(e){
var oOptions = this.scannerDetectionData.options;
var oVars = this.scannerDetectionData.vars;
var sPasteString = (event.clipboardData || window.clipboardData).getData('text');
// if the focus is on an ignored element, abort
if (onScan._isFocusOnIgnoredElement(this)){
return;
}
e.preventDefault();

if (oOptions.stopPropagation) {
e.stopImmediatePropagation();
}
oOptions.onPaste.call(this, sPasteString, event);
oVars.firstCharTime = 0;
oVars.lastCharTime = 0;
// validate the string
onScan._validateScanCode(this, sPasteString);
return;
},
/**
* @private
* @param KeyboardEvent e
* @return void
*/
_handleKeyUp: function(e){
// if the focus is on an ignored element, abort
if (onScan._isFocusOnIgnoredElement(this)){
return;
}
var iKeyCode = onScan._getNormalizedKeyNum(e);
// if hardware key is not being pressed anymore stop the timeout and reset
if (iKeyCode == this.scannerDetectionData.options.scanButtonKeyCode){
clearTimeout(this.scannerDetectionData.vars.longPressTimer);
this.scannerDetectionData.vars.longPressed = false;
}
return;
},
/**
* Returns TRUE the scanner is currently in the middle of a scan sequence.
*
* @param DomElement
* @return boolean
*/
isScanInProgressFor: function(oDomElement) {
return oDomElement.scannerDetectionData.vars.firstCharTime > 0;
},
/**
* Returns TRUE if onScan is attached to the given DOM element and FALSE otherwise.
*
* @param DomElement
* @return boolean
*/
isAttachedTo: function(oDomElement) {
return (oDomElement.scannerDetectionData !== undefined);
}
};
return onScan;
})));

+ 5
- 0
src/main/webapp/resources/js/onscan.min.js
Diff onderdrukt omdat het te groot bestand
Bestand weergeven


Laden…
Annuleren
Opslaan