我试图可靠地识别何时激活和停用浏览器窗口/选项卡。通常,window
的{{1}}和focus
事件会发生,但该文档包含多个iframe。
当iframe被聚焦时,主窗口变得不聚焦,反之亦然,因此我们有以下焦点事件的可能性[blur
表示窗口/选项卡已停用]:
(none)
注册所有这些事件没有问题,如this fiddle所示。但每当我们从主窗口切换到iframe或反之亦然,或者在两个iframe之间切换时,相应的current focus new focus events
----------------------------------------------------------------------
window (none) window:blur
window iframe window:blur + iframe:focus
iframe (none) iframe:blur
iframe window iframe:blur + window:focus
iframe another iframe iframe:blur + iframe:focus
(none) window window:focus
(none) iframe iframe:focus
和blur
事件都会触发;然后他们会稍微耽误一下。
我担心这里的并发性,因为focus
处理程序可以开始做东西,但它应该从未开始,因为用户实际上只是将焦点切换到帧之间的某处。
示例:页面应该在当前未处于活动状态时定期执行某些AJAX请求。也就是说,它应该在用户停用标签时开始请求,并在它再次激活后立即停止请求。因此,我们将函数绑定到发起请求的blur
事件。如果用户只是点击了另一个iframe blur
,那么在此之后不久,就会触发blur
。但focus
处理程序已经消失,在再次停止之前至少发出一个请求。
这就是我的问题:如何可靠地检测用户何时实际(取消)激活包含iframe的浏览器窗口,而不会有导致误报警的风险两个直接的blur
和blur
事件?
我写了一个半生不熟的解决方案,在focus
事件后使用超时,以确定其后是否有blur
个事件(fiddle):
focus
但我相信这可能会造成很大问题,尤其是在较慢的机器上。增加超时也是我不能接受的,50毫秒真的是我的疼痛阈值。
有没有一种方法不依赖于客户端足够快?
答案 0 :(得分:1)
您可以轮询document.hasFocus()值,如果iframe或主窗口被聚焦,则该值应为true
setInterval(function checkFocus(){
if( checkFocus.prev == document.hasFocus() ) return;
if(document.hasFocus()) onFocus();
else onBlur();
checkFocus.prev = document.hasFocus();
},100);
function onFocus(){ console.log('browser window activated') }
function onBlur(){ console.log('browser window deactivated') }
答案 1 :(得分:0)
我试图在没有轮询的情况下进行此操作,但iframe不会触发onblur事件(如果在iframe处于焦点时停用浏览器窗口,我没有触发任何事件),所以我最终需要轮询无论如何它的一半,但也许有人可以用这个代码找出一些东西
function onFocus(){ console.log('browser window activated'); }
function onBlur(){ console.log('browser window deactivated'); }
var inter;
var iframeFocused;
window.focus(); // I needed this for events to fire afterwards initially
addEventListener('focus', function(e){
console.log('global window focused');
if(iframeFocused){
console.log('iframe lost focus');
iframeFocused = false;
clearInterval(inter);
}
else onFocus();
});
addEventListener('blur', function(e){
console.log('global window lost focus');
if(document.hasFocus()){
console.log('iframe focused');
iframeFocused = true;
inter = setInterval(()=>{
if(!document.hasFocus()){
console.log('iframe lost focus');
iframeFocused = false;
onBlur();
clearInterval(inter);
}
},100);
}
else onBlur();
});