[英]Keyboard shortcuts / commands on non-Latin keyboards (JavaScript)
我想讓鍵盤快捷鍵適用於盡可能多的鍵盤布局,包括非拉丁語的。
我知道,就拉丁鍵盤 go 而言,最好使用KeyboardEvent.key
屬性 - 因此,無論鍵盤布局如何,都知道用戶按下了代表字母“L”的鍵。 這似乎與操作系統和其他應用程序的做法一致,因為我只是通過暫時切換到 Dvorak 布局對其進行了測試。
我很確定這種方法不適用於非拉丁鍵盤,即西里爾字母。
我正在尋找的是一種處理其他字母的通用方法,而不必深入研究每種語言的本地化。
因此,例如,如果我想對 Ctrl+L(或 Mac 的 Cmd+L)進行操作,我希望它可以在盡可能多的鍵盤布局上工作,即使這些布局沒有字母 L . 在那個鍵盤布局上獲得相當於 L 的字符。
我還想尊重最基本的操作系統命令:Ctrl+C、Ctrl+A、Ctrl+V、Ctrl+X - 所以我很好奇操作系統是否以同樣的方式執行此操作,即在西里爾字母鍵盤上,是否執行粘貼操作出現為 Ctrl + (相當於西里爾文中的 V )還是取決於語言環境?
事實證明, 大多數非拉丁鍵盤都印有 2 個字母,拉丁字母和它自己的字母 - 用戶可以在布局之間切換。
因此,如果用戶處於拉丁布局模式,則KeyboardEvent.key
應該開箱即用。 問題是當用戶處於非拉丁模式時,鍵盤命令將不起作用,因為KeyboardEvent.key
將是該字母表中的一個字母。
幸運的是,這些鍵盤中的大多數都遵循標准的 Qwerty 布局,因此KeyboardEvent.code
可以作為參考拉丁字符的后備。
我創建了一個 function,如果檢測到非拉丁字符,給定KeyboardEvent.key
和KeyboardEvent.code
應該回退到絕對 Qwerty 代碼值。
執照:麻省理工學院
/**
* Gets key associated with a Keyboard event with a fallback to use absolute code value for
* non-Latin keyboard layouts.
*
* Most commonly non-Latin keyboards have 2 sets of alphabets printed and 2 modes to switch between
* them. The Latin mode usually follows the standard Qwerty layout so by falling back to use key
* codes, a keyboard command can work even though the layout is in non-Latin mode.
*
* Limitations:
* - some non-Latin layouts have a symbol on KeyQ which makes it impossible to distinguish it
* (without checking the entire layout) from Latin Dvorak layout, therefore KeyQ will not work for
* those
* - if the Latin layout mode is not Qwerty some of the mappings will not be correct
*
* @returns if `key` is a non-Latin letter (unicode >= 880) and `code` represents a letter or a
* digit on a Qwerty layout, it will return the corresponding letter (uppercase) or digit on a
* Qwerty layout. Otherwise it will return `key` (transformed to uppercase if it's a letter).
*
* License: MIT; Copyright 2021 Maciej Krawczyk
*/
function getLatinKey(key, code) {
if (key.length !== 1) {
return key;
}
const capitalHetaCode = 880;
const isNonLatin = key.charCodeAt(0) >= capitalHetaCode;
if (isNonLatin) {
if (code.indexOf('Key') === 0 && code.length === 4) { // i.e. 'KeyW'
return code.charAt(3);
}
if (code.indexOf('Digit') === 0 && code.length === 6) { // i.e. 'Digit7'
return code.charAt(5);
}
}
return key.toUpperCase();
}
示例用法:
document.addEventListener('keydown', (e) => {
if (e.ctrlKey && getLatinKey(e.key, e.code) === 'L') {
alert('Ctrl+L');
}
});
測試:
describe('getLatinKey', () => {
it('gets a Latin letter', () => {
expect(getLatinKey('A', 'irrelevant')).toBe('A');
});
it('gets a digit', () => {
expect(getLatinKey('0', 'irrelevant')).toBe('0');
});
it('transforms letters to uppercase', () => {
expect(getLatinKey('a', 'irrelevant')).toBe('A');
});
it('converts non-Latin letters to code values if available', () => {
expect(getLatinKey('β', 'KeyB')).toBe('B');
expect(getLatinKey('я', 'KeyZ')).toBe('Z');
// Not a real-world example, but it tests getting digits.
expect(getLatinKey('я', 'Digit1')).toBe('1');
});
it('does not convert non-Latin letters on special keys', () => {
expect(getLatinKey('ё', 'Backquote')).toBe('Ё');
});
it('does not convert Latin diacritics', () => {
expect(getLatinKey('ś', 'KeyS')).toBe('Ś');
expect(getLatinKey('ü', 'KeyU')).toBe('Ü');
expect(getLatinKey('ž', 'KeyZ')).toBe('Ž');
});
});
Keyboard.getLayoutMap()
來確定布局是否為非拉丁語,這也可以使 KeyQ 工作。 However, it's an experimental API and is not supported by Firefox and Safari (and it may never be, as Firefox currently rejected it on privacy terms - fingerprinting). 這也是一個缺點,因為 API 不是同步的,如果需要,不可能在鍵盤事件上調用e.preventDefault()
。keyboard-layout
npm 模塊可以實現更高級的實現,而不會受到相同的限制。至於復制、粘貼、撤消的操作系統快捷方式,它似乎是您所期望的(至少這是我在 Mac OS 上切換鍵盤布局后得到的印象)。
至於一些一般提示,請避免使用符號作為鍵盤快捷鍵。 它們到處都是,即使在拉丁 Qwerty 布局中也是如此。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.