브라우저 창이 현재 활성화되어 있지 않은지를 감지하는 방법이 있습니까? 것이 좋습니다. JavaScript를 사용하여이를 수행 할

정기적으로 활동하는 JavaScript가 있습니다. 사용자가 사이트를보고 있지 않은 경우 (예 : 창 또는 탭에 포커스가없는 경우) 실행하지 않는 것이 좋습니다.

JavaScript를 사용하여이를 수행 할 수있는 방법이 있습니까?

내 기준점 : 사용중인 창이 활성화되어 있지 않으면 Gmail 채팅에서 소리가납니다.



답변

원래이 답변을 작성한 이후 W3C 덕분에 새로운 사양이 권장 상태에 도달했습니다 . 페이지 가시성 API (에 MDN는 ) 이제 페이지가 사용자에게 숨겨져 때 우리가보다 정확하게 감지 할 수 있습니다.

document.addEventListener("visibilitychange", onchange);

현재 브라우저 지원 :

  • 크롬 13+
  • Internet Explorer 10 이상
  • Firefox 10 이상
  • Opera 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있다 IE 9에 필요한 낮출 모든 다른 사람을 활용하면서, onfocus그리고 onblur아이폰 OS, 용도를 제외 onpageshow하고 onpagehide.


답변

jQuery를 사용하면됩니다.

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

또는 적어도 그것은 나를 위해 일했습니다.


답변

사용자가 HTML 페이지를 볼 수 있는지 판별하는 데 사용되는 3 가지 일반적인 방법이 있지만 그 중 어느 것도 완벽하게 작동하지는 않습니다.

  • W3C 페이지 가시성 API는 이 작업을 수행 할 예정이다 (파이어 폭스 10, MSIE (10), 크롬 13부터 지원). 그러나이 API는 브라우저 탭이 완전히 재정의 된 경우 (예 : 사용자가 한 탭에서 다른 탭으로 변경하는 경우)에만 이벤트를 발생시킵니다. 가시성을 100 % 정확도로 확인할 수없는 경우 API는 이벤트를 발생시키지 않습니다 (예 : 다른 애플리케이션으로 전환하기 위해 Alt + Tab).

  • 사용 초점 / 흐림 기반의 방법은 당신에게 거짓 양성을 많이 제공합니다. 예를 들어, 사용자가 브라우저 창 위에 작은 창을 표시하면 브라우저 창에서 포커스를 잃지 onblur만 ( 상승) 사용자는 여전히 볼 수 있으므로 여전히 새로 고쳐야합니다. http://javascript.info/tutorial/focus 도 참조하십시오

  • 사용자 활동 (마우스 이동, 클릭, 키 입력) 에 의존 하면 오 탐지가 많이 발생합니다. 위와 동일한 경우 또는 사용자가 비디오를보고 있다고 생각하십시오.

위에서 설명한 불완전한 동작을 개선하기 위해 W3C Visibility API의 3 가지 방법을 조합 한 다음 오 탐지율을 줄이기 위해 포커스 / 블러 및 사용자 활동 방법을 사용합니다. 이를 통해 다음과 같은 이벤트를 관리 할 수 ​​있습니다.

  • 브라우저 탭을 다른 것으로 변경 (W3C 페이지 가시성 API 덕분에 100 % 정확도)
  • Alt + Tab으로 인해 다른 창에 의해 잠재적으로 숨겨져있는 페이지
  • 잠재적으로 HTML 페이지에 초점을 맞추지 않은 사용자주의 (확률 = 100 % 정확하지 않음)

