New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

angular-hotkeys

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

angular-hotkeys - npm Package Compare versions

Comparing version 1.3.1 to 1.4.0

2

bower.json
{
"name": "angular-hotkeys",
"version": "1.3.1",
"version": "1.4.0",
"main": [

@@ -5,0 +5,0 @@ "build/hotkeys.min.js",

/*!
* angular-hotkeys v1.3.1
* angular-hotkeys v1.4.0
* https://chieffancypants.github.io/angular-hotkeys

@@ -108,3 +108,3 @@ * Copyright (c) 2014 Wes Cruver

*
* @param {String} combo The keycombo
* @param {array} combo The keycombo. it's an array to support multiple combos
* @param {String} description Description for the keycombo

@@ -120,3 +120,4 @@ * @param {Function} callback function to execute when keycombo pressed

// supplied values
this.combo = combo;
this.combo = combo instanceof Array ? combo : [combo];
this.description = description;

@@ -139,12 +140,6 @@ this.callback = callback;

var combo = this.combo;
// Don't show all the possible key combos, just the first one. Not sure
// of usecase here, so open a ticket if my assumptions are wrong
var combo = this.combo[0];
// if the combo is an array, it means the there are multiple bindings to
// the same callback. Don't show all the possible key combos, just the
// first one. Not sure of usecase here, so open a ticket if my
// assumptions are wrong
if (combo instanceof Array) {
combo = combo[0];
}
var sequence = combo.split(/[\s]/);

@@ -183,2 +178,12 @@ for (var i = 0; i < sequence.length; i++) {

/**
* Holds references to the different scopes that have bound hotkeys
* attached. This is useful to catch when the scopes are `$destroy`d and
* then automatically unbind the hotkey.
*
* @type {Array}
*/
var boundScopes = [];
$rootScope.$on('$routeChangeSuccess', function (event, route) {

@@ -368,3 +373,5 @@ purgeHotkeys();

scope.hotkeys.push(new Hotkey(combo, description, callback, action, allowIn, persistent));
var hotkey = new Hotkey(combo, description, callback, action, allowIn, persistent);
scope.hotkeys.push(hotkey);
return hotkey;
}

@@ -383,7 +390,24 @@

for (var i = 0; i < scope.hotkeys.length; i++) {
if (scope.hotkeys[i].combo === combo) {
scope.hotkeys.splice(i, 1);
if (combo instanceof Array) {
var retStatus = true;
for (var i = 0; i < combo.length; i++) {
retStatus = _del(combo[i]) && retStatus;
}
return retStatus;
} else {
var index = scope.hotkeys.indexOf(_get(combo));
if (index > -1) {
// if the combo has other combos bound, don't unbind the whole thing, just the one combo:
if (scope.hotkeys[index].combo.length > 1) {
scope.hotkeys[index].combo.splice(scope.hotkeys[index].combo.indexOf(combo), 1);
} else {
scope.hotkeys.splice(index, 1);
}
return true;
}
}
return false;
}

@@ -398,7 +422,13 @@

function _get (combo) {
var hotkey;
for (var i = 0; i < scope.hotkeys.length; i++) {
if (scope.hotkeys[i].combo === combo) {
return scope.hotkeys[i];
hotkey = scope.hotkeys[i];
if (hotkey.combo.indexOf(combo) > -1) {
return hotkey;
}
}
return false;

@@ -408,2 +438,38 @@ }

/**
* Binds the hotkey to a particular scope. Useful if the scope is
* destroyed, we can automatically destroy the hotkey binding.
*
* @param {Object} scope The scope to bind to
*/
function bindTo (scope) {
// Add the scope to the list of bound scopes
boundScopes[scope.$id] = [];
scope.$on('$destroy', function () {
var i = boundScopes[scope.$id].length;
while (i--) {
_del(boundScopes[scope.$id][i]);
delete boundScopes[scope.$id][i];
}
});
// return an object with an add function so we can keep track of the
// hotkeys and their scope that we added via this chaining method
return {
add: function (args) {
var hotkey;
if (arguments.length > 1) {
hotkey = _add.apply(this, arguments);
} else {
hotkey = _add(args);
}
boundScopes[scope.$id].push(hotkey);
return this;
}
};
}
/**
* All callbacks sent to Mousetrap are wrapped using this function

@@ -444,2 +510,3 @@ * so that we can force a $scope.$apply()

get : _get,
bindTo : bindTo,
template : this.template,

@@ -462,7 +529,17 @@ toggleCheatSheet : toggleCheatSheet,

link: function (scope, el, attrs) {
var key;
var key, allowIn;
angular.forEach(scope.$eval(attrs.hotkey), function (func, hotkey) {
// split and trim the hotkeys string into array
allowIn = attrs.hotkeyAllowIn.split(/[\s,]+/);
key = hotkey;
hotkeys.add(hotkey, attrs.hotkeyDescription, func, attrs.hotkeyAction);
hotkeys.add({
combo: hotkey,
description: attrs.hotkeyDescription,
callback: func,
action: attrs.hotkeyAction,
allowIn: allowIn
});
});

@@ -469,0 +546,0 @@

/*!
* angular-hotkeys v1.3.1
* angular-hotkeys v1.4.0
* https://chieffancypants.github.io/angular-hotkeys

@@ -7,2 +7,2 @@ * Copyright (c) 2014 Wes Cruver

*/
!function(){"use strict";angular.module("cfp.hotkeys",[]).provider("hotkeys",function(){this.includeCheatSheet=!0,this.template='<div class="cfp-hotkeys-container fade" ng-class="{in: helpVisible}"><div class="cfp-hotkeys"><h4 class="cfp-hotkeys-title">{{ title }}</h4><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 class="cfp-hotkeys-close" ng-click="helpVisible = false">×</div></div></div>',this.cheatSheetHotkey="?",this.cheatSheetDescription="Show / hide this help menu",this.$get=["$rootElement","$rootScope","$compile","$window","$document",function(a,b,c,d,e){function f(a){var b={command:"⌘",shift:"⇧",left:"←",right:"→",up:"↑",down:"↓","return":"↩",backspace:"⌫"};a=a.split("+");for(var c=0;c<a.length;c++)"mod"===a[c]&&(a[c]=d.navigator&&d.navigator.platform.indexOf("Mac")>=0?"command":"ctrl"),a[c]=b[a[c]]||a[c];return a.join(" + ")}function g(a,b,c,d,e,f){this.combo=a,this.description=b,this.callback=c,this.action=d,this.allowIn=e,this.persistent=f}function h(){for(var a=n.hotkeys.length;a--;){var b=n.hotkeys[a];b&&!b.persistent&&k(b)}}function i(){n.helpVisible=!n.helpVisible,n.helpVisible?(r=l("esc"),k("esc"),j("esc",r.description,i)):(k("esc"),r!==!1&&j(r))}function j(a,b,c,d,e,f){var h,i=["INPUT","SELECT","TEXTAREA"],j=Object.prototype.toString.call(a);if("[object Object]"===j&&(b=a.description,c=a.callback,d=a.action,f=a.persistent,e=a.allowIn,a=a.combo),b instanceof Function?(d=c,c=b,b="$$undefined$$"):angular.isUndefined(b)&&(b="$$undefined$$"),void 0===f&&(f=!0),"function"==typeof c){h=c,e instanceof Array||(e=[]);for(var k,l=0;l<e.length;l++)e[l]=e[l].toUpperCase(),k=i.indexOf(e[l]),-1!==k&&i.splice(k,1);c=function(a){var b=!0,c=a.target||a.srcElement,d=c.nodeName.toUpperCase();if((" "+c.className+" ").indexOf(" mousetrap ")>-1)b=!0;else for(var e=0;e<i.length;e++)if(i[e]===d){b=!1;break}b&&m(h.apply(this,arguments))}}"string"==typeof d?Mousetrap.bind(a,m(c),d):Mousetrap.bind(a,m(c)),n.hotkeys.push(new g(a,b,c,d,e,f))}function k(a){var b=a instanceof g?a.combo:a;Mousetrap.unbind(b);for(var c=0;c<n.hotkeys.length;c++)n.hotkeys[c].combo===b&&n.hotkeys.splice(c,1)}function l(a){for(var b=0;b<n.hotkeys.length;b++)if(n.hotkeys[b].combo===a)return n.hotkeys[b];return!1}function m(a){return function(c,d){if(a instanceof Array){var e=a[0],f=a[1];a=function(){f.scope.$eval(e)}}b.$apply(function(){a(c,l(d))})}}Mousetrap.stopCallback=function(a,b){return(" "+b.className+" ").indexOf(" mousetrap ")>-1?!1:b.contentEditable&&"true"==b.contentEditable},g.prototype.format=function(){var a=this.combo;a instanceof Array&&(a=a[0]);for(var b=a.split(/[\s]/),c=0;c<b.length;c++)b[c]=f(b[c]);return b};var n=b.$new();if(n.hotkeys=[],n.helpVisible=!1,n.title="Keyboard Shortcuts:",b.$on("$routeChangeSuccess",function(a,b){h(),b.hotkeys&&angular.forEach(b.hotkeys,function(a){var c=a[2];("string"==typeof c||c instanceof String)&&(a[2]=[c,b]),a[5]=!1,j.apply(this,a)})}),this.includeCheatSheet){var o=e[0],p=a[0],q=angular.element(this.template);j(this.cheatSheetHotkey,this.cheatSheetDescription,i),(p===o||p===o.documentElement)&&(p=o.body),angular.element(p).append(c(q)(n))}var r=!1,s={add:j,del:k,get:l,template:this.template,toggleCheatSheet:i,includeCheatSheat:this.includeCheatSheat,cheatSheetHotkey:this.cheatSheetHotkey,cheatSheetDescription:this.cheatSheetDescription,purgeHotkeys:h};return s}]}).directive("hotkey",["hotkeys",function(a){return{restrict:"A",link:function(b,c,d){var e;angular.forEach(b.$eval(d.hotkey),function(b,c){e=c,a.add(c,d.hotkeyDescription,b,d.hotkeyAction)}),c.bind("$destroy",function(){a.del(e)})}}}]).run(["hotkeys",function(){}])}(),function(a,b){function c(a,b,c){return a.addEventListener?void a.addEventListener(b,c,!1):void a.attachEvent("on"+b,c)}function d(a){if("keypress"==a.type){var b=String.fromCharCode(a.which);return a.shiftKey||(b=b.toLowerCase()),b}return y[a.which]?y[a.which]:z[a.which]?z[a.which]:String.fromCharCode(a.which).toLowerCase()}function e(a,b){return a.sort().join(",")===b.sort().join(",")}function f(a){a=a||{};var b,c=!1;for(b in E)a[b]?c=!0:E[b]=0;c||(H=!1)}function g(a,b,c,d,f,g){var h,i,j=[],k=c.type;if(!C[a])return[];for("keyup"==k&&n(a)&&(b=[a]),h=0;h<C[a].length;++h)if(i=C[a][h],(d||!i.seq||E[i.seq]==i.level)&&k==i.action&&("keypress"==k&&!c.metaKey&&!c.ctrlKey||e(b,i.modifiers))){var l=!d&&i.combo==f,m=d&&i.seq==d&&i.level==g;(l||m)&&C[a].splice(h,1),j.push(i)}return j}function h(a){var b=[];return a.shiftKey&&b.push("shift"),a.altKey&&b.push("alt"),a.ctrlKey&&b.push("ctrl"),a.metaKey&&b.push("meta"),b}function i(a){return a.preventDefault?void a.preventDefault():void(a.returnValue=!1)}function j(a){return a.stopPropagation?void a.stopPropagation():void(a.cancelBubble=!0)}function k(a,b,c,d){J.stopCallback(b,b.target||b.srcElement,c,d)||a(b,c)===!1&&(i(b),j(b))}function l(a,b,c){var d,e=g(a,b,c),h={},i=0,j=!1;for(d=0;d<e.length;++d)e[d].seq&&(i=Math.max(i,e[d].level));for(d=0;d<e.length;++d)if(e[d].seq){if(e[d].level!=i)continue;j=!0,h[e[d].seq]=1,k(e[d].callback,c,e[d].combo,e[d].seq)}else j||k(e[d].callback,c,e[d].combo);var l="keypress"==c.type&&G;c.type!=H||n(a)||l||f(h),G=j&&"keydown"==c.type}function m(a){"number"!=typeof a.which&&(a.which=a.keyCode);var b=d(a);if(b)return"keyup"==a.type&&F===b?void(F=!1):void J.handleKey(b,h(a),a)}function n(a){return"shift"==a||"ctrl"==a||"alt"==a||"meta"==a}function o(){clearTimeout(x),x=setTimeout(f,1e3)}function p(){if(!w){w={};for(var a in y)a>95&&112>a||y.hasOwnProperty(a)&&(w[y[a]]=a)}return w}function q(a,b,c){return c||(c=p()[a]?"keydown":"keypress"),"keypress"==c&&b.length&&(c="keydown"),c}function r(a,b,c,e){function g(b){return function(){H=b,++E[a],o()}}function h(b){k(c,b,a),"keyup"!==e&&(F=d(b)),setTimeout(f,10)}E[a]=0;for(var i=0;i<b.length;++i){var j=i+1===b.length,l=j?h:g(e||t(b[i+1]).action);u(b[i],l,e,a,i)}}function s(a){return"+"===a?["+"]:a.split("+")}function t(a,b){var c,d,e,f=[];for(c=s(a),e=0;e<c.length;++e)d=c[e],B[d]&&(d=B[d]),b&&"keypress"!=b&&A[d]&&(d=A[d],f.push("shift")),n(d)&&f.push(d);return b=q(d,f,b),{key:d,modifiers:f,action:b}}function u(a,b,c,d,e){D[a+":"+c]=b,a=a.replace(/\s+/g," ");var f,h=a.split(" ");return h.length>1?void r(a,h,b,c):(f=t(a,c),C[f.key]=C[f.key]||[],g(f.key,f.modifiers,{type:f.action},d,a,e),void C[f.key][d?"unshift":"push"]({callback:b,modifiers:f.modifiers,action:f.action,seq:d,level:e,combo:a}))}function v(a,b,c){for(var d=0;d<a.length;++d)u(a[d],b,c)}for(var w,x,y={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"},z={106:"*",107:"+",109:"-",110:".",111:"/",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},A={"~":"`","!":"1","@":"2","#":"3",$:"4","%":"5","^":"6","&":"7","*":"8","(":"9",")":"0",_:"-","+":"=",":":";",'"':"'","<":",",">":".","?":"/","|":"\\"},B={option:"alt",command:"meta","return":"enter",escape:"esc",mod:/Mac|iPod|iPhone|iPad/.test(navigator.platform)?"meta":"ctrl"},C={},D={},E={},F=!1,G=!1,H=!1,I=1;20>I;++I)y[111+I]="f"+I;for(I=0;9>=I;++I)y[I+96]=I;c(b,"keypress",m),c(b,"keydown",m),c(b,"keyup",m);var J={bind:function(a,b,c){return a=a instanceof Array?a:[a],v(a,b,c),this},unbind:function(a,b){return J.bind(a,function(){},b)},trigger:function(a,b){return D[a+":"+b]&&D[a+":"+b]({},a),this},reset:function(){return C={},D={},this},stopCallback:function(a,b){return(" "+b.className+" ").indexOf(" mousetrap ")>-1?!1:"INPUT"==b.tagName||"SELECT"==b.tagName||"TEXTAREA"==b.tagName||b.isContentEditable},handleKey:l};a.Mousetrap=J,"function"==typeof define&&define.amd&&define(J)}(window,document);
!function(){"use strict";angular.module("cfp.hotkeys",[]).provider("hotkeys",function(){this.includeCheatSheet=!0,this.template='<div class="cfp-hotkeys-container fade" ng-class="{in: helpVisible}"><div class="cfp-hotkeys"><h4 class="cfp-hotkeys-title">{{ title }}</h4><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 class="cfp-hotkeys-close" ng-click="helpVisible = false">×</div></div></div>',this.cheatSheetHotkey="?",this.cheatSheetDescription="Show / hide this help menu",this.$get=["$rootElement","$rootScope","$compile","$window","$document",function(a,b,c,d,e){function f(a){var b={command:"⌘",shift:"⇧",left:"←",right:"→",up:"↑",down:"↓","return":"↩",backspace:"⌫"};a=a.split("+");for(var c=0;c<a.length;c++)"mod"===a[c]&&(a[c]=d.navigator&&d.navigator.platform.indexOf("Mac")>=0?"command":"ctrl"),a[c]=b[a[c]]||a[c];return a.join(" + ")}function g(a,b,c,d,e,f){this.combo=a instanceof Array?a:[a],this.description=b,this.callback=c,this.action=d,this.allowIn=e,this.persistent=f}function h(){for(var a=o.hotkeys.length;a--;){var b=o.hotkeys[a];b&&!b.persistent&&k(b)}}function i(){o.helpVisible=!o.helpVisible,o.helpVisible?(t=l("esc"),k("esc"),j("esc",t.description,i)):(k("esc"),t!==!1&&j(t))}function j(a,b,c,d,e,f){var h,i=["INPUT","SELECT","TEXTAREA"],j=Object.prototype.toString.call(a);if("[object Object]"===j&&(b=a.description,c=a.callback,d=a.action,f=a.persistent,e=a.allowIn,a=a.combo),b instanceof Function?(d=c,c=b,b="$$undefined$$"):angular.isUndefined(b)&&(b="$$undefined$$"),void 0===f&&(f=!0),"function"==typeof c){h=c,e instanceof Array||(e=[]);for(var k,l=0;l<e.length;l++)e[l]=e[l].toUpperCase(),k=i.indexOf(e[l]),-1!==k&&i.splice(k,1);c=function(a){var b=!0,c=a.target||a.srcElement,d=c.nodeName.toUpperCase();if((" "+c.className+" ").indexOf(" mousetrap ")>-1)b=!0;else for(var e=0;e<i.length;e++)if(i[e]===d){b=!1;break}b&&n(h.apply(this,arguments))}}"string"==typeof d?Mousetrap.bind(a,n(c),d):Mousetrap.bind(a,n(c));var m=new g(a,b,c,d,e,f);return o.hotkeys.push(m),m}function k(a){var b=a instanceof g?a.combo:a;if(Mousetrap.unbind(b),b instanceof Array){for(var c=!0,d=0;d<b.length;d++)c=k(b[d])&&c;return c}var e=o.hotkeys.indexOf(l(b));return e>-1?(o.hotkeys[e].combo.length>1?o.hotkeys[e].combo.splice(o.hotkeys[e].combo.indexOf(b),1):o.hotkeys.splice(e,1),!0):!1}function l(a){for(var b,c=0;c<o.hotkeys.length;c++)if(b=o.hotkeys[c],b.combo.indexOf(a)>-1)return b;return!1}function m(a){return p[a.$id]=[],a.$on("$destroy",function(){for(var b=p[a.$id].length;b--;)k(p[a.$id][b]),delete p[a.$id][b]}),{add:function(b){var c;return c=arguments.length>1?j.apply(this,arguments):j(b),p[a.$id].push(c),this}}}function n(a){return function(c,d){if(a instanceof Array){var e=a[0],f=a[1];a=function(){f.scope.$eval(e)}}b.$apply(function(){a(c,l(d))})}}Mousetrap.stopCallback=function(a,b){return(" "+b.className+" ").indexOf(" mousetrap ")>-1?!1:b.contentEditable&&"true"==b.contentEditable},g.prototype.format=function(){for(var a=this.combo[0],b=a.split(/[\s]/),c=0;c<b.length;c++)b[c]=f(b[c]);return b};var o=b.$new();o.hotkeys=[],o.helpVisible=!1,o.title="Keyboard Shortcuts:";var p=[];if(b.$on("$routeChangeSuccess",function(a,b){h(),b.hotkeys&&angular.forEach(b.hotkeys,function(a){var c=a[2];("string"==typeof c||c instanceof String)&&(a[2]=[c,b]),a[5]=!1,j.apply(this,a)})}),this.includeCheatSheet){var q=e[0],r=a[0],s=angular.element(this.template);j(this.cheatSheetHotkey,this.cheatSheetDescription,i),(r===q||r===q.documentElement)&&(r=q.body),angular.element(r).append(c(s)(o))}var t=!1,u={add:j,del:k,get:l,bindTo:m,template:this.template,toggleCheatSheet:i,includeCheatSheat:this.includeCheatSheat,cheatSheetHotkey:this.cheatSheetHotkey,cheatSheetDescription:this.cheatSheetDescription,purgeHotkeys:h};return u}]}).directive("hotkey",["hotkeys",function(a){return{restrict:"A",link:function(b,c,d){var e,f;angular.forEach(b.$eval(d.hotkey),function(b,c){f=d.hotkeyAllowIn.split(/[\s,]+/),e=c,a.add({combo:c,description:d.hotkeyDescription,callback:b,action:d.hotkeyAction,allowIn:f})}),c.bind("$destroy",function(){a.del(e)})}}}]).run(["hotkeys",function(){}])}(),function(a,b){function c(a,b,c){return a.addEventListener?void a.addEventListener(b,c,!1):void a.attachEvent("on"+b,c)}function d(a){if("keypress"==a.type){var b=String.fromCharCode(a.which);return a.shiftKey||(b=b.toLowerCase()),b}return y[a.which]?y[a.which]:z[a.which]?z[a.which]:String.fromCharCode(a.which).toLowerCase()}function e(a,b){return a.sort().join(",")===b.sort().join(",")}function f(a){a=a||{};var b,c=!1;for(b in E)a[b]?c=!0:E[b]=0;c||(H=!1)}function g(a,b,c,d,f,g){var h,i,j=[],k=c.type;if(!C[a])return[];for("keyup"==k&&n(a)&&(b=[a]),h=0;h<C[a].length;++h)if(i=C[a][h],(d||!i.seq||E[i.seq]==i.level)&&k==i.action&&("keypress"==k&&!c.metaKey&&!c.ctrlKey||e(b,i.modifiers))){var l=!d&&i.combo==f,m=d&&i.seq==d&&i.level==g;(l||m)&&C[a].splice(h,1),j.push(i)}return j}function h(a){var b=[];return a.shiftKey&&b.push("shift"),a.altKey&&b.push("alt"),a.ctrlKey&&b.push("ctrl"),a.metaKey&&b.push("meta"),b}function i(a){return a.preventDefault?void a.preventDefault():void(a.returnValue=!1)}function j(a){return a.stopPropagation?void a.stopPropagation():void(a.cancelBubble=!0)}function k(a,b,c,d){J.stopCallback(b,b.target||b.srcElement,c,d)||a(b,c)===!1&&(i(b),j(b))}function l(a,b,c){var d,e=g(a,b,c),h={},i=0,j=!1;for(d=0;d<e.length;++d)e[d].seq&&(i=Math.max(i,e[d].level));for(d=0;d<e.length;++d)if(e[d].seq){if(e[d].level!=i)continue;j=!0,h[e[d].seq]=1,k(e[d].callback,c,e[d].combo,e[d].seq)}else j||k(e[d].callback,c,e[d].combo);var l="keypress"==c.type&&G;c.type!=H||n(a)||l||f(h),G=j&&"keydown"==c.type}function m(a){"number"!=typeof a.which&&(a.which=a.keyCode);var b=d(a);if(b)return"keyup"==a.type&&F===b?void(F=!1):void J.handleKey(b,h(a),a)}function n(a){return"shift"==a||"ctrl"==a||"alt"==a||"meta"==a}function o(){clearTimeout(x),x=setTimeout(f,1e3)}function p(){if(!w){w={};for(var a in y)a>95&&112>a||y.hasOwnProperty(a)&&(w[y[a]]=a)}return w}function q(a,b,c){return c||(c=p()[a]?"keydown":"keypress"),"keypress"==c&&b.length&&(c="keydown"),c}function r(a,b,c,e){function g(b){return function(){H=b,++E[a],o()}}function h(b){k(c,b,a),"keyup"!==e&&(F=d(b)),setTimeout(f,10)}E[a]=0;for(var i=0;i<b.length;++i){var j=i+1===b.length,l=j?h:g(e||t(b[i+1]).action);u(b[i],l,e,a,i)}}function s(a){return"+"===a?["+"]:a.split("+")}function t(a,b){var c,d,e,f=[];for(c=s(a),e=0;e<c.length;++e)d=c[e],B[d]&&(d=B[d]),b&&"keypress"!=b&&A[d]&&(d=A[d],f.push("shift")),n(d)&&f.push(d);return b=q(d,f,b),{key:d,modifiers:f,action:b}}function u(a,b,c,d,e){D[a+":"+c]=b,a=a.replace(/\s+/g," ");var f,h=a.split(" ");return h.length>1?void r(a,h,b,c):(f=t(a,c),C[f.key]=C[f.key]||[],g(f.key,f.modifiers,{type:f.action},d,a,e),void C[f.key][d?"unshift":"push"]({callback:b,modifiers:f.modifiers,action:f.action,seq:d,level:e,combo:a}))}function v(a,b,c){for(var d=0;d<a.length;++d)u(a[d],b,c)}for(var w,x,y={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"},z={106:"*",107:"+",109:"-",110:".",111:"/",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},A={"~":"`","!":"1","@":"2","#":"3",$:"4","%":"5","^":"6","&":"7","*":"8","(":"9",")":"0",_:"-","+":"=",":":";",'"':"'","<":",",">":".","?":"/","|":"\\"},B={option:"alt",command:"meta","return":"enter",escape:"esc",mod:/Mac|iPod|iPhone|iPad/.test(navigator.platform)?"meta":"ctrl"},C={},D={},E={},F=!1,G=!1,H=!1,I=1;20>I;++I)y[111+I]="f"+I;for(I=0;9>=I;++I)y[I+96]=I;c(b,"keypress",m),c(b,"keydown",m),c(b,"keyup",m);var J={bind:function(a,b,c){return a=a instanceof Array?a:[a],v(a,b,c),this},unbind:function(a,b){return J.bind(a,function(){},b)},trigger:function(a,b){return D[a+":"+b]&&D[a+":"+b]({},a),this},reset:function(){return C={},D={},this},stopCallback:function(a,b){return(" "+b.className+" ").indexOf(" mousetrap ")>-1?!1:"INPUT"==b.tagName||"SELECT"==b.tagName||"TEXTAREA"==b.tagName||b.isContentEditable},handleKey:l};a.Mousetrap=J,"function"==typeof define&&define.amd&&define(J)}(window,document);
{
"name": "angular-hotkeys",
"author": "Wes Cruver",
"version": "1.3.1",
"version": "1.4.0",
"license": "MIT",

@@ -6,0 +6,0 @@ "description": "Automatic keyboard shortcuts for your Angular Apps",

@@ -76,3 +76,11 @@ angular-hotkeys

#### Binding hotkeys in controllers:
It is important to note that by default, hotkeys bound using the `hotkeys.add()`
method are persistent, meaning they will continue to exist through route
changes, DOM manipulation, or anything else.
However, it is possible to bind the hotkey to a particular scope, and when that
scope is destroyed, the hotkey is automatically removed. This should be
considered the best practice when binding hotkeys from a controller. For this
usage example, see the `hotkeys.bindTo()` method below:
```js

@@ -82,3 +90,4 @@ angular.module('myApp').controller('NavbarCtrl', function($scope, hotkeys) {

// Pass it an object:
// You can pass it an object. This hotkey will not be unbound unless manually removed
// using the hotkeys.del() method
hotkeys.add({

@@ -92,6 +101,12 @@ combo: 'ctrl+up',

// or pass it arguments:
hotkeys.add('ctrl+down', 'Turn the volume down on this hotness', function() {
$scope.volume -= 1;
});
// when you bind it to the controller's scope, it will automatically unbind
// the hotkey when the scope is destroyed (due to ng-if or something that changes the DOM)
hotkeys.bindTo($scope)
.add({
combo: 'w',
description: 'blah blah',
callback: function() {}
})
// you can chain these methods for ease of use:
.add ({...});

@@ -149,23 +164,11 @@ });

#### hotkeys.add(combo, description, callback)
#### hotkeys.add(object)
`object`: An object with the following parameters:
- `combo`: They keyboard combo (shortcut) you want to bind to
- `description`: [OPTIONAL] The description for what the combo does and is only used for the Cheat Sheet. If it is not supplied, it will not show up, and in effect, allows you to have unlisted hotkeys.
- `callback`: The function to execute when the key(s) are pressed. Passes along two arguments, `event` and `hotkey`
- `action`: [OPTIONAL] The type of event to listen for, such as `keypress`, `keydown` or `keyup`
- `allowIn`: [OPTIONAL] an array of tag names to allow this combo in ('INPUT', 'SELECT', and/or 'TEXTAREA')
```js
hotkeys.add('ctrl+w', 'Description goes here', function (event, hotkey) {
event.preventDefault();
});
// this hotkey will not show up on the cheat sheet:
hotkeys.add('ctrl+y', function (event, hotkey) {
event.preventDefault();
});
```
#### hotkeys.add(object)
- `object`: An object version of the above parameters.
```js
hotkeys.add({

@@ -178,2 +181,8 @@ combo: 'ctrl+w',

});
// this hotkey will not show up on the cheat sheet:
hotkeys.add({
combo: 'ctrl+x',
callback: function(event, hotkey) {...}
});
```

@@ -186,3 +195,3 @@

hotkeys.get('ctrl+w');
// -> Hotkey { combo: 'ctrl+w', description: 'Description goes here', callback: function (event, hotkey) }
// -> Hotkey { combo: ['ctrl+w'], description: 'Description goes here', callback: function (event, hotkey) }
```

@@ -189,0 +198,0 @@

@@ -102,3 +102,3 @@ /*

*
* @param {String} combo The keycombo
* @param {array} combo The keycombo. it's an array to support multiple combos
* @param {String} description Description for the keycombo

@@ -114,3 +114,4 @@ * @param {Function} callback function to execute when keycombo pressed

// supplied values
this.combo = combo;
this.combo = combo instanceof Array ? combo : [combo];
this.description = description;

@@ -133,12 +134,6 @@ this.callback = callback;

var combo = this.combo;
// Don't show all the possible key combos, just the first one. Not sure
// of usecase here, so open a ticket if my assumptions are wrong
var combo = this.combo[0];
// if the combo is an array, it means the there are multiple bindings to
// the same callback. Don't show all the possible key combos, just the
// first one. Not sure of usecase here, so open a ticket if my
// assumptions are wrong
if (combo instanceof Array) {
combo = combo[0];
}
var sequence = combo.split(/[\s]/);

@@ -177,2 +172,12 @@ for (var i = 0; i < sequence.length; i++) {

/**
* Holds references to the different scopes that have bound hotkeys
* attached. This is useful to catch when the scopes are `$destroy`d and
* then automatically unbind the hotkey.
*
* @type {Array}
*/
var boundScopes = [];
$rootScope.$on('$routeChangeSuccess', function (event, route) {

@@ -362,3 +367,5 @@ purgeHotkeys();

scope.hotkeys.push(new Hotkey(combo, description, callback, action, allowIn, persistent));
var hotkey = new Hotkey(combo, description, callback, action, allowIn, persistent);
scope.hotkeys.push(hotkey);
return hotkey;
}

@@ -377,7 +384,24 @@

for (var i = 0; i < scope.hotkeys.length; i++) {
if (scope.hotkeys[i].combo === combo) {
scope.hotkeys.splice(i, 1);
if (combo instanceof Array) {
var retStatus = true;
for (var i = 0; i < combo.length; i++) {
retStatus = _del(combo[i]) && retStatus;
}
return retStatus;
} else {
var index = scope.hotkeys.indexOf(_get(combo));
if (index > -1) {
// if the combo has other combos bound, don't unbind the whole thing, just the one combo:
if (scope.hotkeys[index].combo.length > 1) {
scope.hotkeys[index].combo.splice(scope.hotkeys[index].combo.indexOf(combo), 1);
} else {
scope.hotkeys.splice(index, 1);
}
return true;
}
}
return false;
}

@@ -392,7 +416,13 @@

function _get (combo) {
var hotkey;
for (var i = 0; i < scope.hotkeys.length; i++) {
if (scope.hotkeys[i].combo === combo) {
return scope.hotkeys[i];
hotkey = scope.hotkeys[i];
if (hotkey.combo.indexOf(combo) > -1) {
return hotkey;
}
}
return false;

@@ -402,2 +432,38 @@ }

/**
* Binds the hotkey to a particular scope. Useful if the scope is
* destroyed, we can automatically destroy the hotkey binding.
*
* @param {Object} scope The scope to bind to
*/
function bindTo (scope) {
// Add the scope to the list of bound scopes
boundScopes[scope.$id] = [];
scope.$on('$destroy', function () {
var i = boundScopes[scope.$id].length;
while (i--) {
_del(boundScopes[scope.$id][i]);
delete boundScopes[scope.$id][i];
}
});
// return an object with an add function so we can keep track of the
// hotkeys and their scope that we added via this chaining method
return {
add: function (args) {
var hotkey;
if (arguments.length > 1) {
hotkey = _add.apply(this, arguments);
} else {
hotkey = _add(args);
}
boundScopes[scope.$id].push(hotkey);
return this;
}
};
}
/**
* All callbacks sent to Mousetrap are wrapped using this function

@@ -438,2 +504,3 @@ * so that we can force a $scope.$apply()

get : _get,
bindTo : bindTo,
template : this.template,

@@ -456,7 +523,17 @@ toggleCheatSheet : toggleCheatSheet,

link: function (scope, el, attrs) {
var key;
var key, allowIn;
angular.forEach(scope.$eval(attrs.hotkey), function (func, hotkey) {
// split and trim the hotkeys string into array
allowIn = attrs.hotkeyAllowIn.split(/[\s,]+/);
key = hotkey;
hotkeys.add(hotkey, attrs.hotkeyDescription, func, attrs.hotkeyAction);
hotkeys.add({
combo: hotkey,
description: attrs.hotkeyDescription,
callback: func,
action: attrs.hotkeyAction,
allowIn: allowIn
});
});

@@ -463,0 +540,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc