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

标签 javascript jquery iframe jquery-events onfocus

我正在尝试可靠地识别浏览器窗口/选项卡何时激活和停用。通常,windowfocusblur 事件就可以了,但文档包含多个 iframe。
当 iframe 获得焦点时,主窗口失去焦点,反之亦然,因此我们有以下可能的焦点事件 [(none) 表示窗口/选项卡已停用]:

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

注册所有这些事件是没有问题的,如图this fiddle .但是每当我们从主窗口切换到 iframe 或反之亦然,或者在两个 iframe 之间切换时,相应的 blurfocus 事件都会触发;他们开火的时间稍有延迟。

我担心这里的并发性,因为 blur 处理程序可以开始做一些事情,但它应该永远不会开始,因为用户实际上只是在帧之间的某个地方切换了焦点。
示例:一个页面应该在当前不活动时定期执行一些 AJAX 请求。也就是说,它应该在用户停用选项卡时开始请求,并在再次激活时停止请求。因此,我们将一个函数绑定(bind)到启动请求的 blur 事件。如果用户只是点击另一个 iframe,blur,紧接着,focus 被触发。但是 blur 处理程序已经触发,至少发出一个请求才能再次停止。

这就是我的问题:我如何才能可靠地检测到用户何时实际(停用)激活包含 iframe 的浏览器窗口,而不会冒因两个即时 blurfocus 事件?

我写了一个半生不熟的解决方案,它在 blur 事件之后使用超时来确定它之后是否有立即的 focus 事件 ( 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 ms 真的是我的痛阈

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

最佳答案

您可以轮询 document.hasFocus() 值,如果 iframe 或主窗口获得焦点,该值应该为真

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

关于javascript - 使用 iframe 识别窗口焦点/模糊事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24619114/

相关文章:

javascript - 为页面上的每个 iFrame 添加 `load` 事件

vue.js - vuejs如何从iframe获取src

javascript - Jquery post success变量范围

影响我的 HTML 图像链接的 jQuery 代码?

javascript - 检查元素是否具有特定的类和特定的 ID

jquery - 使用 jquery 将状态 json 数据放入下拉列表中选择

javascript - Angular ng-Model不同的观点和值(value)

javascript - paperjs - 增加鼠标对鼠标事件的容忍度

javascript - puppeteer 表演时间表?

javascript - iFrame 自动调整大小