diff --git a/CHANGELOG.md b/CHANGELOG.md index f3a5e7a0..d7569ce5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## v1.39.2 (22 Dec 2023) + +* feat(hotkey): support element option + ## v1.39.1 (21 Nov 2023) * fix: lazyImport diff --git a/DOC.md b/DOC.md index 460af3ba..39ade529 100644 --- a/DOC.md +++ b/DOC.md @@ -6723,8 +6723,15 @@ Capture keyboard input to trigger given events.
Type Definition
-const hotkey: {
+namespace hotkey {
+    interface IOptions {
+        element?: HTMLElement;
+    }
+}
+const hotkey: {
+    on(key: string, options: hotkey.IOptions, listener: types.AnyFn): void;
     on(key: string, listener: types.AnyFn): void;
+    off(key: string, options: hotkey.IOptions, listener: types.AnyFn): void;
     off(key: string, listener: types.AnyFn): void;
 };
 
@@ -6744,9 +6751,16 @@ Register keyboard listener. Unregister keyboard listener. ```javascript -hotkey.on('k', function() { - console.log('k is pressed'); -}); +const container = document.getElementById('container'); +hotkey.on( + 'k', + { + element: container + }, + function() { + console.log('k is pressed'); + } +); function keyDown() {} hotkey.on('shift+a, shift+b', keyDown); hotkey.off('shift+a', keyDown); diff --git a/DOC_CN.md b/DOC_CN.md index 21384273..01fa8965 100644 --- a/DOC_CN.md +++ b/DOC_CN.md @@ -6716,8 +6716,15 @@ sum('2', '5'); // -> 7
类型定义
-const hotkey: {
+namespace hotkey {
+    interface IOptions {
+        element?: HTMLElement;
+    }
+}
+const hotkey: {
+    on(key: string, options: hotkey.IOptions, listener: types.AnyFn): void;
     on(key: string, listener: types.AnyFn): void;
+    off(key: string, options: hotkey.IOptions, listener: types.AnyFn): void;
     off(key: string, listener: types.AnyFn): void;
 };
 
@@ -6737,9 +6744,16 @@ sum('2', '5'); // -> 7 注销监听器。 ```javascript -hotkey.on('k', function() { - console.log('k is pressed'); -}); +const container = document.getElementById('container'); +hotkey.on( + 'k', + { + element: container + }, + function() { + console.log('k is pressed'); + } +); function keyDown() {} hotkey.on('shift+a, shift+b', keyDown); hotkey.off('shift+a', keyDown); diff --git a/index.json b/index.json index e4f44032..651f101b 100644 --- a/index.json +++ b/index.json @@ -2997,7 +2997,8 @@ "each", "unique", "trim", - "map" + "map", + "isFn" ], "description": "Capture keyboard input to trigger given events.", "env": [ diff --git a/package.json b/package.json index fd43c086..2202486c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "licia", - "version": "1.39.1", + "version": "1.39.2", "description": "Useful utility collection with zero dependencies", "bin": { "licia": "./bin/licia.js" diff --git a/src/hotkey.js b/src/hotkey.js index 4bf938c6..c712f6a6 100644 --- a/src/hotkey.js +++ b/src/hotkey.js @@ -15,9 +15,16 @@ */ /* example - * hotkey.on('k', function() { - * console.log('k is pressed'); - * }); + * const container = document.getElementById('container'); + * hotkey.on( + * 'k', + * { + * element: container + * }, + * function() { + * console.log('k is pressed'); + * } + * ); * function keyDown() {} * hotkey.on('shift+a, shift+b', keyDown); * hotkey.off('shift+a', keyDown); @@ -28,27 +35,81 @@ */ /* typescript + * export declare namespace hotkey { + * interface IOptions { + * element?: HTMLElement; + * } + * } * export declare const hotkey: { + * on(key: string, options: hotkey.IOptions, listener: types.AnyFn): void; * on(key: string, listener: types.AnyFn): void; + * off(key: string, options: hotkey.IOptions, listener: types.AnyFn): void; * off(key: string, listener: types.AnyFn): void; * }; */ -_('Emitter keyCode each unique trim map types'); +_('Emitter keyCode each unique trim map types isFn'); exports = { - on(keys, listener) { + on(keys, options, listener) { + if (isFn(options)) { + listener = options; + options = {}; + } + keys = keys.split(regComma); each(keys, function(key) { - emitter.on(normalizeKey(key), listener); + key = normalizeKey(key); + if (options.element) { + const { element } = options; + const hotkeyListeners = element._hotkeyListeners || {}; + element._hotkeyListeners = hotkeyListeners; + hotkeyListeners[key] = hotkeyListeners[key] || []; + const hotkeyListener = function(e) { + if (key === getKeysFromEvent(e)) { + listener(e); + } + }; + hotkeyListeners[key].push({ + listener: hotkeyListener, + origin: listener + }); + element.addEventListener('keydown', hotkeyListener); + } else { + emitter.on(key, listener); + } }); }, - off(keys, listener) { + off(keys, options, listener) { + if (isFn(options)) { + listener = options; + options = {}; + } + keys = keys.split(regComma); each(keys, function(key) { - emitter.off(normalizeKey(key), listener); + key = normalizeKey(key); + if (options.element) { + const { element } = options; + const hotkeyListeners = element._hotkeyListeners; + if (hotkeyListeners && hotkeyListeners[key]) { + const listeners = hotkeyListeners[key]; + let hotkeyListener; + for (let i = 0, len = listeners.length; i < len; i++) { + if (listeners[i].origin === listener) { + hotkeyListener = listeners[i].listener; + listeners.splice(i, 1); + } + } + if (hotkeyListener) { + element.removeEventListener('keydown', hotkeyListener); + } + } + } else { + emitter.off(key, listener); + } }); } }; @@ -56,6 +117,10 @@ exports = { const emitter = new Emitter(); document.addEventListener('keydown', function(e) { + emitter.emit(getKeysFromEvent(e), e); +}); + +function getKeysFromEvent(e) { const keys = []; if (e.ctrlKey) keys.push('ctrl'); @@ -63,8 +128,8 @@ document.addEventListener('keydown', function(e) { keys.push(keyCode(e.keyCode)); - emitter.emit(normalizeKey(keys.join('+')), e); -}); + return normalizeKey(keys.join('+')); +} function normalizeKey(keyStr) { let keys = keyStr.split(regPlus); diff --git a/test/hotkey.js b/test/hotkey.js index 21c44df2..62502471 100644 --- a/test/hotkey.js +++ b/test/hotkey.js @@ -1,4 +1,14 @@ const trigger = util.trigger; +let $dom; + +before(function() { + jQuery('body').append('
'); + $dom = jQuery('#hotkey'); +}); + +after(function() { + $dom.remove(); +}); it('basic', function() { let num = 0; @@ -37,3 +47,37 @@ it('multiple', function() { trigger('keydown', { keyCode: b }); expect(num).to.equal(3); }); + +it('element', () => { + let num = 0; + const a = 65; + const element = $dom[0]; + function addOne() { + num++; + } + + hotkey.on( + 'shift+a', + { + element + }, + addOne + ); + trigger(element, 'keydown', { + shiftKey: true, + keyCode: a + }); + expect(num).to.equal(1); + hotkey.off( + 'shift+a', + { + element + }, + addOne + ); + trigger(element, 'keydown', { + shiftKey: true, + keyCode: a + }); + expect(num).to.equal(1); +});