How can I add a keyboard shortcut to an existing JavaScript Function?
Asked Answered
P

12

81

Here is my code:

function pauseSound() {
    var pauseSound = document.getElementById("backgroundMusic");
    pauseSound.pause(); 
}

I would like to add a keyboard shortcut to this code, how can I do this so that the function can also be executed when a button is clicked too?

Tried to add an else if statement but it doesn't work, any ideas?

function doc_keyUp(e) {
    if (e.ctrlKey && e.keyCode == 88) {
        pauseSound();
    }

    else if (e.ctrlKey && e.keyCode == 84) {
        playSound();
    }
}
Phyllisphylloclade answered 24/3, 2010 at 21:2 Comment(1)
actual syntax for an else-if would be else if (<condition>) { <code> }. remove the hyphen.Modie
M
122

Handle the keyup event on the document.

Note that KeyboardEvent.keyCode was deprecated. Assuming the question code means to check keys by physical location, KeyboardEvent.code is the proper way to do so now.

// define a handler
function doc_keyUp(e) {

    // this would test for whichever key is 40 (down arrow) and the ctrl key at the same time
    if (e.ctrlKey && e.code === 'ArrowDown') {
        // call your function to do the thing
        pauseSound();
    }
}
// register the handler 
document.addEventListener('keyup', doc_keyUp, false);
Modie answered 24/3, 2010 at 21:16 Comment(7)
This works very well, thank you. How could I use this code twice because I need another shortcut key for 'playSound()'?Phyllisphylloclade
add an else-if statement similar to the first if statement, but change the keycode as necessary. make your playSound() call from there. if you want to use the same key for both activities, you'll have to set up a flag variable and check/set it whenever the key is pushed to determine which action to take.Modie
And what about those browsers that don't support addEventListener?Boogeyman
IE is the only one i've worked with that doesn't, and you would use document.attachEvent('onkeyup', doc_keyUp); there should be lots of references around to these about checking if a function exists before calling it.Modie
I tried to add an else-if but it doesn't work, please refer to the topic post to see the updated code.Phyllisphylloclade
@Chris: in your event handler you should add var e = e || window.event; to cover IE's specific event object.Ory
The Mozilla deprecation message says to use KeyboardEvent.code (in caution): "You should avoid using this if possible; it's been deprecated for some time. Instead, you should use KeyboardEvent.code, if it's implemented." developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCodeGarbers
C
11

If you want to trigger an event after pressing a key, try:

In this example press ALT+a:

document.onkeyup = function () {
  var e = e || window.event; // for IE to cover IEs window event-object
  if(e.altKey && e.which == 65) {
    alert('Keyboard shortcut working!');
    return false;
  }
}

Here is a fiddle: https://jsfiddle.net/dmtf6n27/38/

Please also note there is a difference for the keycode numbers, whether you are using onkeypress or onkeyup. W3 Schools' "KeyboardEvent keyCode" Property has more information.

Christine answered 20/2, 2016 at 15:40 Comment(2)
You writed "functione" instead of "function"Inductive
And you need to write the () after "function"Inductive
B
9
//For single key: Short cut key for 'Z'
document.onkeypress = function (e) {
    var evt = window.event || e;
    switch (evt.keyCode) {
        case 90:  
            // Call your method Here
            break;
    }
}

//For combine keys like Alt+P
document.onkeyup = function (e) {
    var evt = window.event || e;   
        if (evt.keyCode == 80 && evt.altKey) {
            // Call Your method here   
        }
    }
}
    //ensure if short cut keys are case sensitive.
    //    If its not case sensitive then
    //check with the evt.keyCode values for both upper case and lower case. ......
Beachhead answered 12/2, 2018 at 12:22 Comment(0)
B
5

Here's my solution:

HTMLElement.prototype.onshortcut = function(shortcut, handler) {
    var currentKeys = []
    
    function reset() {
        currentKeys = []
    }

    function shortcutMatches() {
        currentKeys.sort()
        shortcut.sort()

        return (
            JSON.stringify(currentKeys) ==
            JSON.stringify(shortcut)
        )
    }

    this.onkeydown = function(ev) {
        currentKeys.push(ev.key)

        if (shortcutMatches()) {
            ev.preventDefault()
            reset()
            handler(this)
        }

    }

    this.onkeyup = reset
}


document.body.onshortcut(["Control", "Shift", "P"], el => {
    alert("Hello!")
})
  • When you call my function, it will create an array called currentKeys; these are the keys that will are being held down at that moment.
  • Every time a key is pressed, sensed because of onkeydown, it is added to the currentKeys array.
  • When the keys are released, sensed because of onkeyup, the array is reset meaning that no keys are being pressed at that moment.
  • Each time it will check if the shortcut matches. If it does it will call the handler.
Behistun answered 7/3, 2021 at 16:0 Comment(0)
H
3

This worked for me

