我有定期进行活动的 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"});
})();
onfocusinandonfocusout是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为我返回)