All files hotkeys.js

66.87% Statements 109/163
51.33% Branches 77/150
68.18% Functions 15/22
73.72% Lines 101/137

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352                    1x 1x         1x       2x 2x                   20x 20x 20x 20x         50x     50x 50x 50x     50x 3x 3x 3x     50x         24x 24x   24x 24x     6x     1x                             1x           1x 1x         1x 1x     1x 19x       1x 1x   1x   1x 52x         2x       49x                 41x   41x                                                                                                           5x 5x 5x 5x   5x   6x     6x     6x 6x     6x     6x       6x 30x   30x 6x               91x     91x   75x   75x 300x       75x 45x                     41x   41x     41x       41x   41x                   41x 164x   41x     41x     41x             41x   40x   91x         45x 45x 45x     45x 43x 43x       45x 46x 46x     46x     46x 46x     46x   46x                   1x 1x 41x   1x         1x 1x 7x 1x 1x 1x           1x     1x      
/*!
 * hotkeys-js v3.0.0
 * A simple micro-library for defining and dispatching keyboard shortcuts. It has no dependencies.
 * 
 * Copyright (c) 2018 kenny wong <wowohoo@qq.com>
 * 
 * 
 * Licensed under the MIT license.
 */
 
(function (global, factory) {
	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
	typeof define === 'function' && define.amd ? define(factory) :
	(global.hotkeys = factory());
}(this, (function () { 'use strict';
 
var isff = typeof navigator !== 'undefined' ? navigator.userAgent.toLowerCase().indexOf('firefox') > 0 : false;
 
// 绑定事件
function addEvent(object, event, method) {
  Eif (object.addEventListener) {
    object.addEventListener(event, method, false);
  } else if (object.attachEvent) {
    object.attachEvent('on' + event, function () {
      method(window.event);
    });
  }
}
 
// 修饰键转换成对应的键码
function getMods(modifier, key) {
  var mods = key.slice(0, key.length - 1);
  for (var i = 0; i < mods.length; i++) {
    mods[i] = modifier[mods[i].toLowerCase()];
  }return mods;
}
 
// 处理传的key字符串转换成数组
function getKeys(key) {
  Iif (!key) key = '';
  var keys, index;
 
  key = key.replace(/\s/g, ''); // 匹配任何空白字符,包括空格、制表符、换页符等等
  keys = key.split(','); // 同时设置多个快捷键,以','分割
  index = keys.lastIndexOf('');
 
  // 快捷键可能包含',',需特殊处理
  for (; index >= 0;) {
    keys[index - 1] += ',';
    keys.splice(index, 1);
    index = keys.lastIndexOf('');
  }
 
  return keys;
}
 
//比较修饰键的数组
function compareArray(a1, a2) {
  var arr1 = a1.length >= a2.length ? a1 : a2;
  var arr2 = a1.length >= a2.length ? a2 : a1;
 
  for (var i = 0; i < arr1.length; i++) {
    if (arr2.indexOf(arr1[i]) === -1) return false;
  }
 
  return true;
}
 
var _keyMap = { // 特殊键
  backspace: 8, tab: 9, clear: 12,
  enter: 13, 'return': 13,
  esc: 27, escape: 27, space: 32,
  left: 37, up: 38, right: 39, down: 40,
  del: 46, 'delete': 46,
  ins: 45, 'insert': 45,
  home: 36, end: 35,
  pageup: 33, pagedown: 34, '⇪': 20, 'capslock': 20,
  ',': 188, '.': 190, '/': 191,
  '`': 192, '-': isff ? 173 : 189, '=': isff ? 61 : 187,
  ';': isff ? 59 : 186, '\'': 222,
  '[': 219, ']': 221, '\\': 220
};
 
var _modifier = { //修饰键
  '⇧': 16, shift: 16,
  '⌥': 18, alt: 18, option: 18,
  '⌃': 17, ctrl: 17, control: 17,
  '⌘': isff ? 224 : 91, cmd: isff ? 224 : 91, command: isff ? 224 : 91
};
var _downKeys = []; // 记录摁下的绑定键
var modifierMap = {
  16: 'shiftKey',
  18: 'altKey',
  17: 'ctrlKey'
};
var _mods = { 16: false, 18: false, 17: false };
var _handlers = {};
 
// F1~F12 特殊键
for (var k = 1; k < 20; k++) {
  _keyMap['f' + k] = 111 + k;
}
 
// 兼容Firefox处理
modifierMap[isff ? 224 : 91] = 'metaKey';
_mods[isff ? 224 : 91] = false;
 
var _scope = 'all'; //默认热键范围
// 返回键码
var code = function code(x) {
  return _keyMap[x.toLowerCase()] || x.toUpperCase().charCodeAt(0);
};
 
// 设置获取当前范围(默认为'所有')
function setScope(scope) {
  _scope = scope || 'all';
}
// 获取当前范围
function getScope() {
  return _scope || 'all';
}
// 获取摁下绑定键的键值
function getPressedKeyCodes() {
  return _downKeys.slice(0);
}
 
// 表单控件控件判断 返回 Boolean
function filter(event) {
  var tagName = (event.target || event.srcElement).tagName;
  // 忽略这些标签情况下快捷键无效
  return !(tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA');
}
 
// 判断摁下的键是否为某个键,返回true或者false
function isPressed(keyCode) {
  if (typeof keyCode === 'string') {
    keyCode = code(keyCode); // 转换成键码
  }
 
  return _downKeys.indexOf(keyCode) !== -1;
}
 
// 循环删除handlers中的所有 scope(范围)
function deleteScope(scope, newScope) {
  var handlers = void 0;
  var i = void 0;
 
  // 没有指定scope,获取scope
  if (!scope) scope = getScope();
 
  for (var key in _handlers) {
    handlers = _handlers[key];
 
    for (i = 0; i < handlers.length;) {
      if (handlers[i].scope === scope) handlers.splice(i, 1);else i++;
    }
  }
 
  // 如果scope被删除,将scope重置为all
  if (getScope() === scope) setScope(newScope || 'all');
}
 
// 清除修饰键
function clearModifier(event) {
  var key = event.keyCode || event.which || event.charCode;
  var i = _downKeys.indexOf(key);
 
  // 从列表中清除按压过的键
  if (i >= 0) _downKeys.splice(i, 1);
 
  // 修饰键 shiftKey altKey ctrlKey (command||metaKey) 清除
  if (key === 93 || key === 224) key = 91;
  if (key in _mods) {
    _mods[key] = false;
 
    // 将修饰键重置为false
    for (var k in _modifier) {
      if (_modifier[k] === key) hotkeys[k] = false;
    }
  }
}
 
// 解除绑定某个范围的快捷键
function unbind(key, scope) {
  var multipleKeys = getKeys(key),
      keys = void 0,
      mods = [],
      obj = void 0;
 
  for (var i = 0; i < multipleKeys.length; i++) {
    // 将组合快捷键拆分为数组
    keys = multipleKeys[i].split('+');
 
    // 记录每个组合键中的修饰键的键码 返回数组
    Eif (keys.length > 1) mods = getMods(_modifier, keys);
 
    // 获取除修饰键外的键值key
    key = keys[keys.length - 1];
    key = key === '*' ? '*' : code(key);
 
    // 判断是否传入范围,没有就获取范围
    if (!scope) scope = getScope();
 
    // 如何key不在 _handlers 中返回不做处理
    Iif (!_handlers[key]) return;
 
    // 清空 handlers 中数据,
    // 让触发快捷键键之后没有事件执行到达解除快捷键绑定的目的
    for (var r = 0; r < _handlers[key].length; r++) {
      obj = _handlers[key][r];
      // 判断是否在范围内并且键值相同
      if (obj.scope === scope && compareArray(obj.mods, mods)) {
        _handlers[key][r] = {};
      }
    }
  }
}
 
// 对监听对应快捷键的回调函数进行处理
function eventHandler(event, handler, scope) {
  var modifiersMatch = void 0;
 
  // 看它是否在当前范围
  if (handler.scope === scope || handler.scope === 'all') {
    //检查是否匹配修饰符(如果有返回true)
    modifiersMatch = handler.mods.length > 0;
 
    for (var y in _mods) {
      if (!_mods[y] && handler.mods.indexOf(+y) > -1 || _mods[y] && handler.mods.indexOf(+y) === -1) modifiersMatch = false;
    }
 
    // 调用处理程序,如果是修饰键不做处理
    if (handler.mods.length === 0 && !_mods[16] && !_mods[18] && !_mods[17] && !_mods[91] || modifiersMatch || handler.shortcut === '*') {
      Iif (handler.method(event, handler) === false) {
        if (event.preventDefault) event.preventDefault();else event.returnValue = false;
        if (event.stopPropagation) event.stopPropagation();
        if (event.cancelBubble) event.cancelBubble = true;
      }
    }
  }
}
 
// 处理keydown事件
function dispatch(event) {
  var key = event.keyCode || event.which || event.charCode,
      scope,
      asterisk = _handlers['*'];
 
  // 搜集绑定的键
  if (_downKeys.indexOf(key) === -1) _downKeys.push(key);
 
  // Gecko(Firefox)的command键值224,在Webkit(Chrome)中保持一致
  // Webkit左右command键值不一样
  Iif (key === 93 || key === 224) key = 91;
 
  Iif (key in _mods) {
    _mods[key] = true;
 
    // 将特殊字符的key注册到 hotkeys 上
    for (var k in _modifier) {
      if (_modifier[k] === key) hotkeys[k] = true;
    }if (!asterisk) return;
  }
 
  // 将modifierMap里面的修饰键绑定到event中
  for (var e in _mods) {
    _mods[e] = event[modifierMap[e]];
  } // 表单控件过滤 默认表单控件不触发快捷键
  Iif (!hotkeys.filter.call(this, event)) return;
 
  // 获取范围 默认为all
  scope = getScope();
 
  // 对任何快捷键都需要做的处理
  Iif (asterisk) {
    for (i = 0; i < asterisk.length; i++) {
      if (asterisk[i].scope === scope) eventHandler(event, asterisk[i], scope);
    }
  }
 
  // key 不在_handlers中返回
  if (!(key in _handlers)) return;
 
  for (var i = 0; i < _handlers[key].length; i++) {
    // 找到处理内容
    eventHandler(event, _handlers[key][i], scope);
  }
}
 
function hotkeys(key, scope, method) {
  var keys = getKeys(key); // 需要处理的快捷键列表
  var mods = [];
  var i = 0;
 
  // 对为设定范围的判断
  if (method === undefined) {
    method = scope;
    scope = 'all'; // scope默认为all,所有范围都有效
  }
 
  // 对于每个快捷键进行处理
  for (; i < keys.length; i++) {
    key = keys[i].split('+'); // 按键列表
    mods = [];
 
    // 如果是组合快捷键取得组合快捷键
    if (key.length > 1) mods = getMods(_modifier, key);
 
    // 将非修饰键转化为键码
    key = key[key.length - 1];
    key = key === '*' ? '*' : code(key); // *表示匹配所有快捷键
 
    // 判断key是否在_handlers中,不在就赋一个空数组
    if (!(key in _handlers)) _handlers[key] = [];
 
    _handlers[key].push({
      scope: scope, mods: mods,
      shortcut: keys[i],
      method: method,
      key: keys[i]
    });
  }
}
 
// 在全局document上设置快捷键
Eif (typeof document !== 'undefined') {
  addEvent(document, "keydown", function (e) {
    dispatch(e);
  });
  addEvent(document, "keyup", function (e) {
    clearModifier(e);
  });
}
 
var _api = { setScope: setScope, getScope: getScope, deleteScope: deleteScope, getPressedKeyCodes: getPressedKeyCodes, isPressed: isPressed, filter: filter, unbind: unbind };
for (var a in _api) {
  hotkeys[a] = _api[a];
}Eif (typeof window !== 'undefined') {
  var _hotkeys = window.hotkeys;
  hotkeys.noConflict = function (deep) {
    if (deep && window.hotkeys === hotkeys) {
      window.hotkeys = _hotkeys;
    }
    return hotkeys;
  };
  window.hotkeys = hotkeys;
}
 
return hotkeys;
 
})));