How does one capture a Mac's command key via JavaScript? - javascript

How does one capture a Mac's Cmd key via JavaScript?

EDIT: As of 2019, e.metaKey is supported on all major browsers as per the MDN.
Note that on Windows, although the ⊞ Windows key is considered to be the "meta" key, it is not going to be captured by browsers as such.
This is only for the command key on MacOS/keyboards.
Unlike Shift/Alt/Ctrl, the Cmd (“Apple”) key is not considered a modifier key—instead, you should listen on keydown/keyup and record when a key is pressed and then depressed based on event.keyCode.
Unfortunately, these key codes are browser-dependent:
Firefox: 224
Opera: 17
WebKit browsers (Safari/Chrome): 91 (Left Command) or 93 (Right Command)
You might be interested in reading the article JavaScript Madness: Keyboard Events, from which I learned that knowledge.

You can also look at the event.metaKey attribute on the event if you are working with keydown events. Worked wonderfully for me! You can try it here.

I found that you can detect the command key in the latest version of Safari (7.0: 9537.71) if it is pressed in conjunction with another key. For example, if you want to detect ⌘+x:, you can detect the x key AND check if event.metaKey is set to true. For example:
var key = event.keyCode || event.charCode || 0;
console.log(key, event.metaKey);
When pressing x on it's own, this will output 120, false. When pressing ⌘+x, it will output 120, true
This only seems to work in Safari - not Chrome

Basing on Ilya's data, I wrote a Vanilla JS library for supporting modifier keys on Mac: https://github.com/MichaelZelensky/jsLibraries/blob/master/macKeys.js
Just use it like this, e.g.:
document.onclick = function (event) {
if (event.shiftKey || macKeys.shiftKey) {
//do something interesting
}
}
Tested on Chrome, Safari, Firefox, Opera on Mac. Please check if it works for you.

For people using jQuery, there is an excellent plugin for handling key events:
jQuery hotkeys on GitHub
For capturing ⌘+S and Ctrl+S I'm using this:
$(window).bind('keydown.ctrl_s keydown.meta_s', function(event) {
event.preventDefault();
// Do something here
});

keyCode and which are now deprecated so it's advisable to avoid the answers that use those here.
One way to do this now is using the key property on the event argument that comes with DOM keyup and keypress events. Here's a simple example of how to do it:
document.onkeypress = (event) => {
if (event.key === 'Meta') {
console.log("Mac or Windows key was pressed!");
} else {
console.log("Another key was pressed")
}
}
This will trigger on the cmd key press on Mac (See Meta on the MDN docs). The only thing to note here is it will also trigger on the Windows key press too for the users keyboard/OS that support it.
If you need more granular understanding of which Meta key has been pressed, you can use the code property on event which can be either MetaLeft or MetaRight depending on which physical meta key ( cmd) was pressed.

Here is how I did it in AngularJS
app = angular.module('MM_Graph')
class Keyboard
constructor: ($injector)->
#.$injector = $injector
#.$window = #.$injector.get('$window') # get reference to $window and $rootScope objects
#.$rootScope = #.$injector.get('$rootScope')
on_Key_Down:($event)=>
#.$rootScope.$broadcast 'keydown', $event # broadcast a global keydown event
if $event.code is 'KeyS' and ($event.ctrlKey or $event.metaKey) # detect S key pressed and either OSX Command or Window's Control keys pressed
#.$rootScope.$broadcast '', $event # broadcast keyup_CtrS event
#$event.preventDefault() # this should be used by the event listeners to prevent default browser behaviour
setup_Hooks: ()=>
angular.element(#.$window).bind "keydown", #.on_Key_Down # hook keydown event in window (only called once per app load)
#
app.service 'keyboard', ($injector)=>
return new Keyboard($injector).setup_Hooks()

var element = //the DOM element to listen for the key on.
element.onkeyup = function(e) {
if(e.metaKey) {
//command key was pressed
}
}

if you use Vuejs, just make it by vue-shortkey plugin, everything will be simple
https://www.npmjs.com/package/vue-shortkey
v-shortkey="['meta', 'enter']"·
#shortkey="metaEnterTrigged"

Related

Can CMD/CTRL+Shift+1-9 be captured in browser js?

I'm building an SPA where it would be quite useful if I could capture the shortcuts cmd/ctrl+shift+1 through 9. It appears to me that this should be possible, since no browser I know binds these keys to anything else, but for some reason, pressing cmd+shift+1 (I'm using a macbook) fails to even cause a keyboard event.
Is this an inherent limitation of Chrome, or is there some special thing that I don't know of that needs to be done to capture these events?
I don't have a macbook, but I can capture ctrl+shift+1 (be sure to give focus to the snippet results frame):
document.body.addEventListener('keyup', function(e)
{
if((e.code == 'Digit1' || e.code == 'Numpad1') && e.ctrlKey && e.shiftKey)
{
console.log('ctrl+shift+1');
}
else
{
console.log(e.key, 'pressed')
}
});
This is layout dependent, i.e. if you are not using QWERTY, beware! See the KeyboardEvent page for help with different keyboard layouts.

