I am trying to make an event/character pass-through in javascript/jQuery that basically delays the "actuating" of the keypress event by about 2000ms. I've set up a handler to capture all keypress events and put them in a buffer. But I am having trouble "playing back" the sequence of keypresses stored in the buffer.
The way it works (and you will see this in the snippet) is that hitting the "+" key starts the buffering. After you hit "+", any keys you hit after that are stored into a buffer. And after 2000ms, the buffering is turned off. If you hit "Enter" within 2000ms of hitting "+", then the buffer is emptied (and I'm doing something else there in my real code). But, if you do not hit "Enter" within 2000ms, then the keypresses need to be played back. And that's where I am having the issue.
When the keyBuffer
is played back, I want the characters (that should result from triggering a keypress) to appear in whichever input control the user happens to be in (at the cursor). But when I trigger the events, nothing is showing up. I may be doing this completely wrong, but I am not sure. I am also keeping the string of characters that coincide with the keyBuffer
(stored in stringBuffer
, in case I can use the string to insert the characters (instead of playing back the keypresses). But the problem there is that I do not know which input control the user might be in.
Is there a way to modify my code (below) so that the keypress events I am programmatically triggering (in my loop) will make the characters show up in the focused input control?
var checkForSwipe = false;
var stringBuffer = '';
var keyBuffer = [];
$('body').keypress(function (e) {
var charCode = (e.which) ? e.which : e.keyCode
if (charCode == 43) { // "+"
//ENABLE KEY BUFFERING:
e.preventDefault();
e.stopPropagation();
checkForSwipe = true;
stringBuffer = '';
keyBuffer = [];
//AFTER A SET INTERVAL, IF ENTER HAS NOT BEEN PRESSED, THEN REPLAY THE KEYPRESSES:
setTimeout(function () {
checkForSwipe = false;
//REPLAY THE STORED KEYPRESSES:
if (keyBuffer && keyBuffer.length) {
$('#monitor').append('<b>Enter not pressed. Replaying keypresses:</b><br/>');
for (var i in keyBuffer) {
var which = keyBuffer[i]
var press = jQuery.Event("keypress");
press.ctrlKey = false;
press.which = which;
if (which != 43) {
$('#monitor').append(' ' + which + ' ');
$("body").trigger(press);
}
}
}
stringBuffer = '';
keyBuffer = [];
}, 2000);
}
if (e.keyCode == 13) { // "Enter"
if (checkForSwipe) {
e.preventDefault();
e.stopPropagation();
checkForSwipe = false;
stringBuffer += String.fromCharCode(charCode);
keyBuffer.push(e.which);
//DO SOMETHING WITH THE stringBuffer...
//THEN RESET:
stringBuffer = '';
keyBuffer = [];
}
}
//IF "+" HAS BEEN PRESSED IN THE INTERVAL, STORE THE KEYS IN THE BUFFER:
if (checkForSwipe) {
e.preventDefault();
e.stopPropagation();
stringBuffer += String.fromCharCode(charCode);
keyBuffer.push(e.which);
}
});
#monitor {
background-color:#222;
color:#fff;
min-height:100px;
max-height:300px;
overflow:auto;
padding:4px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="i1" />
<input id="i2" />
<input id="i3" />
<input id="i4" />
<input id="i5" />
<div id='monitor'></div>
I think you can simply use your string buffer if you take advantage of activeElement. Just need to strip off the leading "+".
You can use selectionStart to identify where in the string you need to insert the text.
var checkForSwipe = false;
var stringBuffer = '';
var keyBuffer = [];
$('body').keypress(function (e) {
var charCode = (e.which) ? e.which : e.keyCode
if (charCode == 43) { // "+"
//ENABLE KEY BUFFERING:
e.preventDefault();
e.stopPropagation();
checkForSwipe = true;
stringBuffer = '';
keyBuffer = [];
//AFTER A SET INTERVAL, IF ENTER HAS NOT BEEN PRESSED, THEN REPLAY THE KEYPRESSES:
setTimeout(function () {
checkForSwipe = false;
//REPLAY THE STORED KEYPRESSES:
if (keyBuffer && keyBuffer.length) {
$('#monitor').append('<b>Enter not pressed. Replaying keypresses:</b><br/>');
var currentText = document.activeElement.value;
var currentIndx = document.activeElement.selectionStart;
var newText = currentText.slice(0, currentIndx) + stringBuffer.substr(1) + currentText.slice(currentIndx,currentText.length);
document.activeElement.value = newText;
}
stringBuffer = '';
keyBuffer = [];
}, 2000);
}
if (e.keyCode == 13) { // "Enter"
if (checkForSwipe) {
e.preventDefault();
e.stopPropagation();
checkForSwipe = false;
stringBuffer += String.fromCharCode(charCode);
keyBuffer.push(e.which);
//DO SOMETHING WITH THE stringBuffer...
//THEN RESET:
stringBuffer = '';
keyBuffer = [];
}
}
//IF "+" HAS BEEN PRESSED IN THE INTERVAL, STORE THE KEYS IN THE BUFFER:
if (checkForSwipe) {
e.preventDefault();
e.stopPropagation();
stringBuffer += String.fromCharCode(charCode);
keyBuffer.push(e.which);
}
});
#monitor {
background-color:#222;
color:#fff;
min-height:100px;
max-height:300px;
overflow:auto;
padding:4px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="i1" />
<input id="i2" />
<input id="i3" />
<input id="i4" />
<input id="i5" />
<div id='monitor'></div>