PageSourceSearch

https://tringlocalhistorymuseum.org.uk/history/lucknowwebs-WCP/content-protector.js

js tringlocalhistorymuseum.org.uk collected 2026-10-02 13:45:38 UTC 29,740 bytes, 947 lines download raw bytes

1/**
2 *	Product Name: Website Content Protector
3 * @encoding        UTF-8
4 * @copyright       Copyright (C) 2018 - 2020 Copyright (C) 2020 Lucknowwebs ( http://lucknowwebs.com ). All rights reserved.
5 **/
6
7"use strict";
8
9const t42ContentProtector = ( function () {
10
11    "use strict";
12
13    function _ContentProtector( options= {
14        // Default parameters.
15        disableSelectAll: true,
16        disableCopy: true,
17        disableCut: true,
18        disablePaste: true,
19        disableSave: true,
20        disableViewSource: true,
21        disablePrintPage: true,
22        disableDeveloperTool: true,
23        disableReaderMode: true,
24        disableRightClick: true,
25        disableTextSelection: true,
26        disableImageDragging: true
27    } ) {
28
29        function init( options ) {
30
31            /** Disable Select All. */
32            if ( options.disableSelectAll ) { disableSelectAll(); }
33
34            /** Disable Copy. */
35            if ( options.disableCopy ) { disableCopy(); }
36
37            /** Disable Cut. */
38            if ( options.disableCut ) { disableCut(); }
39
40            /** Disable Paste. */
41            if ( options.disablePaste ) { disablePaste(); }
42
43            /** Disable Save. */
44            if ( options.disableSave ) { disableSave(); }
45
46            /** Disable View Source. */
47            if ( options.disableViewSource ) { disableViewSource(); }
48
49            /** Disable Print Page. */
50            if ( options.disablePrintPage ) { disablePrintPage(); }
51
52            /** Disable Developer Tool. */
53            if ( options.disableDeveloperTool ) { disableDeveloperTool(); }
54
55            /** Disable Reader Mode. */
56            if ( options.disableReaderMode ) { disableReaderMode(); }
57
58            /** Disable Right Click. */
59            if ( options.disableRightClick ) { disableRightClick(); }
60
61            /** Disable Text Selection. */
62            if ( options.disableTextSelection ) { disableTextSelection(); }
63
64            /** Disable Image Dragging by Mouse. */
65            if ( options.disableImageDragging ) { disableImageDragging(); }
66
67        }
68
69        /**
70         * Disable Select All, HotKeys: Ctrl+A, ⌘+A.
71         * Protect Your Text from Being Copied by Select All HotKeys.
72         **/
73        function disableSelectAll() {
74
75            disable_key( 65 ); // Ctrl+A, ⌘+A.
76
77        }
78
79        /**
80         * Disable Copy, HotKeys: Ctrl+C, ⌘+C.
81         * Protect Your Text from Being Copied by Copy HotKeys.
82         **/
83        function disableCopy() {
84
85            disable_key( 67 ); // Ctrl+C, ⌘+C.
86
87        }
88
89        /**
90         * Disable Cut, HotKeys: Ctrl+X, ⌘+X.
91         * Protect Your Text from Being Copied by Cut HotKeys.
92         **/
93        function disableCut() {
94
95            disable_key( 88 ); // Ctrl+X, ⌘+X.
96
97        }
98
99        /**
100         * Disable Paste, HotKeys: Ctrl+V, ⌘+V.
101         * Disable Peaste HotKeys.
102         **/
103        function disablePaste() {
104
105            disable_key( 86 ); // Ctrl+V, ⌘+V.
106
107        }
108
109        /**
110         * Disable Save, HotKeys: Ctrl+S, ⌘+S.
111         * Protect Your Text from Being Saved by Save HotKeys.
112         **/
113        function disableSave() {
114
115            disable_key( 83 ); // Ctrl+S, ⌘+S.
116
117        }
118
119        /**
120         * Disable View Source, HotKeys: Ctrl+U, ⌘+U.
121         * Disable to View Source Code of Page by HotKeys.
122         **/
123        function disableViewSource() {
124
125            disable_key( 85 ); // Ctrl+U, ⌘+U.
126
127        }
128
129        /**
130         * Disable Print Page, HotKeys: Ctrl+P, ⌘+P.
131         * Protect Your Page from Being Printed by HotKeys.
132         **/
133        function disablePrintPage() {
134
135            disable_key( 80 ); // Ctrl+P, ⌘+P.
136
137        }
138
139        /**
140         * Disable Reader Mode in Safari, HotKeys: ⌘+Shift+P.
141         * Protect Your Page from Being open in Reader mode
142         **/
143        function disableReaderMode() {
144
145            if ( navigator.userAgent.toLowerCase().includes( 'safari' ) && !navigator.userAgent.toLowerCase().includes( 'chrome' ) ) {
146
147                window.addEventListener( 'keydown', function( e ) {
148
149                    if ( ( e.ctrlKey || e.metaKey ) && e.shiftKey && e.keyCode === 82 ) {
150                        e.preventDefault();
151                    }
152
153                } );
154
155            }
156
157        }
158
159        /**
160         * Disable Developer Tool, HotKeys: Ctrl+Shift+I, ⌘+⌥+I, F12
161         * Disable to View Source Code of Page by Developer Tools.
162         **/
163        function disableDeveloperTool() {
164
165            hotkeys( 'command+option+j,command+option+i,command+shift+c,command+option+c,command+option+k,command+option+z,command+option+e,f12,ctrl+shift+i,ctrl+shift+j,ctrl+shift+c,ctrl+shift+k,ctrl+shift+e,shift+f7,shift+f5,shift+f9,shift+f12', function( event, handler ) {
166                event.preventDefault();
167            } );
168
169            /** Remove body, if you can open dev tools. */
170            let checkStatus;
171
172            let element = new Image();
173            Object.defineProperty( element, 'id', {
174                get:function() {
175                    checkStatus = 'on';
176                    throw new Error( 'Dev tools checker' );
177                }
178            } );
179
180            requestAnimationFrame( function check() {
181                checkStatus = 'off';
182                console.dir( element );
183                if ( 'on' === checkStatus ) {
184                    document.body.parentNode.removeChild( document.body );
185                    document.head.parentNode.removeChild( document.head );
186                    /** Block JS debugger. */
187                    setTimeout( function() {
188                        // noinspection InfiniteLoopJS
189                        while (true) {
190                            eval("debugger");
191                        }
192                    }, 100 );
193                } else {
194                    requestAnimationFrame( check );
195                }
196            } );
197
198        }
199
200        /**
201         * Disable Right Click, Context Menu by Mouse Right Click.
202         * Protect Your Content from Being Copied by Context Menu.
203         **/
204        function disableRightClick() {
205
206            document.oncontextmenu = function( e ) {
207
208                var t = e || window.event;
209                var n = t.target || t.srcElement;
210
211                if ( n.nodeName !== 'A' ) {
212                    return false;
213                }
214
215            };
216
217            document.body.oncontextmenu = function () {
218                return false;
219            };
220
221            document.onmousedown = function ( e ) {
222                if ( e.button === 2 ) {
223                    return false;
224                }
225            };
226
227            /** To block "Enable Right Click" extensions */
228            let enableRightClickExtensionsInterval = setInterval( function () {
229
230                if ( null === document.oncontextmenu ) {
231                    document.body.parentNode.removeChild( document.body );
232                    document.head.parentNode.removeChild( document.head );
233
234                    clearInterval( enableRightClickExtensionsInterval );
235                }
236
237            }, 500 );
238
239        }
240
241        /**
242         * Disable Text Selection.
243         * Disable Text Highlight (Text Selection) by Mouse.
244         **/
245        function disableTextSelection() {
246
247            if ( typeof document.body.onselectstart != 'undefined' ){
248                document.body.onselectstart = function(){ return false; };
249            } else if ( typeof document.body.style.MozUserSelect !== 'undefined' ) {
250                document.body.style.MozUserSelect = 'none';
251            } else if ( typeof document.body.style.webkitUserSelect !== 'undefined' ) {
252                document.body.style.webkitUserSelect = 'none';
253            } else {
254                document.body.onmousedown = function(){ return false; };
255            }
256
257            document.body.style.cursor = 'default';
258
259            document.documentElement.style.webkitTouchCallout = "none";
260            document.documentElement.style.webkitUserSelect = "none";
261            /** Add css layer protection. */
262            let css = document.createElement( 'style' );
263            document.head.appendChild( css );
264            css.type = 'text/css';
265            css.innerText = "* {-webkit-user-select: none !important; -moz-user-select: none !important; -ms-user-select: none !important; user-select: none !important; }";
266
267        }
268
269        /**
270         * Disable Image Dragging by Mouse.
271         **/
272        function disableImageDragging() {
273
274            document.ondragstart = function() { return false; };
275
276        }
277
278        /**
279         * Disable CTRL|CMD + Key by key Code.
280         *
281         * @param {number} code
282         **/
283        function disable_key( code ) {
284
285            window.addEventListener( 'keydown', function( e ) {
286
287                /** For Windows Check CTRL. */
288                if ( e.ctrlKey && e.which === code ) { e.preventDefault(); }
289
290                /** For Mac Check Metakey. */
291                if ( e.metaKey && e.which === code ) { e.preventDefault(); }
292
293            } );
294
295            document.keypress = function( e ) {
296
297                /** For Windows Check CTRL. */
298                if ( e.ctrlKey && e.which === code ) { return false; }
299
300                /** For Mac Check Metakey. */
301                if ( e.metaKey && e.which === code ) { return false; }
302
303            };
304
305        }
306
307        return {
308            init: init( options )
309        };
310
311    }
312
313    return _ContentProtector;
314
315} )();
316
317document.addEventListener( 'DOMContentLoaded', function () {
318
319    /** Content Protector Options. */
320    let options = {
321
322        /**
323         * Disable Select All: Disable HotKeys: Ctrl+A (Windows and Linux), ⌘+A (macOS).
324         * Protect Your Text from Being Copied by Select All HotKeys.
325         **/
326        disableSelectAll: true,
327
328        /**
329         * Disable Copy: Disable HotKeys: Ctrl+C (Windows and Linux), ⌘+C (macOS).
330         * Protect Your Text from Being Copied by Copy HotKeys.
331         **/
332        disableCopy: true,
333
334        /**
335         * Disable Cut:	Disable HotKeys: Ctrl+X (Windows and Linux), ⌘+X (macOS).
336         * Protect Your Text from Being Copied by Cut HotKeys.
337         **/
338        disableCut: true,
339
340        /**
341         * Disable Paste: Disable HotKeys: Ctrl+V (Windows and Linux), ⌘+V (macOS).
342         * Disable Paste HotKeys.
343         **/
344        disablePaste: true,
345
346        /**
347         * Disable Save: Disable HotKeys: Ctrl+S (Windows and Linux), ⌘+S (macOS).
348         * Protect Your Text from Being Saved by Save HotKeys.
349         **/
350        disableSave: true,
351
352        /**
353         * Disable View Source: Disable HotKeys: Ctrl+U (Windows and Linux), ⌘+U (macOS).
354         * Disable to View Source Code of Page by HotKeys.
355         **/
356        disableViewSource: true,
357
358        /**
359         * Disable Print Page: Disable HotKeys: Ctrl+P (Windows and Linux), ⌘+P (macOS).
360         * Protect Your Page from Being Printed by HotKeys.
361         **/
362        disablePrintPage: true,
363
364        /**
365         * Disable Developer Tool: Disable HotKeys: Ctrl+Shift+I (Windows and Linux), ⌘+⌥+I (macOS).
366         * Disable to View Source Code of Page by Developer Tools.
367         **/
368        disableDeveloperTool: true,
369
370        /**
371         * Disable Safari Reader Mode: Disable Reader mode in Safari: ⌘+Shift+R (macOS).
372         * Protect Your Text and Images from being copied in the Safari Reader mode.
373         **/
374        disableReaderMode: true,
375
376        /**
377         * Disable Right Click: Disable Mouse Right Click.
378         * Protect Your Content from Being Copied by Context Menu.
379         **/
380        disableRightClick: true,
381
382        /**
383         * Disable Text Selection: Disable Text Selection.
384         * Disable Text Highlight (Text Selection) by Mouse.
385         **/
386        disableTextSelection: true,
387
388        /**
389         * Disable Image Dragging by Mouse.
390         **/
391        disableImageDragging: true
392    };
393
394    new t42ContentProtector( options );
395
396} );
397
398/**
399 * hotkeys-js v3.7.3
400 * A simple micro-library for defining and dispatching keyboard shortcuts. It has no depen
400dencies.
401 *
402 * Copyright (c) 2019 kenny wong <[email protected]>
403 * http://jaywcjlove.github.io/hotkeys
404 *
405 * Licensed under the MIT license.
406 **/
407
408(function (global, factory) {
409    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
410        typeof define === 'function' && define.amd ? define(factory) :
411            (global = global || self, global.hotkeys = factory());
412}(this, (function () { 'use strict';
413
414    function _typeof(obj) {
415        if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
416            _typeof = function (obj) {
417                return typeof obj;
418            };
419        } else {
420            _typeof = function (obj) {
421                return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
422            };
423        }
424
425        return _typeof(obj);
426    }
427
428    var isff = typeof navigator !== 'undefined' ? navigator.userAgent.toLowerCase().indexOf('firefox') > 0 : false; // 绑定事件
429
430    function addEvent(object, event, method) {
431        if (object.addEventListener) {
432            object.addEventListener(event, method, false);
433        } else if (object.attachEvent) {
434            object.attachEvent("on".concat(event), function () {
435                method(window.event);
436            });
437        }
438    } // 修饰键转换成对应的键码
439
440
441    function getMods(modifier, key) {
442        var mods = key.slice(0, key.length - 1);
443
444        for (var i = 0; i < mods.length; i++) {
445            mods[i] = modifier[mods[i].toLowerCase()];
446        }
447
448        return mods;
449    } // 处理传的key字符串转换成数组
450
451
452    function getKeys(key) {
453        if (typeof key !== 'string') key = '';
454        key = key.replace(/\s/g, ''); // 匹配任何空白字符,包括空格、制表符、换页符等等
455
456        var keys = key.split(','); // 同时设置多个快捷键,以','分割
457
458        var index = keys.lastIndexOf(''); // 快捷键可能包含',',需特殊处理
459
460        for (; index >= 0;) {
461            keys[index - 1] += ',';
462            keys.splice(index, 1);
463            index = keys.lastIndexOf('');
464        }
465
466        return keys;
467    } // 比较修饰键的数组
468
469
470    function compareArray(a1, a2) {
471        var arr1 = a1.length >= a2.length ? a1 : a2;
472        var arr2 = a1.length >= a2.length ? a2 : a1;
473        var isIndex = true;
474
475        for (var i = 0; i < arr1.length; i++) {
476            if (arr2.indexOf(arr1[i]) === -1) isIndex = false;
477        }
478
479        return isIndex;
480    }
481
482    var _keyMap = {
483        backspace: 8,
484        tab: 9,
485        clear: 12,
486        enter: 13,
487        "return": 13,
488        esc: 27,
489        escape: 27,
490        space: 32,
491        left: 37,
492        up: 38,
493        right: 39,
494        down: 40,
495        del: 46,
496        "delete": 46,
497        ins: 45,
498        insert: 45,
499        home: 36,
500        end: 35,
501        pageup: 33,
502        pagedown: 34,
503        capslock: 20,
504        '⇪': 20,
505        ',': 188,
506        '.': 190,
507        '/': 191,
508        '`': 192,
509        '-': isff ? 173 : 189,
510        '=': isff ? 61 : 187,
511        ';': isff ? 59 : 186,
512        '\'': 222,
513        '[': 219,
514        ']': 221,
515        '\\': 220
516    }; // Modifier Keys
517
518    var _modifier = {
519        // shiftKey
520        '⇧': 16,
521        shift: 16,
522        // altKey
523        '⌥': 18,
524        alt: 18,
525        option: 18,
526        // ctrlKey
527        '⌃': 17,
528        ctrl: 17,
529        control: 17,
530        // metaKey
531        '⌘': 91,
532        cmd: 91,
533        command: 91
534    };
535    var modifierMap = {
536        16: 'shiftKey',
537        18: 'altKey',
538        17: 'ctrlKey',
539        91: 'metaKey',
540        shiftKey: 16,
541        ctrlKey: 17,
542        altKey: 18,
543        metaKey: 91
544    };
545    var _mods = {
546        16: false,
547        18: false,
548        17: false,
549        91: false
550    };
551    var _handlers = {}; // F1~F12 special key
552
553    for (var k = 1; k < 20; k++) {
554        _keyMap["f".concat(k)] = 111 + k;
555    }
556
557    var _downKeys = []; // 记录摁下的绑定键
558
559    var _scope = 'all'; // 默认热键范围
560
561    var elementHasBindEvent = []; // 已绑定事件的节点记录
562    // 返回键码
563
564    var code = function code(x) {
565        return _keyMap[x.toLowerCase()] || _modifier[x.toLowerCase()] || x.toUpperCase().charCo
vendor: 10,349 bytes, lines 565-852
565deAt(0);
566    }; // 设置获取当前范围(默认为'所有')
567
568
569    function setScope(scope) {
570        _scope = scope || 'all';
571    } // 获取当前范围
572
573
574    function getScope() {
575        return _scope || 'all';
576    } // 获取摁下绑定键的键值
577
578
579    function getPressedKeyCodes() {
580        return _downKeys.slice(0);
581    } // 表单控件控件判断 返回 Boolean
582    // hotkey is effective only when filter return true
583
584
585    function filter(event) {
586        var target = event.target || event.srcElement;
587        var tagName = target.tagName;
588        var flag = true; // ignore: isContentEditable === 'true', <input> and <textarea> when readOnly state is false, <select>
589
590        if (target.isContentEditable || (tagName === 'INPUT' || tagName === 'TEXTAREA') && !target.readOnly) {
591            flag = false;
592        }
593
594        return flag;
595    } // 判断摁下的键是否为某个键,返回true或者false
596
597
598    function isPressed(keyCode) {
599        if (typeof keyCode === 'string') {
600            keyCode = code(keyCode); // 转换成键码
601        }
602
603        return _downKeys.indexOf(keyCode) !== -1;
604    } // 循环删除handlers中的所有 scope(范围)
605
606
607    function deleteScope(scope, newScope) {
608        var handlers;
609        var i; // 没有指定scope,获取scope
610
611        if (!scope) scope = getScope();
612
613        for (var key in _handlers) {
614            if (Object.prototype.hasOwnProperty.call(_handlers, key)) {
615                handlers = _handlers[key];
616
617                for (i = 0; i < handlers.length;) {
618                    if (handlers[i].scope === scope) handlers.splice(i, 1);else i++;
619                }
620            }
621        } // 如果scope被删除,将scope重置为all
622
623
624        if (getScope() === scope) setScope(newScope || 'all');
625    } // 清除修饰键
626
627
628    function clearModifier(event) {
629        var key = event.keyCode || event.which || event.charCode;
630
631        var i = _downKeys.indexOf(key); // 从列表中清除按压过的键
632
633
634        if (i >= 0) {
635            _downKeys.splice(i, 1);
636        } // 特殊处理 cmmand 键,在 cmmand 组合快捷键 keyup 只执行一次的问题
637
638
639        if (event.key && event.key.toLowerCase() === 'meta') {
640            _downKeys.splice(0, _downKeys.length);
641        } // 修饰键 shiftKey altKey ctrlKey (command||metaKey) 清除
642
643
644        if (key === 93 || key === 224) key = 91;
645
646        if (key in _mods) {
647            _mods[key] = false; // 将修饰键重置为false
648
649            for (var k in _modifier) {
650                if (_modifier[k] === key) hotkeys[k] = false;
651            }
652        }
653    }
654
655    function unbind(keysInfo) {
656        // unbind(), unbind all keys
657        if (!keysInfo) {
658            Object.keys(_handlers).forEach(function (key) {
659                return delete _handlers[key];
660            });
661        } else if (Array.isArray(keysInfo)) {
662            // support like : unbind([{key: 'ctrl+a', scope: 's1'}, {key: 'ctrl-a', scope: 's2', splitKey: '-'}])
663            keysInfo.forEach(function (info) {
664                if (info.key) eachUnbind(info);
665            });
666        } else if (_typeof(keysInfo) === 'object') {
667            // support like unbind({key: 'ctrl+a, ctrl+b', scope:'abc'})
668            if (keysInfo.key) eachUnbind(keysInfo);
669        } else if (typeof keysInfo === 'string') {
670            for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
671                args[_key - 1] = arguments[_key];
672            }
673
674            // support old method
675            // eslint-disable-line
676            var scope = args[0],
677                method = args[1];
678
679            if (typeof scope === 'function') {
680                method = scope;
681                scope = '';
682            }
683
684            eachUnbind({
685                key: keysInfo,
686                scope: scope,
687                method: method,
688                splitKey: '+'
689            });
690        }
691    } // 解除绑定某个范围的快捷键
692
693
694    var eachUnbind = function eachUnbind(_ref) {
695        var key = _ref.key,
696            scope = _ref.scope,
697            method = _ref.method,
698            _ref$splitKey = _ref.splitKey,
699            splitKey = _ref$splitKey === void 0 ? '+' : _ref$splitKey;
700        var multipleKeys = getKeys(key);
701        multipleKeys.forEach(function (originKey) {
702            var unbindKeys = originKey.split(splitKey);
703            var len = unbindKeys.length;
704            var lastKey = unbindKeys[len - 1];
705            var keyCode = lastKey === '*' ? '*' : code(lastKey);
706            if (!_handlers[keyCode]) return; // 判断是否传入范围,没有就获取范围
707
708            if (!scope) scope = getScope();
709            var mods = len > 1 ? getMods(_modifier, unbindKeys) : [];
710            _handlers[keyCode] = _handlers[keyCode].map(function (record) {
711                // 通过函数判断,是否解除绑定,函数相等直接返回
712                var isMatchingMethod = method ? record.method === method : true;
713
714                if (isMatchingMethod && record.scope === scope && compareArray(record.mods, mods)) {
715                    return {};
716                }
717
718                return record;
719            });
720        });
721    }; // 对监听对应快捷键的回调函数进行处理
722
723
724    function eventHandler(event, handler, scope) {
725        var modifiersMatch; // 看它是否在当前范围
726
727        if (handler.scope === scope || handler.scope === 'all') {
728            // 检查是否匹配修饰符(如果有返回true)
729            modifiersMatch = handler.mods.length > 0;
730
731            for (var y in _mods) {
732                if (Object.prototype.hasOwnProperty.call(_mods, y)) {
733                    if (!_mods[y] && handler.mods.indexOf(+y) > -1 || _mods[y] && handler.mods.indexOf(+y) === -1) {
734                        modifiersMatch = false;
735                    }
736                }
737            } // 调用处理程序,如果是修饰键不做处理
738
739
740            if (handler.mods.length === 0 && !_mods[16] && !_mods[18] && !_mods[17] && !_mods[91] || modifiersMatch || handler.shortcut === '*') {
741                if (handler.method(event, handler) === false) {
742                    if (event.preventDefault) event.preventDefault();else event.returnValue = false;
743                    if (event.stopPropagation) event.stopPropagation();
744                    if (event.cancelBubble) event.cancelBubble = true;
745                }
746            }
747        }
748    } // 处理keydown事件
749
750
751    function dispatch(event) {
752        var asterisk = _handlers['*'];
753        var key = event.keyCode || event.which || event.charCode; // 表单控件过滤 默认表单控件不触发快捷键
754
755        if (!hotkeys.filter.call(this, event)) return; // Gecko(Firefox)的command键值224,在Webkit(Chrome)中保持一致
756        // Webkit左右 command 键值不一样
757
758        if (key === 93 || key === 224) key = 91;
759        /**
760         * Collect bound keys
761         * If an Input Method Editor is processing key input and the event is keydown, return 229.
762         * https://stackoverflow.com/questions/25043934/is-it-ok-to-ignore-keydown-events-with-keycode-229
763         * http://lists.w3.org/Archives/Public/www-dom/2010JulSep/att-0182/keyCode-spec.html
764         */
765
766        if (_downKeys.indexOf(key) === -1 && key !== 229) _downKeys.push(key);
767        /**
768         * Jest test cases are required.
769         * ===============================
770         */
771
772        ['ctrlKey', 'altKey', 'shiftKey', 'metaKey'].forEach(function (keyName) {
773            var keyNum = modifierMap[keyName];
774
775            if (event[keyName] && _downKeys.indexOf(keyNum) === -1) {
776                _downKeys.push(keyNum);
777            } else if (!event[keyName] && _downKeys.indexOf(keyNum) > -1) {
778                _downKeys.splice(_downKeys.indexOf(keyNum), 1);
779            }
780        });
781        /**
782         * -------------------------------
783         */
784
785        if (key in _mods) {
786            _mods[key] = true; // 将特殊字符的key注册到 hotkeys 上
787
788            for (var k in _modifier) {
789                if (_modifier[k] === key) hotkeys[k] = true;
790            }
791
792            if (!asterisk) return;
793        } // 将 modifierMap 里面的修饰键绑定到 event 中
794
795
796        for (var e in _mods) {
797            if (Object.prototype.hasOwnProperty.call(_mods, e)) {
798                _mods[e] = event[modifierMap[e]];
799            }
800        } // 获取范围 默认为 `all`
801
802
803        var scope = getScope(); // 对任何快捷键都需要做的处理
804
805        if (asterisk) {
806            for (var i = 0; i < asterisk.length; i++) {
807                if (asterisk[i].scope === scope && (event.type === 'keydown' && asterisk[i].keydown || event.type === 'keyup' && asterisk[i].keyup)) {
808                    eventHandler(event, asterisk[i], scope);
809                }
810            }
811        } // key 不在 _handlers 中返回
812
813
814        if (!(key in _handlers)) return;
815
816        for (var _i = 0; _i < _handlers[key].length; _i++) {
817            if (event.type === 'keydown' && _handlers[key][_i].keydown || event.type === 'keyup' && _handlers[key][_i].keyup) {
818                if (_handlers[key][_i].key) {
819                    var record = _handlers[key][_i];
820                    var splitKey = record.splitKey;
821                    var keyShortcut = record.key.split(splitKey);
822                    var _downKeysCurrent = []; // 记录当前按键键值
823
824                    for (var a = 0; a < keyShortcut.length; a++) {
825                        _downKeysCurrent.push(code(keyShortcut[a]));
826                    }
827
828                    if (_downKeysCurrent.sort().join('') === _downKeys.sort().join('')) {
829                        // 找到处理内容
830                        eventHandler(event, record, scope);
831                    }
832                }
833            }
834        }
835    } // 判断 element 是否已经绑定事件
836
837
838    function isElementBind(element) {
839        return elementHasBindEvent.indexOf(element) > -1;
840    }
841
842    function hotkeys(key, option, method) {
843        _downKeys = [];
844        var keys = getKeys(key); // 需要处理的快捷键列表
845
846        var mods = [];
847        var scope = 'all'; // scope默认为all,所有范围都有效
848
849        var element = document; // 快捷键事件绑定节点
850
851        var i = 0;
852        var keyup = false;
853        var keydown = true;
854        var splitKey = '+'; // 对为设定范围的判断
855
856        if (method === undefined && typeof option === 'function') {
857            method = option;
858        }
859
860        if (Object.prototype.toString.call(option) === '[object Object]') {
861            if (option.scope) scope = option.scope; // eslint-disable-line
862
863            if (option.element) element = option.element; // eslint-disable-line
864
865            if (option.keyup) keyup = option.keyup; // eslint-disable-line
866
867            if (option.keydown !== undefined) keydown = option.keydown; // eslint-disable-line
868
869            if (typeof option.splitKey === 'string') splitKey = option.splitKey; // eslint-disable-line
870        }
871
872        if (typeof option === 'string') scope = option; // 对于每个快捷键进行处理
873
874        for (; i < keys.length; i++) {
875            key = keys[i].split(splitKey); // 按键列表
876
877            mods = []; // 如果是组合快捷键取得组合快捷键
878
879            if (key.length > 1) mods = getMods(_modifier, key); // 将非修饰键转化为键码
880
881            key = key[key.length - 1];
882            key = key === '*' ? '*' : code(key); // *表示匹配所有快捷键
883            // 判断key是否在_handlers中,不在就赋一个空数组
884
885            if (!(key in _handlers)) _handlers[key] = [];
886
887            _handlers[key].push({
888                keyup: keyup,
889                keydown: keydown,
890                scope: scope,
891                mods: mods,
892                shortcut: keys[i],
893                method: method,
894                key: keys[i],
895                splitKey: splitKey
896            });
897        } // 在全局document上设置快捷键
898
899
900        if (typeof element !== 'undefined' && !isElementBind(element) && window) {
901            elementHasBindEvent.push(element);
902            addEvent(element, 'keydown', function (e) {
903                dispatch(e);
904            });
905            addEvent(window, 'focus', function () {
906                _downKeys = [];
907            });
908            addEvent(element, 'keyup', function (e) {
909                dispatch(e);
910                clearModifier(e);
911            });
912        }
913    }
914
915    var _api = {
916        setScope: setScope,
917        getScope: getScope,
918        deleteScope: deleteScope,
919        getPressedKeyCodes: getPressedKeyCodes,
920        isPressed: isPressed,
921        filter: filter,
922        unbind: unbind
923    };
924
925    for (var a in _api) {
926        if (Object.prototype.hasOwnProperty.call(_api, a)) {
927            hotkeys[a] = _api[a];
928        }
929    }
930
931    if (typeof window !== 'undefined') {
932        var _hotkeys = window.hotkeys;
933
934        hotkeys.noConflict = function (deep) {
935            if (deep && window.hotkeys === hotkeys) {
936                window.hotkeys = _hotkeys;
937            }
938
939            return hotkeys;
940        };
941
942        window.hotkeys = hotkeys;
943    }
944
945    return hotkeys;
946
947})));

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.