angular-hotkeys.js 9.8 KB

1
  1. !function(){"use strict";angular.module("cfp.hotkeys",[]).provider("hotkeys",["$injector",function(e){this.includeCheatSheet=!0,this.useNgRoute=e.has("ngViewDirective"),this.templateTitle="Keyboard Shortcuts:",this.templateHeader=null,this.templateFooter=null,this.template='<div class="cfp-hotkeys-container fade" ng-class="{in: helpVisible}" style="display: none;"><div class="cfp-hotkeys"><h4 class="cfp-hotkeys-title" ng-if="!header">{{ title }}</h4><div ng-bind-html="header" ng-if="header"></div><table><tbody><tr ng-repeat="hotkey in hotkeys | filter:{ description: \'!$$undefined$$\' }"><td class="cfp-hotkeys-keys"><span ng-repeat="key in hotkey.format() track by $index" class="cfp-hotkeys-key">{{ key }}</span></td><td class="cfp-hotkeys-text">{{ hotkey.description }}</td></tr></tbody></table><div ng-bind-html="footer" ng-if="footer"></div><div class="cfp-hotkeys-close" ng-click="toggleCheatSheet()">&#215;</div></div></div>',this.cheatSheetHotkey="?",this.cheatSheetDescription="Show / hide this help menu",this.$get=["$rootElement","$rootScope","$compile","$window","$document",function(e,t,n,i,o){function r(e){var t={command:"⌘",shift:"⇧",left:"←",right:"→",up:"↑",down:"↓",return:"⏎",backspace:"⌫"};e=e.split("+");for(var n=0;n<e.length;n++)"mod"===e[n]&&(i.navigator&&i.navigator.platform.indexOf("Mac")>=0?e[n]="command":e[n]="ctrl"),e[n]=t[e[n]]||e[n];return e.join(" + ")}function a(e,t,n,i,o,r){this.combo=e instanceof Array?e:[e],this.description=t,this.callback=n,this.action=i,this.allowIn=o,this.persistent=r,this._formated=null}function s(){for(var e=d.hotkeys.length;e--;){var t=d.hotkeys[e];t&&!t.persistent&&h(t)}}function c(){d.helpVisible=!d.helpVisible,d.helpVisible?(g=u("esc"),h("esc"),l("esc",g.description,c,null,["INPUT","SELECT","TEXTAREA"])):(h("esc"),!1!==g&&l(g))}function l(e,t,n,i,o,r){var s,c=["INPUT","SELECT","TEXTAREA"];if("[object Object]"===Object.prototype.toString.call(e)&&(t=e.description,n=e.callback,i=e.action,r=e.persistent,o=e.allowIn,e=e.combo),h(e),t instanceof Function?(i=n,n=t,t="$$undefined$$"):angular.isUndefined(t)&&(t="$$undefined$$"),void 0===r&&(r=!0),"function"==typeof n){s=n,o instanceof Array||(o=[]);for(var l,u=0;u<o.length;u++)o[u]=o[u].toUpperCase(),-1!==(l=c.indexOf(o[u]))&&c.splice(l,1);n=function(e){var t=!0;if(e){var n=e.target||e.srcElement,i=n.nodeName.toUpperCase();if((" "+n.className+" ").indexOf(" mousetrap ")>-1)t=!0;else for(var o=0;o<c.length;o++)if(c[o]===i){t=!1;break}}t&&f(s.apply(this,arguments))}}"string"==typeof i?Mousetrap.bind(e,f(n),i):Mousetrap.bind(e,f(n));var p=new a(e,t,n,i,o,r);return d.hotkeys.push(p),p}function h(e){var t=e instanceof a?e.combo:e;if(Mousetrap.unbind(t),angular.isArray(t)){for(var n=!0,i=t.length;i--;)n=h(t[i])&&n;return n}var o=d.hotkeys.indexOf(u(t));return o>-1&&(d.hotkeys[o].combo.length>1?d.hotkeys[o].combo.splice(d.hotkeys[o].combo.indexOf(t),1):(angular.forEach(y,function(e){var t=e.indexOf(d.hotkeys[o]);-1!==t&&e.splice(t,1)}),d.hotkeys.splice(o,1)),!0)}function u(e){if(!e)return d.hotkeys;for(var t,n=0;n<d.hotkeys.length;n++)if((t=d.hotkeys[n]).combo.indexOf(e)>-1)return t;return!1}function f(e){return function(n,i){if(e instanceof Array){var o=e[0],r=e[1];e=function(e){r.scope.$eval(o)}}t.$apply(function(){e(n,u(i))})}}var p=!0;Mousetrap.prototype.stopCallback=function(e,t){return!p||!((" "+t.className+" ").indexOf(" mousetrap ")>-1)&&(t.contentEditable&&"true"==t.contentEditable)},a.prototype.format=function(){if(null===this._formated){for(var e=this.combo[0].split(/[\s]/),t=0;t<e.length;t++)e[t]=r(e[t]);this._formated=e}return this._formated};var d=t.$new();d.hotkeys=[],d.helpVisible=!1,d.title=this.templateTitle,d.header=this.templateHeader,d.footer=this.templateFooter,d.toggleCheatSheet=c;var y={};if(this.useNgRoute&&t.$on("$routeChangeSuccess",function(e,t){s(),t&&t.hotkeys&&angular.forEach(t.hotkeys,function(e){var n=e[2];("string"==typeof n||n instanceof String)&&(e[2]=[n,t]),e[5]=!1,l.apply(this,e)})}),this.includeCheatSheet){var k=o[0],m=e[0],v=angular.element(this.template);l(this.cheatSheetHotkey,this.cheatSheetDescription,c),m!==k&&m!==k.documentElement||(m=k.body),angular.element(m).append(n(v)(d))}var g=!1;return{add:l,del:h,get:u,bindTo:function(e){return e.$id in y||(y[e.$id]=[],e.$on("$destroy",function(){for(var t=y[e.$id].length;t--;)h(y[e.$id].pop())})),{add:function(t){var n;return n=arguments.length>1?l.apply(this,arguments):l(t),y[e.$id].push(n),this}}},template:this.template,toggleCheatSheet:c,includeCheatSheet:this.includeCheatSheet,cheatSheetHotkey:this.cheatSheetHotkey,cheatSheetDescription:this.cheatSheetDescription,useNgRoute:this.useNgRoute,purgeHotkeys:s,templateTitle:this.templateTitle,pause:function(){p=!1},unpause:function(){p=!0}}}]}]).directive("hotkey",["hotkeys",function(e){return{restrict:"A",link:function(t,n,i){var o,r=[];angular.forEach(t.$eval(i.hotkey),function(t,n){o="string"==typeof i.hotkeyAllowIn?i.hotkeyAllowIn.split(/[\s,]+/):[],r.push(n),e.add({combo:n,description:i.hotkeyDescription,callback:t,action:i.hotkeyAction,allowIn:o})}),n.bind("$destroy",function(){angular.forEach(r,e.del)})}}}]).run(["hotkeys",function(e){}])}(),function(e,t,n){function i(e,t,n){e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent("on"+t,n)}function o(e){if("keypress"==e.type){var t=String.fromCharCode(e.which);return e.shiftKey||(t=t.toLowerCase()),t}return m[e.which]?m[e.which]:v[e.which]?v[e.which]:String.fromCharCode(e.which).toLowerCase()}function r(e,t){return e.sort().join(",")===t.sort().join(",")}function a(e){var t=[];return e.shiftKey&&t.push("shift"),e.altKey&&t.push("alt"),e.ctrlKey&&t.push("ctrl"),e.metaKey&&t.push("meta"),t}function s(e){e.preventDefault?e.preventDefault():e.returnValue=!1}function c(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0}function l(e){return"shift"==e||"ctrl"==e||"alt"==e||"meta"==e}function h(){if(!k){k={};for(var e in m)e>95&&e<112||m.hasOwnProperty(e)&&(k[m[e]]=e)}return k}function u(e,t,n){return n||(n=h()[e]?"keydown":"keypress"),"keypress"==n&&t.length&&(n="keydown"),n}function f(e){return"+"===e?["+"]:(e=e.replace(/\+{2}/g,"+plus")).split("+")}function p(e,t){var n,i,o,r=[];for(n=f(e),o=0;o<n.length;++o)i=n[o],b[i]&&(i=b[i]),t&&"keypress"!=t&&g[i]&&(i=g[i],r.push("shift")),l(i)&&r.push(i);return t=u(i,r,t),{key:i,modifiers:r,action:t}}function d(e,n){return e!==t&&(e===n||d(e.parentNode,n))}function y(e){function n(e){e=e||{};var t,n=!1;for(t in b)e[t]?n=!0:b[t]=0;n||(E=!1)}function h(e,t,n,i,o,a){var s,c,h=[],u=n.type;if(!v._callbacks[e])return[];for("keyup"==u&&l(e)&&(t=[e]),s=0;s<v._callbacks[e].length;++s)if(c=v._callbacks[e][s],(i||!c.seq||b[c.seq]==c.level)&&u==c.action&&("keypress"==u&&!n.metaKey&&!n.ctrlKey||r(t,c.modifiers))){var f=!i&&c.combo==o,p=i&&c.seq==i&&c.level==a;(f||p)&&v._callbacks[e].splice(s,1),h.push(c)}return h}function u(e,t,n,i){v.stopCallback(t,t.target||t.srcElement,n,i)||!1===e(t,n)&&(s(t),c(t))}function f(e){"number"!=typeof e.which&&(e.which=e.keyCode);var t=o(e);t&&("keyup"!=e.type||$!==t?v.handleKey(t,a(e),e):$=!1)}function d(){clearTimeout(g),g=setTimeout(n,1e3)}function k(e,t,i,r){b[e]=0;for(var a=0;a<t.length;++a){var s=a+1===t.length?function(t){u(i,t,e),"keyup"!==r&&($=o(t)),setTimeout(n,10)}:function(t){return function(){E=t,++b[e],d()}}(r||p(t[a+1]).action);m(t[a],s,r,e,a)}}function m(e,t,n,i,o){v._directMap[e+":"+n]=t;var r,a=(e=e.replace(/\s+/g," ")).split(" ");a.length>1?k(e,a,t,n):(r=p(e,n),v._callbacks[r.key]=v._callbacks[r.key]||[],h(r.key,r.modifiers,{type:r.action},i,e,o),v._callbacks[r.key][i?"unshift":"push"]({callback:t,modifiers:r.modifiers,action:r.action,seq:i,level:o,combo:e}))}var v=this;if(e=e||t,!(v instanceof y))return new y(e);v.target=e,v._callbacks={},v._directMap={};var g,b={},$=!1,w=!1,E=!1;v._handleKey=function(e,t,i){var o,r=h(e,t,i),a={},s=0,c=!1;for(o=0;o<r.length;++o)r[o].seq&&(s=Math.max(s,r[o].level));for(o=0;o<r.length;++o)if(r[o].seq){if(r[o].level!=s)continue;c=!0,a[r[o].seq]=1,u(r[o].callback,i,r[o].combo,r[o].seq)}else c||u(r[o].callback,i,r[o].combo);var f="keypress"==i.type&&w;i.type!=E||l(e)||f||n(a),w=c&&"keydown"==i.type},v._bindMultiple=function(e,t,n){for(var i=0;i<e.length;++i)m(e[i],t,n)},i(e,"keypress",f),i(e,"keydown",f),i(e,"keyup",f)}for(var k,m={8:"backspace",9:"tab",13:"enter",16:"shift",17:"ctrl",18:"alt",20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"ins",46:"del",91:"meta",93:"meta",224:"meta"},v={106:"*",107:"+",109:"-",110:".",111:"/",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},g={"~":"`","!":"1","@":"2","#":"3",$:"4","%":"5","^":"6","&":"7","*":"8","(":"9",")":"0",_:"-","+":"=",":":";",'"':"'","<":",",">":".","?":"/","|":"\\"},b={option:"alt",command:"meta",return:"enter",escape:"esc",plus:"+",mod:/Mac|iPod|iPhone|iPad/.test(navigator.platform)?"meta":"ctrl"},$=1;$<20;++$)m[111+$]="f"+$;for($=0;$<=9;++$)m[$+96]=$;y.prototype.bind=function(e,t,n){var i=this;return e=e instanceof Array?e:[e],i._bindMultiple.call(i,e,t,n),i},y.prototype.unbind=function(e,t){var n=this;return n.bind.call(n,e,function(){},t)},y.prototype.trigger=function(e,t){var n=this;return n._directMap[e+":"+t]&&n._directMap[e+":"+t]({},e),n},y.prototype.reset=function(){var e=this;return e._callbacks={},e._directMap={},e},y.prototype.stopCallback=function(e,t){var n=this;return!((" "+t.className+" ").indexOf(" mousetrap ")>-1)&&(!d(t,n.target)&&("INPUT"==t.tagName||"SELECT"==t.tagName||"TEXTAREA"==t.tagName||t.isContentEditable))},y.prototype.handleKey=function(){var e=this;return e._handleKey.apply(e,arguments)},y.init=function(){var e=y(t);for(var n in e)"_"!==n.charAt(0)&&(y[n]=function(t){return function(){return e[t].apply(e,arguments)}}(n))},y.init(),e.Mousetrap=y,"undefined"!=typeof module&&module.exports&&(module.exports=y),"function"==typeof define&&define.amd&&define(function(){return y})}(window,document);