我有定期进行活动的 JavaScript。当用户不在查看站点时(即,窗口或选项卡没有焦点),最好不要运行。
有没有办法使用 JavaScript 做到这一点?
我的参考点:如果您使用的窗口未处于活动状态,Gmail 聊天会播放声音。
我有定期进行活动的 JavaScript。当用户不在查看站点时(即,窗口或选项卡没有焦点),最好不要运行。
有没有办法使用 JavaScript 做到这一点?
我的参考点:如果您使用的窗口未处于活动状态,Gmail 聊天会播放声音。
自从最初编写此答案以来,由于 W3C ,新规范已达到推荐状态。在网页浏览权限API(在MDN)现在允许当一个页面被隐藏到用户我们更准确地检测。
document.addEventListener("visibilitychange", onchange);
当前浏览器支持:
以下代码在不兼容的浏览器中退回到不太可靠的模糊/聚焦方法:
(function() {
var hidden = "hidden";
// Standards:
if (hidden in document)
document.addEventListener("visibilitychange", onchange);
else if ((hidden = "mozHidden") in document)
document.addEventListener("mozvisibilitychange", onchange);
else if ((hidden = "webkitHidden") in document)
document.addEventListener("webkitvisibilitychange", onchange);
else if ((hidden = "msHidden") in document)
document.addEventListener("msvisibilitychange", onchange);
// IE 9 and lower:
else if ("onfocusin" in document)
document.onfocusin = document.onfocusout = onchange;
// All others:
else
window.onpageshow = window.onpagehide
= window.onfocus = window.onblur = onchange;
function onchange (evt) {
var v = "visible", h = "hidden",
evtMap = {
focus:v, focusin:v, pageshow:v, blur:h, focusout:h, pagehide:h
};
evt = evt || window.event;
if (evt.type in evtMap)
document.body.className = evtMap[evt.type];
else
document.body.className = this[hidden] ? "hidden" : "visible";
}
// set the initial state (but only if browser supports the Page Visibility API)
if( document[hidden] !== undefined )
onchange({type: document[hidden] ? "blur" : "focus"});
})();
onfocusin
andonfocusout
是IE 9 及更低版本所必需的,而所有其他版本都使用onfocus
和onblur
,iOS 除外,它使用onpageshow
和onpagehide
。
我会使用 jQuery,因为那样你所要做的就是:
$(window).blur(function(){
//your code here
});
$(window).focus(function(){
//your code
});
或者至少它对我有用。
有 3 种典型的方法用于确定用户是否可以看到 HTML 页面,但是它们都不能完美地工作:
在W3C网页浏览权限API应该做到这一点(支持,因为:火狐10,MSIE 10,铬13)。但是,此 API 仅在浏览器选项卡被完全覆盖时(例如,当用户从一个选项卡更改为另一个选项卡时)才会引发事件。当无法以 100% 的准确度确定可见性时(例如 Alt+Tab 切换到另一个应用程序),API 不会引发事件。
使用基于焦点/模糊的方法会给你带来很多误报。例如,如果用户在浏览器窗口的顶部显示一个较小的窗口,则浏览器窗口将失去焦点(onblur
升高)但用户仍然可以看到它(因此它仍然需要刷新)。另请参阅http://javascript.info/tutorial/focus
为了改善上述不完美的行为,我使用了 3 种方法的组合:W3C Visibility API,然后是焦点/模糊和用户活动方法,以降低误报率。这允许管理以下事件:
它是这样工作的:当文档失去焦点时,监视文档上的用户活动(例如鼠标移动)以确定窗口是否可见。页面可见概率与用户最后一次在页面上活动的时间成反比:如果用户长时间没有对文档进行任何活动,则该页面很可能是不可见的。下面的代码模仿了 W3C 页面可见性 API:它的行为方式相同,但误报率很小。它具有多浏览器的优势(在 Firefox 5、Firefox 10、MSIE 9、MSIE 7、Safari 5、Chrome 9 上测试)。
<div id="x"></div> <脚本> /** 将处理程序注册到给定对象的事件。 @param obj 将引发事件的对象 @param evType 事件类型:单击、按键、鼠标悬停…… @param fn 事件处理函数 @param isCapturing 设置事件模式(true = 捕获事件,false = 冒泡事件) @return true 如果事件处理程序已正确附加 */ 函数 addEvent(obj, evType, fn, isCapturing){ if (isCapturing==null) isCapturing=false; 如果(obj.addEventListener){ // 火狐 obj.addEventListener(evType, fn, isCapturing); 返回真; } else if (obj.attachEvent){ // MSIE var r = obj.attachEvent('on'+evType, fn); 返回 r; } 别的 { 返回假; } } // 注册到潜在的页面可见性变化 addEvent(文档,“潜在可见性变化”,函数(事件){ document.getElementById("x").innerHTML+="potentialVisilityChange: potentialHidden="+document.potentialHidden+", document.potentiallyHiddenSince="+document.potentiallyHiddenSince+" s<br>"; }); // 注册到 W3C 页面可见性 API 变量隐藏=空; varvisibilityChange=null; if (typeof document.mozHidden !== "undefined") { 隐藏=“mozHidden”; visibilityChange="mozvisibilitychange"; } else if (typeof document.msHidden !== "undefined") { 隐藏=“msHidden”; visibilityChange="msvisibilitychange"; } else if (typeof document.webkitHidden!=="undefined") { hidden="webkitHidden"; visibilityChange="webkitvisibilitychange"; } else if (typeof document.hidden !=="hidden") { 隐藏=“隐藏”; 可见性变化=“可见性变化”; } 如果(隐藏!=空&&可见性变化!=空){ 添加事件(文档,可见性变化,功能(事件){ document.getElementById("x").innerHTML+=visibilityChange+": "+hidden+"="+document[hidden]+"<br>"; }); } var potentialPageVisibility = { pageVisibilityChangeThreshold:3*3600, // 以秒为单位 初始化:函数(){ 函数 setAsNotHidden() { var dispatchEventRequired=document.potentialHidden; document.potentialHidden=false; document.potentiallyHiddenSince=0; if (dispatchEventRequired) dispatchPageVisibilityChangeEvent(); } 函数 initPotentiallyHiddenDetection() { 如果(!hasFocusLocal){ // 窗口没有焦点 => 检查窗口中的用户活动 lastActionDate=new Date(); 如果(超时处理器!=空){ clearTimeout(timeoutHandler); } timeoutHandler = setTimeout(checkPageVisibility, potentialPageVisibility.pageVisibilityChangeThreshold*1000+100); // +100 ms 以避免 Firefox 下的舍入问题 } } 函数 dispatchPageVisibilityChangeEvent() { UnifiedVisilityChangeEventDispatchAllowed=false; var evt = document.createEvent("事件"); evt.initEvent("potentialvisilitychange", true, true); document.dispatchEvent(evt); } 函数 checkPageVisibility() { var potentialHiddenDuration=(hasFocusLocal || lastActionDate==null?0:Math.floor((new Date().getTime()-lastActionDate.getTime())/1000)); document.potentiallyHiddenSince=potentialHiddenDuration; 如果(potentialHiddenDuration>=potentialPageVisibility.pageVisibilityChangeThreshold && !document.potentialHidden){ // 页面可见性更改阈值 raiched => 提高偶数 document.potentialHidden=true; dispatchPageVisibilityChangeEvent(); } } var lastActionDate=null; var hasFocusLocal=true; var hasMouseOver=true; document.potentialHidden=false; document.potentiallyHiddenSince=0; var timeoutHandler = null; addEvent(文档,“页面展示”,函数(事件){ document.getElementById("x").innerHTML+="pageshow/doc:<br>"; }); addEvent(文档,“页面隐藏”,函数(事件){ document.getElementById("x").innerHTML+="pagehide/doc:<br>"; }); 添加事件(窗口,“页面展示”,函数(事件){ document.getElementById("x").innerHTML+="pageshow/win:<br>"; // 当页面第一次显示时引发 }); 添加事件(窗口,“页面隐藏”,函数(事件){ document.getElementById("x").innerHTML+="pagehide/win:<br>"; // 没有提升 }); addEvent(文档,“鼠标移动”,函数(事件){ lastActionDate=new Date(); }); addEvent(文档,“鼠标悬停”,函数(事件){ hasMouseOver=true; setAsNotHidden(); }); addEvent(文档,“鼠标移出”,函数(事件){ hasMouseOver=false; initPotentiallyHiddenDetection(); }); addEvent(窗口,“模糊”,函数(事件){ hasFocusLocal=false; initPotentiallyHiddenDetection(); }); addEvent(窗口,“焦点”,函数(事件){ hasFocusLocal=true; setAsNotHidden(); }); setAsNotHidden(); } } potentialPageVisibility.pageVisibilityChangeThreshold=4; // 4 秒进行测试 potentialPageVisibility.init(); </脚本>
由于目前没有没有误报的跨浏览器解决方案,您最好在禁用网站上的定期活动时三思而后行。
使用: 页面可见性 API
document.addEventListener( 'visibilitychange' , function() {
if (document.hidden) {
console.log('bye');
} else {
console.log('well back');
}
}, false );
GitHub 上有一个简洁的库:
https://github.com/serkanyersen/ifvisible.js
例子:
// If page is visible right now
if( ifvisible.now() ){
// Display pop-up
openPopUp();
}
我已经在我拥有的所有浏览器上测试了 1.0.1 版,并且可以确认它适用于:
...可能所有较新的版本。
不完全适用于:
.now()
始终true
为我返回)