使用iframe识别窗口焦点/模糊事件 [英] Identifying window focus/blur events with iframes
问题描述
我正在尝试可靠地确定何时激活和停用浏览器窗口/选项卡.通常,window
的focus
和blur
事件都可以,但是文档包含多个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之间切换,就会分别触发blur
和focus
事件;他们为此开了一点延迟.
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的浏览器窗口,而又不会冒由两个即时blur
和focus
事件?
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屋!