Trapping keydown with basic JavaScript - javascript

I am fairly new to coding (Doing the foundation course on The Odin Project).
I am having some problems with the calculator project.
I want the calculator to be driven by both mouse & keyboard.
But when I press keys like "/", "." these are not trapped by Firefox or Chrome additionally Chrome is not trapping some more keys like "-" & "+".
window.addEventListener("click", mouseClick);
window.addEventListener("keydown", keyPress);
The keyPress function simply calls the element.click() so that mouseClick() is emulated.
It seems if I press the above keys - the keys are not trapped by the "click" event handler.
Any help will be highly appreciated.
My System Details:
Firefox 93.0 / Chrome 94.0.4606.81 on Fedora 34 x64.
The two functions are below, as requested:
A small addition: I have uBlock Origin/ Bitwarden installed in Firefox (no addons on chrome), but I guess they should not interfere in anyway?
window.addEventListener("click", mouseClick);
window.addEventListener("keydown", keyPress);
function keyPress(event){
let keyCode = event.keyCode;
if(keyCode === 13){
keyCode = 61;
}
let btnPressed = document.querySelector(`button[data-key="${keyCode}"]`);
if(!btnPressed){
return;
}
console.log(btnPressed);
btnPressed.click(); };
function mouseClick(event){
if(!(event.target.tagName === "BUTTON")){
return;
}
let currentButton = event.target.textContent;
if(event.target.classList.contains("num-key")){
if(tmpNumArray.some(item => (item === ".")) && currentButton === "."){
return;
}
tmpNumArray.push(currentButton);
currNum = tmpNumArray.join("");
refreshDisplay();
}else{
alert ("pressed operator");
} };

Related

How to detect Caps Lock is ON on web browser on Android Devices using JavaScript?

We can very well detect CapsLock is ON/not on iPhone web browser using KeyboardEvent.getModifierState(), with sample code,
function checkCapsLock(e) {
if (e.getModifierState("CapsLock")) {
alert("Caps ON");
}
}
But it doesn't work on a browser on Android Devices. I've tried many other solutions using charCode, keyCode, shiftKey, which, etc. methods on the event with listeners like keyup, keydown, keypress, etc. But no luck.
I've gone through the answers mentioned on stackoverflow, and other links too. But still no luck.
Is there any workaround for this?
I'm asking about the issue on the Android web browser!
With Key Event Viewer, we can observe that CapsLock can be detected on Web or mobile web browser on iPhone, but not on a web browser on Android devices.
While this code works on some Android devices, it won't work on all, because the e.ShiftKey turns out to be false in Android. On android, it actually depends on your keyboard.
This is the best, I was able to come up with.
document.addEventListener ('keyup', function (event){
let status = checkCapsLock(event);
document.getElementById("status").innerHTML += ('<span class="'+ status +'">Status: ' + status + '</span>');
});
function checkCapsLock(e) {
e = e ? e : window.event;
if (e.getModifierState('CapsLock'))
return true;
let isShiftOn = e.shiftKey;
let s = e.key;
if(s.length != 1){
let keyCode = e.keyCode; //e.KeyCode is always 229 on Android;
if(keyCode == 229)
s = (e.target.value).split('').pop();
}
if ( (s.length != 0 ) && (s.toUpperCase() === s) && !isShiftOn )
return true;
return false;
}
span{
display: block;
background: red;
}
span.true{
background: green;
}
Input: <input id="targetInput">
<p id="status"></p>

jquery mobile - keyup keydown on mobile devices

