切换时忽略 blur/focusout 事件 tabs/windows
Ignore blur/focusout events when switching tabs/windows
我有一个表单,只要其中一个字段成为焦点(即, 用户单击或标签进入),一个 div 包含有关的额外信息显示该字段。非常简单:onFocus
在此信息窗格上设置 display: none;
,然后 onBlur
将其删除。
我只希望在单击同一页面上的其他元素时触发这些事件,但在切换到另一个 window 或选项卡时它们也会触发。每次 <Alt>-<Tab>
.
看到内容在页面上来来去去超级烦人
JS有什么办法区分这两种模糊事件吗?
编辑: I made a codepen to illustrate the problem。打开它,单击文本输入字段,然后按 alt-tab 到另一个 window 以查看一些文本消失。
这里是有问题的代码:
<input id="foo" />
<p>
Lorem ipsum dolor <span id="bar">sit amet consectetur</span>
</p>
.hidden {
display: none;
}
const inputField = document.getElementById('foo')
const hiddenSpan = document.getElementById('bar')
inputField.addEventListener('focus', () => hiddenSpan.classList.add('hidden'))
inputField.addEventListener('blur', () => hiddenSpan.classList.remove('hidden'))
window 模糊时的预期行为是保留输入的焦点。
调查表明,当取消选择 window 时,首先会向活动元素发送模糊事件,然后向 window 发送模糊事件。
这两个 blur
事件快速连续发生,因此您可以利用它在适当的时候重新聚焦输入:
- 记录最后一次输入blur的时间
- 拦截window模糊事件
- 如果输入模糊和 window 模糊之间的时间很短,重新聚焦输入
工作示例:
const inputField = document.getElementById('input');
const inputSpan = document.getElementById('bar');
const windowSpan = document.getElementById('window-span');
let inputBlurTime = 0;
inputField.addEventListener('focus', () => {
inputSpan.innerHTML = ' FOCUSED';
});
inputField.addEventListener('blur', evt => {
inputSpan.innerHTML = ' BLURRED';
inputBlurTime = new Date().getTime();
});
window.addEventListener('focus', () => {
windowSpan.innerHTML = ' FOCUSED';
});
window.addEventListener('blur', () => {
windowSpan.innerHTML = ' BLURRED';
const windowBlurTime = new Date().getTime();
if (windowBlurTime - inputBlurTime < 100) {
windowSpan.innerHTML += ' (re-focusing input)';
inputField.focus();
inputSpan.innerHTML = ' RE-FOCUSED';
}
});
<h4>Preserve Input Focus on Window Blur</h4>
<input id="input" />
<p>Input <span id="bar">INIT</span></p>
<p>Window <span id="window-span">INIT</span></p>
Credit to Reddit user /u/jcunews1 for this answer:使用document.activeElement
判断焦点是否真正离开了目标元素.
const inputField = document.getElementById('foo');
const hiddenSpan = document.getElementById('bar');
inputField.addEventListener('focus', () => hiddenSpan.classList.add('hidden'));
inputField.addEventListener('blur', (event) => {
if (event.target !== document.activeElement) { // This is where the magic happens!
hiddenSpan.classList.remove('hidden');
}
});
.hidden {
display: none;
}
<input id="foo" />
<p>
Lorem ipsum dolor <span id="bar">sit amet consectetur</span>
</p>
我有一个表单,只要其中一个字段成为焦点(即, 用户单击或标签进入),一个 div 包含有关的额外信息显示该字段。非常简单:onFocus
在此信息窗格上设置 display: none;
,然后 onBlur
将其删除。
我只希望在单击同一页面上的其他元素时触发这些事件,但在切换到另一个 window 或选项卡时它们也会触发。每次 <Alt>-<Tab>
.
JS有什么办法区分这两种模糊事件吗?
编辑: I made a codepen to illustrate the problem。打开它,单击文本输入字段,然后按 alt-tab 到另一个 window 以查看一些文本消失。
这里是有问题的代码:
<input id="foo" />
<p>
Lorem ipsum dolor <span id="bar">sit amet consectetur</span>
</p>
.hidden {
display: none;
}
const inputField = document.getElementById('foo')
const hiddenSpan = document.getElementById('bar')
inputField.addEventListener('focus', () => hiddenSpan.classList.add('hidden'))
inputField.addEventListener('blur', () => hiddenSpan.classList.remove('hidden'))
window 模糊时的预期行为是保留输入的焦点。
调查表明,当取消选择 window 时,首先会向活动元素发送模糊事件,然后向 window 发送模糊事件。
这两个 blur
事件快速连续发生,因此您可以利用它在适当的时候重新聚焦输入:
- 记录最后一次输入blur的时间
- 拦截window模糊事件
- 如果输入模糊和 window 模糊之间的时间很短,重新聚焦输入
工作示例:
const inputField = document.getElementById('input');
const inputSpan = document.getElementById('bar');
const windowSpan = document.getElementById('window-span');
let inputBlurTime = 0;
inputField.addEventListener('focus', () => {
inputSpan.innerHTML = ' FOCUSED';
});
inputField.addEventListener('blur', evt => {
inputSpan.innerHTML = ' BLURRED';
inputBlurTime = new Date().getTime();
});
window.addEventListener('focus', () => {
windowSpan.innerHTML = ' FOCUSED';
});
window.addEventListener('blur', () => {
windowSpan.innerHTML = ' BLURRED';
const windowBlurTime = new Date().getTime();
if (windowBlurTime - inputBlurTime < 100) {
windowSpan.innerHTML += ' (re-focusing input)';
inputField.focus();
inputSpan.innerHTML = ' RE-FOCUSED';
}
});
<h4>Preserve Input Focus on Window Blur</h4>
<input id="input" />
<p>Input <span id="bar">INIT</span></p>
<p>Window <span id="window-span">INIT</span></p>
Credit to Reddit user /u/jcunews1 for this answer:使用document.activeElement
判断焦点是否真正离开了目标元素.
const inputField = document.getElementById('foo');
const hiddenSpan = document.getElementById('bar');
inputField.addEventListener('focus', () => hiddenSpan.classList.add('hidden'));
inputField.addEventListener('blur', (event) => {
if (event.target !== document.activeElement) { // This is where the magic happens!
hiddenSpan.classList.remove('hidden');
}
});
.hidden {
display: none;
}
<input id="foo" />
<p>
Lorem ipsum dolor <span id="bar">sit amet consectetur</span>
</p>