브라우저 탭에 포커스가 있는지 감지


149

탭에 포커스가 있음을 감지하는 신뢰할 수있는 브라우저 간 방법이 있습니까?

시나리오는 주가에 대해 정기적으로 설문 조사를하는 애플리케이션이 있고, 페이지에 초점이 맞지 않으면 설문 조사를 중단하고 모든 사람들이 교통 소음을 줄일 수 있습니다. 특히 사람들이 다른 포트폴리오를 가진 여러 탭을 여는 팬이라면 더욱 그렇습니다.

인가 window.onblurwindow.onfocus이에 대한 옵션?


답변:


127

예, window.onfocus그리고 window.onblur당신의 시나리오에 대해 작동합니다 :

http://www.thefutureoftheweb.com/blog/detect-browser-window-focus


3
이것의 onfocusin / onfocusout 측면과 사용자에게 일시 중지되었음을 알려주는 메모는 실제로 좋은 메모입니다. 감사.
Fenton

7
이 방법으로 페이지를로드 할 때 페이지를 활성화 또는 비활성화하는 것을 구분할 수 없습니다.
pimvdb

@SteveFenton-크로스 브라우저입니다. onfocus언급 한 이벤트가 IE 전용입니다. 왜 이것이 좋은 메모인지 고려할 수 없습니다 ..
vsync

1
@vsync-링크 된 기사를 읽으면 'onfocusin'과 'onfocus'를 모두 사용 하는 것을 볼 수 있습니다.
Fenton

둘 사이의 차이점을 적어도 언급 할 수 있습니까?
Lenar Hoyt

53

중요 편집 : 이 답변은 구식입니다. 그것을 작성한 이후 Visibility API ( mdn , example , spec )가 도입되었습니다. 이 문제를 해결하는 더 좋은 방법입니다.


var focused = true;

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

AFAIK, focus그리고 blur모든에 ... 모두 지원됩니다. ( http://www.quirksmode.org/dom/events/index.html 참조 )


2
이 모든 솔루션을 사용하면 자바 스크립트가 완전히로드되기 전에 사용자가 탭을 변경 할 위험이 있으므로 초점을 맞출 잘못된 값이 할당됩니다. 그 주위에 좋은 방법이 있는지 확실하지 않습니다.
JayD3e

업데이트 링크는 내가 찾던 것입니다. 추가해 주셔서 감사합니다!
webLacky3rdClass

문제는 구체적으로 페이지에 초점이 있는지 여부를 감지하는 것인데, 이는 페이지가 보이는지 감지하는 것과 다릅니다. 여러 페이지를 동시에 (다른 창에서) 볼 수 있지만 한 페이지 만 포커스를 가질 수 있습니다. 필요에 맞는 기술을 사용하되 그 차이를 알고 있어야합니다.
jaredjacobs

1
더 큰 응용 프로그램에서 다른 이벤트 리스너를 재정의 할 위험이 있으므로 위험한 솔루션입니다. 대신 다음 답변을 따라야합니다. stackoverflow.com/a/21935031/549503
mmmeff

51

이 문제를 검색하는 동안 Page Visibility API를 사용해야한다는 권장 사항을 찾았습니다 . 대부분의 최신 브라우저는 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];
    }
  });
});

업데이트 : 위의 예제는 Gecko 및 WebKit 브라우저의 접두사 속성을 사용했지만 이전에는 접두사가없는 Page Visibility API를 제공했기 때문에 해당 구현을 제거했습니다. IE10과 호환되도록 Microsoft 전용 접두사를 유지했습니다.


공급 업체 접두사가 이것에서 나올 때, 아마도 전환 할 것입니다!
Fenton 2019

공식 W3C 권장 사항 (2013 년 10 월 29 일자)이 있기 때문에이 문제에 대한 실제 문제는 공급 업체 접두사가 아닙니다. 경우에 따라 문제는 페이지 가시성 API가 IE10 이상에서 지원된다는 것입니다. IE9를 지원해야한다면 다른 접근법을 찾아야합니다…
Ilija