I have a need for an input (type='text') to go send results to the my server to check availability of something typed by the user.
I use the delegate to add the event handlers to the elements:
$(document).delegate('#signup', 'pageshow', function() {
var keydown = function(e) {
e = e || window.event;
var char = e.which || e.keyCode;
if (char == 8) {
$(".pagemessage").text("Pressed: '<BACKSPACE>'");
appcheckDomainOnKeyDown();
}
return true;
};
var keyup = function(e) {
e = e || window.event;
var char = e.which || e.keyCode;
if (char == 8) {
appcheckDomainOnKeyUp();
}
return true;
};
var keypress = function(e) {
e = e || window.event;
var char = e.which || e.keyCode;
var str = String.fromCharCode(char);
$(".pagemessage").text("Pressed: '" + str +"'");
if (/[a-zA-Z0-9-\._]/.test(str) || char == 8 || char == 9) {
appcheckDomainOnKeyDown();
appcheckDomainOnKeyUp();
return true;
}
return false;
};
The key handers work perfectly on my desktop but not on a mobile device. Hopefully you can see that I'm trying to allow certain characters into the box (and a backspace to delete the characters.
From the fact I cannot see the pagemessage element update, 'keypress' does not seem to be trapped. I tried handling this in the keyup/keydown, but I'm not sure how to apply the shiftKey bits to get an actual character pressed - for example pressing + 5 would give '%' however in the keydown it returns shiftKey and 5.
I read the documentation and the closest I could find to 'keypress' was a 'tap' event, but that didn't work either.
I have tried trapping the 'keypress' event as suggested in one post here, and on a desktop this does not trap the backspace, and does nothing at all on a mobile device.
I then tried this as suggested in another post:
var inputEV = 'oninput' in window ? 'input' : 'keyup';
$("#new_domain").off(inputEV);
$("#new_domain").on(inputEV, function (e) {
keydown(e);
keyup(e);
});
and it does not work in either desktop browser or mobile device.
I then tried changing the input type to 'search', and I get a pretty enhancement, that a keypress does add a clear button... but does nothing on the mobile device regarding my own functionality.
I think I have run out of things to try, the only thing left is to add a button to go check - and no one wants that :)
Anyone know how I can do what I need?
In case it's relevant, I'm using chrome on my desktop and android device (HTC one, and Nexus 5)
Keyup should work. It works in this example: http://jsbin.com/aNEBIKA/2/. That tested find on my Galaxy S3. Each keypress updates the footer h3 element with the text entered.
Could it be that you are binding your listeners at the wrong time? The documentation does suggest binding like this:
$(document).bind('pageinit')
http://demos.jquerymobile.com/1.2.0/docs/api/events.html

Noninterrupting keyevents while preserving individual keystrokes

I am designing a keyboard interface through javascript, and I want to define keystroke combinations, like shift+rightkey or ctrl+tab. But after tinkering with javascript, as seen here, I've noticed that all keyevents are interrupting. In the provided example, if you go to hit the shiftkey while holding down the rightkey, the functionality of the rightkey is interrupted!
v = 1; /*v is the variable of velocity.*/
window.addEventListener("keydown", function(event)
{
if(event.keyCode == 39) /*39 is the keycode of rightarrowkey.*/
{
//moves an element by the velocity.
var keystroke = document.getElementById("keystroke");
keystroke.style.left = parseInt(keystroke.style.left.slice(0,-2))+v+"px";
}
if(event.keyCode == 16) /*16 is the keycode of shift.*/
{
//increases the velocity of the element by four.
document.getElementById("keystroke").style.borderColor = "red";
v = 4;
}
}, false); //but hitting the shiftkey while hitting the rightkey interrupts..!
I also experimented with recording all keystrokes through an object which is then iterated through at a designated interval for defined keystrokes, as seen here. But this system of handling the keyboard doesn't preserve the individual keystrokes; if I hit a key too fast, it may not be considered, or if I hold a key for too long, it may be overconsidered!
After giving it a bit of thought, I may have figured out a method to both preserve each keystroke while handling interrupting keyevents. My code is somewhat quirky, but it works well for managing the keystrokes from the users.
The solution to handling each keystroke without interruptions was through registering each keyevent within an object, as was previously suggested in my question. The code continually iterates through this object to handle any new keyevents.
But to ensure each keystroke is preserved and handled at least once, a keybinding must be registered for each keyevent. I expanded the scripting for the object to register both keystrokes as well as keybindings.
var kbdin =
{
stroked: new Object(),
upbinded: new Object(),
downbinded: new Object(),
downbindKeystroke: function(keycode, functionality) {this.downbinded[keycode] = functionality;},
upbindKeystroke: function(keycode, functionality) {this.upbinded[keycode] = functionality;},
isDownbinded: function(keycode) {return this.downbinded[keycode];},
isUpbinded: function(keycode) {return this.upbinded[keycode];},
isStroked: function(keycode) {return this.stroked[keycode];},
onDownstroke: function(event)
{
var keycode = event.keyCode;
if(!this.isStroked(keycode))
{
this.stroked[keycode] = 1;
if(this.isDownbinded(keycode))
{this.downbinded[keycode]();}
}
if(this.isDownbinded(keycode))
{event.preventDefault();}
},
onUpstroke: function(event)
{
var keycode = event.keyCode;
delete this.stroked[keycode];
if(this.isUpbinded(keycode))
{
this.upbinded[keycode]();
event.preventDefault();
}
},
handleKeystrokes: function()
{
for(var keycode in this.downbinded)
{
if(this.isStroked(keycode) > 5)
{this.downbinded[keycode]();}
}
for(var keycode in this.stroked)
{this.stroked[keycode]++;}
}
};
document.addEventListener("keyup", function(event) {kbdin.onUpstroke(event);}, false);
document.addEventListener("keydown", function(event) {kbdin.onDownstroke(event);}, false);
window.setInterval(function() {kbdin.handleKeystrokes();}, 50);
Now both the keystrokes and keybindings are coupled together, supporting each keyevent with the functionality to both signal a keystroke and execute a keybinding. It may be a bit quirky, but this code handles noninterrupting keyevents while still preserving individual keystrokes!

Handling 'ctrl+s' keypress event for browser

I was trying to implement the CTRL+S feature for a browser based application. I made a search and came across two scripts in the following to questions
Best cross-browser method to capture CTRL+S with JQuery?
Ctrl+S preventDefault in Chrome
However, when I tried to implement it, it worked but, I still get the default browser save dialog box/window.
My Code:For shortcut.js:
shortcut.add("Ctrl+S",function() {
alert("Hi there!");
},
{
'type':'keydown',
'propagate':false,
'target':document
});
jQuery hotkeys.js:
$(document).bind('keydown', 'ctrl+s', function(e) {
e.preventDefault();
alert('Ctrl+S');
return false;
});
I believe e.preventDefault(); should do the trick, but for some reason it doesn't work. Where am I going wrong.Sorry if it is simple, still learning jJvascript.
You don't need any of those libraries, just try this:
$(document).on('keydown', function(e){
if(e.ctrlKey && e.which === 83){ // Check for the Ctrl key being pressed, and if the key = [S] (83)
console.log('Ctrl+S!');
e.preventDefault();
return false;
}
});
The problem was that your code halted at the alert(), preventing your function from interrupting the save dialogue.
(Still uses jQuery)
This is to just add a different implementation to the question used by me.
Adapted from a SO answer.Also,works for MAC
document.addEventListener("keydown", function(e) {
if (e.keyCode == 83 && (navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey)) {
e.preventDefault();
//your implementation or function calls
}
}, false);
People are still viewing this it seems, so it's probably worth pointing out that there is no need for jQuery on this one, here:
function keydown (event) {
var isCtrlKeyDown = navigator.platform.indexOf("Mac") > -1 ? event.metaKey : event.ctrlKey,
isSDown = (event.key && event.key === "s") || (event.keyCode || event.which) === 83 // falls back to keycode if no event.key
if (isCtrlKeyDown && isSDown) {
// prevent default event on newer browsers
if (event.preventDefault) {
event.preventDefault()
}
// ... your code here ...
// prevent default event on older browsers
return false
}
}
// register the event
if (document.addEventListener) {
document.addEventListener("keydown", keydown)
} else {
document.onkeydown = keydown
}
That should work in all browsers, this will also work for folks using alternative keyboard layouts from QWERTY on Windows, which reports incorrect key codes (at least on Chrome 56 on Windows 10 in my testing)
However, this looks kind of clunky, and confusing, so if you are only supporting modern browsers, you can do the following instead:
document.addEventListener("keydown", function keydown (event) {
if (navigator.platform === "MacIntel" ? event.metaKey : event.ctrlKey && event.key === "s") {
event.preventDefault()
// ... your code here ...
}
})
As of 2017, instead of using e.keyCode === 83 you should use e.key === 's' as the former is deprecated.
No need to use any plugin, just use below jquery code
$(document).bind('keydown', 'ctrl+s', function (e) {
if (e.ctrlKey && (e.which == 83)) {
e.preventDefault();
//Your method()
return false;
}
});
Since you are using alert, the execution halts at the alert and "return false" is not executed until you close the alertbox, thats the reason you see the default dialog.
If your method is long running better use asyn method method instead.

Stuck alt / modifier key with Javascript

I have a library that creates an editor on the fly (http://epiceditor.com) and also sets up key shortcuts automatically. The shortcuts can be configured in the options so I can't use e.altKey, e.ctrlKey, etc just a heads up.
For some reason the modifier key isn't being set back to false sometimes on Mac/Ubuntu browsers.
On Windows it seems to happen every time. You can reproduce this by clicking render in JSBin then pressing alt+p. You should see "Yay" appear. Now, if on Windows press just p again. You'll see "Yay appear again. Mac and Ubuntu users have seen this same issue occasionally but it's hard to reproduce it.
Also note this only happens with the alt key it seems. Below I have 16 (shift) next to the 18 (alt). If you swap those out it'll work as expected.
The code for the stripped down test case is:
var modKey = false;
var modKeyCode = 18; //16
document.body.addEventListener('keydown', function (e) {
if (!modKey && modKeyCode == e.keyCode) {
modKey = true;
}
if (modKey && e.keyCode == 80) {
console.log('Yay!');
}
});
document.body.addEventListener('keyup', function (e) {
if (modKey && modKeyCode == e.keyCode) {
modKey = false;
}
});
Demo: http://jsbin.com/uhupah/3/edit#javascript,html
I do not have access to my Linux box at the moment, so i cannot test your code.
Thus here is more of a suggestion:
Linux (in my experience) is finicky when it it comes to keyCodes and order of key events. Perhaps combine the if(..) from keyup with that of keydown
if (!modKey && modKeyCode == e.keyCode) {
modKey = true;
} else if (modKey && modKeyCode == e.keyCode) {
modKey = false;
}
The above suggestion is made with assumption that you have no specific requirement to have both 'keydown' and 'keyup'.
I've come up with a fix, albeit a sort of crappy fix, but a fix nonetheless.
The fix I went with was to reset the modifier var when any key combo was successful. I.e. one the p in alt+p is pressed reset the modKey to false like this:
var modKey = false;
var modKeyCode = 18; //16
document.body.addEventListener('keydown', function (e) {
if (!modKey && modKeyCode == e.keyCode) {
modKey = true;
}
if (modKey && e.keyCode == 80) {
console.log('Yay!');
modKey = false; //THIS
}
});
document.body.addEventListener('keyup', function (e) {
if (modKey && modKeyCode == e.keyCode) {
modKey = false;
}
});
The problem with this tho is that you can't do back to back key commands. Most of the time this is alright because the user will do a key command like "save" or "preview" or something, type some more, then do another key command. But you wouldn't be able to, let's say: alt+p s to trigger alt+p then alt+s without having to let go of the alt key.

Categories