Triggering key combinations with the command key on mac

2 views
Skip to first unread message

pencilk...@gmail.com

unread,
Feb 27, 2014, 9:40:55 AM2/27/14
to node-...@googlegroups.com
I haven't seen any good solutions for this so I figure I would post it. I was trying to put in save and open keyboard shortcut functionality in my app and of course everything is done with the command (apple) key on the mac instead of the control key, so we need something for mac users. By the way this example uses jQuery and I could not find a way to do this without it. 

Creating keyboard shortcuts is riddled with strange behavior(even when we only have to worry about one browser!) so I hope this might prove useful for someone.

First in your html file, include these two inputs, one for save and for open, as per the documentation:

<input id="openInput" class="openInput" type="file" style="display:none" accept=".json" />
<input id="saveInput" type="file" nwsaveas style="display:none" accept=".json" />

I won't go into the nuances of the inputs as you can read about it in the wiki.

Next in our JS file we create a function that will listen for keyboard combinations of (CTRL + O or CMD + O) and (CTRL + S or CMD + S)
Once the key combination is detected we use a click handler function. For some reason you need the console.log otherwise it might not work.

// Listen for keydown events concerning saving and opening files
function listen_for_key_down ()
{
$(document).keydown(function(e) {
     console.log(e);

        // listen for CRL + O or CMD + O
if ( e.which == 79 && (e.ctrlKey || e.metaKey) )
{
    clickInput ('openInput');

}
                 // listen for CTRL + S or CMD + S
else if ( e.which == 83 && (e.ctrlKey || e.metaKey) )
{
                     clickInput ('saveInput');
}
});
}

And here's our click handler:
function clickInput(id)
{
    setTimeout(function() {
        $('#' + id).click();
     },1);
}

The handler takes the ID of the input that we want to click. Notice something weird though? First of all, I am using a setTimeout and second of all its only for one millisecond!
If we don't use a setTimeout what happens is that right after the input click is triggered, (I assume) because we are using a CMD + S command, the resulting save dialog that pops up immediately gets its save button pressed and pops back up, which is not what we want. So in order to fix this issue we can use a setTimeout, even though its only for one millisecond it prevents the save button in the save dialog from being pressed and the dialog disappearing. Ok! First bug tackled!

Next let's execute our function that starts this whole process:
listen_for_key_down();

If we left the code as is, it would almost work. The problem is that for some reason when you use the command key in a key combination, the first time you do it, the keyboard event seems to fire, however the input is mysteriously not clicked and therefore we are left without our dialog. If you do the key combo a second time, it works. This is of course a usability problem and will leave your app looking unprofessional, and we are professionals right?

We can solve this by simulating a keydown event. This is where jQuery comes in extra handy. Also notice the console.log here again, we need it otherwise it won’t work!

//simulate a keydown event
function simulateKeyDown ()
{
    setTimeout(function() {
        var e = $.Event('keydown');
   
e.metaKey = true;
        e.which = 83;
        $(document).trigger(e);
        
        console.log(e);
    }, 200);
}

simulateKeyDown ();

As you can see we use a setTimeout event again. If we don't, it doesn't work :/
We create a jQuery keydown event and populate the keys that will be 'pressed' by hand.

And Shazam! Now when you press CMD + S or CMD + O, you will get the correct functionality like a normal person :D
In this example though, we aren't actually saving anything, like some data to a file for example, for this functionality you can check out this tutorial and merge it with this code. 

I hope the devs see what kind of trouble a mac user has to go through to get simple functionality like this. What do you think? Got an easier way to do this? Share!  

Mikkel Schmidt

unread,
Feb 27, 2014, 4:56:04 PM2/27/14
to node-...@googlegroups.com, pencilk...@gmail.com
Have you tried https://github.com/madrobby/keymaster ? Much nicer to work with.

pencilk...@gmail.com

unread,
Feb 27, 2014, 6:49:11 PM2/27/14
to node-...@googlegroups.com, pencilk...@gmail.com
Just tried it. Gonna scrap all that code and use keymaster instead. Thanks!

Mikkel Schmidt

unread,
Feb 27, 2014, 7:21:03 PM2/27/14
to node-...@googlegroups.com
You're welcome :)

Med venlig hilsen / Kind regards.
Mikkel Schmidt
Founder
Circadio


--
You received this message because you are subscribed to a topic in the Google Groups "node-webkit" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/node-webkit/PcXrUoLFPVE/unsubscribe.
To unsubscribe from this group and all its topics, send an email to node-webkit...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply all
Reply to author
Forward
0 new messages