Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6895957
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 27, 20262026-05-27T06:58:29+00:00 2026-05-27T06:58:29+00:00

I have a web app I’m developing and I’m trying to have CTRL+S and

  • 0

I have a web app I’m developing and I’m trying to have CTRL+S and COMMAND+S be the shortcut keys to save. I’ve looked at http://www.openjs.com/scripts/events/keyboard_shortcuts/ and it doesn’t properly capture the “meta” key.

Any advice?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-27T06:58:29+00:00Added an answer on May 27, 2026 at 6:58 am

    Latest Edit: Please, before downvoting this response take in mind that this is a very old response (2011) and has not been updated. Obviously there are better responses now (like the one by lapin) but that doesn’t mean that mine is invalid.

    You can use jquery hotkeys.

    Edit: There’s a newer version on github and you can use the ‘meta’ modifier to grab command+:

     $(document).bind('keydown', 'meta+s', myaction.save);
    

    Edit2: You can also use the Mousetrap library/vendor, which is jQuery-free.

    Download the latest version and modify it following the changes in this attachment: http://code.google.com/p/js-hotkeys/issues/detail?id=26

    You only need to add three lines:

    At line 188 aprox. (under ctrl = event.ctrlKey,) add this:

    cmd = event.metaKey && !ctrl,
    

    Then, add a negation to the if at line 203 aprox. ( if(!shift && !ctrl && !alt){ ):

    if(!shift && !ctrl && !alt && !cmd){
    

    Finally, under if(shift) modif += 'shift+'; add this:

    if(cmd) modif += 'command+';
    

    Now when you create a binding to command+whatever it will grab it:

    $(document).bind('keydown', 'command+s', myaction.save);
    

    Here you can grab the latest current version (0.7.9) modified:

    /*
    (c) Copyrights 2007 - 2008
    
    Original idea by by Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/
    
    jQuery Plugin by Tzury Bar Yochay 
    tzury.by@gmail.com
    http://evalinux.wordpress.com
    http://facebook.com/profile.php?id=513676303
    
    Project's sites: 
    http://code.google.com/p/js-hotkeys/
    http://github.com/tzuryby/hotkeys/tree/master
    
    License: same as jQuery license. 
    
    USAGE:
        // simple usage
        $(document).bind('keydown', 'Ctrl+c', function(){ alert('copy anyone?');});
    
        // special options such as disableInIput
        $(document).bind('keydown', {combi:'Ctrl+x', disableInInput: true} , function() {});
    
    Note:
        This plugin wraps the following jQuery methods: $.fn.find, $.fn.bind and $.fn.unbind
    */
    
    (function (jQuery){
        // keep reference to the original $.fn.bind, $.fn.unbind and $.fn.find
        jQuery.fn.__bind__ = jQuery.fn.bind;
        jQuery.fn.__unbind__ = jQuery.fn.unbind;
        jQuery.fn.__find__ = jQuery.fn.find;
    
        var hotkeys = {
            version: '0.7.9',
            override: /keypress|keydown|keyup/g,
            triggersMap: {},
    
            specialKeys: { 27: 'esc', 9: 'tab', 32:'space', 13: 'return', 8:'backspace', 145: 'scroll', 
                20: 'capslock', 144: 'numlock', 19:'pause', 45:'insert', 36:'home', 46:'del',
                35:'end', 33: 'pageup', 34:'pagedown', 37:'left', 38:'up', 39:'right',40:'down', 
                109: '-', 
                112:'f1',113:'f2', 114:'f3', 115:'f4', 116:'f5', 117:'f6', 118:'f7', 119:'f8', 
                120:'f9', 121:'f10', 122:'f11', 123:'f12', 191: '/'},
    
            shiftNums: { "`":"~", "1":"!", "2":"@", "3":"#", "4":"$", "5":"%", "6":"^", "7":"&", 
                "8":"*", "9":"(", "0":")", "-":"_", "=":"+", ";":":", "'":"\"", ",":"<", 
                ".":">",  "/":"?",  "\\":"|" },
    
            newTrigger: function (type, combi, callback) { 
                // i.e. {'keyup': {'ctrl': {cb: callback, disableInInput: false}}}
                var result = {};
                result[type] = {};
                result[type][combi] = {cb: callback, disableInInput: false};
                return result;
            }
        };
        // add firefox num pad char codes
        //if (jQuery.browser.mozilla){
        // add num pad char codes
        hotkeys.specialKeys = jQuery.extend(hotkeys.specialKeys, { 96: '0', 97:'1', 98: '2', 99: 
            '3', 100: '4', 101: '5', 102: '6', 103: '7', 104: '8', 105: '9', 106: '*', 
            107: '+', 109: '-', 110: '.', 111 : '/'
            });
        //}
    
        // a wrapper around of $.fn.find 
        // see more at: http://groups.google.com/group/jquery-en/browse_thread/thread/18f9825e8d22f18d
        jQuery.fn.find = function( selector ) {
            this.query = selector;
            return jQuery.fn.__find__.apply(this, arguments);
        };
    
        jQuery.fn.unbind = function (type, combi, fn){
            if (jQuery.isFunction(combi)){
                fn = combi;
                combi = null;
            }
            if (combi && typeof combi === 'string'){
                var selectorId = ((this.prevObject && this.prevObject.query) || (this[0].id && this[0].id) || this[0]).toString();
                var hkTypes = type.split(' ');
                for (var x=0; x<hkTypes.length; x++){
                    delete hotkeys.triggersMap[selectorId][hkTypes[x]][combi];
                }
            }
            // call jQuery original unbind
            return  this.__unbind__(type, fn);
        };
    
        jQuery.fn.bind = function(type, data, fn){
            // grab keyup,keydown,keypress
            var handle = type.match(hotkeys.override);
    
            if (jQuery.isFunction(data) || !handle){
                // call jQuery.bind only
                return this.__bind__(type, data, fn);
            }
            else{
                // split the job
                var result = null,            
                // pass the rest to the original $.fn.bind
                pass2jq = jQuery.trim(type.replace(hotkeys.override, ''));
    
                // see if there are other types, pass them to the original $.fn.bind
                if (pass2jq){
                    result = this.__bind__(pass2jq, data, fn);
                }            
    
                if (typeof data === "string"){
                    data = {'combi': data};
                }
                if(data.combi){
                    for (var x=0; x < handle.length; x++){
                        var eventType = handle[x];
                        var combi = data.combi.toLowerCase(),
                            trigger = hotkeys.newTrigger(eventType, combi, fn),
                            selectorId = ((this.prevObject && this.prevObject.query) || (this[0].id && this[0].id) || this[0]).toString();
    
                        //trigger[eventType][combi].propagate = data.propagate;
                        trigger[eventType][combi].disableInInput = data.disableInInput;
    
                        // first time selector is bounded
                        if (!hotkeys.triggersMap[selectorId]) {
                            hotkeys.triggersMap[selectorId] = trigger;
                        }
                        // first time selector is bounded with this type
                        else if (!hotkeys.triggersMap[selectorId][eventType]) {
                            hotkeys.triggersMap[selectorId][eventType] = trigger[eventType];
                        }
                        // make trigger point as array so more than one handler can be bound
                        var mapPoint = hotkeys.triggersMap[selectorId][eventType][combi];
                        if (!mapPoint){
                            hotkeys.triggersMap[selectorId][eventType][combi] = [trigger[eventType][combi]];
                        }
                        else if (mapPoint.constructor !== Array){
                            hotkeys.triggersMap[selectorId][eventType][combi] = [mapPoint];
                        }
                        else {
                            hotkeys.triggersMap[selectorId][eventType][combi][mapPoint.length] = trigger[eventType][combi];
                        }
    
                        // add attribute and call $.event.add per matched element
                        this.each(function(){
                            // jQuery wrapper for the current element
                            var jqElem = jQuery(this);
    
                            // element already associated with another collection
                            if (jqElem.attr('hkId') && jqElem.attr('hkId') !== selectorId){
                                selectorId = jqElem.attr('hkId') + ";" + selectorId;
                            }
                            jqElem.attr('hkId', selectorId);
                        });
                        result = this.__bind__(handle.join(' '), data, hotkeys.handler)
                    }
                }
                return result;
            }
        };
        // work-around for opera and safari where (sometimes) the target is the element which was last 
        // clicked with the mouse and not the document event it would make sense to get the document
        hotkeys.findElement = function (elem){
            if (!jQuery(elem).attr('hkId')){
                if (jQuery.browser.opera || jQuery.browser.safari){
                    while (!jQuery(elem).attr('hkId') && elem.parentNode){
                        elem = elem.parentNode;
                    }
                }
            }
            return elem;
        };
        // the event handler
        hotkeys.handler = function(event) {
            var target = hotkeys.findElement(event.currentTarget), 
                jTarget = jQuery(target),
                ids = jTarget.attr('hkId');
    
            if(ids){
                ids = ids.split(';');
                var code = event.which,
                    type = event.type,
                    special = hotkeys.specialKeys[code],
                    // prevent f5 overlapping with 't' (or f4 with 's', etc.)
                    character = !special && String.fromCharCode(code).toLowerCase(),
                    shift = event.shiftKey,
                    ctrl = event.ctrlKey,            
                    // patch for jquery 1.2.5 && 1.2.6 see more at:  
                    // http://groups.google.com/group/jquery-en/browse_thread/thread/83e10b3bb1f1c32b
                    cmd = event.metaKey && !ctrl,
                    alt = event.altKey || event.originalEvent.altKey,
                    mapPoint = null;
    
                for (var x=0; x < ids.length; x++){
                    if (hotkeys.triggersMap[ids[x]][type]){
                        mapPoint = hotkeys.triggersMap[ids[x]][type];
                        break;
                    }
                }
    
                //find by: id.type.combi.options            
                if (mapPoint){ 
                    var trigger;
                    // event type is associated with the hkId
                    if(!shift && !ctrl && !alt && !cmd) { // No Modifiers
                        trigger = mapPoint[special] ||  (character && mapPoint[character]);
                    }
                    else{
                        // check combinations (alt|ctrl|shift+anything)
                        var modif = '';
                        if(alt) modif +='alt+';
                        if(ctrl) modif+= 'ctrl+';
                        if(shift) modif += 'shift+';
                        if(cmd) modif += 'command+';
                        // modifiers + special keys or modifiers + character or modifiers + shift character or just shift character
                        trigger = mapPoint[modif+special];
                        if (!trigger){
                            if (character){
                                trigger = mapPoint[modif+character] 
                                    || mapPoint[modif+hotkeys.shiftNums[character]]
                                    // '$' can be triggered as 'Shift+4' or 'Shift+$' or just '$'
                                    || (modif === 'shift+' && mapPoint[hotkeys.shiftNums[character]]);
                            }
                        }
                    }
                    if (trigger){
                        var result = false;
                        for (var x=0; x < trigger.length; x++){
                            if(trigger[x].disableInInput){
                                // double check event.currentTarget and event.target
                                var elem = jQuery(event.target);
                                if (jTarget.is("input") || jTarget.is("textarea") || jTarget.is("select") 
                                    || elem.is("input") || elem.is("textarea") || elem.is("select")) {
                                    return true;
                                }
                            }                       
                            // call the registered callback function
                            result = result || trigger[x].cb.apply(this, [event]);
                        }
                        return result;
                    }
                }
            }
        };
        // place it under window so it can be extended and overridden by others
        window.hotkeys = hotkeys;
        return jQuery;
    })(jQuery);
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have this folder structure: /www/project/web/app.php I can access it via /project/web/index.php . The
I have a web app with a form that I am trying to pass
I am new to spring security I have web.xml <?xml version=1.0 encoding=UTF-8?> <web-app xmlns=http://java.sun.com/xml/ns/javaee
I have a web app. I'm trying to disable/prevent the scrolling that occurs when
need ask you about some help. I have web app running in Net 2.0.
I have a web app which connects to a server using a TCP connection
I have a web app for commercial property management that needs spreadsheet-like functionality for
I have a web-app-database 3 tier server setup. Web requests data from app, and
I have a web app that is heavily loaded in javascript and css. First
I have a web app that only registered users can use, therefore I should

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.