检查窗口是否拥有焦点

43

我需要检查用户是否正在使用Windows,目前我正在执行以下操作:

var isonfocus=true;  
window.onblur = function(){  
  isonfocus=false;  
}  
window.onfocus = function(){  
  isonfocus=true;  
}

每当我需要检查用户是否关注Windows时,我只需执行if(isonfocus==true)

问题:如果用户在页面加载前失去了焦点,则即使我执行if(isonfocus==true),它也将返回true,即使窗口没有焦点,并将变量定义为false var isonfocus=false; 也会反转。

有人能帮帮我吗?谢谢。

更新
想象一个付费点击(PTC)网站,当您单击广告以查看时,大多数网站都会验证用户是否实际上正在查看广告商网站(具有焦点)或否(失去焦点)。
这类似于我所需要的,我需要一种方法来验证用户是否拥有包含iframe的窗口的焦点。
而要获得焦点,用户可以单击iframe、文档或选项卡。
请注意,这需要在所有主要浏览器上工作。


1
正确答案应该是:https://dev59.com/d3NA5IYBdhLWcg3wL6sc - Jordan
7个回答

93
使用hasFocus方法:
if (document.hasFocus()) {
  // ...
}

如果您的页面上有iframe,它们需要单独检查:
function isFocused() {
  return document.hasFocus() || document.getElementById('iframe').contentWindow.document.hasFocus();
}

9
我需要检查窗口是否具有焦点,而不是文档。 - user2536244
1
@user2536244,文档中指出:“布尔值表示文档或文档内的任何元素是否具有焦点” - 这也适用于窗口被聚焦的情况。 - James
如果窗口有iframe(点击iframe以获得焦点),似乎它无法正常工作。 - user2536244
我认为这是正确的,因为iframe应该像一个独立的窗口一样运行。 - James
1
使用Chrome浏览器时,出现了两个错误:阻止了一个源为“xxx”的框架访问一个源为“yyy”的框架。协议、域和端口必须匹配。 类型错误:无法调用未定义的“hasFocus”方法。 - user2536244
显示剩余3条评论

19

12
很不幸,这并不正确。除非页面完全被屏幕遮挡,例如窗口最小化、用户在同一窗口的其他选项卡中、或者显示器关闭,否则visibilityStatevisible。仅仅被其他窗口遮挡仍然被视为“可见”。 - Christopher Swasey
在我的情况下,这正是我所需要的。老实说,当我读到上面的问题时,我相信这就是正确答案,应该被标记为这样。使用JavaScript无法判断窗口是否被其他窗口遮盖。 - Ange Loron
如果您想知道浏览器是否是活动/焦点窗口,请参见我的答案。 - kuceb
看起来 document.hasFocus() 在 Windows 上可以工作,但是在 Android 上如果你切换到另一个应用程序时它就不起作用了——页面仍然认为它处于焦点状态。所以我不得不使用 document.visibilityState == "visible",在我的情况下两者都能很好地工作。你的情况可能会有所不同。 - Pavel

4
var has_focus = true;

function loading_time() {
    $(":focus").each(function() {
      if($(this).attr("id")=="iframeID") has_focus = true;
    });

    if(has_focus==true) alert('page has focus');
    else alert('page has not focus');

    setTimeout("loading_time()", 2000);
}

window.onblur = function(){  
    has_focus=false;  
}  
window.onfocus = function(){  
    has_focus=true;  
}

$(window).load(function(){
    setTimeout("loading_time()", 2000);
});

为了提高效率,您需要添加var has_focus = false;并让用户在页面上的某个位置点击。

1

0

跨浏览器jQuery解决方案!以下插件将通过您对IE、Chrome、Firefox、Safari等各个版本的标准测试,并相应地建立您声明的方法。它还处理了以下问题:

  • 定时器!呕呕呕!
  • onblur|.blur/onfocus|.focus“重复”调用
  • 窗口失去焦点,选择备选应用程序(如Word)
    • 这往往是不希望的,因为如果您打开了一个银行页面,它的onblur事件告诉它掩盖页面,那么如果您打开计算器,您将看不到页面了!
  • 不在页面加载时触发

使用非常简单:

$.winFocus(function(event, isVisible) {
    console.log("Combo\t\t", event, isVisible);
});

//  OR Pass False boolean, and it will not trigger on load,
//  Instead, it will first trigger on first blur of current tab_window
$.winFocus(function(event, isVisible) {
    console.log("Combo\t\t", event, isVisible);
}, false);

//  OR Establish an object having methods "blur" & "focus", and/or "blurFocus"
//  (yes, you can set all 3, tho blurFocus is the only one with an 'isVisible' param)
$.winFocus({
    blur: function(event) {
        console.log("Blur\t\t", event);
    },
    focus: function(event) {
        console.log("Focus\t\t", event);
    }
});

//  OR First method becoms a "blur", second method becoms "focus"!
$.winFocus(function(event) {
    console.log("Blur\t\t", event);
},
function(event) {
    console.log("Focus\t\t", event);
});

&改进的版本,适用于纯JavaScriptjQuery,请到此处查看!


