Javascript 是否有方法检测浏览器窗口当前是否未处于活动状态?
我有JavaScript,它定期进行活动。当用户没有查看站点时(即窗口或选项卡没有焦点),最好不要运行 有没有一种方法可以使用JavaScript实现这一点Javascript 是否有方法检测浏览器窗口当前是否未处于活动状态?,javascript,browser,focus,window,Javascript,Browser,Focus,Window,我有JavaScript,它定期进行活动。当用户没有查看站点时(即窗口或选项卡没有焦点),最好不要运行 有没有一种方法可以使用JavaScript实现这一点 我的参考点是:如果你使用的窗口不活动,Gmail聊天会播放声音 自从最初编写这个答案以来,多亏了W3C,一个新的规范已经达到了推荐状态。 (on)现在允许我们更准确地检测用户何时隐藏页面 document.addEventListener("visibilitychange", onchange); 当前浏览器支持: 铬13+ Inte
我的参考点是:如果你使用的窗口不活动,Gmail聊天会播放声音 自从最初编写这个答案以来,多亏了W3C,一个新的规范已经达到了推荐状态。 (on)现在允许我们更准确地检测用户何时隐藏页面
document.addEventListener("visibilitychange", onchange);
当前浏览器支持:
- 铬13+
- Internet Explorer 10+
- 火狐10+
- 歌剧12.10+[]
(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
和onfocusout
是,而除iOS外,其他所有的都使用onfocus
和onblur
,iOS使用onpageshow
和onpagehide一种稍微复杂一点的方法是使用setInterval()
检查鼠标位置并与上次检查进行比较。如果鼠标在设定的时间内没有移动,则用户可能处于空闲状态
这样做的另一个好处是可以告诉用户是否空闲,而不仅仅是检查窗口是否处于活动状态
正如许多人指出的,这并不总是检查用户或浏览器窗口是否空闲的好方法,因为用户甚至可能没有使用鼠标或正在观看视频或类似内容。我只是建议一种检查空闲状态的可能方法。在HTML 5中,您还可以使用:
onpageshow
:窗口可见时要运行的脚本
onpagehide
:隐藏窗口时要运行的脚本
见:
我会使用jQuery,因为这样您所要做的就是:
$(window).blur(function(){
//your code here
});
$(window).focus(function(){
//your code
});
或者至少它对我有效。有3种典型的方法用于确定用户是否可以看到HTML页面,但是没有一种方法可以完美地工作:
- 应该这样做(从Firefox 10、MSIE 10、Chrome 13开始支持)。但是,此API仅在完全覆盖浏览器选项卡时(例如,当用户从一个选项卡更改为另一个选项卡时)才会引发事件。当无法100%准确地确定可见性时(例如,Alt+Tab切换到其他应用程序),API不会引发事件
- 使用基于聚焦/模糊的方法会产生大量假阳性。例如,如果用户在浏览器窗口顶部显示一个较小的窗口,浏览器窗口将失去焦点(
onblur
risted),但用户仍能看到它(因此仍需要刷新)。另见
- 依赖用户活动(鼠标移动、单击、键入键)也会给您带来很多误报。考虑与上面相同的情况,或者用户正在观看视频
为了改善上述不完美行为,我结合使用了3种方法:W3C Visibility API、focus/blur和user activity方法,以降低误报率。这允许管理以下事件:
- 将浏览器选项卡更改为另一个选项卡(由于W3C页面可见性API,精确度达到100%)
- 页面可能被另一个窗口隐藏,例如由于Alt+Tab(概率=不100%准确)
- 用户注意力可能不集中在HTML页面上(概率=不100%准确)
这就是它的工作原理:当文档失去焦点时,会监视文档上的用户活动(如鼠标移动),以确定窗口是否可见。页面可见性概率与页面上最后一个用户活动的时间成反比:如果用户长时间不在文档上活动,则页面很可能不可见。下面的代码模拟了W3C页面可见性API:其行为方式相同,但误报率很低。它具有多浏览器的优势(在Firefox 5、Firefox 10、MSIE 9、MSIE 7、Safari 5、Chrome 9上测试)
/**
将处理程序注册到给定对象的事件。
@param obj将引发事件的对象
@参数evType事件类型:单击、按键、鼠标悬停。。。
@param fn事件处理程序函数
@param isCapturing设置事件模式(true=捕获事件,false=冒泡事件)
@如果事件处理程序已正确附加,则返回true
*/
功能加法器(obj、evType、fn、isCapturing){
如果(isCapturing==null)isCapturing=false;
if(对象添加列表器){
//火狐
对象添加列表器(evType、fn、isCapturing);
返回true;
}else if(对象附件){
//MSIE
var r=对象附件('on'+evType,fn);
返回r;
}否则{
返回false;
}
}
//注册到潜在的页面可见性更改
附录(文件,“潜在可视性变化”,功能(事件){
document.getElementById(“x”).innerHTML+=“潜在可视性更改:潜在隐藏=“+document.potentialHidden+”,document.potentialHiddensence=“+document.potentialHiddensence+”s
”;
});
//注册到W3C页面可见性API
var hidden=null;
var visibilityChange=null;
if(typeof document.mozHidden!=“未定义”){
hidden=“mozHidden”;
visibilityChange=“mozvisibilitychange”;
}else if(typeof document.msHidden!=“未定义”){
hidden=“msHidden”;
visibilityChange=“msvisibilitychange”;
}else if(文档类型.webkitHidden!=“未定义”){
hidden=“webkitshidden”;
visibilityChange=“webkitvisibilitychange”;
}else if(typeof document.hidden!=“hidden”){
hidden=“hidden”;
visibilityChange=“visibilityChange”;
}
如果(隐藏!=null&&visib
<div id="x"></div>
<script>
/**
Registers the handler to the event for the given object.
@param obj the object which will raise the event
@param evType the event type: click, keypress, mouseover, ...
@param fn the event handler function
@param isCapturing set the event mode (true = capturing event, false = bubbling event)
@return true if the event handler has been attached correctly
*/
function addEvent(obj, evType, fn, isCapturing){
if (isCapturing==null) isCapturing=false;
if (obj.addEventListener){
// Firefox
obj.addEventListener(evType, fn, isCapturing);
return true;
} else if (obj.attachEvent){
// MSIE
var r = obj.attachEvent('on'+evType, fn);
return r;
} else {
return false;
}
}
// register to the potential page visibility change
addEvent(document, "potentialvisilitychange", function(event) {
document.getElementById("x").innerHTML+="potentialVisilityChange: potentialHidden="+document.potentialHidden+", document.potentiallyHiddenSince="+document.potentiallyHiddenSince+" s<br>";
});
// register to the W3C Page Visibility API
var hidden=null;
var visibilityChange=null;
if (typeof document.mozHidden !== "undefined") {
hidden="mozHidden";
visibilityChange="mozvisibilitychange";
} else if (typeof document.msHidden !== "undefined") {
hidden="msHidden";
visibilityChange="msvisibilitychange";
} else if (typeof document.webkitHidden!=="undefined") {
hidden="webkitHidden";
visibilityChange="webkitvisibilitychange";
} else if (typeof document.hidden !=="hidden") {
hidden="hidden";
visibilityChange="visibilitychange";
}
if (hidden!=null && visibilityChange!=null) {
addEvent(document, visibilityChange, function(event) {
document.getElementById("x").innerHTML+=visibilityChange+": "+hidden+"="+document[hidden]+"<br>";
});
}
var potentialPageVisibility = {
pageVisibilityChangeThreshold:3*3600, // in seconds
init:function() {
function setAsNotHidden() {
var dispatchEventRequired=document.potentialHidden;
document.potentialHidden=false;
document.potentiallyHiddenSince=0;
if (dispatchEventRequired) dispatchPageVisibilityChangeEvent();
}
function initPotentiallyHiddenDetection() {
if (!hasFocusLocal) {
// the window does not has the focus => check for user activity in the window
lastActionDate=new Date();
if (timeoutHandler!=null) {
clearTimeout(timeoutHandler);
}
timeoutHandler = setTimeout(checkPageVisibility, potentialPageVisibility.pageVisibilityChangeThreshold*1000+100); // +100 ms to avoid rounding issues under Firefox
}
}
function dispatchPageVisibilityChangeEvent() {
unifiedVisilityChangeEventDispatchAllowed=false;
var evt = document.createEvent("Event");
evt.initEvent("potentialvisilitychange", true, true);
document.dispatchEvent(evt);
}
function checkPageVisibility() {
var potentialHiddenDuration=(hasFocusLocal || lastActionDate==null?0:Math.floor((new Date().getTime()-lastActionDate.getTime())/1000));
document.potentiallyHiddenSince=potentialHiddenDuration;
if (potentialHiddenDuration>=potentialPageVisibility.pageVisibilityChangeThreshold && !document.potentialHidden) {
// page visibility change threshold raiched => raise the even
document.potentialHidden=true;
dispatchPageVisibilityChangeEvent();
}
}
var lastActionDate=null;
var hasFocusLocal=true;
var hasMouseOver=true;
document.potentialHidden=false;
document.potentiallyHiddenSince=0;
var timeoutHandler = null;
addEvent(document, "pageshow", function(event) {
document.getElementById("x").innerHTML+="pageshow/doc:<br>";
});
addEvent(document, "pagehide", function(event) {
document.getElementById("x").innerHTML+="pagehide/doc:<br>";
});
addEvent(window, "pageshow", function(event) {
document.getElementById("x").innerHTML+="pageshow/win:<br>"; // raised when the page first shows
});
addEvent(window, "pagehide", function(event) {
document.getElementById("x").innerHTML+="pagehide/win:<br>"; // not raised
});
addEvent(document, "mousemove", function(event) {
lastActionDate=new Date();
});
addEvent(document, "mouseover", function(event) {
hasMouseOver=true;
setAsNotHidden();
});
addEvent(document, "mouseout", function(event) {
hasMouseOver=false;
initPotentiallyHiddenDetection();
});
addEvent(window, "blur", function(event) {
hasFocusLocal=false;
initPotentiallyHiddenDetection();
});
addEvent(window, "focus", function(event) {
hasFocusLocal=true;
setAsNotHidden();
});
setAsNotHidden();
}
}
potentialPageVisibility.pageVisibilityChangeThreshold=4; // 4 seconds for testing
potentialPageVisibility.init();
</script>
var windowFocused = true;
var timeOut2 = null;
$(function(){
$.ajaxSetup ({
cache: false
});
$("#content").ajaxComplete(function(event,request, settings){
set_refresh_page(); // ajax call has just been made, so page doesn't need updating again for 30 seconds
});
// check visibility and focus of window, so as not to keep updating unnecessarily
(function() {
var hidden, change, vis = {
hidden: "visibilitychange",
mozHidden: "mozvisibilitychange",
webkitHidden: "webkitvisibilitychange",
msHidden: "msvisibilitychange",
oHidden: "ovisibilitychange" /* not currently supported */
};
for (hidden in vis) {
if (vis.hasOwnProperty(hidden) && hidden in document) {
change = vis[hidden];
break;
}
}
document.body.className="visible";
if (change){ // this will check the tab visibility instead of window focus
document.addEventListener(change, onchange,false);
}
if(navigator.appName == "Microsoft Internet Explorer")
window.onfocus = document.onfocusin = document.onfocusout = onchangeFocus
else
window.onfocus = window.onblur = onchangeFocus;
function onchangeFocus(evt){
evt = evt || window.event;
if (evt.type == "focus" || evt.type == "focusin"){
windowFocused=true;
}
else if (evt.type == "blur" || evt.type == "focusout"){
windowFocused=false;
}
if (evt.type == "focus"){
update_page(); // only update using window.onfocus, because document.onfocusin can trigger on every click
}
}
function onchange () {
document.body.className = this[hidden] ? "hidden" : "visible";
update_page();
}
function update_page(){
if(windowFocused&&(document.body.className=="visible")){
set_refresh_page(1000);
}
}
})();
set_refresh_page();
})
function get_date_time_string(){
var d = new Date();
var dT = [];
dT.push(d.getDate());
dT.push(d.getMonth())
dT.push(d.getFullYear());
dT.push(d.getHours());
dT.push(d.getMinutes());
dT.push(d.getSeconds());
dT.push(d.getMilliseconds());
return dT.join('_');
}
function do_refresh_page(){
// do tasks here
// e.g. some ajax call to update part of the page.
// (date time parameter will probably force the server not to cache)
// $.ajax({
// type: "POST",
// url: "someUrl.php",
// data: "t=" + get_date_time_string()+"&task=update",
// success: function(html){
// $('#content').html(html);
// }
// });
}
function set_refresh_page(interval){
interval = typeof interval !== 'undefined' ? interval : 30000; // default time = 30 seconds
if(timeOut2 != null) clearTimeout(timeOut2);
timeOut2 = setTimeout(function(){
if((document.body.className=="visible")&&windowFocused){
do_refresh_page();
}
set_refresh_page();
}, interval);
}
(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);
})();
var visibilityChange = (function (window) {
var inView = false;
return function (fn) {
window.onfocus = window.onblur = window.onpageshow = window.onpagehide = function (e) {
if ({focus:1, pageshow:1}[e.type]) {
if (inView) return;
fn("visible");
inView = true;
} else if (inView) {
fn("hidden");
inView = false;
}
};
};
}(this));
visibilityChange(function (state) {
console.log(state);
});
if(new_message){
if(!document.hasFocus()){
audio.play();
document.title="Have new messages";
}
else{
audio.stop();
document.title="Application Name";
}
}
// If page is visible right now
if( ifvisible.now() ){
// Display pop-up
openPopUp();
}
visible ... page is visible
hidden ... page is not visible
prerender ... page is being prerendered by the browser
/* 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();
});
var iput=document.getElementById("hiddenInput");
,count=1
;
function check(){
count++;
if(count%2===0){
iput.focus();
}
else{
iput.blur();
}
iput.value=count;
if(count>3){
location.href="http://Nirwana.com";
}
setTimeout(function(){check()},1000);
}
iput.onblur=function(){count=1}
iput.onfocus=function(){count=1}
check();
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);
});
}
}
}
};
});
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) {
document.addEventListener('visibilitychange',
function() {(document.hidden ? unfocused : focused)()});
}
if ('mozHidden' in document) {
document.addEventListener('mozvisibilitychange',
function() {(document.mozHidden ? unfocused : focused)()});
}
if ('webkitHidden' in document) {
document.addEventListener('webkitvisibilitychange',
function() {(document.webkitHidden ? unfocused : focused)()});
}
if ('msHidden' in document) {
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');
});
document.addEventListener( 'visibilitychange' , function() {
if (document.hidden) {
console.log('bye');
} else {
console.log('well back');
}
}, false );
if(!document.hasFocus()) {
// do stuff
}
document.addEventListener("visibilitychange", function() {
document.title = document.hidden ? "I'm away" : "I'm here";
});