osx - How can I capture COMMAND+S in jQuery? -


i have web app i'm developing , i'm trying have ctrl+s , command+s shortcut keys save. i've looked @ http://www.openjs.com/scripts/events/keyboard_shortcuts/ , doesn't capture "meta" key.

any advice?

latest edit: please, before downvoting response take in mind old response (2011) , has not been updated. there better responses (like the 1 lapin) doesn't mean mine invalid.

you can use jquery hotkeys.

edit: there's newer version on github , can use 'meta' modifier grab command+:

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

edit2: can use mousetrap library/vendor, jquery-free.

download latest version , modify following changes in attachment: http://code.google.com/p/js-hotkeys/issues/detail?id=26

you need add 3 lines:

at line 188 aprox. (under ctrl = event.ctrlkey,) add this:

cmd = event.metakey && !ctrl, 

then, add negation if @ 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 create binding command+whatever grab it:

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

here can grab latest current version (0.7.9) modified:

/* (c) copyrights 2007 - 2008  original idea by binny v a, http://www.openjs.com/scripts/events/keyboard_shortcuts/  jquery plugin 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 jquery license.   usage:     // simple usage     $(document).bind('keydown', 'ctrl+c', function(){ alert('copy anyone?');});      // special options such disableiniput     $(document).bind('keydown', {combi:'ctrl+x', disableininput: true} , function() {});  note:     plugin wraps following jquery methods: $.fn.find, $.fn.bind , $.fn.unbind */  (function (jquery){     // keep reference original $.fn.bind, $.fn.unbind , $.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 : '/'         });     //}      // 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(' ');             (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             return this.__bind__(type, data, fn);         }         else{             // split job             var result = null,                         // pass rest original $.fn.bind             pass2jq = jquery.trim(type.replace(hotkeys.override, ''));              // see if there other types, pass them original $.fn.bind             if (pass2jq){                 result = this.__bind__(pass2jq, data, fn);             }                          if (typeof data === "string"){                 data = {'combi': data};             }             if(data.combi){                 (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 bounded                     if (!hotkeys.triggersmap[selectorid]) {                         hotkeys.triggersmap[selectorid] = trigger;                     }                     // first time selector bounded type                     else if (!hotkeys.triggersmap[selectorid][eventtype]) {                         hotkeys.triggersmap[selectorid][eventtype] = trigger[eventtype];                     }                     // make trigger point array more 1 handler can 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 , call $.event.add per matched element                     this.each(function(){                         // jquery wrapper current element                         var jqelem = jquery(this);                          // element associated 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 opera , safari (sometimes) target element last      // clicked mouse , not document event make sense 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;     };     // 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 't' (or f4 's', etc.)                 character = !special && string.fromcharcode(code).tolowercase(),                 shift = event.shiftkey,                 ctrl = event.ctrlkey,                             // patch 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;              (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 associated 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 shift character                     trigger = mappoint[modif+special];                     if (!trigger){                         if (character){                             trigger = mappoint[modif+character]                                  || mappoint[modif+hotkeys.shiftnums[character]]                                 // '$' can triggered 'shift+4' or 'shift+$' or '$'                                 || (modif === 'shift+' && mappoint[hotkeys.shiftnums[character]]);                         }                     }                 }                 if (trigger){                     var result = false;                     (var x=0; x < trigger.length; x++){                         if(trigger[x].disableininput){                             // double check event.currenttarget , 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 registered callback function                         result = result || trigger[x].cb.apply(this, [event]);                     }                     return result;                 }             }         }     };     // place under window can extended , overridden others     window.hotkeys = hotkeys;     return jquery; })(jquery); 

Comments