/*    Begin Plugin    */
;;(function($){$.winFocus||($.extend({winFocus:function(){var a=!0,b=[];$(document).data("winFocus")||$(document).data("winFocus",$.winFocus.init());for(x in arguments)"object"==typeof arguments[x]?(arguments[x].blur&&$.winFocus.methods.blur.push(arguments[x].blur),arguments[x].focus&&$.winFocus.methods.focus.push(arguments[x].focus),arguments[x].blurFocus&&$.winFocus.methods.blurFocus.push(arguments[x].blurFocus),arguments[x].initRun&&(a=arguments[x].initRun)):"function"==typeof arguments[x]?b.push(arguments[x]):
"boolean"==typeof arguments[x]&&(a=arguments[x]);b&&(1==b.length?$.winFocus.methods.blurFocus.push(b[0]):($.winFocus.methods.blur.push(b[0]),$.winFocus.methods.focus.push(b[1])));if(a)$.winFocus.methods.onChange()}}),$.winFocus.init=function(){$.winFocus.props.hidden in document?document.addEventListener("visibilitychange",$.winFocus.methods.onChange):($.winFocus.props.hidden="mozHidden")in document?document.addEventListener("mozvisibilitychange",$.winFocus.methods.onChange):($.winFocus.props.hidden=
"webkitHidden")in document?document.addEventListener("webkitvisibilitychange",$.winFocus.methods.onChange):($.winFocus.props.hidden="msHidden")in document?document.addEventListener("msvisibilitychange",$.winFocus.methods.onChange):($.winFocus.props.hidden="onfocusin")in document?document.onfocusin=document.onfocusout=$.winFocus.methods.onChange:window.onpageshow=window.onpagehide=window.onfocus=window.onblur=$.winFocus.methods.onChange;return $.winFocus},$.winFocus.methods={blurFocus:[],blur:[],focus:[],
exeCB:function(a){$.winFocus.methods.blurFocus&&$.each($.winFocus.methods.blurFocus,function(b,c){this.apply($.winFocus,[a,!a.hidden])});a.hidden&&$.winFocus.methods.blur&&$.each($.winFocus.methods.blur,function(b,c){this.apply($.winFocus,[a])});!a.hidden&&$.winFocus.methods.focus&&$.each($.winFocus.methods.focus,function(b,c){this.apply($.winFocus,[a])})},onChange:function(a){var b={focus:!1,focusin:!1,pageshow:!1,blur:!0,focusout:!0,pagehide:!0};if(a=a||window.event)a.hidden=a.type in b?b[a.type]:
document[$.winFocus.props.hidden],$(window).data("visible",!a.hidden),$.winFocus.methods.exeCB(a);else try{$.winFocus.methods.onChange.call(document,new Event("visibilitychange"))}catch(c){}}},$.winFocus.props={hidden:"hidden"})})(jQuery);
/*    End Plugin      */

// Simple example
$(function() {
 $.winFocus(function(event, isVisible) {
  $('td tbody').empty();
  $.each(event, function(i) {
   $('td tbody').append(
    $('<tr />').append(
     $('<th />', { text: i }),
     $('<td />', { text: this.toString() })
    )
   )
  });
  if (isVisible) 
   $("#isVisible").stop().delay(100).fadeOut('fast', function(e) {
    $('body').addClass('visible');
    $(this).stop().text('TRUE').fadeIn('slow');
   });
  else {
   $('body').removeClass('visible');
   $("#isVisible").text('FALSE');
  }
 });
})
body { background: #AAF; }
table { width: 100%; }
table table { border-collapse: collapse; margin: 0 auto; width: auto; }
tbody > tr > th { text-align: right; }
td { width: 50%; }
th, td { padding: .1em .5em; }
td th, td td { border: 1px solid; }
.visible { background: #FFA; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h3>See Console for Event Object Returned</h3>
<table>
    <tr>
        <th><p>Is Visible?</p></th>
        <td><p id="isVisible">TRUE</p></td>
    </tr>
    <tr>
        <td colspan="2">
            <table>
                <thead>
                    <tr>
                        <th colspan="2">Event Data <span style="font-size: .8em;">{ See Console for More Details }</span></th>
                    </tr>
                </thead>
                <tbody></tbody>
            </table>
        </td>
    </tr>
</table>


它无法检测用户是否使用alt-tab切换了窗口。 - Ivan

0

如果您不关心Opera支持,您可以使用document.hasFocus()方法获得更好的结果。有关更多信息,请参见此处


1
我需要检查窗口是否具有焦点,而不是文档。 - user2536244
对于 Opera 浏览器,您应该编写一个 hasHasFocus 函数:function hasHasFocus() { return typeof document.hasFocus === 'function'; } 我只是觉得这个名称很有趣。 - Patrick Roberts

-6
如果用户的浏览器窗口处于焦点/活动状态,但刚刚点击了刷新按钮(或URL栏等),document.hasFocus()将告诉您该窗口不是活动的。
然而,您可以调用window.focus()并查看是否实际触发了focus事件。如果是,则浏览器仍然处于焦点/活动状态。
const windowHasFocus = function () {
  if (document.hasFocus()) return true
  let hasFocus = false

  window.addEventListener('focus', function () {
    hasFocus = true
  })
  window.focus()

  return hasFocus
}


1
调用 window.focus() 将发出请求将窗口置于前台。https://developer.mozilla.org/zh-CN/docs/Web/API/Window/focus - cameron.townsend

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接