Similar to this solution how can I re-use the code to include both keyDown and keyUp events? I added one even for each KeyUp and KeyDown but there are problems when user holds down and releases a key and the events from the original keyUp event no longer continuously fire.
Example:
User presses and holds down Ctrl + Shift so KeyDown is continuously fired and prints Ctrl + Shift is pressed.
User releases Shift while still holding Ctrl so KeyUp is fired once but KeyDown for Ctrl no longer continue to fire
How can I improve this? The aim is to pair this with a mousescrollwheel event. If ctrl+mousewheel then scale plot along x axis. If Alt+moussewheel then scale along ploy Y axis. If both or neither then scale X and Y. Lastly, how can I pair this key modifier event with the mouse scroll wheel I provided to be in a responsive manner? I notice there are times where the key events will block the scroll event.
var scrollDelta = 0;
$(document).on("keydown", reportKeyEvent("Pressed") );
$(document).on("keyup", reportKeyEvent("Released") );
$(document).bind("wheel", updateScroll);
function reportKeyEvent (e, eventName) {
var keyStr = ["Control", "Shift", "Alt"].includes(e.key) ? "" : e.key + " ";
var out =
eventName + " " +
( e.ctrlKey ? "Control " : "" ) +
( e.shiftKey ? "Shift " : "" ) +
( e.altKey ? "Alt " : "" ) +
keyStr + "key(s)"
;
console.log(out)
ctrlKeyPressed = e.ctrlkey;
shiftKeyPressed = e.shiftkey;
altKeyPressed = e.altkey;
// add shift+scroll?
// add ctrl+scroll?
e.stopPropagation ();
e.preventDefault ()
}
function updateScroll(e){
if(e.deltaY < 0){
scrollDelta +=50;
}else if (e.delaY > 0){
scrollDelta -=50;
}else{
scrollDelta = 0;
}
}
You can keep your reportKeyEvent function. Just change to use the interval instead of the event
var keydownIntervalID;
var keys = new Set();
$(document).keyDown(function(e) {
keys.add(e.keyCode);
if (!keydownIntervalID) {
keydownIntervalID = setTimeout(reportKeyEvent, 50);
}
});
$(document).keyUp(function(e) {
keys.delete(e.keyCode);
if (keys.size === 0) {
clearInterval(keydownIntervalID);
keydownIntervalID = undefined;
}
});
Related
I'm trying to make a hotkey for a web app, for example Ctrl + z performs the undo function.
It seems that when I press the keys fast (as I'm used to from using desktop apps a lot), it doesn't register. The single key press registers, but it misses the combination for some reason.
From what I understand, you have to keep track of which buttons are held down via keypress events, which is what I've done below.
Try the code below. Hitting Z outputs Z. Hitting CTRL then Z slowly outputs CTRL + Z. Hitting CTRL then Z quickly outputs Z. When I perform the action at the same speed in say Notepad for windows, it works flawlessly almost every time.
https://codepen.io/samkeddy/pen/YQjgdZ?editors=1010#0
var ctrlPressed=false, altPressed=false;
window.addEventListener("keydown", function (e) {
hotkey = e;
if (e.keyCode == 17) ctrlPressed = true;
if (e.keyCode == 18) altPressed = true;
e.preventDefault();
});
window.addEventListener("keyup", function (e) {
hotkey = window.event;
if (e.keyCode == 17) ctrlPressed = false;
if (e.keyCode == 18) altPressed = false;
if (e.keyCode == 90){
if (altPressed && ctrlPressed && e.keyCode == 90)
addText('ALT + CTRL + Z');
else if (ctrlPressed && e.keyCode == 90)
addText('CTRL + Z');
else
addText('Z');
}
});
//meaningless, just adds text to doc so you can see it
function addText(text) {
var theDiv = document.getElementById("output");
theDiv.appendChild(document.createElement("br"));
var content = document.createTextNode(text);
theDiv.appendChild(content);
}
Use e.ctrlKey to check if ctrl is down instead of variables, and just check for the hotkey combination on keydown, don't do anything on key up.
https://codepen.io/samkeddy/pen/gRdBpq
function KeyPress(e) {
var evtobj = window.event? event : e
if (evtobj.keyCode == 90 && evtobj.ctrlKey) addText("CTRL + Z");
else if (evtobj.keyCode == 90) addText("Z");
}
document.onkeydown = KeyPress;
I have used a function which is activated on click events. I want to do the same using keypress events.
function addToText(target) {
var exp = target.target;
//alert(exp.value);
if (newExp) {
//clearText();
document.getElementById("expression").value = exp.value;
newExp=false;
}
else
document.getElementById("expression").value = document.getElementById("expression").value + exp.value;
}
This is the function used. How do I modify it to use for keypress events also. Currently, it does not work initially(for keypress events). But after clicking once, then any keypress returns the same number that was previously clicked.
Full code here:http://codepen.io/jpninanjohn/pen/JXVpYb?editors=1010
Here's is your final solution, I test if charcode is between 48 and 57, what it means, numbers between 0 and 9.
document.addEventListener('keypress', function(e){
if (e.which >= 48 && e.which <= 57)
document.getElementById("expression").value+= String.fromCharCode(e.which);
});
You can use this function-
window.onkeyup = function(e) {
var key = e.keyCode ? e.keyCode : e.which;
document.getElementById("expression").value += key-48; //for getting the number
alert(key);
if (key == 38) {
//whatever
}else if (key == 40) {
// whatever
}
}
source
And you need to add + to the =
document.getElementById("expression").value+=
instead of -
document.getElementById("expression").value=
You have to add a different function for keyPress event, because the keypress event get the value of pressed key differently, not target.target
function addToTextKeypress(event) {
var exp = String.fromCharCode(event.keyCode);
//alert(exp);
if (newExp) {
//clearText();
document.getElementById("expression").value = exp;
newExp=false;
}
else
document.getElementById("expression").value = document.getElementById("expression").value + exp;
}
Later you need to remove exp.value since it has the direct value
In my code below, the problem I have is that the focusPosition function is called but the console does not log the desired string: ("shift + left/right arrow")
// Hold reference to the currently focused position
var currentPosition = 0;
// Maximum position we can navigate to is the last item in the summary list
var maxFocusablePosition = summaryList.length - 1;
// Utility function to focus a given position value
function focusPosition(position) {
console.log("focus position is called");
$('#' + summaryList[position]).focus();
};
// Focus the first one by default
focusPosition(currentPosition);
$(document).keydown(function (event) {
if (event.which === 37 && event.which === 16) {
currentPosition = (currentPosition > 0) ? parseInt(currentPosition) - 1 : maxFocusablePosition;
console.log(' shift + left');
}
if (event.which === 39 && event.which === 16) {
currentPosition = (currentPosition < maxFocusablePosition) ? parseInt(currentPosition) + 1 : 0;
console.log('shift + right');
}
focusPosition(currentPosition);
});
Look for the arrow key in which, and look for event.shiftKey being truthy to know whether the shift key is down. That's how modifier keys work with the keydown event (there's shiftKey, ctrlKey, altKey, and metaKey).
I'm making a system where you press a key and it changes text box. I only want to be able to put the values X, x, E, e, /
My current jQuery code is
$('.today').keyup(function(e) {
var self = $(this);
var currentInput = self.data('number');
var next = $(currentInput + 1);
var previous = $(currentInput - 1);
var keyCode = e.keyCode || e.which;
var num = self.data('number') + 1;
var nom = self.data('number') - 1;
if(('input.today[data-number="' + num +'"]').length && keyCode === 40)
$('input.today[data-number="' + num +'"]').focus()
else if(('input.today[data-number="' + nom +'"]').length && keyCode === 38)
$('input.today[data-number="' + nom +'"]').focus();
else if(('input.today[data-number="' + num +'"]').length && self.val().length == self.attr('size')) {
$('input.today[data-number="' + num +'"]').focus();
}
});
I only want the focused box to move if the key up is one of these: X, x, E, e, /, UP, DOWN, LEFT, RIGHT. And if the values are not X, x, E, e, / then to not write in the box
This might help:
$('.today').keyup(function(e) {
if(~[38, 39, 40, ...].indexOf(e.keyCode || e.which)) {
e.preventDefault();
return;
}
...
}
The key there being the call to e.preventDefault().
You also have of the element the keyup event originated in as e.target.
HTH
You can examine the key that was pressed to determine how the event should proceed. If you don't want text to appear on certain key presses, then you can either return false from the handler, or call e.preventDefault():
if ($.inArray(e.keyCode, [69, 88, 191]) === -1) { // e, x, / respectively
e.preventDefault(); // don't print the character
}
You can get a list of the JavaScript keycodes here: Key Codes.
This isn't a jQuery only question as it has to do with events and order of operation. Consider the following code, which is based on jQuery multiSelect plugin (please post citation if you can find it):
Fiddle with it here
var debug = $('#debug');
var updateLog = function (msg){
debug.prepend(msg + '\n');
};
var title = $('#title').focus();
var container = $('#container');
title.keydown(function(e){
// up or down arrows
if (e.keyCode == 40 || e.keyCode == 38) {
var labels = container.find('label');
var idx_old = labels.index(labels.filter('.hover'));
var idx_new = -1;
if (idx_old < 0) {
container.find('label:first').addClass('hover');
} else if (e.keyCode == 40 && idx_old < labels.length - 1) {
idx_new = idx_old + 1;
} else if (e.keyCode == 38 && idx_old > 0) {
idx_new = idx_old - 1;
}
if (idx_new >= 0) {
jQuery(labels.get(idx_old)).removeClass('hover');
jQuery(labels.get(idx_new)).addClass('hover');
}
return false;
}
// space/return buttons
if (e.keyCode == 13 || e.keyCode == 32) {
var input_obj = container.find('label.hover input:checkbox');
input_obj.click();
return false;
}
});
// When the input is triggered with mouse
container
.find('input:checkbox')
.click(function(){
var cb = $(this);
var class = "checked";
if (cb.prop(class)){
cb.parent('label').addClass(class);
} else {
cb.parent('label').removeClass(class);
}
updateLog( cb.closest('label').text().split(/[\s\n]+/).join(' ') + ': '
+ this.checked + ' , '
+ cb.prop(class));
title.focus();
})
;
Notice the difference in the checkbox value for when you click directly on the checkbox, versus when you select the checkbox with the space/enter key. I believe this is because it's calling click during the keydown event, so the value of the checkbox is not yet changed; whereas if you actually click the input, the mouseup event occurs before the click (?), so the setting is applied.
The multiselect plugin does not call the click event, it has almost duplicate code. I'm curious if it would be better to pass a parameter to the click event (or use a global) to detect if it issued by the keyboard or mouse, or if it is better to just do what the plugin did and have the code inside the keydown function.
Obviously, if the log were after the click() runs, the keydown would return trues, but there are things that happen inside of click that are based on the input's checked status.
Changed it to use the change event instead of the click event for the checkboxes
http://jsfiddle.net/QJsPc/4/