我有JavaScript,它周期性地执行活动。当用户没有在看站点时(例如,窗口或选项卡没有焦点),最好不要运行。
是否有一种方法可以使用JavaScript来做到这一点?
我的参考点:如果你正在使用的窗口不活跃,Gmail聊天就会播放声音。
我有JavaScript,它周期性地执行活动。当用户没有在看站点时(例如,窗口或选项卡没有焦点),最好不要运行。
是否有一种方法可以使用JavaScript来做到这一点?
我的参考点:如果你正在使用的窗口不活跃,Gmail聊天就会播放声音。
当前回答
在HTML 5中,你也可以使用:
onpageshow:当窗口变得可见时运行的脚本 onpagehide:当窗口隐藏时运行的脚本
See:
https://developer.mozilla.org/en-US/docs/Web/Events/pageshow https://developer.mozilla.org/en-US/docs/Web/Events/pagehide
其他回答
对于没有jQuery的解决方案,请参阅Visibility.js,它提供了关于三个页面状态的信息
visible ... page is visible
hidden ... page is not visible
prerender ... page is being prerendered by the browser
以及setInterval的方便包装器
/* Perform action every second if visible */
Visibility.every(1000, function () {
action();
});
/* Perform action every second if visible, every 60 sec if not visible */
Visibility.every(1000, 60*1000, function () {
action();
});
旧版浏览器(IE < 10;iOS < 7)也可用
在HTML 5中,你也可以使用:
onpageshow:当窗口变得可见时运行的脚本 onpagehide:当窗口隐藏时运行的脚本
See:
https://developer.mozilla.org/en-US/docs/Web/Events/pageshow https://developer.mozilla.org/en-US/docs/Web/Events/pagehide
这适用于所有现代浏览器:
更改制表符时 更改窗口时(Alt+Tab) 当从任务栏最大化另一个程序时
var eventName;
var visible = true;
var propName = "hidden";
if (propName in document) eventName = "visibilitychange";
else if ((propName = "msHidden") in document) eventName = "msvisibilitychange";
else if ((propName = "mozHidden") in document) eventName = "mozvisibilitychange";
else if ((propName = "webkitHidden") in document) eventName = "webkitvisibilitychange";
if (eventName) document.addEventListener(eventName, handleChange);
if ("onfocusin" in document) document.onfocusin = document.onfocusout = handleChange; //IE 9
window.onpageshow = window.onpagehide = window.onfocus = window.onblur = handleChange;// Changing tab with alt+tab
// Initialize state if Page Visibility API is supported
if (document[propName] !== undefined) handleChange({ type: document[propName] ? "blur" : "focus" });
function handleChange(evt) {
evt = evt || window.event;
if (visible && (["blur", "focusout", "pagehide"].includes(evt.type) || (this && this[propName]))){
visible = false;
console.log("Out...")
}
else if (!visible && (["focus", "focusin", "pageshow"].includes(evt.type) || (this && !this[propName]))){
visible = true;
console.log("In...")
}
}
这真的很棘手。考虑到以下要求,似乎没有解决方案。
该页包括您无法控制的iframe 您希望跟踪可见性状态更改,而不管更改是由选项卡更改(ctrl+ TAB)或窗口更改(alt+ TAB)触发的。
这是因为:
页面可视性API可以可靠地告诉您一个选项卡更改(即使使用iframes),但它不能告诉您用户何时更改了窗口。 监听窗口模糊/聚焦事件可以检测alt+选项卡和ctrl+选项卡,只要iframe没有焦点。
考虑到这些限制,可以实现一个组合的解决方案 -页面可见性API -窗口模糊/聚焦 ——document.activeElement
能够:
1)当父页有焦点时按ctrl+tab: YES 2) iframe有焦点时按ctrl+tab: YES 3)当父页有焦点时,alt+tab: YES 4)当iframe有focus时,alt+tab: NO <——bummer
当iframe有焦点时,你的模糊/焦点事件根本不会被调用,页面可视性API也不会在alt+选项卡上触发。
我以@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
我还没有在足够多的浏览器上测试这个功能。 如果你能找到更多关于哪里不行的信息,请在下面的评论中告诉我。
U可以使用:
(function () {
var requiredResolution = 10; // ms
var checkInterval = 1000; // ms
var tolerance = 20; // percent
var counter = 0;
var expected = checkInterval / requiredResolution;
//console.log('expected:', expected);
window.setInterval(function () {
counter++;
}, requiredResolution);
window.setInterval(function () {
var deviation = 100 * Math.abs(1 - counter / expected);
// console.log('is:', counter, '(off by', deviation , '%)');
if (deviation > tolerance) {
console.warn('Timer resolution not sufficient!');
}
counter = 0;
}, checkInterval);
})();