document.onkeyup=function(e){
  var e = e || window.event;
  if(e.which == 37) {
    $("#prev").click()
  }else if(e.which == 39){
    $("#next").click()
  }
}
Heartsome answered 8/7, 2017 at 11:13 Comment(1)
I tried using onkeyup but it was running 18 times on one press. Use onkeydown instead, it ran only once.Lepidosiren
A
1

Catch the key code and then call your function. This example catches the ESC key and calls your function:

function getKey(key) {
    if ( key == null ) {
        keycode = event.keyCode;
    // To Mozilla
    } else {
        keycode = key.keyCode;
    }
    // Return the key in lower case form    
    if (keycode ==27){
        //alert(keycode);
        pauseSound();
        return false;
    }
    //return String.fromCharCode(keycode).toLowerCase();
}
$(document).ready( function (){
    $(document).keydown(function (eventObj){
        //alert("Keydown: The key is: "+getKey(eventObj));
        getKey(eventObj);
    });
});

You'll need JQUERY for this example.

Archimedes answered 24/3, 2010 at 21:17 Comment(0)
W
1

Here's some stuff to use if you want. You can register a bunch of keys and handler with it.

Comments are in the code, but in short it sets up a listener on the document and manages a hash with the key combinations for which you want to listen.

  • When you register a key (combination) to listen for, you submit the keycode (preferrably as a constant taken from the exported "key" property, to which you can add more constants for yourself), a handler function and possibly an options hash where you say if the Ctrl and/or Alt key are involved in your plans for this key.
  • When you de-register a key (combination) you just submit the key and the optional hash for Ctrl/Alt-ness.
window.npup = (function keypressListener() {
    // Object to hold keyCode/handler mappings
    var mappings = {};
    // Default options for additional meta keys
    var defaultOptions = {ctrl:false, alt:false};
    // Flag for if we're running checks or not
    var active = false;
    
    // The function that gets called on keyup.
    // Tries to find a handler to execute
    function driver(event) {
        var keyCode = event.keyCode, ctrl = !!event.ctrlKey, alt = !!event.altKey;
        var key = buildKey(keyCode, ctrl, alt);
        var handler = mappings[key];
        if (handler) {handler(event);}
    }
    
    // Take the three props and make a string to use as key in the hash
    function buildKey(keyCode, ctrl, alt) {return (keyCode+'_'+ctrl+'_'+alt);}
    
    function listen(keyCode, handler, options) {
        // Build default options if there are none submitted
        options = options || defaultOptions;
        if (typeof handler!=='function') {throw new Error('Submit a handler for keyCode #'+keyCode+'(ctrl:'+!!options.ctrl+', alt:'+options.alt+')');}
        // Build a key and map handler for the key combination
        var key = buildKey(keyCode, !!options.ctrl, !!options.alt);
        mappings[key] = handler;
    }
    
    function unListen(keyCode, options) {
        // Build default options if there are none submitted
        options = options || defaultOptions;
        // Build a key and map handler for the key combination
        var key = buildKey(keyCode, !!options.ctrl, !!options.alt);
        // Delete what was found
        delete mappings[key];
    }
    
    // Rudimentary attempt att cross-browser-ness
    var xb = {
        addEventListener: function (element, eventName, handler) {
            if (element.attachEvent) {element.attachEvent('on'+eventName, handler);}
            else {element.addEventListener(eventName, handler, false);}
        }
        , removeEventListener: function (element, eventName, handler) {
            if (element.attachEvent) {element.detachEvent('on'+eventName, handler);}
            else {element.removeEventListener(eventName, handler, false);}
        }
    };
    
    function setActive(activate) {
        activate = (typeof activate==='undefined' || !!activate); // true is default
        if (activate===active) {return;} // already in the desired state, do nothing
        var addOrRemove = activate ? 'addEventListener' : 'removeEventListener';
        xb[addOrRemove](document, 'keyup', driver);
        active = activate;
    }
    
    // Activate on load
    setActive();
    
    // export API
    return {
        // Add/replace handler for a keycode.
        // Submit keycode, handler function and an optional hash with booleans for properties 'ctrl' and 'alt'
        listen: listen
        // Remove handler for a keycode
        // Submit keycode and an optional hash with booleans for properties 'ctrl' and 'alt'
        , unListen: unListen
        // Turn on or off the whole thing.
        // Submit a boolean. No arg means true
        , setActive: setActive
        // Keycode constants, fill in your own here
        , key : {
            VK_F1 : 112
            , VK_F2: 113
            , VK_A: 65
            , VK_B: 66
            , VK_C: 67
        }
    };
})();
  
// Small demo of listen and unListen
// Usage:
//   listen(key, handler [,options])
//   unListen(key, [,options])
npup.listen(npup.key.VK_F1, function (event) {
    console.log('F1, adding listener on \'B\'');
    npup.listen(npup.key.VK_B, function (event) {
        console.log('B');
    });
});
npup.listen(npup.key.VK_F2, function (event) {
    console.log('F2, removing listener on \'B\'');
    npup.unListen(npup.key.VK_B);
});
npup.listen(npup.key.VK_A, function (event) {
    console.log('ctrl-A');
}, {ctrl: true});
npup.listen(npup.key.VK_A, function (event) {
    console.log('ctrl-alt-A');
}, {ctrl: true, alt: true});
npup.listen(npup.key.VK_C, function (event) {
    console.log('ctrl-alt-C => It all ends!');
    npup.setActive(false);
}, {ctrl: true, alt: true});

