使用iframe识别窗口焦点/模糊事件 [英] Identifying window focus/blur events with iframes

查看:297
本文介绍了使用iframe识别窗口焦点/模糊事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试可靠地确定何时激活和停用浏览器窗口/选项卡.通常,windowfocusblur事件都可以,但是文档包含多个iframe.
当iframe处于焦点状态时,主窗口将变得没有焦点,反之亦然,因此我们有以下焦点事件的可能性[(none)表示窗口/标签被停用]:

I'm trying to reliably identify when a browser window/tab is activated and deactivated. Normally, window's focus and blur events would do, but the document contains several iframes.
When an iframe is focused, the main window gets unfocused and vice versa, so we have the following possibilities of focus events [(none) means the window/tab is deactivated]:

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

注册所有这些事件没有问题,如此小提琴所示.但是,只要我们从主窗口切换到iframe或反之,或者在两个iframe之间切换,就会分别触发blurfocus事件;他们为此开了一点延迟.

It is no problem to register all of these events, as shown by this fiddle. But whenever we switch from the main window to an iframe or vice versa, or between two iframes, the respective blur and focus events both fire; and they fire with a small delay at that.

我担心这里的并发性,因为blur处理程序可以开始执行工作,但是它应该永远不会开始,因为用户实际上只是在框架之间的某个位置切换了焦点.
示例:只要页面当前未处于活动状态,它就应该定期执行一些AJAX请求.也就是说,无论何时用户停用选项卡,它都应开始请求,并在再次激活该选项卡时立即停止请求.因此,我们将一个函数绑定到启动请求的blur事件.如果用户仅点击另一个iframe blur,然后不久,就会触发focus.但是blur处理程序已经触发,至少发出一个请求,然后才能再次将其停止.

I am worried about the concurrency here, since the blur handler could go and start doing stuff, but it should have never started because the user actually just switched focus somewhere in between the frames.
Example: A page should do some AJAX requests periodically whenever it is currently not active. That is, it should start requesting whenever the user deactivates the tab and stop requesting as soon as it's activated again. So we bind a function to the blur event that initiates the requests. If the user just clicks on another iframe, blur, and shortly after that, focus is triggered. But the blur handler already fires away, making at least one request before it can be stopped again.

那是我的问题:如何可靠地检测用户何时实际(取消激活)包含iframe的浏览器窗口,而又不会冒由两个即时blurfocus事件?

And that's my problem: How can I reliably detect when a user actually (de-)activates a browser window containing iframes, without risking to get a false alarm caused by two immediate blur and focus events?

我编写了一个半熟的解决方案,该解决方案使用blur事件后的超时来确定其后是否有立即的focus事件(

I wrote a half-baked solution that uses a timeout after a blur event in order to determine if there was an immediate focus event after it (fiddle):

var active = false,
    timeout = 50, // ms
    lastBlur = 0,
    lastFocus = 0;

function handleBlur() {
    if (lastBlur - lastFocus > timeout) {
        active = false;
    }
}
function handleFocus() {
    if (lastFocus - lastBlur > timeout) {
        active = true;
    }
}

$(window).on('focus', function () {
    lastFocus = Date.now();
    handleFocus();
}).on('blur', function () {
    lastBlur = Date.now();
    window.setTimeout(handleBlur, timeout);
});

$('iframe').each(function () {
    $(this.contentWindow).on('focus', function () {
        lastFocus = Date.now();
        handleFocus();
    }).on('blur', function () {
        lastBlur = Date.now();
        window.setTimeout(handleBlur, timeout);
    });
});

但是我相信这可能会带来很大的问题,尤其是在速度较慢的机器上.增加超时也不是我所接受的,50毫秒实际上是我的痛苦阈值.

But I believe this could be very problematic, especially on slower machines. Increasing the timeout is also not acceptable to me, 50 ms is really my pain threshold.

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

Is there a way that doesn't depend on the client to be fast enough?

推荐答案

您可以轮询document.hasFocus()值,如果对iframe或主窗口进行了聚焦,则该值为true

you could poll for the document.hasFocus() value, which should be true if either an iframe or the main window are focused

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') }

这篇关于使用iframe识别窗口焦点/模糊事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