Mam JavaScript, który okresowo wykonuje czynności. Gdy użytkownik nie patrzy na stronę (tzn. Okno lub karta nie ma fokusa), fajnie byłoby nie uruchamiać.
Czy można to zrobić za pomocą JavaScript?
Mój punkt odniesienia: Czat Gmaila odtwarza dźwięk, jeśli okno, którego używasz, nie jest aktywne.
javascript
browser
focus
window
Luke Francl
źródło
źródło
requestAnimationFrame
API lub skorzystaj z nowoczesnej funkcji zmniejszania częstotliwościsetTimeout
/,setInterval
gdy okno nie jest widoczne (na przykład 1 sekunda w Chrome).blur
/focus
w przeglądarkach, które go nie obsługują.Odpowiedzi:
Od czasu napisania tej odpowiedzi nowa specyfikacja osiągnęła status rekomendacji dzięki W3C. Page Widoczność API (na MDN ) teraz pozwala nam bardziej precyzyjnie wykryć, gdy strona jest ukryta dla użytkownika.
Bieżąca obsługa przeglądarki:
Poniższy kod wraca do mniej niezawodnej metody rozmycia / ostrości w niekompatybilnych przeglądarkach:
onfocusin
ionfocusout
są wymagane dla IE 9 i niższych , podczas gdy wszystkie inne korzystają zonfocus
ionblur
, z wyjątkiem iOS, który używaonpageshow
ionpagehide
.źródło
focusin
ifocusout
od iframe do górnego okna. W przypadku nowszych przeglądarek wystarczy obsłużyć zdarzeniafocus
iblur
nawindow
obiekcie każdego elementu iframe . Powinieneś użyć zaktualizowanego kodu, który właśnie dodałem, który przynajmniej obejmie te przypadki w nowszych przeglądarkach.Użyłbym jQuery, ponieważ wtedy wszystko, co musisz zrobić, to:
A przynajmniej mi się udało.
źródło
window
spowoduje utratę fokusu, co jest słuszne, ale w zależności od tego, czego nie zamierzasz chcieć.Istnieją 3 typowe metody określania, czy użytkownik może zobaczyć stronę HTML, jednak żadna z nich nie działa idealnie:
W3C API widoczności strony ma to zrobić (obsługiwany od: Firefox 10, MSIE 10, Chrome 13). Jednak ten interfejs API wywołuje zdarzenia tylko wtedy, gdy karta przeglądarki jest całkowicie przesłonięta (np. Gdy użytkownik przechodzi z jednej karty do drugiej). Interfejs API nie wywołuje zdarzeń, gdy nie można określić widoczności ze 100% dokładnością (np. Alt + Tab, aby przejść do innej aplikacji).
Stosowanie metod opartych na ogniskowaniu / rozmyciu daje wiele fałszywie pozytywnych wyników. Na przykład, jeśli użytkownik wyświetli mniejsze okno u góry okna przeglądarki, okno przeglądarki utraci fokus (
onblur
podniesiony), ale użytkownik nadal będzie mógł go zobaczyć (więc nadal trzeba go odświeżyć). Zobacz także http://javascript.info/tutorial/focusAby poprawić opisane powyżej niedoskonałe zachowania, używam kombinacji 3 metod: API Widoczności W3C, następnie metody skupienia / rozmycia i aktywności użytkownika w celu zmniejszenia wskaźnika fałszywie dodatnich. Pozwala to zarządzać następującymi zdarzeniami:
Oto jak to działa: gdy dokument traci fokus, aktywność użytkownika (na przykład ruch myszy) na dokumencie jest monitorowana w celu ustalenia, czy okno jest widoczne, czy nie. Prawdopodobieństwo widoczności strony jest odwrotnie proporcjonalne do czasu ostatniej aktywności użytkownika na stronie: jeśli użytkownik nie wykonuje żadnej czynności w dokumencie przez dłuższy czas, strona najprawdopodobniej nie jest widoczna. Poniższy kod naśladuje interfejs API widoczności strony W3C: zachowuje się w ten sam sposób, ale ma niewielką liczbę wyników fałszywie dodatnich. Ma tę zaletę, że może być multibrowser (testowany na Firefox 5, Firefox 10, MSIE 9, MSIE 7, Safari 5, Chrome 9).
Ponieważ obecnie nie ma działającego rozwiązania dla różnych przeglądarek bez fałszywego pozytywu, lepiej dwa razy pomyśleć o wyłączeniu okresowej aktywności na swojej stronie internetowej.
źródło
Na GitHub dostępna jest zgrabna biblioteka:
https://github.com/serkanyersen/ifvisible.js
Przykład:
Testowałem wersję 1.0.1 na wszystkich przeglądarkach, które posiadam i mogę potwierdzić, że działa ona z:
... i prawdopodobnie wszystkie nowsze wersje.
Nie działa w pełni z:
.now()
zawsze zwracatrue
mi)źródło
Używanie: API widoczności strony
Mogę uzyć ? http://caniuse.com/#feat=pagevisibility
źródło
Tworzę Czat Komety dla mojej aplikacji, a kiedy otrzymuję wiadomość od innego użytkownika, używam:
źródło
document.hasFocus()
jest najczystszym sposobem na zrobienie tego. Wszystkie inne sposoby korzystania z interfejsu widoczności lub zdarzenia opartego na zdarzeniu lub szukania różnych poziomów aktywności użytkownika / braku aktywności stają się nadmiernie skomplikowane i pełne przypadków i dziur na krawędziach. ustaw go w prostym odstępie czasu i wywołaj niestandardowe zdarzenie, gdy zmienią się wyniki. Przykład: jsfiddle.net/59utucz6/1Zacząłem od odpowiedzi na wiki społeczności, ale zdałem sobie sprawę, że nie wykrywa ona zdarzeń Alt-Tab w Chrome. Wynika to z faktu, że korzysta z pierwszego dostępnego źródła zdarzeń, aw tym przypadku jest to interfejs API widoczności strony, który w Chrome wydaje się nie śledzić tabulacji.
Postanowiłem trochę zmodyfikować skrypt, aby śledzić wszystkie możliwe zdarzenia związane ze zmianami fokusu strony. Oto funkcja, w którą możesz wpaść:
Użyj tego w ten sposób:
Ta wersja nasłuchuje wszystkich różnych zdarzeń widoczności i uruchamia oddzwonienie, jeśli którekolwiek z nich spowoduje zmianę. Programy obsługi
focused
iunfocused
upewniają się, że wywołanie zwrotne nie zostanie wywołane wiele razy, jeśli wiele interfejsów API wykryje tę samą zmianę widoczności.źródło
document.hidden
idocument.webkitHidden
. Bezelse
wif
budowie chcielibyśmy dostać 2 wywołań zwrotnych prawda?To jest naprawdę trudne. Wydaje się, że nie ma rozwiązania, biorąc pod uwagę następujące wymagania.
Dzieje się tak, ponieważ:
Biorąc pod uwagę te ograniczenia, możliwe jest wdrożenie rozwiązania, które łączy - Interfejs API widoczności strony - rozmycie / fokus okna - document.activeElement
To jest w stanie:
Gdy ramka iframe jest aktywna, zdarzenia rozmycia / ostrości nie są w ogóle wywoływane, a interfejs API widoczności strony nie uruchamia się na klawiszach alt + tab.
Zbudowałem rozwiązanie @ AndyE i wdrożyłem to (prawie dobre) rozwiązanie tutaj: https://dl.dropboxusercontent.com/u/2683925/estante-components/visibility_test1.html (przepraszam, miałem pewne problemy z JSFiddle).
Jest to również dostępne na Github: https://github.com/qmagico/estante-components
Działa na chrom / chrom. To działa w Firefoksie, z wyjątkiem tego, że nie ładuje treści iframe (jakiś pomysł, dlaczego?)
W każdym razie, aby rozwiązać ostatni problem (4), jedynym sposobem, aby to zrobić, jest nasłuchiwanie zdarzeń rozmycia / skupienia w ramce iframe. Jeśli masz kontrolę nad ramkami iframe, możesz to zrobić za pomocą interfejsu API postMessage.
https://dl.dropboxusercontent.com/u/2683925/estante-components/visibility_test2.html
Nadal nie testowałem tego z wystarczającą liczbą przeglądarek. Jeśli możesz znaleźć więcej informacji o tym, gdzie to nie działa, daj mi znać w komentarzach poniżej.
źródło
http://jsfiddle.net/ARTsinn/JTxQY/
źródło
to działa dla mnie na Chrome 67, Firefox 67,
źródło
możesz użyć:
źródło
W HTML 5 możesz także użyć:
onpageshow
: Skrypt do uruchomienia, gdy okno stanie się widoczneonpagehide
: Skrypt do uruchomienia, gdy okno jest ukryteWidzieć:
źródło
To jest adaptacja odpowiedzi Andy'ego E.
Spowoduje to wykonanie zadania, np. Odświeżanie strony co 30 sekund, ale tylko wtedy, gdy strona jest widoczna i zogniskowana.
Jeśli nie można wykryć widoczności, zostanie użyty tylko fokus.
Jeśli użytkownik skoncentruje stronę, zostanie ona natychmiast zaktualizowana
Strona zaktualizuje się dopiero po 30 sekundach od jakiegokolwiek wywołania ajax
źródło
Aby znaleźć rozwiązanie bez jQuery, sprawdź Visibility.js, który zawiera informacje o trzech stanach strony
a także owijarki dla setInterval
Dostępna jest również funkcja rezerwowa dla starszych przeglądarek (IE <10; iOS <7)
źródło
Nieco bardziej skomplikowanym sposobem byłoby użycie
setInterval()
sprawdzenie pozycji myszy i porównanie z ostatnim sprawdzaniem. Jeśli mysz nie poruszyła się w ustalonym czasie, użytkownik prawdopodobnie jest bezczynny.Ma to tę dodatkową zaletę, że informuje, czy użytkownik jest bezczynny, a nie tylko sprawdzać, czy okno nie jest aktywne.Jak wiele osób zauważyło, nie zawsze jest to dobry sposób na sprawdzenie, czy okno użytkownika lub przeglądarki jest bezczynne, ponieważ użytkownik może nawet nie korzystać z myszy, oglądać wideo lub podobne. Po prostu sugeruję jeden z możliwych sposobów sprawdzenia bezczynności.
źródło
W przypadku angular.js, oto dyrektywa (oparta na przyjętej odpowiedzi), która pozwoli twojemu kontrolerowi zareagować na zmianę widoczności:
Możesz użyć tego w następujący sposób:
<div react-on-window-focus="refresh()">
gdzie, gdzierefresh()
jest funkcja zasięgu w zakresie dowolnego kontrolera, który jest w zasięgu.źródło
Oto solidne, nowoczesne rozwiązanie. (Krótko słodko 👌🏽)
Spowoduje to skonfigurowanie nasłuchiwania do wyzwalania, gdy zostanie uruchomione dowolne zdarzenie widoczności, które może być skupieniem lub rozmyciem.
źródło
Jeśli chcesz reagować na rozmycie całej przeglądarki : tak jak skomentowałem, jeśli przeglądarka przestanie być aktywna, żadne z sugerowanych zdarzeń nie zostanie uruchomione. Moim pomysłem jest policzyć w pętli i zresetować licznik, jeśli nastąpi zdarzenie. Jeśli licznik osiągnie limit, robię lokalizację. Odsyłam do innej strony. To również strzela, jeśli pracujesz na narzędziach programistycznych.
Jest to projekt pomyślnie przetestowany na FF.
źródło