home *** CD-ROM | disk | FTP | other *** search
/ Chip 2011 March / Chip_2011.03_CD.iso / Tools / modules / jquery.hotkeys-0.7.9.js < prev    next >
Encoding:
JavaScript  |  2010-12-14  |  10.7 KB  |  245 lines

  1. /*
  2. (c) Copyrights 2007 - 2008
  3.  
  4. Original idea by by Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/
  5.  
  6. jQuery Plugin by Tzury Bar Yochay 
  7. tzury.by@gmail.com
  8. http://evalinux.wordpress.com
  9. http://facebook.com/profile.php?id=513676303
  10.  
  11. Project's sites: 
  12. http://code.google.com/p/js-hotkeys/
  13. http://github.com/tzuryby/hotkeys/tree/master
  14.  
  15. License: same as jQuery license. 
  16.  
  17. USAGE:
  18.     // simple usage
  19.     $(document).bind('keydown', 'Ctrl+c', function(){ alert('copy anyone?');});
  20.     
  21.     // special options such as disableInIput
  22.     $(document).bind('keydown', {combi:'Ctrl+x', disableInInput: true} , function() {});
  23.     
  24. Note:
  25.     This plugin wraps the following jQuery methods: $.fn.find, $.fn.bind and $.fn.unbind
  26. */
  27.  
  28. (function (jQuery){
  29.     // keep reference to the original $.fn.bind, $.fn.unbind and $.fn.find
  30.     jQuery.fn.__bind__ = jQuery.fn.bind;
  31.     jQuery.fn.__unbind__ = jQuery.fn.unbind;
  32.     jQuery.fn.__find__ = jQuery.fn.find;
  33.     
  34.     var hotkeys = {
  35.         version: '0.7.9',
  36.         override: /keypress|keydown|keyup/g,
  37.         triggersMap: {},
  38.         
  39.         specialKeys: { 27: 'esc', 9: 'tab', 32:'space', 13: 'return', 8:'backspace', 145: 'scroll', 
  40.             20: 'capslock', 144: 'numlock', 19:'pause', 45:'insert', 36:'home', 46:'del',
  41.             35:'end', 33: 'pageup', 34:'pagedown', 37:'left', 38:'up', 39:'right',40:'down', 
  42.             109: '-', 
  43.             112:'f1',113:'f2', 114:'f3', 115:'f4', 116:'f5', 117:'f6', 118:'f7', 119:'f8', 
  44.             120:'f9', 121:'f10', 122:'f11', 123:'f12', 191: '/'},
  45.         
  46.         shiftNums: { "`":"~", "1":"!", "2":"@", "3":"#", "4":"$", "5":"%", "6":"^", "7":"&", 
  47.             "8":"*", "9":"(", "0":")", "-":"_", "=":"+", ";":":", "'":"\"", ",":"<", 
  48.             ".":">",  "/":"?",  "\\":"|" },
  49.         
  50.         newTrigger: function (type, combi, callback) { 
  51.             // i.e. {'keyup': {'ctrl': {cb: callback, disableInInput: false}}}
  52.             var result = {};
  53.             result[type] = {};
  54.             result[type][combi] = {cb: callback, disableInInput: false};
  55.             return result;
  56.         }
  57.     };
  58.     // add firefox num pad char codes
  59.     //if (jQuery.browser.mozilla){
  60.     // add num pad char codes
  61.     hotkeys.specialKeys = jQuery.extend(hotkeys.specialKeys, { 96: '0', 97:'1', 98: '2', 99: 
  62.         '3', 100: '4', 101: '5', 102: '6', 103: '7', 104: '8', 105: '9', 106: '*', 
  63.         107: '+', 109: '-', 110: '.', 111 : '/'
  64.         });
  65.     //}
  66.     
  67.     // a wrapper around of $.fn.find 
  68.     // see more at: http://groups.google.com/group/jquery-en/browse_thread/thread/18f9825e8d22f18d
  69.     jQuery.fn.find = function( selector ) {
  70.         this.query = selector;
  71.         return jQuery.fn.__find__.apply(this, arguments);
  72.     };
  73.     
  74.     jQuery.fn.unbind = function (type, combi, fn){
  75.         if (jQuery.isFunction(combi)){
  76.             fn = combi;
  77.             combi = null;
  78.         }
  79.         if (combi && typeof combi === 'string'){
  80.             var selectorId = ((this.prevObject && this.prevObject.query) || (this[0].id && this[0].id) || this[0]).toString();
  81.             var hkTypes = type.split(' ');
  82.             for (var x=0; x<hkTypes.length; x++){
  83.                 delete hotkeys.triggersMap[selectorId][hkTypes[x]][combi];
  84.             }
  85.         }
  86.         // call jQuery original unbind
  87.         return  this.__unbind__(type, fn);
  88.     };
  89.     
  90.     jQuery.fn.bind = function(type, data, fn){
  91.         // grab keyup,keydown,keypress
  92.         var handle = type.match(hotkeys.override);
  93.         
  94.         if (jQuery.isFunction(data) || !handle){
  95.             // call jQuery.bind only
  96.             return this.__bind__(type, data, fn);
  97.         }
  98.         else{
  99.             // split the job
  100.             var result = null,            
  101.             // pass the rest to the original $.fn.bind
  102.             pass2jq = jQuery.trim(type.replace(hotkeys.override, ''));
  103.             
  104.             // see if there are other types, pass them to the original $.fn.bind
  105.             if (pass2jq){
  106.                 result = this.__bind__(pass2jq, data, fn);
  107.             }            
  108.             
  109.             if (typeof data === "string"){
  110.                 data = {'combi': data};
  111.             }
  112.             if(data.combi){
  113.                 for (var x=0; x < handle.length; x++){
  114.                     var eventType = handle[x];
  115.                     var combi = data.combi.toLowerCase(),
  116.                         trigger = hotkeys.newTrigger(eventType, combi, fn),
  117.                         selectorId = ((this.prevObject && this.prevObject.query) || (this[0].id && this[0].id) || this[0]).toString();
  118.                         
  119.                     //trigger[eventType][combi].propagate = data.propagate;
  120.                     trigger[eventType][combi].disableInInput = data.disableInInput;
  121.                     
  122.                     // first time selector is bounded
  123.                     if (!hotkeys.triggersMap[selectorId]) {
  124.                         hotkeys.triggersMap[selectorId] = trigger;
  125.                     }
  126.                     // first time selector is bounded with this type
  127.                     else if (!hotkeys.triggersMap[selectorId][eventType]) {
  128.                         hotkeys.triggersMap[selectorId][eventType] = trigger[eventType];
  129.                     }
  130.                     // make trigger point as array so more than one handler can be bound
  131.                     var mapPoint = hotkeys.triggersMap[selectorId][eventType][combi];
  132.                     if (!mapPoint){
  133.                         hotkeys.triggersMap[selectorId][eventType][combi] = [trigger[eventType][combi]];
  134.                     }
  135.                     else if (mapPoint.constructor !== Array){
  136.                         hotkeys.triggersMap[selectorId][eventType][combi] = [mapPoint];
  137.                     }
  138.                     else {
  139.                         hotkeys.triggersMap[selectorId][eventType][combi][mapPoint.length] = trigger[eventType][combi];
  140.                     }
  141.                     
  142.                     // add attribute and call $.event.add per matched element
  143.                     this.each(function(){
  144.                         // jQuery wrapper for the current element
  145.                         var jqElem = jQuery(this);
  146.                         
  147.                         // element already associated with another collection
  148.                         if (jqElem.attr('hkId') && jqElem.attr('hkId') !== selectorId){
  149.                             selectorId = jqElem.attr('hkId') + ";" + selectorId;
  150.                         }
  151.                         jqElem.attr('hkId', selectorId);
  152.                     });
  153.                     result = this.__bind__(handle.join(' '), data, hotkeys.handler)
  154.                 }
  155.             }
  156.             return result;
  157.         }
  158.     };
  159.     // work-around for opera and safari where (sometimes) the target is the element which was last 
  160.     // clicked with the mouse and not the document event it would make sense to get the document
  161.     hotkeys.findElement = function (elem){
  162.         if (!jQuery(elem).attr('hkId')){
  163.             if (jQuery.browser.opera || jQuery.browser.safari){
  164.                 while (!jQuery(elem).attr('hkId') && elem.parentNode){
  165.                     elem = elem.parentNode;
  166.                 }
  167.             }
  168.         }
  169.         return elem;
  170.     };
  171.     // the event handler
  172.     hotkeys.handler = function(event) {
  173.         var target = hotkeys.findElement(event.currentTarget), 
  174.             jTarget = jQuery(target),
  175.             ids = jTarget.attr('hkId');
  176.         
  177.         if(ids){
  178.             ids = ids.split(';');
  179.             var code = event.which,
  180.                 type = event.type,
  181.                 special = hotkeys.specialKeys[code],
  182.                 // prevent f5 overlapping with 't' (or f4 with 's', etc.)
  183.                 character = !special && String.fromCharCode(code).toLowerCase(),
  184.                 shift = event.shiftKey,
  185.                 ctrl = event.ctrlKey,            
  186.                 // patch for jquery 1.2.5 && 1.2.6 see more at:  
  187.                 // http://groups.google.com/group/jquery-en/browse_thread/thread/83e10b3bb1f1c32b
  188.                 alt = event.altKey || event.originalEvent.altKey,
  189.                 mapPoint = null;
  190.  
  191.             for (var x=0; x < ids.length; x++){
  192.                 if (hotkeys.triggersMap[ids[x]][type]){
  193.                     mapPoint = hotkeys.triggersMap[ids[x]][type];
  194.                     break;
  195.                 }
  196.             }
  197.             
  198.             //find by: id.type.combi.options            
  199.             if (mapPoint){ 
  200.                 var trigger;
  201.                 // event type is associated with the hkId
  202.                 if(!shift && !ctrl && !alt) { // No Modifiers
  203.                     trigger = mapPoint[special] ||  (character && mapPoint[character]);
  204.                 }
  205.                 else{
  206.                     // check combinations (alt|ctrl|shift+anything)
  207.                     var modif = '';
  208.                     if(alt) modif +='alt+';
  209.                     if(ctrl) modif+= 'ctrl+';
  210.                     if(shift) modif += 'shift+';
  211.                     // modifiers + special keys or modifiers + character or modifiers + shift character or just shift character
  212.                     trigger = mapPoint[modif+special];
  213.                     if (!trigger){
  214.                         if (character){
  215.                             trigger = mapPoint[modif+character] 
  216.                                 || mapPoint[modif+hotkeys.shiftNums[character]]
  217.                                 // '$' can be triggered as 'Shift+4' or 'Shift+$' or just '$'
  218.                                 || (modif === 'shift+' && mapPoint[hotkeys.shiftNums[character]]);
  219.                         }
  220.                     }
  221.                 }
  222.                 if (trigger){
  223.                     var result = false;
  224.                     for (var x=0; x < trigger.length; x++){
  225.                         if(trigger[x].disableInInput){
  226.                             // double check event.currentTarget and event.target
  227.                             var elem = jQuery(event.target);
  228.                             if (jTarget.is("input") || jTarget.is("textarea") || jTarget.is("select") 
  229.                                 || elem.is("input") || elem.is("textarea") || elem.is("select")) {
  230.                                 return true;
  231.                             }
  232.                         }                       
  233.                         // call the registered callback function
  234.                         result = result || trigger[x].cb.apply(this, [event]);
  235.                     }
  236.                     return result;
  237.                 }
  238.             }
  239.         }
  240.     };
  241.     // place it under window so it can be extended and overridden by others
  242.     window.hotkeys = hotkeys;
  243.     return jQuery;
  244. })(jQuery);
  245.