How to hijack key combos in javascript? - javascript

In Gmail, for example, when one presses Ctrl + B, instead of it getting passed to the browser (which would normally bring up some sort of bookmark manager), it hijacks it for formatting purposes, i.e. turn on bold formatting for the message ur in the middle of comoposing. Same for Ctrl+i, Ctrl+u.
How is this done?

You would attach an onkeydown or onkeyup event handler to the global document object. For example, if I wanted to make the title bar change to "asdf" each time Ctrl-M was pressed, I would register the event handler through window.onload, like this:
window.onload = function()
{
document.onkeydown = function(event)
{
var keyCode;
if (window.event) // IE/Safari/Chrome/Firefox(?)
{
keyCode = event.keyCode;
}
else if (event.which) // Netscape/Firefox/Opera
{
keyCode = event.which;
}
var keyChar = String.fromCharCode(keyCode).toLowerCase();
if (keyChar == "m" && event.ctrlKey)
{
document.title = "asdf";
return false; // To prevent normal minimizing command
}
};
};
W3Schools has more information on using these events: onkeydown and onkeyup.
Also, I think I should note that there are some discrepancies across browsers in regards to the event properties (like, for example, in Firefox, you're supposed to access the keycode through event.which, while in IE it's event.keyCode, although Firefox may support event.keycode—confusing, isn't it?). Due to that, I'd recommend doing this stuff through a JavaScript framework, such as Prototype or jQuery, as they take care of all the icky compatibility stuff for you.

Here is the source for an HTML page that uses jQuery and does what htw's solution does.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Hijack Example</title>
<script type="text/javascript" src="../scripts/jquery-1.2.1.js">
</script>
<script type="text/javascript">
$(function(){
document.title = "before keypress detected";
$(document).keydown(function(event) {
// alert('stuff happened: ' + msg + " " + event.keyCode);
var keyChar = String.fromCharCode(event.keyCode).toLowerCase();
if (keyChar == "m" && event.ctrlKey) {
document.title = "ctrl-m pressed!";
}
});
});
</script>
</head>
<body id="body">
<p>Change the path to jquery above as needed (search for ../scripts/jquery-1.2.1.js)</p>
<p>Watch the title bar, then press control-M, then watch the title bar again!</p>
</body>
</html>
Hope this helps somebody!

Use the onkeydown or onkeyup event to fire a handler function:
var body = document.getElementsByTagName("body")[0];
body.onkeydown = function(event) {
var str = "";
for (var prop in event) {
str += prop + ": " + event[prop] + "<br>";
}
body.innerHTML = str;
};
With that you can see what properties an event object has.

Related

Native callback previous value of text input using JavaScript?

Edited:
I forgot to add a 'native' (for JS or browser) word to questions, as browsers (or JS i'm not sure) have a undo/redo feature in inputs, but it don't work with programmatically edited input and my main question is, if it is possible to add a code to trigger that native callback to previous value feature.
I tried to do this with document.execCommand paste/insertText but it didn't work and is marked as obsolete.
Old:
I have a custom action on keypress in input, for example where number have changed sign(+-) when '-' button is pressed.
I want to add that action to native undo/redo (ctrl+z/y) history stack, with preventing others default actions triggered when button responsible for my action is clicked.
Is this possible?
If no, to remove current, native undo/redo input feature, using event.preventDefault in crtl+z/y click detection would be enough? To replace it by custom undo/redo.
Is this dependable on browser?
I experimented with code on Firefox and Edge.
Is there something like History API for input available for JS and where i can read about it and how it is named in code?
As for similar topics in stack are old and i tried them but they didn't work (or i used them in wrong way).
$(document).ready(function() {
$(":input").on('keypress', function(e) {
//On minus button click, reverse sign for number in input:
if (e.key === '-') {
e.preventDefault();
//TODO: Add this change in input to undo/redo changes history:
$(this).val(-$(this).val());
}
});
});
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
Number: <input type="text" name="num"><br>
</body>
</html>
i3z slighty enchanted answer:
Ctrl+z instead of '-' button for Undo action.
Fixed bug with 2 clicks needed to use undo action after adding new element.
Sign change action from my question is added to code.
Added empty "" as default in history stack.
// Global Varaibles
// Edited: Added empty undo element, fixed undo working from 2nd click after adding new element to history.
var historyValues = [''];
var undoSteps = 2;
var maxSteps = 1;
var currentUndo = 1;
// Add event listener to track input and update historyValues
$(":input").on('input', function (evt) {
historyValues.push(this.value);
maxSteps = historyValues.length;
//console.log(historyValues);
// Check if 'Undo' been used if yes reset cause input been changed
if (undoSteps !== 2) {
undoSteps = 2;
}
});
$(document).ready(function() {
$(":input").on('keydown', function(e) {
if (undoSteps > maxSteps) {
// When you run out of backward steps, reset steps
undoSteps = 1;
}
// check for key (Edited: changed to z) and ensure 'currentUndo' not less than 0
if (e.ctrlKey && e.key === 'z' && currentUndo >= 0) {
e.preventDefault();
// tracking steps backward for every-time key '-' pressed
currentUndo = (maxSteps - undoSteps);
//console.log(maxSteps+' maxSteps - undoSteps '+undoSteps);
// Get previous value from history array
var newValue = historyValues[currentUndo];
//console.log(currentUndo+' current - value '+newValue);
$(this).val(newValue);
// Add +1 steps as we used undo once
undoSteps++;
}
});
$(":input").on('keypress', function(e) {
//Edited: Added custom action on key '-' press
if (e.key === '-') {
e.preventDefault();
$(this).val(-$(this).val());
//Trigger history
$(this).trigger('input');
}
});
});
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
Number: <input type="text" name="num"><br>
</body>
</html>
Simple Undo JS Script
You'll be able to capture event of (⌘ + z) or (CTRL + z). Therefore, you'll be able to preform this Undo JS implementation to have history stack of values every-time input changes.
You should have Event Listener (input) either via DOM or jQuery e.g.
$(":input").on('input', function (evt) {
console.log(this.value)
}
Now, you can trace any changes in input been targeted using jQuery Selector.
You should also define global variables inside your document, where you can track following:
History Stack (historyValues)
Steps To Take (undoSteps)
Maximum Steps (maxSteps)
Current Step (currentUndo)
Source Code
// Global Varaibles (Controls)
var historyValues = [''];
var undoSteps = 2;
var maxSteps = 1;
var currentUndo = 1;
// Add event listener to track input changes and update historyValues
$(":input").on('input', function (evt) {
historyValues.push(this.value);
maxSteps = historyValues.length;
//console.log(historyValues);
// Check if 'Undo' been used if yes reset cause input been changed
if (undoSteps !== 2) {
undoSteps = 2;
}
});
$(document).ready(function() {
$(":input").on('keydown', function(e) {
if (undoSteps > maxSteps) {
// When you run out of backward steps, reset steps
undoSteps = 1;
}
// Edited: Supports (⌘ + z and CTRL + z)
if ( (e.ctrlKey && e.key === 'z') || (e.metaKey && e.key === 'z') ) {
e.preventDefault();
// Ensure 'currentUndo' not less than 0
if (currentUndo >= 0) {
// tracking steps backward
currentUndo = (maxSteps - undoSteps);
// Get previous value from history array
var newValue = historyValues[currentUndo];
$(this).val(newValue);
// Add +1 steps as we used undo once
undoSteps++;
}
}
});
});
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
Number: <input type="text" name="num"><br>
</body>
</html>

Write keycode to console. Repeatedly

I'm having a small mental block: I've got a javascript function in html that writes the keycode when a key is pressed. I've got it hooked up to a function that tells me exactly what character and keycode is pressed (not included).
My question is how do I modify the code to print up keypress after keypress after keypress. At the moment it does just the one and then that's that.
There's a rather nicer version of what I'm doing here on css-tricks, with the code here
Admittedly the latter is running JS Babel which might be the difference. However, I need to do this in pure Javascript.
Bonus points: is keypress one word or two ;)
</script>
function check_keycode(e)
{
var keycode;
if (window.event)
{
keycode = window.event.keyCode;
}
else if (e)
{
keycode = e.which;
}
document.write("keycode: " + keycode);
//console.log("keycode: " + keycode);
}
</script>
I think you want some thing like this. I tried with chrome console.
HTML
<p id="log"></p>
JS:
const log = document.getElementById('log');
document.addEventListener('keypress', logKey);
function logKey(e) {
log.textContent += ` ${e.key}`;
}

event.altKey not working in chrome and IE

Assume we have this code:
<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script type="text/javascript">
var p = 0;
function reset()
{
// some efforts
}
function code(e) {
e = e || window.event;
return(e.keyCode || e.which);
}
window.onload = function(){
document.onkeypress = function(e){
var key = code(e);
if(key == 38 || key == 40)
{}
else if(e.altKey)
{
alert('altkey pressed');
}
else
{
// Another THING!
}
};
};
</script>
</head>
<body style="padding:30px; font-size:30px;font-family: Courier;">
<span onclick="reset();" accesskey="r"></span>
</body>
</html>
It works great in Firefox but not in IE an Chrome.
When I change alt into shift it works on all browsers. but as you may notice, I wanted to use this for Shortcut key and I think this is a problem of Alt key in Chrome and IE (because both use Alt for accesskey attribute but Firefox uses Alt+Shift as mentoned here).
So guys what you suggest me to do ?
You can not detect alt button on chrome because it enables the window menu, so your page lose focus and the event "keypress" is not called. The event "keydown" on the other hand is called so you can use it with no problem.

How can I capture keyboard events are from which keys?

I googled and got the following codes on the Net.However, when I press a keyboard key,it is not displaying me an alert box. I want to get which character I have pressed in the alert box. How do I fix this?
<script type="text/javascript">
var charfield=document.getElementById("char")
charfield.onkeydown=function(e){
var e=window.event || e;
alert(e.keyCode);
}
</script>
</head>
<body id="char">
</body>
</html>
If you want to get the character typed, you must use the keypress event rather than the keydown event. Something like the following:
var charfield = document.getElementById("char");
charfield.onkeypress = function(e) {
e = e || window.event;
var charCode = (typeof e.which == "number") ? e.which : e.keyCode;
if (charCode > 0) {
alert("Typed character: " + String.fromCharCode(charCode));
}
};
try this jquery code
$("body").keypress(function(e){
alert(e.which);
});
I can't off the top of my head think of a good situation in which to use the "on some event" method of a DOM element to deal with events on that element.
The best practice is to use addEventListener (or attachEvent in older versions of Internet Explorer) like so:
charfield.addEventListener('keydown', function (e) { alert(e.keyCode); }, false);
If you want to account for attachEvent as well:
(function (useListen) {
if (useListen) {
charfield.addEventListener('keydown', alertKeyCode, false);
} else {
charfield.attachEvent('onkeydown', alertKeyCode);
}
})(charfield.addEventListener);
function alertKeyCode(e) {
alert(e.keyCode);
}
You'll get the appropriate key code:
charfield.onkeydown=function(evt){
var keyCode = (evt.which?evt.which:(evt.keyCode?evt.keyCode:0))
alert(keyCode);
}

onKeyUp not firing for ESC in IE

I have a page where I have to close a dialog when Esc is pressed. I wrote the following simplified code example for this task:
<html>
<head>
<script language="JavaScript">
function keyUpExample() {
alert('on' + event.type + ' event fired by ' + '"' + event.srcElement.id + '" ' + ' ' + event.which)
}
</script>
</head>
<body id="myBody" onkeyup="keyUpExample()">
Trying keyUp event: Press any key...
</body>
</html>
This works as expected under Chrome but is NOT working under IE 7. Is there any workaround on order to cope this problem?
Thanks in advance!
Key events don't have to be caught by the body, but document or window works across browsers. Also, keyCode returns the correct value for keyup or down events.
<!doctype html>
<html lang="en">
<head>
<meta charset= "utf-8">
<title>Small Page</title>
<html>
<head>
<script>
function keyUpExample(e){
e=e || window.event;
var who= e.target || e.srcElement;
alert(e.type+' caught at '+who.nodeName+ ': key #'+e.keyCode)
}
window.onload=function(){
document.onkeyup= keyUpExample;
document.body.onkeyup= keyUpExample;
}
</script>
</head>
<body>
Trying keyUp event: Press any key...
</body>
</html>
Pass event as an argument to the callback, and check for window.event for IE.
<html>
<head>
<script>
function keyUpExample(e) {
e = e || window.event;
alert('on' + e.type + ' event fired by ' + '"' + e.srcElement.id + '" ' + ' ' + e.which)
}
</script>
</head>
<body id="myBody" onkeyup="keyUpExample()">
Trying keyUp event: Press any key...
</body>
</html>
Demo
element.onkeyup reference
However
You're better off using a library which smooths out all the ugly cross-browser inconsistencies. Take your pick: jQuery, Prototype, YUI, Dojo, MooTools, RightJS...
Are you allowed to use jQuery? If so, then you can accomplish it with .keyup().
Using jQuery also means you can generally leave the cross-browser worries to somebody else.
try
function keyUpExample(e) {
var evt = e || event;
alert('on' + evt.type + ' event fired by ' + '"' + ((evt.srcElement)?evt.srcElement.id:evt.target.id) + '" ' + ' ' + ((evt.which)?evt.which:evt.keyCode))
}
It is actually very simple, a raw JavaScript solution could look kinda like this
function callback(event) {
if (event.keyCode == 27) {
alert('Here you go!');
}
}
if (document.addEventListener) {
document.addEventListener('keydown', callback, false);
} else {
document.attachEvent('onkeydown', callback);
}
Just attach it to the document no need for any onload trickery.
Also, as people suggested you, check RightJS, it's very lightweight and friendly, and you will be able to do things like those :)
http://rightjs.org/plugins/keys

Categories