我有JavaScript,它周期性地执行活动。当用户没有在看站点时(例如,窗口或选项卡没有焦点),最好不要运行。

是否有一种方法可以使用JavaScript来做到这一点?

我的参考点:如果你正在使用的窗口不活跃,Gmail聊天就会播放声音。


当前回答

在GitHub上有一个简洁的库:

https://github.com/serkanyersen/ifvisible.js

例子:

// If page is visible right now
if( ifvisible.now() ){
  // Display pop-up
  openPopUp();
}

我已经在我拥有的所有浏览器上测试了1.0.1版本,并可以确认它适用于:

的问世,IE9 FF 26.0 Chrome 34.0

... 可能还有所有更新的版本。

不完全适用于:

IE8 -总是指示标签/窗口当前是活跃的(.now()总是为我返回true)

其他回答

我开始使用社区维基答案,但意识到它没有检测alt-tab事件在Chrome。这是因为它使用了第一个可用的事件源,在这种情况下,它是页面可见性API,在Chrome中似乎不跟踪alt-tab。

我决定稍微修改一下脚本,以跟踪页面焦点更改的所有可能事件。这是一个你可以放入的函数:

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) {
        visible = !document.hidden;
        document.addEventListener('visibilitychange',
            function() {(document.hidden ? unfocused : focused)()});
    }
    if ('mozHidden' in document) {
        visible = !document.mozHidden;
        document.addEventListener('mozvisibilitychange',
            function() {(document.mozHidden ? unfocused : focused)()});
    }
    if ('webkitHidden' in document) {
        visible = !document.webkitHidden;
        document.addEventListener('webkitvisibilitychange',
            function() {(document.webkitHidden ? unfocused : focused)()});
    }
    if ('msHidden' in document) {
        visible = !document.msHidden;
        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');
});

该版本监听所有不同的可见性事件,并在其中任何事件导致更改时触发回调。焦点处理程序和非焦点处理程序确保如果多个api捕捉到相同的可见性更改,不会多次调用回调。

我会使用jQuery,因为这样你所要做的就是:

$(window).blur(function(){
  //your code here
});
$(window).focus(function(){
  //your code
});

至少对我有用。

我重读了@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);
        };
    };
};

在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

在GitHub上有一个简洁的库:

https://github.com/serkanyersen/ifvisible.js

例子:

// If page is visible right now
if( ifvisible.now() ){
  // Display pop-up
  openPopUp();
}

我已经在我拥有的所有浏览器上测试了1.0.1版本,并可以确认它适用于:

的问世,IE9 FF 26.0 Chrome 34.0

... 可能还有所有更新的版本。

不完全适用于:

IE8 -总是指示标签/窗口当前是活跃的(.now()总是为我返回true)