It is not terribly tested, but seemed to work OK.

Look at Javascript Char Codes (Key Codes) to find a lot of keyCodes to use,

Waisted answered 25/3, 2010 at 0:8 Comment(0)
B
1

These appear to all be using the deprecated keyCode and which properties. Here is a non-deprecated version using jQuery to wire up the event:

$("body").on("keyup", function (e) {
    if(e.ctrlKey && e.key == 'x')
        pauseSound();
    else if(e.ctrlKey && e.key == 't')
        playSound();
})

Note: Ctrl+t may already be assigned to opening a new browser tab.

Benedict answered 30/5, 2018 at 21:36 Comment(2)
.key is the non-deprecated property?Countermand
It does look like key is the recommended property, although it is not supported in Safari: w3schools.com/jsref/event_key_key.aspHollywood
A
0

Solution:

var activeKeys = [];

//determine operating system
var os = false;
window.addEventListener('load', function() {
  var userAgent = navigator.appVersion;
  if (userAgent.indexOf("Win") != -1) os = "windows";
  if (userAgent.indexOf("Mac") != -1) os = "osx";
  if (userAgent.indexOf("X11") != -1) os = "unix";
  if (userAgent.indexOf("Linux") != -1) os = "linux";
});

window.addEventListener('keydown', function(e) {
  if (activeKeys.indexOf(e.which) == -1) {
    activeKeys.push(e.which);
  }

  if (os == 'osx') {

  } else {
    //use indexOf function to check for keys being pressed IE
    if (activeKeys.indexOf(17) != -1 && activeKeys.indexOf(86) != -1) {
      console.log('you are trying to paste with control+v keys');
    }
    /*
      the control and v keys (for paste)
      if(activeKeys.indexOf(17) != -1 && activeKeys.indexOf(86) != -1){
        command and v keys are being pressed
      }
    */
  }
});

window.addEventListener('keyup', function(e) {
  var result = activeKeys.indexOf(e.which);
  if (result != -1) {
    activeKeys.splice(result, 1);
  }
});

Explanation: I ran into this same problem and came up with my own solution. e.metaKey didn't seem to work with the keyup event in Chrome and Safari. However, I'm not sure if it was specific to my application since I had other algorithms blocking some key events and I may have mistakenly blocked the meta key.

This algorithm monitors for keys going down and then adds them to a list of keys that are currently being pressed. When released, the key is removed from the list. Check for simultaneous keys in the list by using indexOf to find key codes in the array.

Aurlie answered 14/2, 2016 at 5:5 Comment(0)
L
0

Saving with ctrl+s in React

useEffect(() => {
        document.onkeydown = function (e) {
            if (e.ctrlKey == true && e.key == 's') {
                e.preventDefault() // to override browser's default save page feature
                alert('ctrl+s is working for save!') // invoke your API to save
            }
        }
}, [])
Lepidosiren answered 27/8, 2021 at 7:51 Comment(0)
T
0

Many of these answers suggest forcibly overriding document.onkeypress. This is not a good practice because it only allows for a single event handler to be assigned. If any other handlers were previously set up by another script they will be replaced by your function. If you assign another handler later, it will replace the one you assigned here.

A much better approach is to use addEventListener to attach your keyboard shortcut. This allows you to attach as many handlers as necessary and will not interfere with any external libraries that may have attached their own.

Additionally, the UIEvent.which property was never standardized and should not be used. The same goes for KeyboardEvent.keyCode. The current standards compliant property you should use to check which key was pressed is KeyboardEvent.key. Find the key you want in the full list of available values.

For best performance, return early if your desired modifier key is not pressed. As well, rather than having multiple keypress event listeners, use a single one with a swtich/case statement to react appropriately to each key that you want to handle.

Also, do not forget to cancel the default behavior of the key with Event.preventDefault if necessary. Though, there are some shortcuts that you cannot override like ctrl+w.

document.addEventListener('keypress', event => {
  if (!event.ctrlKey) { return; }
  event.preventDefault();
  switch (event.key) {
    case 'x' : doSomething(); break
    case 'z' : doSomethingElse(); break;
    default : console.log('unhandled key was pressed');
  }
});
Telemark answered 5/6, 2022 at 17:25 Comment(0)
T
0

This works for Ctrl + Shift + L

document.onkeydown = function (e) {
  // Detect if Ctrl + Shift is pressed together
  if (e.ctrlKey && e.shiftKey) {
    // Detect if L is pressed after Ctrl + Shift
    if (e.key == "L")
    {
      // Your code...
    }
  }
};
Tuchman answered 17/12, 2023 at 22:37 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.