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
Post a Comment