diff --git a/index.html b/index.html new file mode 100644 index 0000000..2d045b1 --- /dev/null +++ b/index.html @@ -0,0 +1,234 @@ + + + + + + + +

Testsite for ScannerDetector

+

Settings:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + +
+ + +
+ + + + + + + + \ No newline at end of file diff --git a/onscan.js b/onscan.js new file mode 100644 index 0000000..f4feda4 --- /dev/null +++ b/onscan.js @@ -0,0 +1,257 @@ +var scannerDetector = { + attachTo: function(oDomElement, oOptions) { + + if(oDomElement.scannerDetectionData != undefined){ + throw new Error("scannerDetector is already inizialized"); + } + + var oDefaults = { + onComplete:false, // Callback after detection of a successfull scanning (scanned string in parameter) + onError:false, // Callback after detection of a unsuccessfull scanning (scanned string in parameter) + onReceive:false, // Callback after receiving and processing a char (scanned char in parameter) + onKeyDetect:false, // Callback after detecting a keyDown (key char in parameter) - in contrast to onReceive, this fires for non-character keys like tab, arrows, etc. too! + 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 + endChar:[9,13], // Chars to remove and means end of scanning + startChar:[], // Chars to remove and means start of scanning + ignoreIfFocusOn:false, // do not handle scans if the currently focused element matches this selector + scanButtonKeyCode:false, // Key code of the scanner hardware button (if the scanner button a acts as a key itself) + scanButtonLongPressThreshold:3, // How many times the hardware button should issue a pressed event before a barcode is read to detect a longpress + onScanButtonLongPressed:false, // Callback after detection of a successfull scan while the scan button was pressed and held down + stopPropagation:false, // Stop immediate propagation on keypress event + preventDefault:false // Prevent default action on keypress event + } + + if(typeof oOptions!=="object"){ + oOptions=oDefaults; + }else{ + + oOptions = this._mergeOptions(oDefaults, oOptions); + + } + oDomElement.scannerDetectionData = { + options: oOptions, + vars:{ + firstCharTime: 0, + lastCharTime: 0, + stringWriting: '', + callIsScanner: false, + scanButtonCounter: 0, + testTimer: false + } + + }; + + this._reinizialize(oDomElement); + + oDomElement.addEventListener("keydown", this._handleKeyDown); + oDomElement.addEventListener("keypress", this._handleScannerDetection); + + }, + + detachFrom: function(oDomElement) { + oDomElement.removeEventListener("keydown", this._handleKeyDown); + oDomElement.removeEventListener("keypress", this._handleScannerDetection); + oDomElement.scannerDetectionData = undefined; + //oDomElement['scannerDetectionData'] = undefined; + + }, + + simulate: function(oDomElement, sTestString){ + var vars = oDomElement['scannerDetectionData'].vars; + vars.FirstCharTime = 0; + vars.LastCharTime = 0; + vars.stringWriting = sTestString; + this._validateScanCode(oDomElement); + return this; + }, + + _reinizialize: function(oDomElement){ + var vars = oDomElement['scannerDetectionData'].vars; + vars.firstCharTime=0; + vars.stringWriting=''; + vars.scanButtonCounter=0; + }, + + _isFocusOnIgnoredElement: function(oDomElement){ + + oIgnoredObject = oDomElement['scannerDetectionData'].options.ignoreIfFocusOn; + + if(!oIgnoredObject) return false; + if(typeof oIgnoredObject === 'string') return document.activeElement.is(oIgnoredObject); // TODO? + if(typeof oIgnoredObject === 'object'){ + var oFocused = document.activeElement; + + if (Array.isArray(oIgnoredObject)){ + for(var i=0; i=oOptions.minLength + && iLastCharTime - iFirstCharTime < sScanCode.length * oOptions.avgTimeByChar){ + if(oOptions.onScanButtonLongPressed && + iScanButtonCounter > oOptions.scanButtonLongPressThreshold) + oOptions.onScanButtonLongPressed.call(oDomElement, sScanCode, iScanButtonCounter); + else if(oOptions.onComplete) oOptions.onComplete.call(oDomElement, sScanCode, iScanButtonCounter); + var oEvent = new CustomEvent( + 'scannerDetectionComplete', + { + detail: { + code: sScanCode, + qty: iScanButtonCounter + } + } + ); + oDomElement.dispatchEvent(oEvent); + scannerDetector._reinizialize(oDomElement); + return true; + }else{ + if(oOptions.onError) oOptions.onError.call(oDomElement,sScanCode); + + var oEvent = new CustomEvent('scannerDetectionError'); + oDomElement.dispatchEvent(oEvent); + + scannerDetector._reinizialize(oDomElement); + return false; + } + + }, + + _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; + }, + + _getKeyNum: function(e){ + var iKeyNum; + if(window.event) { // IE + iKeyNum = e.keyCode; + } else if(e.which){ // Netscape/Firefox/Opera + iKeyNum = e.which; + } + return iKeyNum; + }, + + + _handleKeyDown: function(e){ + var iKeyNum = scannerDetector._getKeyNum(e); + var oOptions = this['scannerDetectionData'].options; + var oVars = this['scannerDetectionData'].vars; + + if(oOptions.scanButtonKeyCode !== false && iKeyNum==oOptions.scanButtonKeyCode) { + this['scannerDetectionData'].vars.scanButtonCounter++; + // Cancel default + e.preventDefault(); + e.stopImmediatePropagation(); + } + // Add event on keydown because keypress is not triggered for non character keys (tab, up, down...) + // So need that to check endChar and startChar (that is often tab or enter) and call keypress if necessary + else if((oVars.firstCharTime && oOptions.endChar.indexOf(iKeyNum)!==-1) + || (!oVars.firstCharTime && oOptions.startChar.indexOf(iKeyNum)!==-1)){ + // Clone event, set type and trigger it + this.dispatchEvent(new KeyboardEvent('keypress',e)); + + // Cancel default + e.preventDefault(); + e.stopImmediatePropagation(); + } + // Fire keyDetect event in any case! + if(oOptions.onKeyDetect) oOptions.onKeyDetect.call(this,e); + + var oEvent = new CustomEvent( + 'scannerDetectionKeyDetect', + { + evt: e + } + ); + this.dispatchEvent(oEvent); + + + + }, + + _handleScannerDetection: function(e){ + var iKeyNum = scannerDetector._getKeyNum(e); + var oOptions = this['scannerDetectionData'].options; + var oVars = this['scannerDetectionData'].vars; + + if (scannerDetector._isFocusOnIgnoredElement(this)) return; + if(oOptions.stopPropagation) e.stopImmediatePropagation(); + if(oOptions.preventDefault) e.preventDefault(); + + if(oVars.firstCharTime && oOptions.endChar.indexOf(iKeyNum)!==-1){ + e.preventDefault(); + e.stopImmediatePropagation(); + this['scannerDetectionData'].vars.callIsScanner=true; + }else if(!oVars.firstCharTime && oOptions.startChar.indexOf(iKeyNum)!==-1){ + e.preventDefault(); + e.stopImmediatePropagation(); + oVars.callIsScanner=false; + }else{ + if (typeof(iKeyNum) != 'undefined'){ + oVars.stringWriting += String.fromCharCode(iKeyNum); + } + oVars.callIsScanner=false; + } + + if(!oVars.firstCharTime){ + oVars.firstCharTime=Date.now(); + } + oVars.lastCharTime=Date.now(); + + if(oVars.testTimer) clearTimeout(oVars.testTimer); + if(oVars.callIsScanner){ + scannerDetector._validateScanCode(this); + oVars.testTimer=false; + }else{ + oVars.testTimer=setTimeout(scannerDetector._validateScanCode, oOptions.timeBeforeScanTest, this); + } + + if(oOptions.onReceive) oOptions.onReceive.call(this,e); + + var oEvent = new CustomEvent( + 'scannerDetectionKeyReceive', + { + evt: e + } + ); + this.dispatchEvent(oEvent); + + } + }; \ No newline at end of file