检测浏览器选项卡是否有焦点



是否有一种可靠的跨浏览器方法来检测选项卡是否有焦点?

这个场景是,我们有一个应用程序定期对股票价格进行投票,如果页面没有焦点,我们可以停止投票并为每个人节省交通噪音,特别是当人们喜欢打开不同投资组合的几个选项卡时。

window.onblurwindow.onfocus是一个选项吗?

是的,window.onfocuswindow.onblur应该适用于您的场景。

居然没人提到document.hasFocus

if (document.hasFocus()) console.log('Tab is active')

MDN更多信息。

重要编辑: 这个答案已经过时了。在编写它之后,引入了可见性API (mdn、示例、规范)。这是解决这个问题的更好的办法。


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

AFAIK, focusblur都支持在…一切。(见http://www.quirksmode.org/dom/events/index.html)

在搜索这个问题时,我发现应该使用页面可见性API的建议。根据Can I Use: http://caniuse.com/#feat=pagevisibility.

,大多数现代浏览器都支持此API。

下面是一个工作示例(来自这个代码片段):

$(document).ready(function() {
  var hidden, visibilityState, visibilityChange;
  if (typeof document.hidden !== "undefined") {
    hidden = "hidden", visibilityChange = "visibilitychange", visibilityState = "visibilityState";
  } else if (typeof document.msHidden !== "undefined") {
    hidden = "msHidden", visibilityChange = "msvisibilitychange", visibilityState = "msVisibilityState";
  }
  var document_hidden = document[hidden];
  document.addEventListener(visibilityChange, function() {
    if(document_hidden != document[hidden]) {
      if(document[hidden]) {
        // Document hidden
      } else {
        // Document shown
      }
      document_hidden = document[hidden];
    }
  });
});

Update:上面的例子曾经有Gecko和WebKit浏览器的前缀属性,但我删除了这个实现,因为这些浏览器已经提供了一段时间没有前缀的页面可见性API了。为了与IE10兼容,我保留了微软特有的前缀

发表这个答案,因为我发现一个错误在接受的答案。

这个bug是当你在焦点窗口上打开开发者控制台并点击它的任何地方时,开发者控制台现在有焦点了,此时窗口。onfocus窗口。onblur没有任何效果

这是我的解,

document.addEventListener("visibilitychange", function() {
    if (document.visibilityState === 'visible') {
        console.log('has focus');
    } else {
        console.log('lost focus');
    }
});

阅读更多https://developer.mozilla.org/en-US/docs/Web/API/Document/visibilitychange_event

我会这样做(参考http://www.w3.org/TR/page-visibility/):

    window.onload = function() {
        // check the visiblility of the page
        var hidden, visibilityState, visibilityChange;
        if (typeof document.hidden !== "undefined") {
            hidden = "hidden", visibilityChange = "visibilitychange", visibilityState = "visibilityState";
        }
        else if (typeof document.mozHidden !== "undefined") {
            hidden = "mozHidden", visibilityChange = "mozvisibilitychange", visibilityState = "mozVisibilityState";
        }
        else if (typeof document.msHidden !== "undefined") {
            hidden = "msHidden", visibilityChange = "msvisibilitychange", visibilityState = "msVisibilityState";
        }
        else if (typeof document.webkitHidden !== "undefined") {
            hidden = "webkitHidden", visibilityChange = "webkitvisibilitychange", visibilityState = "webkitVisibilityState";
        }

        if (typeof document.addEventListener === "undefined" || typeof hidden === "undefined") {
            // not supported
        }
        else {
            document.addEventListener(visibilityChange, function() {
                console.log("hidden: " + document[hidden]);
                console.log(document[visibilityState]);
                switch (document[visibilityState]) {
                case "visible":
                    // visible
                    break;
                case "hidden":
                    // hidden
                    break;
                }
            }, false);
        }
        if (document[visibilityState] === "visible") {
            // visible
        }
    };  

跨浏览器jQuery解决方案! 原始文件可在GitHub获取

有趣,易于使用!

以下插件将通过各种版本的IE, Chrome, Firefox, Safari等的标准测试。并相应地建立已声明的方法。它还处理以下问题:

  • onblur | .blur/聚焦事件|。focus "duplicate"呼叫
  • 窗口失去焦点通过选择替代应用程序,如word
    • 这往往是不受欢迎的,因为,如果你有一个银行页面打开,它的onblur事件告诉它屏蔽页面,然后如果你打开计算器,你不能再看到页面了!
  • 页面加载时不触发
  • 的用法很简单:向下滚动到'运行代码段'

    $.winFocus(function(event, isVisible) {
        console.log("Combott", 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("Combott", 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("Blurtt", event);
        },
        focus: function(event) {
            console.log("Focustt", event);
        }
    });
    //  OR First method becoms a "blur", second method becoms "focus"!
    $.winFocus(function(event) {
        console.log("Blurtt", event);
    },
    function(event) {
        console.log("Focustt", event);
    });
    

    /*    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>

    这是10岁了。这是一个更新的版本:切换选项卡时暂停/恢复CSS动画

    基本使用mozilla Javascript https://developer.mozilla.org/en-US/docs/Web/API/Window/focus_event

     function pause() {
     //Do something
     }
     function play() {
     //Do something
     }
     window.addEventListener('blur', pause);
     window.addEventListener('focus', play);
    

    一个React hook版本,基于上面所有这些好的绅士的回答:

    import { useEffect, useState } from 'react';
    const EVENT_NAME = 'visibilitychange';
    export const useTabFocus = () => {
        const [hasFocus, setHasFocus] = useState(isVisible());
        useEffect(() => {
            const onVisibilityChange = () => {
                setHasFocus(isVisible());
            };
            document.addEventListener(EVENT_NAME, onVisibilityChange);
            return () => {
                document.removeEventListener(EVENT_NAME, onVisibilityChange);
            };
        }, []);
        return hasFocus;
    };
    const isVisible = () => document.visibilityState === 'visible';
    

    相关内容

    • 没有找到相关文章

    最新更新