이것은 모든 최신 브라우저에서 올바른 방법입니다. +1
Ajedi32

이러한 공급 업체 접두사도 필요합니까? MDN과 CanIUse에 따르면 버전 32부터 Chrome 또는 17에서 Firefox에서는 필요하지 않았으며 IE에서는 필요하지 않았습니다.
Ajedi32

@ Ajedi32 감사합니다. 나는 여전히 관련성이 있는지, 그리고 지금 무엇을 남길 수 있는지 확인하기 위해 몇 가지 테스트와 파기를해야합니다.
Ilija

37

아무도 언급하지 않은 것을보고 놀랐습니다. document.hasFocus

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

MDN에 자세한 정보가 있습니다.


나를 위해 작동합니다 (Chrome 및 Firefox에서 테스트). 허용 된 답변 (onfocus / onblur)이 작동 하지 않습니다
harmv

정답은 다시 맨 아래에 있습니다. StackOverflow로가는 길!
10 월 11

정말로 이것이 완벽한 답이 아닌가? 누구나 단점이 있습니까?
gaspar

2
이것의 유일한 단점은 탭이 iframe 내에서 초점을 맞추고 있는지 확인하려고하면 부모 페이지에 여전히 초점이 맞지 않을 때 iframe 이로 드 된 경우 실패한다는 것입니다. 이를 다루려면 페이지 가시성 API를 사용해야합니다.
이반

29

네, 당신을 위해 일해야합니다. 당신은 저에게이 기술을 이용하는 링크를 발견했습니다. 재미있는 읽을 거리


2
+1-그것은 매우 영리한 속임수입니다. 많은 사람들을 속이는 것을 상상할 수 있습니다.
Fenton

2
얼마나 독창적이고 악의적 인 공격입니까? 재미있게 읽어 주셔서 감사합니다.
Voo

4

나는 이것을 이렇게 할 것이다 (참조 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
        }

    };  

이 답변이 @Ilija가 제공 한 답변과 어떻게 다른지 설명 할 수 있습니까? 차이가있을 수 있지만 미묘합니다. 그래서 그것이 무엇인지, 왜 다른지 설명해야합니다.
Fenton

2

크로스 브라우저 jQuery 솔루션! GitHub 에서 제공되는 Raw

재미 있고 사용하기 쉬운!

다음 플러그인은 다양한 버전의 IE, Chrome, Firefox, Safari 등의 표준 테스트를 거쳐 선언 된 메소드를 설정합니다. 또한 다음과 같은 문제를 다룹니다.

  • onblur | .blur / onfocus | .focus " 중복 "호출
  • 단어와 같은 대체 앱을 선택하여 초점을 잃는 창
    • 이것은 은행 페이지가 열려 있고 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);
});

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


플러그인에 대해 코드를 최소화하지 않아야합니다.
Patrick Desjardins

@PatrickDesjardins 예. 이번 주말에 다른 것들과 함께 계획하십시오. 나는? 내가 가진 많은 것들에 대해 요점을 밝히십시오. github의 Jdmckinstry. 요점에 추가 될 때 이와 같은 이전 답변에 대한 링크를 추가합니다.
SpYk3HH

"워드"또는 "계산기"와 같은 다른 앱으로 전환 할 때 페이지의 포커스를 잃고 싶다면 어떻게해야합니까?
Benas

@Benas 잘못되었을 수도 있지만 jQuery(window).blur/focus, 이것이 매우 기본적 인 기본 기능이라고 생각합니다. 많은 사람들이 원하지 않았기 때문에이 플러그인을 만든 이유 중 하나입니다. 이 플러그인은 jQuery가 제공하지 않는 기능을 제공하기위한 것입니다.
SpYk3HH
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.