HTML输入框CapsLock检测异常问题及修复方案咨询
修复CapsLock状态检测的异常问题
使用getModifierState('CapsLock')检测输入框CapsLock状态时,按下CapsLock键会出现提示闪烁、显示状态与实际相反,且事件触发两次的问题,多浏览器测试均存在该现象。相关代码如下:
function handle(ev, el) { //if (ev.isComposing || ev.keyCode === 229) return; // for firefox let isCapsLockOn = ev.getModifierState('CapsLock'); document.getElementById('message').innerText = isCapsLockOn ? 'CAPS LOCK' : '.'; let log = document.getElementById('log'); log.innerText = new Date() + '\n' + log.innerText; }
<input onkeydown="handle(event, this)" /> <div id="message"></div> <div id="log"></div>
问题原因
按下CapsLock键时,浏览器会触发两次keydown事件:第一次是按键按下瞬间,此时系统尚未完成CapsLock状态切换,getModifierState返回的是切换前的状态;第二次是状态切换完成后,浏览器再次触发keydown,此时返回的是切换后的状态。两次状态相反,导致提示闪烁且显示错误。
修复方案
方案1:改用keyup事件监听
keyup事件在CapsLock状态完全切换后才会触发,且只会触发一次,能直接获取到正确的状态。修改后的代码如下:
function handle(ev, el) { // 保留Firefox输入法兼容逻辑(按需启用) if (ev.isComposing || ev.keyCode === 229) return; let isCapsLockOn = ev.getModifierState('CapsLock'); document.getElementById('message').innerText = isCapsLockOn ? 'CAPS LOCK' : '.'; let log = document.getElementById('log'); log.innerText = new Date() + '\n' + log.innerText; }
<input onkeyup="handle(event, this)" /> <div id="message"></div> <div id="log"></div>
方案2:覆盖输入场景的完整检测
如果需要在用户输入字符时也检测CapsLock状态(比如输入小写字母但CapsLock开启时给出提示),可以同时监听keyup和keypress事件,结合输入字符的大小写与Shift键状态判断,覆盖更多场景:
function checkCapsLock(ev) { if (ev.isComposing || ev.keyCode === 229) return; let isCapsLockOn = false; // 处理CapsLock按键本身的切换事件 if (ev.key === 'CapsLock') { isCapsLockOn = ev.getModifierState('CapsLock'); } else { // 处理输入字符的情况:输入大写未按Shift,或输入小写按了Shift,说明CapsLock开启 const isUpperCase = ev.key >= 'A' && ev.key <= 'Z'; const isShiftPressed = ev.getModifierState('Shift'); isCapsLockOn = (isUpperCase && !isShiftPressed) || (!isUpperCase && isShiftPressed); } document.getElementById('message').innerText = isCapsLockOn ? 'CAPS LOCK' : '.'; }
<input onkeyup="checkCapsLock(event)" onkeypress="checkCapsLock(event)" /> <div id="message"></div> <div id="log"></div>
内容的提问来源于stack exchange,提问作者lonix
相关产品推荐
相关产品推荐

