Ignore repeated keyboard events when holding down the keys - javascript

My code below, which fires update_doc_text() on pressing Ctrl+Shift+Enter, seems to call the function multiple times for some users (it happens when I hold down on those keys as well). What can I do to make sure the function only executes once?
var ctrlDown = false,
ctrlKey = 17,
shiftDown = false,
shiftKey = 16,
KeyEnter = 13,
$(document).keydown(function(e) {
if (e.keyCode == ctrlKey)
ctrlDown = true;
if (e.keyCode == shiftKey)
shiftDown = true;
if (ctrlDown && shiftDown && (e.keyCode == KeyEnter))
update_doc_text();
}).keyup(function(e) {
if (e.keyCode == ctrlKey)
ctrlDown = false;
if (e.keyCode == shiftKey)
shiftDown = false;
});

The problem is due to how you're structured the logic; it's more complicated that it needs to be.
You can achieve what you need by reading the ctrlKey and shiftKey flags from the event to make sure they were held down at the same time as the return key was pressed.
To avoid the repetition when the keys are held down you can use a setTimeout() to set a flag which disables the repeated action for a set amount of time. Try this:
$(document).keydown(function(e) {
var $doc = $(this);
if (e.ctrlKey && e.shiftKey && e.which === 13 && !$doc.data('ctrlShiftReturnDisabled')) {
update_doc_text();
$doc.data('ctrlShiftReturnDisabled', true);
setTimeout(function() {
$doc.data('ctrlShiftReturnDisabled', false);
}, 2000); // 2 seconds, change as needed
}
});
function update_doc_text() {
console.log('update_doc_text');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

You can use object to store pressed keys and get key code by e.which property. Also you can use one variable pressed to keep track if the keys are pressed and run your code only if that variable is false.
var keys = {}, pressed = false, codes = [13, 16, 17]
var check = keys => codes.every(k => keys[k]);
$(document).keydown(function(e) {
keys[e.which] = true;
if (check(keys) && !pressed) {
// run your code here
console.log('pressed')
pressed = true;
}
}).keyup(function(e) {
keys[e.which] = false;
if (codes.includes(e.which)) {
pressed = false
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Related

Detecting two keyboard keys being down at the same time

I tried with this code to detect two keyboard arrows being simultaneously pressed:
document.addEventListener('keydown', event => {
if (event.keyCode === 38) {
console.log('up Arrow')
}
if (event.keyCode === 39) {
console.log('right Arrow')
}
})
But it doesn't work, however hard I try to press them at exactly the same time.
How can I cleanly fix this and detect when both keys are down ?
There's only one keyCode per event. You have to track the keys going down, and up:
// if you keep both up and down keys down, you'll get a message
let downKeys = {}; // the set of keys currently down
document.addEventListener('keydown', event => {
downKeys[event.keyCode] = true;
if (downKeys[38] && downKeys[40]) {
console.log("both down!");
}
});
document.addEventListener('keyup', event => {
downKeys[event.keyCode] = false;
});
(you have to go full page to test this snippet)
Here I use 2 flags to check if you are holding the keys.
If both flags are true then it means that you are holding both keys. So, you can perform anything inside the condition.
let holdKeyUp = false;
let holdKeyRight = false;
document.addEventListener('keydown', event => {
if (event.keyCode === 38) {
holdKeyUp = true;
}
if (event.keyCode === 39) {
holdKeyRight = true;
}
if (holdKeyUp && holdKeyRight) {
console.log("Both keys are pressed.");
}
})
document.addEventListener('keyup', event => {
if (event.keyCode === 38) {
holdKeyUp = false;
}
if (event.keyCode === 39) {
holdKeyRight = false;
}
})

Javascript several keyboard events

I'm currently building a music player with three buttons (actually simple divs) for Play/Pause (id="play"), Previous (id=rew) and Next (id="fwd").
I want the Play/Pause to be "clicked" when pressing SPACEBAR.
I want the Previous to be "clicked" when pressing LEFT ARROW.
I want the Next to be "clicked" when pressing RIGHT ARROW.
I've successfully managed the SPACEBAR control of Play with this :
var play = document.getElementById("play");
document.onkeydown = function (e) {
if (e.keyCode == 32) {
play.click();
}
};
However, when I add the same for the two other buttons in my script, the SPACEBAR control of Play does not work anymore, as well as the other two.
So, what I have currently in my script and which is obviously not working is this :
<script>
var play = document.getElementById("play");
document.onkeydown = function (e) {
if (e.keyCode == 32) {
play.click();
}
};
var rew = document.getElementById("rew");
document.onkeydown = function (e) {
if (e.keyCode == 37) {
rew.click();
}
};
var fwd = document.getElementById("fwd");
document.onkeydown = function (e) {
if (e.keyCode == 39) {
fwd.click();
}
};
</script>
What am I doing wrong ?
Each of your keydown events is overwriting the previous one.
Instead, put all the logic into one keydown event, like this:
var play = document.getElementById("play");
var rew = document.getElementById("rew");
var fwd = document.getElementById("fwd");
document.onkeydown = function(e) {
if (e.keyCode == 32) {
play.click();
} else if (e.keyCode == 37) {
rew.click();
} else if (e.keyCode == 39) {
fwd.click();
}
};
When you assign to onkeydown several times only the last one will be assigned because it will override the previous one. You can use addEventListener instead but that isn't the best approach neither. Just make more test inside one event listener like this:
var play = document.getElementById("play");
var rew = document.getElementById("rew");
var fwd = document.getElementById("fwd");
document.onkeydown = function (e) {
if (e.keyCode == 32) {
play.click();
}
else if(e.keyCode == 32) {
rev.click();
}
else if(e.keyCode == 32) {
fwd.click();
}
};

Javascript keypress event with time limit

So my problem is multipressing key with function keydown and i need to apply time limit, when u hit key wait 5 sec and then you can again hit the key. How can i do this? example:
$(document).keydown(function (e) {
var keyCode = e.keyCode || e.which,
arrow = {left: 37, up: 38, right: 39, down: 40 };
if(keyCode == arrow.left) {
ex1();
} else if (keyCode ==arrow.right) {
ex2();
} else if (keyCode == arrow.up) {
ex3();
} else if(keyCode == arrow.down) {
ex4();
}
});
This is a very simple way to achieve this (If i've understood you correctly)
$(function() {
var pressed = false; //Global var to hold state
$(document).keydown(function (e) {
if( pressed === true ) { //Already pressed don't allow another press
alert("Please wait 5 seconds between key presses");
return false;
}
pressed = true;
setTimeout(function() { pressed = false }, 5000);
var keyCode = e.keyCode || e.which;
var arrow = {left: 37, up: 38, right: 39, down: 40 };
if(keyCode == arrow.left) {
ex1();
} else if (keyCode ==arrow.right) {
ex2();
} else if (keyCode == arrow.up) {
ex3();
} else if(keyCode == arrow.down) {
ex4();
}
});
});
Set a simple variable to hold the pressed state (true or false). If pressed is true return false so that no functionality happens Else let them press the button. set pressed to true and set a 5 second timeout to return the state back to false.

How to detect keyboard modifier (Ctrl or Shift) through JavaScript

I have a function which detect max length. but the problem is that when the max length reached Ctrl+A combination does't work. How can I detect Ctrl+A combination through javascript.
This is my maxlength code.
if (event.keyCode==8 || event.keyCode==9 || event.keyCode==37 || event.keyCode==39 ){
return true;
} else {
if((t.length)>=50) {
return false;
}
}
Check event.ctrlKey:
function keyHandler(event) {
event = event || window.event;
if(event.keyCode==65 && event.ctrlKey) {
// ctrl+a was typed.
}
}
key codes:
shift 16
ctrl 17
alt 18
your jQuery:
$(document).keydown(function (e) {
if (e.keyCode == 18) {
alert("ALT was pressed");
}
});
JavaScript Madness: Keyboard Events
You can use the following:
document.onkeypress = function(evt) {
evt = evt || window.event;
etv = evt;
switch (etv.keyCode) {
case 16:
// Code to do when Shift presed
console.log('Pressed [SHIFT]');
break;
case 17:
// Code to do when CTRL presed
console.log('Pressed [CTRL]');
break;
case 32:
// Code to do when ALT presed
console.log('Pressed [ALT]');
break;
}
};
I needed a solution for this too, so found some stuff that worked, cleaned it up to be a lot less code, and ES6... JSFiddle link
function isCapsLock(event=window.event) {
const code = event.charCode || event.keyCode;
if (code > 64 && code < 91 && !event.shiftKey) {
return true;
}
return false;
}
document.getElementById("text").addEventListener("keypress", event => {
const status = document.getElementById("status");
if (isCapsLock(event)) {
status.innerHTML = "CapsLocks enabled";
status.style.color = "red";
} else {
status.innerHTML = "CapsLocks disabled";
status.style.color = "blue";
}
}, false);
<input type="text" id="text" /><br>
<span id="status"></span>
This is a very old question. gilly3's answer is valid only if we have at hand an event object of type KeyboardEvent passed as a function argument. How to detect the current control key state if we have not event object available such as in this function?
function testModifierKey() {
// have I some modifier key hold down at this running time?
}
I found the solution after a long search from https://gist.github.com/spikebrehm/3747378 of spikebrehm. his solution is tracing the modifier key state at any time using jQuery with a global variable.
The global variable window.modifierKey can be used in any circonstance without requiring event object.
function testModifierKey() {
// have I have some modifier key hold down at this executing time?
if(window.modifierKey) {
console.log("Some modifier key among shift, ctrl, alt key is currently down.");
// do something at this condition... for example, delete item without confirmation.
} else {
console.log("No modifier key is currently down.");
// do something at other condition... for example, delete this item from shopping cart with confirmation.
}
}
Here is his script to load in your HTML document:
// source: https://gist.github.com/spikebrehm/3747378
// modifierKey used to check if cmd+click, shift+click, etc.
!function($, global){
var $doc = $(document);
var keys;
global.modifierKey = false;
global.keys = keys = {
'UP': 38,
'DOWN': 40,
'LEFT': 37,
'RIGHT': 39,
'RETURN': 13,
'ESCAPE': 27,
'BACKSPACE': 8,
'SPACE': 32
};
// borrowed from Galleria.js
var keyboard = {
map: {},
bound: false,
press: function(e) {
var key = e.keyCode || e.which;
if ( key in keyboard.map && typeof keyboard.map[key] === 'function' ) {
keyboard.map[key].call(self, e);
}
},
attach: function(map){
var key, up;
for(key in map) {
if (map.hasOwnProperty(key)) {
up = key.toUpperCase();
if (up in keyboard.keys) {
keyboard.map[keyboard.keys[up]] = map[key];
} else {
keyboard.map[up] = map[key];
}
}
}
if (!keyboard.bound) {
keyboard.bound = true;
$doc.bind('keydown', keyboard.press);
}
},
detach: function() {
keyboard.bound = false;
keyboard.map = {};
$doc.unbind('keydown', keyboard.press);
}
};
$doc.keydown(function(e) {
var key = e.keyCode || e.which;
if (key === 16 || key === 91 || key === 18 || key === 17) {
modifierKey = true;
} else {
modifierKey = false;
}
});
$doc.keyup(function(e) {
modifierKey = false;
});
}(jQuery, window);

Javascript on second keypress

I've been wondering if there was a simple way to detect if a user presses the same character on the keyboard twice within one second. I've written some code that kind of works but it's unreliable.
var escapeCount = 0;
function reset() {
escapeCount = 0;
setTimeout('reset();', 1000);
}
window.onload = function() {
reset();
};
document.onkeyup = function(e) {
if (!e) var e = window.event;
var code = e.keyCode ? e.keyCode : e.which;
if (code == 27) escapeCount +=1;
if (escapeCount == 2) {
// stuff on second escape
}
};
Is there a better way to do this? Thanks
It would make sense to reset after 1 second has passed since the last character was pressed. Example:
var lastChar = -1;
document.onkeyup = function(e) {
if (!e) var e = window.event;
var code = e.keyCode ? e.keyCode : e.which;
if (lastChar == code) {
// Same key was pressed twice in a row within 1 second.
} else {
lastChar = code;
setTimeout(function() {lastChar = -1;}, 1000);
}
};
Your timer resets every second, so you not only have to press Escape again within a second of the last Escape, but that also has to have no timeout in between the presses.
It's probably easier to forget the timeout and just remember the time of the last keypress instead:
var lastescapetime= null;
document.onkeyup= function(event) {
if (event===undefined) event= window.event;
if (event.keyCode===27) {
var now= new Date().getTime();
if (lastescapetime!==null && now<lastescapetime+1000) {
alert('You double-escaped!');
lastescapetime= null;
} else {
lastescapetime= now;
}
} else {
lastescapetime= null;
}
};

Categories

Resources