キーボードで入力することでテキスト入力が満たされたときと、バーコードスキャナーで自動的に入力されたときをプログラムで検出する方法を教えてください。
バーコードはキーイベントを発生させないため、次のようなことができます。
$('#my_field').on({
keypress: function() { typed_into = true; },
change: function() {
if (typed_into) {
alert('type');
typed_into = false; //reset type listener
} else {
alert('not type');
}
}
});
これを評価するタイミングに応じて、変更時ではなく、送信時などにこのチェックを行うことができます。
バーコードスキャナーのMotorola LS1203がキープレスイベントを生成したため、Utkanosのソリューションを使用できないため、この回答を書きました。
私の解決策は次のとおりです。
var BarcodeScanerEvents = function() {
this.initialize.apply(this, arguments);
};
BarcodeScanerEvents.prototype = {
initialize: function() {
$(document).on({
keyup: $.proxy(this._keyup, this)
});
},
_timeoutHandler: 0,
_inputString: '',
_keyup: function (e) {
if (this._timeoutHandler) {
clearTimeout(this._timeoutHandler);
this._inputString += String.fromCharCode(e.which);
}
this._timeoutHandler = setTimeout($.proxy(function () {
if (this._inputString.length <= 3) {
this._inputString = '';
return;
}
$(document).trigger('onbarcodescaned', this._inputString);
this._inputString = '';
}, this), 20);
}
};
jQueryプラグインを使用して次の例を試すことができます https://plugins.jquery.com/scannerdetection/
高度に設定可能な時間ベースのスキャナー検出器。プレフィックス/ポストフィックスベース、時間ベースのバーコードスキャナーのソリューションとして使用できます。
使用方法とベストプラクティスのチュートリアル。さまざまなバーコードスキャナーモデルとその対処方法について説明します。 http://a.kabachnik.info/jquery-scannerdetection-tutorial.html
$(window).ready(function(){
//$("#bCode").scannerDetection();
console.log('all is well');
$(window).scannerDetection();
$(window).bind('scannerDetectionComplete',function(e,data){
console.log('complete '+data.string);
$("#bCode").val(data.string);
})
.bind('scannerDetectionError',function(e,data){
console.log('detection error '+data.string);
})
.bind('scannerDetectionReceive',function(e,data){
console.log('Recieve');
console.log(data.evt.which);
})
//$(window).scannerDetection('success');
<input id='bCode'type='text' value='barcode appears here'/>
非常に便利な 上記のVitallの回答 を採用して、プロトタイプを作成する代わりにIIFEを使用するようにしました。
これはまた、keyupの代わりに 'keypress'イベントを使用します。これにより、KeyboardEvent。は非推奨になっているため、KeyboardEvent.keyを確実に使用できます。これは、バーコードスキャンや磁気ストリップカードスワイプでも機能することがわかりました。
私の経験では、キーアップでカードスワイプを処理すると、「Shift」キーコードを処理する余分な作業が必要になりました。 Shiftコードの後には、「/」を表すコードが続き、目的の文字は「?」になります。 「キープレス」を使用してこれも解決しました。
(function($) {
var _timeoutHandler = 0,
_inputString = '',
_onKeypress = function(e) {
if (_timeoutHandler) {
clearTimeout(_timeoutHandler);
}
_inputString += e.key;
_timeoutHandler = setTimeout(function () {
if (_inputString.length <= 3) {
_inputString = '';
return;
}
$(e.target).trigger('altdeviceinput', _inputString);
_inputString = '';
}, 20);
};
$(document).on({
keypress: _onKeypress
});
})($);
バーコードスキャナーにプレフィックスを設定できる場合は、これをお勧めします(Vitallコードを少し変更しました):
_var BarcodeScanner = function(options) {
this.initialize.call(this, options);
};
BarcodeScanner.prototype = {
initialize: function(options) {
$.extend(this._options,options);
if(this._options.debug) console.log("BarcodeScanner: Initializing");
$(this._options.eventObj).on({
keydown: $.proxy(this._keydown, this),
});
},
destroy: function() {
$(this._options.eventObj).off("keyup",null,this._keyup);
$(this._options.eventObj).off("keydown",null,this._keydown);
},
fire: function(str){
if(this._options.debug) console.log("BarcodeScanner: Firing barcode event with string: "+str);
$(this._options.fireObj).trigger('barcode',[str]);
},
isReading: function(){
return this._isReading;
},
checkEvent: function(e){
return this._isReading || (this._options.isShiftPrefix?e.shiftKey:!e.shiftKey) && e.which==this._options.prefixCode;
},
_options: {timeout: 600, prefixCode: 36, suffixCode: 13, minCode: 32, maxCode: 126, isShiftPrefix: false, debug: false, eventObj: document, fireObj: document},
_isReading: false,
_timeoutHandler: false,
_inputString: '',
_keydown: function (e) {
if(this._input.call(this,e))
return false;
},
_input: function (e) {
if(this._isReading){
if(e.which==this._options.suffixCode){
//read end
if(this._options.debug) console.log("BarcodeScanner: Read END");
if (this._timeoutHandler)
clearTimeout(this._timeoutHandler);
this._isReading=false;
this.fire.call(this,this._inputString);
this._inputString='';
}else{
//char reading
if(this._options.debug) console.log("BarcodeScanner: Char reading "+(e.which));
if(e.which>=this._options.minCode && e.which<=this._options.maxCode)
this._inputString += String.fromCharCode(e.which);
}
return true;
}else{
if((this._options.isShiftPrefix?e.shiftKey:!e.shiftKey) && e.which==this._options.prefixCode){
//start reading
if(this._options.debug) console.log("BarcodeScanner: Start reading");
this._isReading=true;
this._timeoutHandler = setTimeout($.proxy(function () {
//read timeout
if(this._options.debug) console.log("BarcodeScanner: Read timeout");
this._inputString='';
this._isReading=false;
this._timeoutHandler=false;
}, this), this._options.timeout);
return true;
}
}
return false;
}
};
_
必要に応じて、タイムアウト、サフィックス、プレフィックス、最小/最大アスキーコードをカスタマイズします。
_new BarcodeScanner({timeout: 600, prefixKeyCode: 36, suffixKeyCode: 13, minKeyCode: 32, maxKeyCode: 126});
_
また、isShiftPrefix
オプションを追加して、たとえば_$
_ charをこれらのオプションのプレフィックスとして使用します:new BarcodeScanner({prefixKeyCode: 52, isShiftPrefix: true});
これはフィドルです。 https://jsfiddle.net/xmt76ca5/
Vitallのソリューションは、少なくとも1つのキーを既に押した場合にのみ正常に機能します。そうしないと、最初の文字は無視されます(if(this._timeoutHandler)はfalseを返し、charは追加されません)。
すぐにスキャンを開始する場合は、次のコードを使用できます。
var BarcodeScanerEvents = function() {
this.initialize.apply(this, arguments);
};
BarcodeScanerEvents.prototype = {
initialize : function() {
$(document).on({
keyup : $.proxy(this._keyup, this)
});
},
_timeoutHandler : 0,
_inputString : '',
_keyup : function(e) {
if (this._timeoutHandler) {
clearTimeout(this._timeoutHandler);
}
this._inputString += String.fromCharCode(e.which);
this._timeoutHandler = setTimeout($.proxy(function() {
if (this._inputString.length <= 3) {
this._inputString = '';
return;
}
$(document).trigger('onbarcodescaned', this._inputString);
this._inputString = '';
}, this), 20);
}
};
その入力ボックスで「onkeyup」イベントを使用できます。イベントがトリガーされた場合、「キーボードからの入力」と呼ぶことができます。
VitallのES6 2019バージョンの回答。
const events = mitt()
class BarcodeScaner {
initialize = () => {
document.addEventListener('keypress', this.keyup)
if (this.timeoutHandler) {
clearTimeout(this.timeoutHandler)
}
this.timeoutHandler = setTimeout(() => {
this.inputString = ''
}, 10)
}
close = () => {
document.removeEventListener('keypress', this.keyup)
}
timeoutHandler = 0
inputString = ''
keyup = (e) => {
if (this.timeoutHandler) {
clearTimeout(this.timeoutHandler)
this.inputString += String.fromCharCode(e.keyCode)
}
this.timeoutHandler = setTimeout(() => {
if (this.inputString.length <= 3) {
this.inputString = ''
return
}
events.emit('onbarcodescaned', this.inputString)
this.inputString = ''
}, 10)
}
}
次のようなリアクションフックで使用できます。
const ScanComponent = (props) => {
const [scanned, setScanned] = useState('')
useEffect(() => {
const barcode = new BarcodeScaner()
barcode.initialize()
return () => {
barcode.close()
}
}, [])
useEffect(() => {
const scanHandler = code => {
console.log(code)
setScanned(code)
}
events.on('onbarcodescaned', scanHandler)
return () => {
events.off('onbarcodescaned', scanHandler)
}
}, [/* here put dependencies for your scanHandler ;) */])
return <div>{scanned}</div>
}
イベントにはnpmのミットを使用しますが、好きなものを使用できます;)
Zebra DS4208でテスト済み
$(window).ready(function(){
//$("#bCode").scannerDetection();
console.log('all is well');
$(window).scannerDetection();
$(window).bind('scannerDetectionComplete',function(e,data){
console.log('complete '+data.string);
$("#bCode").val(data.string);
})
.bind('scannerDetectionError',function(e,data){
console.log('detection error '+data.string);
})
.bind('scannerDetectionReceive',function(e,data){
console.log('Recieve');
console.log(data.evt.which);
})
//$(window).scannerDetection('success');
<input id='bCode'type='text' value='barcode appears here'/>