How to get platform specific info for shortcuts?

How can I get platform specific shortcut, or key binding for a specific process?
As an example how can I get the information that on Windows shortcut for copying is Ctrl + C ? (I'd like the information on all of the tagged languages if possible) I mean both text editing and file manager usage, and also would like to know if they're independent.
If I understand you, you want rewrite system command of browser. In browser all process start after some event. You can copy text , if you use command for copy: document.execCommand('copy'); and you can rewrite all events except paste.
Example:
document.addEventListener('keydown', (ev) => {
if(ev.keyCode === 67 && ev.ctrlKey === true) { // ctrl+c
console.log(ev);
ev.preventDefault();//block default action of browser
}
});
and trigger copy:
document.addEventListener('keydown', (ev) => { //ctrl+z
if(ev.keyCode === 90 && ev.ctrlKey === true) {
console.log(ev);
document.execCommand('copy');
ev.preventDefault();
}
});
All execCommand: https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand
To expand on my comment above, you need to check for evt.metaKey to catch standard macOS shortcuts, which use the same letter keys for the basic Cut/Copy/Paste/Undo as Windows (X/C/V/Z), but combined with the different command (⌘) modifier key.
It doesn't hurt in most cases if a Mac user can also use their control key as well as the command key for a shortcut, so the easiest solution is to check for both. Here's code from the previous answer modified to do that:
document.addEventListener('keydown', (ev) => {
if (ev.keyCode === 67 && (ev.ctrlKey || ev.metaKey)) { // Copy shortcut
console.log(ev);
ev.preventDefault(); // block default action of browser
}
});
On a Windows system, you'll probably never see a keyboard event with metaKey being true, because as far as I can tell, any keypress using the Win key (⊞), which theoretically maps to metaKey, will be intercepted by Windows before a web browser has any chance to look at it.
If you want to explore more about key events and modifier keys, I threw together a quick CodePen here for that: https://codepen.io/kshetline/pen/MWmKrPM?editors=1010

get ctrl-f/ctrl-a keypresses in node-webkit

I'm building a node-webkit app, am listening for keypress events (in an angular directive).
Most combinations of keypress are working, but ctrl+f and ctrl+a are both not working.
This problem is specific to node-webkit. I've got the ctrl+a etc. working in the browser, but not in node-webkit.
I'm listening for keypress with the usual
document.bind('keypress',function...)
window.bind('keypress', function...)
window.bind('onkeypress', function...)
window.bind('keydown', function...)
any suggestions? Remember, the other combinations of keys ctrl+shift+o, etc. are working.
As this is a node-webkit app, there is no browser based 'find' function, and I'm disabling the 'select all'.
Isn't it an answer you where looking for?
There is a fiddle in answer of ctrl+f. If you replace 70 to 65 in this example, it will also work for ctrl+a.
document.onkeydown = function (e) {
/// check ctrl + f key
if (e.ctrlKey === true && e.keyCode === 70/*65*/) {
e.preventDefault();
console.log('Ctrl + f was hit...');
return false;
}
}
Here is a library you can use to add ctrl+f "find" support in NW.js.
https://github.com/nwutils/find-in-nw
ctrl+a to "select all" is already built in to Normal and SDK versions of NW.js
However, if you want to override the default "ctrl+a", then Andrew's answer is correct and will do that. Listen for the event and prevent default.

Finding function catching key event in Javascript?

I'm writing a user script for a complex web app. The existing code is catching the 'j' and 'k' keydown events.
I'd like to be able to find this function to see what it's doing. Is there a way to list all the key event handlers in a document? Or maybe a way to set a breakpoint somehow in Chrome Developer Tools for when I press the letter?
Yes, in the developer tools, go to the Scripts tab, select the page, go to Event Listener Breakpoints, Keyboard, keydown.
Though this might not necessarily help you much, e.g. if the script is minified or they use a library. But you can give it a try.
If you can get a piece of your script to run first and if the keys are handled at the document level, you can install this intercept to see what part of the code is setting the keyboard handler:
var oldListener = document.addEventListener;
document.addEventListener = function(type, listener, capture) {
if (type == "keydown" || type == "keyup" || type == "keypress") {
console.log("type=" + type + " listener=" + listener.toString().slice(0, 80));
}
return (oldListener.apply(this, arguments));
}

Binding keys with javascript while preventing the browser shortcut keys

I'm making a javascript game and need to bind a lot of keys to different functions. This I know how to do, what I need some help on is over-riding the shortcut keys for the browser. in other-words I want to blur hot keys for the browser and divert them to my application.
I believe that if you stop the propogation of the event, then you will prevent the browser from catching the event.
an example of this:
element.onkeyup = function(e) {
var ev = e || event;
//do stuff here, probably with ev.keyCode
return false;
}

Categories