我有定期执行活动的JavaScript.当用户没有看到该站点时(即窗口或选项卡没有焦点),最好不要运行.
有没有办法使用JavaScript?
我的参考点:如果您使用的窗口未处于活动状态,则Gmail聊天会播放声音.
自从最初撰写此答案以来,由于W3C ,新规范已达到推荐状态.在网页浏览权限API(在MDN)现在允许当一个页面被隐藏到用户我们更准确地检测.
目前的浏览器支持
Chrome 13+
Internet Explorer 10+
Firefox 10+
Opera 12.10+ [ 阅读笔记 ]
以下代码使用API,回退到不兼容的浏览器中不太可靠的模糊/焦点方法.
document.addEventListener("visibilitychange", onchange);
onfocusin
并且onfocusout
是IE 9及更低版本所必需的,而所有其他人都使用onfocus
和onblur
使用onpageshow
和的iOS除外onpagehide
.
我会使用jQuery因为那样你所要做的就是:
$(window).blur(function(){ //your code here }); $(window).focus(function(){ //your code });
或者至少它对我有用.
有3种典型的方法用于确定用户是否可以看到HTML页面,但是它们都不能完美地工作:
在W3C网页浏览权限API应该做到这一点(支持,因为:火狐10,MSIE 10,铬13).但是,此API仅在完全覆盖浏览器选项卡时(例如,当用户从一个选项卡更改为另一个选项卡时)引发事件.当无法以100%的准确度确定可见性时,API不会引发事件(例如,Alt + Tab切换到另一个应用程序).
使用基于焦点/模糊的方法会给您带来很多误报.例如,如果用户在浏览器窗口顶部显示较小的窗口,则浏览器窗口将失去焦点(onblur
凸起),但用户仍然能够看到它(因此仍需要刷新).另见http://javascript.info/tutorial/focus
依靠用户活动(鼠标移动,点击,键入键)也会给你带来很多误报.考虑与上述相同的情况,或观看视频的用户.
为了改善上述不完美行为,我结合使用了3种方法:W3C Visibility API,然后是焦点/模糊和用户活动方法,以降低误报率.这允许管理以下事件:
将浏览器选项卡更改为另一个(由于W3C页面可见性API,100%准确性)
页面可能被另一个窗口隐藏,例如由于Alt + Tab(概率=不是100%准确)
用户注意力可能不会集中在HTML页面上(概率=不是100%准确)
这是它的工作原理:当文档松散焦点时,监视文档上的用户活动(例如鼠标移动)以确定窗口是否可见.页面可见性概率与页面上最后一次用户活动的时间成反比:如果用户长时间未对文档进行任何活动,则该页面很可能不可见.下面的代码模仿W3C页面可见性API:它的行为方式相同,但误报率很低.它具有多浏览器的优势(在Firefox 5,Firefox 10,MSIE 9,MSIE 7,Safari 5,Chrome 9上测试).
由于目前没有可用的跨浏览器解决方案而没有误报,因此您最好三思而后行,禁用网站上的定期活动.
GitHub上有一个整洁的库:
https://github.com/serkanyersen/ifvisible.js
例:
// If page is visible right now if( ifvisible.now() ){ // Display pop-up openPopUp(); }
我已经在我拥有的所有浏览器上测试了版本1.0.1,并且可以确认它适用于:
IE9,IE10
FF 26.0
Chrome 34.0
......可能还有所有新版本.
不完全适用于:
IE8 - 始终指示选项卡/窗口当前处于活动状态(.now()
始终true
为我返回)
我为我的应用程序创建了Comet Chat,当我收到来自其他用户的消息时,我使用:
if(new_message){ if(!document.hasFocus()){ audio.play(); document.title="Have new messages"; } else{ audio.stop(); document.title="Application Name"; } }
使用: 页面可见性API
document.addEventListener( 'visibilitychange' , function() { if (document.hidden) { console.log('bye'); } else { console.log('well back'); } }, false );
我可以用吗 ? http://caniuse.com/#feat=pagevisibility
我开始使用社区维基回答,但意识到它没有检测到Chrome中的alt-tab事件.这是因为它使用了第一个可用的事件源,在这种情况下,它是页面可见性API,在Chrome中似乎不跟踪alt-tabbing.
我决定稍微修改脚本以跟踪页面焦点更改的所有可能事件.这是一个你可以参与的功能:
function onVisibilityChange(callback) { var visible = true; if (!callback) { throw new Error('no callback given'); } function focused() { if (!visible) { callback(visible = true); } } function unfocused() { if (visible) { callback(visible = false); } } // Standards: if ('hidden' in document) { document.addEventListener('visibilitychange', function() {(document.hidden ? unfocused : focused)()}); } if ('mozHidden' in document) { document.addEventListener('mozvisibilitychange', function() {(document.mozHidden ? unfocused : focused)()}); } if ('webkitHidden' in document) { document.addEventListener('webkitvisibilitychange', function() {(document.webkitHidden ? unfocused : focused)()}); } if ('msHidden' in document) { document.addEventListener('msvisibilitychange', function() {(document.msHidden ? unfocused : focused)()}); } // IE 9 and lower: if ('onfocusin' in document) { document.onfocusin = focused; document.onfocusout = unfocused; } // All others: window.onpageshow = window.onfocus = focused; window.onpagehide = window.onblur = unfocused; };
像这样使用它:
onVisibilityChange(function(visible) { console.log('the page is now', visible ? 'focused' : 'unfocused'); });
这真的很棘手.鉴于以下要求,似乎没有解决方案.
该页面包含您无法控制的iframe
无论TAB更改(ctrl + tab)或窗口更改(alt + tab)触发更改,您都希望跟踪可见性状态更改
这是因为:
Visibility API页面可以可靠地告诉您标签更改(即使使用iframe),但它无法告诉您用户何时更改窗口.
只要iframe没有焦点,聆听窗口模糊/焦点事件就可以检测到alt +标签和ctrl +标签.
鉴于这些限制,可以实现一个结合的解决方案 - 页面可见性API - 窗口模糊/焦点 - document.activeElement
这能够:
1)父页面具有焦点时的ctrl + tab:YES
2)当iframe有焦点时按ctrl + tab:YES
3)父页面具有焦点时的alt + tab:YES
4)当iframe有焦点时alt + tab:NO < - 无赖
当iframe具有焦点时,您的模糊/焦点事件根本不会被调用,并且页面Visibility API将不会在alt + tab上触发.
我在@建AndyE的解决方案,并在这里实现这个(差不多好了)的解决方案: https://dl.dropboxusercontent.com/u/2683925/estante-components/visibility_test1.html (对不起,我遇到了一些麻烦的jsfiddle).
这也可以在Github上找到:https://github.com/qmagico/estante-components
这适用于铬/铬.它类似于firefox,除了它不加载iframe内容(任何想法为什么?)
无论如何,要解决最后一个问题(4),你唯一能做的就是在iframe上监听模糊/焦点事件.如果您对iframe有一定的控制权,则可以使用postMessage API来执行此操作.
https://dl.dropboxusercontent.com/u/2683925/estante-components/visibility_test2.html
我还没有用足够的浏览器测试过这个.如果您可以找到有关这不起作用的更多信息,请在下面的评论中告诉我们.
var visibilityChange = (function (window) { var inView = false; return function (fn) { window.onfocus = window.onblur = window.onpageshow = window.onpagehide = function (e) { if ({focus:1, pageshow:1}[e.type]) { if (inView) return; fn("visible"); inView = true; } else if (inView) { fn("hidden"); inView = false; } }; }; }(this)); visibilityChange(function (state) { console.log(state); });
http://jsfiddle.net/ARTsinn/JTxQY/