작동 방식 : 문서가 포커스를 잃을 때, 윈도우의 표시 여부를 결정하기 위해 문서의 사용자 활동 (예 : 마우스 이동)이 모니터링됩니다. 페이지 가시성 확률은 페이지에서 마지막 사용자 활동 시간에 반비례합니다. 사용자가 문서에서 오랫동안 활동을하지 않으면 페이지가 보이지 않을 가능성이 높습니다. 아래 코드는 W3C 페이지 가시성 API를 모방합니다. 동일한 방식으로 작동하지만 오 탐지율이 작습니다. 멀티 브라우저 (Firefox 5, Firefox 10, MSIE 9, MSIE 7, Safari 5, Chrome 9에서 테스트) 이점이 있습니다.

    <div id = "x"> </ div>

    <스크립트>
    / **
    주어진 객체의 이벤트에 핸들러를 등록합니다.
    @param obj 이벤트를 발생시킬 객체
    @param ev 이벤트 유형을 입력하십시오 : click, keypress, mouseover, ...
    @param fn 이벤트 핸들러 함수
    @param isCapturing 이벤트 모드 설정 (true = 캡처 이벤트, false = 버블 링 이벤트)
    이벤트 핸들러가 올바르게 첨부 된 경우 @return
    * /
    addEvent 함수 (obj, evType, fn, isCapturing) {
      (isCapturing == null) 인 경우 isCapturing = false;
      if (obj.addEventListener) {
        // Firefox
        obj.addEventListener (evType, fn, isCapturing);
        true를 반환;
      } 그렇지 않으면 (obj.attachEvent) {
        // MSIE
        var r = obj.attachEvent ( 'on'+ evType, fn);
        리턴 r;
      } else {
        거짓을 반환;
      }
    }

    // 잠재적 페이지 가시성 변경에 등록
    addEvent (문서, "잠재적 가시성 변경", 함수 (이벤트) {
      document.getElementById ( "x"). innerHTML + = "potentialVisilityChange : potentialHidden ="+ document.potentialHidden + ", document.potentiallyHiddenSince ="+ document.potentiallyHiddenSince + "s <br>";
    });

    // W3C 페이지 가시성 API에 등록
    var hidden = 널;
    var visibleChange = null;
    if (typeof document.mozHidden! == "undefined") {
      hidden = "mozHidden";
      visibleChange = "mozvisibilitychange";
    } else if (typeof document.msHidden! == "undefined") {
      hidden = "msHidden";
      visibleChange = "msvisibilitychange";
    } else if (typeof document.webkitHidden! == "undefined") {
      hidden = "webkitHidden";
      visibleChange = "webkitvisibilitychange";
    } else if (typeof document.hidden! == "hidden") {
      hidden = "숨겨진";
      visibleChange = "visibilitychange";
    }
    if (hidden! = null && visibleChange! = null) {
      addEvent (문서, 가시성 변경, 함수 (이벤트) {
        document.getElementById ( "x"). innerHTML + = visibilityChange + ":"+ hidden + "="+ document [hidden] + "<br>";
      });
    }


    var potentialPageVisibility = {
      pageVisibilityChangeThreshold : 3 * 3600, // 초 단위
      init : 함수 () {
        함수 setAsNotHidden () {
          var dispatchEventRequired = document.potentialHidden;
          document.potentialHidden = false;
          document.potentiallyHiddenSince = 0;
          if (dispatchEventRequired) dispatchPageVisibilityChangeEvent ();
        }

        함수 initPotentiallyHiddenDetection () {
          if (! hasFocusLocal) {
            // 창에 포커스가 없습니다 => 창에서 사용자 활동을 확인하십시오.
            lastActionDate = 새 날짜 ();
            if (timeoutHandler! = null) {
              clearTimeout (timeoutHandler);
            }
            timeoutHandler = setTimeout (checkPageVisibility, potentialPageVisibility.pageVisibilityChangeThreshold * 1000 + 100); // Firefox에서 반올림 문제를 피하기 위해 + 100ms
          }
        }

        dispatchPageVisibilityChangeEvent () {함수
          unifiedVisilityChangeEventDispatchAllowed = 거짓;
          var evt = document.createEvent ( "Event");
          evt.initEvent ( "potentialvisilitychange", true, true);
          document.dispatchEvent (evt);
        }

        function checkPageVisibility () {
          var potentialHiddenDuration = (hasFocusLocal || lastActionDate == null? 0 : Math.floor ((새 날짜 () .getTime ()-lastActionDate.getTime ()) / 1000));
                                        document.potentiallyHiddenSince = potentialHiddenDuration;
          if (potentialHiddenDuration> = potentialPageVisibility.pageVisibilityChangeThreshold &&! document.potentialHidden) {
            // 페이지 가시성 변경 임계 값 급증 => 짝수 올리기
            document.potentialHidden = true;
            dispatchPageVisibilityChangeEvent ();
          }
        }

        var lastActionDate = 널;
        var hasFocusLocal = true;
        var hasMouseOver = true;
        document.potentialHidden = false;
        document.potentiallyHiddenSince = 0;
        var timeoutHandler = null;

        addEvent (문서, "pageshow", 함수 (event) {
          document.getElementById ( "x"). innerHTML + = "pageshow / doc : <br>";
        });
        addEvent (문서, "pagehide", 함수 (event) {
          document.getElementById ( "x"). innerHTML + = "pagehide / doc : <br>";
        });
        addEvent (창, "pageshow", 함수 (event) {
          document.getElementById ( "x"). innerHTML + = "pageshow / win : <br>"; // 페이지가 처음 표시 될 때 발생합니다.
        });
        addEvent (창, "pagehide", 함수 (event) {
          document.getElementById ( "x"). innerHTML + = "pagehide / win : <br>"; // 제기되지 않음
        });
        addEvent (문서, "mousemove", 함수 (event) {
          lastActionDate = 새 날짜 ();
        });
        addEvent (문서, "마우스 오버", 함수 (이벤트) {
          hasMouseOver = true;
          setAsNotHidden ();
        });
        addEvent (문서, "마우스 아웃", 함수 (이벤트) {
          hasMouseOver = 거짓;
          initPotentiallyHiddenDetection ();
        });
        addEvent (창, "흐림", 함수 (이벤트) {
          hasFocusLocal = false;
          initPotentiallyHiddenDetection ();
        });
        addEvent (창, "포커스", 함수 (이벤트) {
          hasFocusLocal = true;
          setAsNotHidden ();
        });
        setAsNotHidden ();
      }
    }

    potentialPageVisibility.pageVisibilityChangeThreshold = 4; // 테스트를위한 4 초
    potentialPageVisibility.init ();
    </ script>

