PageSourceSearch

https://www.thechronicle-news.com/wp-content/plugins/accessibility-onetap/assets/js/hotkeys.js?ver=2.14.0

js thechronicle-news.com collected 2026-09-26 02:59:46 UTC 16,283 bytes, 564 lines download raw bytes

vendor: 16,283 bytes, lines 1-564
1/*!
2 * hotkeys-js v3.8.1
3 * A simple micro-library for defining and dispatching keyboard shortcuts. It has no dependencies.
4 * 
5 * Copyright (c) 2020 kenny wong <[email protected]>
6 * http://jaywcjlove.github.io/hotkeys
7 * 
8 * Licensed under the MIT license.
9 */
10
11(function (global, factory) {
12  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
13  typeof define === 'function' && define.amd ? define(factory) :
14  (global = global || self, global.hotkeys = factory());
15}(this, (function () { 'use strict';
16
17  var isff = typeof navigator !== 'undefined' ? navigator.userAgent.toLowerCase().indexOf('firefox') > 0 : false; // 绑定事件
18
19  function addEvent(object, event, method) {
20    if (object.addEventListener) {
21      object.addEventListener(event, method, false);
22    } else if (object.attachEvent) {
23      object.attachEvent("on".concat(event), function () {
24        method(window.event);
25      });
26    }
27  } // 修饰键转换成对应的键码
28
29
30  function getMods(modifier, key) {
31    var mods = key.slice(0, key.length - 1);
32
33    for (var i = 0; i < mods.length; i++) {
34      mods[i] = modifier[mods[i].toLowerCase()];
35    }
36
37    return mods;
38  } // 处理传的key字符串转换成数组
39
40
41  function getKeys(key) {
42    if (typeof key !== 'string') key = '';
43    key = key.replace(/\s/g, ''); // 匹配任何空白字符,包括空格、制表符、换页符等等
44
45    var keys = key.split(','); // 同时设置多个快捷键,以','分割
46
47    var index = keys.lastIndexOf(''); // 快捷键可能包含',',需特殊处理
48
49    for (; index >= 0;) {
50      keys[index - 1] += ',';
51      keys.splice(index, 1);
52      index = keys.lastIndexOf('');
53    }
54
55    return keys;
56  } // 比较修饰键的数组
57
58
59  function compareArray(a1, a2) {
60    var arr1 = a1.length >= a2.length ? a1 : a2;
61    var arr2 = a1.length >= a2.length ? a2 : a1;
62    var isIndex = true;
63
64    for (var i = 0; i < arr1.length; i++) {
65      if (arr2.indexOf(arr1[i]) === -1) isIndex = false;
66    }
67
68    return isIndex;
69  }
70
71  var _keyMap = {
72    backspace: 8,
73    tab: 9,
74    clear: 12,
75    enter: 13,
76    return: 13,
77    esc: 27,
78    escape: 27,
79    space: 32,
80    left: 37,
81    up: 38,
82    right: 39,
83    down: 40,
84    del: 46,
85    delete: 46,
86    ins: 45,
87    insert: 45,
88    home: 36,
89    end: 35,
90    pageup: 33,
91    pagedown: 34,
92    capslock: 20,
93    '⇪': 20,
94    ',': 188,
95    '.': 190,
96    '/': 191,
97    '`': 192,
98    '-': isff ? 173 : 189,
99    '=': isff ? 61 : 187,
100    ';': isff ? 59 : 186,
101    '\'': 222,
102    '[': 219,
103    ']': 221,
104    '\\': 220
105  }; // Modifier Keys
106
107  var _modifier = {
108    // shiftKey
109    '⇧': 16,
110    shift: 16,
111    // altKey
112    '⌥': 18,
113    alt: 18,
114    option: 18,
115    // ctrlKey
116    '⌃': 17,
117    ctrl: 17,
118    control: 17,
119    // metaKey
120    '⌘': 91,
121    cmd: 91,
122    command: 91
123  };
124  var modifierMap = {
125    16: 'shiftKey',
126    18: 'altKey',
127    17: 'ctrlKey',
128    91: 'metaKey',
129    shiftKey: 16,
130    ctrlKey: 17,
131    altKey: 18,
132    metaKey: 91
133  };
134  var _mods = {
135    16: false,
136    18: false,
137    17: false,
138    91: false
139  };
140  var _handlers = {}; // F1~F12 special key
141
142  for (var k = 1; k < 20; k++) {
143    _keyMap["f".concat(k)] = 111 + k;
144  }
145
146  var _downKeys = []; // 记录摁下的绑定键
147
148  var _scope = 'all'; // 默认热键范围
149
150  var elementHasBindEvent = []; // 已绑定事件的节点记录
151  // 返回键码
152
153  var code = function code(x) {
154    return _keyMap[x.toLowerCase()] || _modifier[x.toLowerCase()] || x.toUpperCase().charCodeAt(0);
155  }; // 设置获取当前范围(默认为'所有')
156
157
158  function setScope(scope) {
159    _scope = scope || 'all';
160  } // 获取当前范围
161
162
163  function getScope() {
164    return _scope || 'all';
165  } // 获取摁下绑定键的键值
166
167
168  function getPressedKeyCodes() {
169    return _downKeys.slice(0);
170  } // 表单控件控件判断 返回 Boolean
171  // hotkey is effective only when filter return true
172
173
174  function filter(event) {
175    var target = event.target || event.srcElement;
176    var tagName = target.tagName;
177    var flag = true; // ignore: isContentEditable === 'true', <input> and <textarea> when readOnly state is false, <select>
178
179    if (target.isContentEditable || (tagName === 'INPUT' || tagName === 'TEXTAREA' || tagName === 'SELECT') && !target.readOnly) {
180      flag = false;
181    }
182
183    return flag;
184  } // 判断摁下的键是否为某个键,返回true或者false
185
186
187  function isPressed(keyCode) {
188    if (typeof keyCode === 'string') {
189      keyCode = code(keyCode); // 转换成键码
190    }
191
192    return _downKeys.indexOf(keyCode) !== -1;
193  } // 循环删除handlers中的所有 scope(范围)
194
195
196  function deleteScope(scope, newScope) {
197    var handlers;
198    var i; // 没有指定scope,获取scope
199
200    if (!scope) scope = getScope();
201
202    for (var key in _handlers) {
203      if (Object.prototype.hasOwnProperty.call(_handlers, key)) {
204        handlers = _handlers[key];
205
206        for (i = 0; i < handlers.length;) {
207          if (handlers[i].scope === scope) handlers.splice(i, 1);else i++;
208        }
209      }
210    } // 如果scope被删除,将scope重置为all
211
212
213    if (getScope() === scope) setScope(newScope || 'all');
214  } // 清除修饰键
215
216
217  function clearModifier(event) {
218    var key = event.keyCode || event.which || event.charCode;
219
220    var i = _downKeys.indexOf(key); // 从列表中清除按压过的键
221
222
223    if (i >= 0) {
224      _downKeys.splice(i, 1);
225    } // 特殊处理 cmmand 键,在 cmmand 组合快捷键 keyup 只执行一次的问题
226
227
228    if (event.key && event.key.toLowerCase() === 'meta') {
229      _downKeys.splice(0, _downKeys.length);
230    } // 修饰键 shiftKey altKey ctrlKey (command||metaKey) 清除
231
232
233    if (key === 93 || key === 224) key = 91;
234
235    if (key in _mods) {
236      _mods[key] = false; // 将修饰键重置为false
237
238      for (var k in _modifier) {
239        if (_modifier[k] === key) hotkeys[k] = false;
240      }
241    }
242  }
243
244  function unbind(keysInfo) {
245    // unbind(), unbind all keys
246    if (!keysInfo) {
247      Object.keys(_handlers).forEach(function (key) {
248        return delete _handlers[key];
249      });
250    } else if (Array.isArray(keysInfo)) {
251      // support like : unbind([{key: 'ctrl+a', scope: 's1'}, {key: 'ctrl-a', scope: 's2', splitKey: '-'}])
252      keysInfo.forEach(function (info) {
253        if (info.key) eachUnbind(info);
254      });
255    } else if (typeof keysInfo === 'object') {
256      // support like unbind({key: 'ctrl+a, ctrl+b', scope:'abc'})
257      if (keysInfo.key) eachUnbind(keysInfo);
258    } else if (typeof keysInfo === 'string') {
259      for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
260        args[_key - 1] = arguments[_key];
261      }
262
263      // support old method
264      // eslint-disable-line
265      var scope = args[0],
266          method = args[1];
267
268      if (typeof scope === 'function') {
269        method = scope;
270        scope = '';
271      }
272
273      eachUnbind({
274        key: keysInfo,
275        scope: scope,
276        method: method,
277        splitKey: '+'
278      });
279    }
280  } // 解除绑定某个范围的快捷键
281
282
283  var eachUnbind = function eachUnbind(_ref) {
284    var key = _ref.key,
285        scope = _ref.scope,
286        method = _ref.method,
287        _ref$splitKey = _ref.splitKey,
288        splitKey = _ref$splitKey === void 0 ? '+' : _ref$splitKey;
289    var multipleKeys = getKeys(key);
290    multipleKeys.forEach(function (originKey) {
291      var unbindKeys = originKey.split(splitKey);
292      var len = unbindKeys.length;
293      var lastKey = unbindKeys[len - 1];
294      var keyCode = lastKey === '*' ? '*' : code(lastKey);
295      if (!_handlers[keyCode]) return; // 判断是否传入范围,没有就获取范围
296
297      if (!scope) scope = getScope();
298      var mods = len > 1 ? getMods(_modifier, unbindKeys) : [];
299      _handlers[keyCode] = _handlers[keyCode].map(function (record) {
300        // 通过函数判断,是否解除绑定,函数相等直接返回
301        var isMatchingMethod = method ? record.method === method : true;
302
303        if (isMatchingMethod && record.scope === scope && compareArray(record.mods, mods)) {
304          return {};
305        }
306
307        return record;
308      });
309    });
310  }; // 对监听对应快捷键的回调函数进行处理
311
312
313  function eventHandler(event, handler, scope) {
314    var modifiersMatch; // 看它是否在当前范围
315
316    if (handler.scope === scope || handler.scope === 'all') {
317      // 检查是否匹配修饰符(如果有返回true)
318      modifiersMatch = handler.mods.length > 0;
319
320      for (var y in _mods) {
321        if (Object.prototype.hasOwnProperty.call(_mods, y)) {
322          if (!_mods[y] && handler.mods.indexOf(+y) > -1 || _mods[y] && handler.mods.indexOf(+y) === -1) {
323            modifiersMatch = false;
324          }
325        }
326      } // 调用处理程序,如果是修饰键不做处理
327
328
329      if (handler.mods.length === 0 && !_mods[16] && !_mods[18] && !_mods[17] && !_mods[91] || modifiersMatch || handler.shortcut === '*') {
330        if (handler.method(event, handler) === false) {
331          if (event.preventDefault) event.preventDefault();else event.returnValue = false;
332          if (event.stopPropagation) event.stopPropagation();
333          if (event.cancelBubble) event.cancelBubble = true;
334        }
335      }
336    }
337  } // 处理keydown事件
338
339
340  function dispatch(event) {
341    var asterisk = _handlers['*'];
342    var key = event.keyCode || event.which || event.charCode; // 表单控件过滤 默认表单控件不触发快捷键
343
344    if (!hotkeys.filter.call(this, event)) return; // Gecko(Firefox)的command键值224,在Webkit(Chrome)中保持一致
345    // Webkit左右 command 键值不一样
346
347    if (key === 93 || key === 224) key = 91;
348    /**
349     * Collect bound keys
350     * If an Input Method Editor is processing key input and the event is keydown, return 229.
351     * https://stackoverflow.com/questions/25043934/is-it-ok-to-ignore-keydown-events-with-keycode-229
352     * http://lists.w3.org/Archives/Public/www-dom/2010JulSep/att-0182/keyCode-spec.html
353     */
354
355    if (_downKeys.indexOf(key) === -1 && key !== 229) _downKeys.push(key);
356    /**
357     * Jest test cases are required.
358     * ===============================
359     */
360
361    ['ctrlKey', 'altKey', 'shiftKey', 'metaKey'].forEach(function (keyName) {
362      var keyNum = modifierMap[keyName];
363
364      if (event[keyName] && _downKeys.indexOf(keyNum) === -1) {
365        _downKeys.push(keyNum);
366      } else if (!event[keyName] && _downKeys.indexOf(keyNum) > -1) {
367        _downKeys.splice(_downKeys.indexOf(keyNum), 1);
368      } else if (keyName === 'metaKey' && event[keyName] && _downKeys.length === 3) {
369        /**
370         * Fix if Command is pressed:
371         * ===============================
372         */
373        if (!(event.ctrlKey || event.shiftKey || event.altKey)) {
374          _downKeys = _downKeys.slice(_downKeys.indexOf(keyNum));
375        }
376      }
377    });
378    /**
379     * -------------------------------
380     */
381
382    if (key in _mods) {
383      _mods[key] = true; // 将特殊字符的key注册到 hotkeys 上
384
385      for (var k in _modifier) {
386        if (_modifier[k] === key) hotkeys[k] = true;
387      }
388
389      if (!asterisk) return;
390    } // 将 modifierMap 里面的修饰键绑定到 event 中
391
392
393    for (var e in _mods) {
394      if (Object.prototype.hasOwnProperty.call(_mods, e)) {
395        _mods[e] = event[modifierMap[e]];
396      }
397    }
398    /**
399     * https://github.com/jaywcjlove/hotkeys/pull/129
400     * This solves the issue in Firefox on Windows where hotkeys corresponding to special characters would not trigger.
401     * An example of this is ctrl+alt+m on a Swedish keyboard which is used to type μ.
402     * Browser support: https://caniuse.com/#feat=keyboardevent-getmodifierstate
403     */
404
405
406    if (event.getModifierState && !(event.altKey && !event.ctrlKey) && event.getModifierState('AltGraph')) {
407      if (_downKeys.indexOf(17) === -1) {
408        _downKeys.push(17);
409      }
410
411      if (_downKeys.indexOf(18) === -1) {
412        _downKeys.push(18);
413      }
414
415      _mods[17] = true;
416      _mods[18] = true;
417    } // 获取范围 默认为 `all`
418
419
420    var scope = getScope(); // 对任何快捷键都需要做的处理
421
422    if (asterisk) {
423      for (var i = 0; i < asterisk.length; i++) {
424        if (asterisk[i].scope === scope && (event.type === 'keydown' && asterisk[i].keydown || event.type === 'keyup' && asterisk[i].keyup)) {
425          eventHandler(event, asterisk[i], scope);
426        }
427      }
428    } // key 不在 _handlers 中返回
429
430
431    if (!(key in _handlers)) return;
432
433    for (var _i = 0; _i < _handlers[key].length; _i++) {
434      if (event.type === 'keydown' && _handlers[key][_i].keydown || event.type === 'keyup' && _handlers[key][_i].keyup) {
435        if (_handlers[key][_i].key) {
436          var record = _handlers[key][_i];
437          var splitKey = record.splitKey;
438          var keyShortcut = record.key.split(splitKey);
439          var _downKeysCurrent = []; // 记录当前按键键值
440
441          for (var a = 0; a < keyShortcut.length; a++) {
442            _downKeysCurrent.push(code(keyShortcut[a]));
443          }
444
445          if (_downKeysCurrent.sort().join('') === _downKeys.sort().join('')) {
446            // 找到处理内容
447            eventHandler(event, record, scope);
448          }
449        }
450      }
451    }
452  } // 判断 element 是否已经绑定事件
453
454
455  function isElementBind(element) {
456    return elementHasBindEvent.indexOf(element) > -1;
457  }
458
459  function hotkeys(key, option, method) {
460    _downKeys = [];
461    var keys = getKeys(key); // 需要处理的快捷键列表
462
463    var mods = [];
464    var scope = 'all'; // scope默认为all,所有范围都有效
465
466    var element = document; // 快捷键事件绑定节点
467
468    var i = 0;
469    var keyup = false;
470    var keydown = true;
471    var splitKey = '+'; // 对为设定范围的判断
472
473    if (method === undefined && typeof option === 'function') {
474      method = option;
475    }
476
477    if (Object.prototype.toString.call(option) === '[object Object]') {
478      if (option.scope) scope = option.scope; // eslint-disable-line
479
480      if (option.element) element = option.element; // eslint-disable-line
481
482      if (option.keyup) keyup = option.keyup; // eslint-disable-line
483
484      if (option.keydown !== undefined) keydown = option.keydown; // eslint-disable-line
485
486      if (typeof option.splitKey === 'string') splitKey = option.splitKey; // eslint-disable-line
487    }
488
489    if (typeof option === 'string') scope = option; // 对于每个快捷键进行处理
490
491    for (; i < keys.length; i++) {
492      key = keys[i].split(splitKey); // 按键列表
493
494      mods = []; // 如果是组合快捷键取得组合快捷键
495
496      if (key.length > 1) mods = getMods(_modifier, key); // 将非修饰键转化为键码
497
498      key = key[key.length - 1];
499      key = key === '*' ? '*' : code(key); // *表示匹配所有快捷键
500      // 判断key是否在_handlers中,不在就赋一个空数组
501
502      if (!(key in _handlers)) _handlers[key] = [];
503
504      _handlers[key].push({
505        keyup: keyup,
506        keydown: keydown,
507        scope: scope,
508        mods: mods,
509        shortcut: keys[i],
510        method: method,
511        key: keys[i],
512        splitKey: splitKey
513      });
514    } // 在全局document上设置快捷键
515
516
517    if (typeof element !== 'undefined' && !isElementBind(element) && window) {
518      elementHasBindEvent.push(element);
519      addEvent(element, 'keydown', function (e) {
520        dispatch(e);
521      });
522      addEvent(window, 'focus', function () {
523        _downKeys = [];
524      });
525      addEvent(element, 'keyup', function (e) {
526        dispatch(e);
527        clearModifier(e);
528      });
529    }
530  }
531
532  var _api = {
533    setScope: setScope,
534    getScope: getScope,
535    deleteScope: deleteScope,
536    getPressedKeyCodes: getPressedKeyCodes,
537    isPressed: isPressed,
538    filter: filter,
539    unbind: unbind
540  };
541
542  for (var a in _api) {
543    if (Object.prototype.hasOwnProperty.call(_api, a)) {
544      hotkeys[a] = _api[a];
545    }
546  }
547
548  if (typeof window !== 'undefined') {
549    var _hotkeys = window.hotkeys;
550
551    hotkeys.noConflict = function (deep) {
552      if (deep && window.hotkeys === hotkeys) {
553        window.hotkeys = _hotkeys;
554      }
555
556      return hotkeys;
557    };
558
559    window.hotkeys = hotkeys;
560  }
561
562  return hotkeys;
563
564})));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.