我有JavaScript,它周期性地执行活动。当用户没有在看站点时(例如,窗口或选项卡没有焦点),最好不要运行。
是否有一种方法可以使用JavaScript来做到这一点?
我的参考点:如果你正在使用的窗口不活跃,Gmail聊天就会播放声音。
我有JavaScript,它周期性地执行活动。当用户没有在看站点时(例如,窗口或选项卡没有焦点),最好不要运行。
是否有一种方法可以使用JavaScript来做到这一点?
我的参考点:如果你正在使用的窗口不活跃,Gmail聊天就会播放声音。
当前回答
这真的很棘手。考虑到以下要求,似乎没有解决方案。
该页包括您无法控制的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
我还没有在足够多的浏览器上测试这个功能。 如果你能找到更多关于哪里不行的信息,请在下面的评论中告诉我。
其他回答
这在chrome 67和firefox 67上都适用,
if(!document.hasFocus()) {
// do stuff
}
对于angular.js,这里有一个指令(基于已接受的答案),它将允许你的控制器对可见性的变化做出反应:
myApp.directive('reactOnWindowFocus', function($parse) {
return {
restrict: "A",
link: function(scope, element, attrs) {
var hidden = "hidden";
var currentlyVisible = true;
var functionOrExpression = $parse(attrs.reactOnWindowFocus);
// 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);
else if ("onfocusin" in document) {
// IE 9 and lower:
document.onfocusin = onshow;
document.onfocusout = onhide;
} else {
// All others:
window.onpageshow = window.onfocus = onshow;
window.onpagehide = window.onblur = onhide;
}
function onchange (evt) {
//occurs both on leaving and on returning
currentlyVisible = !currentlyVisible;
doSomethingIfAppropriate();
}
function onshow(evt) {
//for older browsers
currentlyVisible = true;
doSomethingIfAppropriate();
}
function onhide(evt) {
//for older browsers
currentlyVisible = false;
doSomethingIfAppropriate();
}
function doSomethingIfAppropriate() {
if (currentlyVisible) {
//trigger angular digest cycle in this scope
scope.$apply(function() {
functionOrExpression(scope);
});
}
}
}
};
});
你可以像这样使用它:<div react-on-window-focus="refresh()">,其中refresh()是范围内任何控制器范围内的范围函数。
这适用于所有现代浏览器:
更改制表符时 更改窗口时(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...")
}
}
我的代码
let browser_active = ((typeof document.hasFocus != 'undefined' ? document.hasFocus() : 1) ? 1 : 0);
if (!browser_active) {
// active
}
我重读了@daniel-buckmaster的版本 我没有做多次尝试,但是,代码对我来说似乎更优雅…
// on-visibility-change.js v1.0.1, based on https://stackoverflow.com/questions/1060008/is-there-a-way-to-detect-if-a-browser-window-is-not-currently-active#38710376
function onVisibilityChange(callback) {
let d = document;
let visible = true;
let prefix;
if ('hidden' in d) {
prefix = 'h';
} else if ('webkitHidden' in d) {
prefix = 'webkitH';
} else if ('mozHidden' in d) {
prefix = 'mozH';
} else if ('msHidden' in d) {
prefix = 'msH';
} else if ('onfocusin' in d) { // ie 9 and lower
d.onfocusin = focused;
d.onfocusout = unfocused;
} else { // others
window.onpageshow = window.onfocus = focused;
window.onpagehide = window.onblur = unfocused;
};
if (prefix) {
visible = !d[prefix + 'idden'];
d.addEventListener(prefix.substring(0, prefix.length - 1) + 'visibilitychange', function() {
(d[prefix + 'idden'] ? unfocused : focused)();
});
};
function focused() {
if (!visible) {
callback(visible = true);
};
};
function unfocused() {
if (visible) {
callback(visible = false);
};
};
};