현재 오 탐지없이 작동하는 크로스 브라우저 솔루션이 없으므로 웹 사이트에서 주기적 활동을 비활성화하는 것에 대해 두 번 생각하는 것이 좋습니다.


답변

GitHub에는 깔끔한 라이브러리가 있습니다 :

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

예:

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

내가 가지고있는 모든 브라우저에서 버전 1.0.1을 테스트했으며 다음과 함께 작동하는지 확인할 수 있습니다.

  • IE9, IE10
  • FF 26.0
  • 크롬 34.0

… 그리고 아마도 모든 최신 버전 일 것입니다.

다음과 완벽하게 작동하지 않습니다.

  • IE8-항상 탭 / 창이 활성화되어 있음을 나타냅니다 ( .now()항상 true나에게 반환 ).

답변

사용 : 페이지 가시성 API

document.addEventListener( 'visibilitychange' , function() {
    if (document.hidden) {
        console.log('bye');
    } else {
        console.log('well back');
    }
}, false );

사용해도 되나요 ? http://caniuse.com/#feat=pagevisibility


답변

내 앱에 대한 혜성 채팅을 만들고 다른 사용자로부터 메시지를 받으면 다음을 사용합니다.

if(new_message){
    if(!document.hasFocus()){
        audio.play();
        document.title="Have new messages";
    }
    else{
        audio.stop();
        document.title="Application Name";
    }
}


답변

커뮤니티 위키 답변을 사용하기 시작했지만 Chrome에서 Alt-Tab 이벤트를 감지하지 못한다는 것을 깨달았습니다. 사용 가능한 첫 번째 이벤트 소스를 사용하기 때문이며,이 경우 페이지 가시성 API이므로 Chrome에서는 자동 태핑을 추적하지 않는 것 같습니다.

나는 추적 유지하기 위해 스크립트를 조금 수정하기로 결정 모든 페이지 포커스가 변경 가능한 이벤트를. 드롭 할 수있는 기능은 다음과 같습니다.

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');
});

이 버전을 청취 모든 다른 가시성 이벤트 및 화재 그들 중 하나가 변화를 야기하는 경우 콜백. focusedunfocused핸들러는 다수의 API를 같은 가시성 변경을 잡을 경우 콜백이 여러 번 호출하지 않아야합니다.