使用iframe识别窗口焦点/模糊事件

时间:2014-07-07 20:19:51

标签: javascript jquery iframe javascript-events onfocus

我试图可靠地识别何时激活和停用浏览器窗口/选项卡。通常,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的浏览器窗口,而不会有导致误报警的风险两个直接的blurblur事件?

我写了一个半生不熟的解决方案,在focus事件后使用超时,以确定其后是否有blur个事件(fiddle):

focus

但我相信这可能会造成很大问题,尤其是在较慢的机器上。增加超时也是我不能接受的,50毫秒真的是我的疼痛阈值

有没有一种方法不依赖于客户端足够快?

2 个答案:

答案 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不会触发onb​​lur事件(如果在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();
});