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/focus
- Poleganie na aktywności użytkownika (poruszanie myszą, kliknięcia, pisanie na klawiaturze) daje również wiele fałszywych trafień. Pomyśl o tej samej sprawie jak powyżej lub o użytkowniku oglądającym film.
Aby 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:
- Zmiana karty przeglądarki na inną (100% dokładności, dzięki interfejsowi API Widoczności strony W3C)
- Strona potencjalnie ukryta przez inne okno, np. Z powodu Alt + Tab (probabilistyczna = nie w 100% dokładna)
- Uwaga użytkownika potencjalnie nie koncentruje się na stronie HTML (probabilistic = nie w 100% dokładne)
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).
<div id = "x"> </div>
<script>
/ **
Rejestruje moduł obsługi zdarzenia dla danego obiektu.
@param obj obiekt, który wywoła zdarzenie
@param ev Wpisz typ zdarzenia: kliknięcie, naciśnięcie klawisza, kursor myszy, ...
@param fn funkcja obsługi zdarzeń
@param isCapturing ustaw tryb zdarzenia (true = przechwytywanie zdarzenia, false = propagowanie zdarzenia)
@return true, jeśli moduł obsługi zdarzeń został poprawnie dołączony
* /
funkcja addEvent (obj, evType, fn, isCapturing) {
if (isCapturing == null) isCapturing = false;
if (obj.addEventListener) {
// Firefox
obj.addEventListener (evType, fn, isCapturing);
zwróć prawdę;
} else if (obj.attachEvent) {
// MSIE
var r = obj.attachEvent ('on' + evType, fn);
return r;
} else {
zwracać fałsz;
}
}
// zarejestruj się do potencjalnej zmiany widoczności strony
addEvent (dokument, „potencjałvisilitychange”, funkcja (zdarzenie) {
document.getElementById ("x"). innerHTML + = "potencjałVisilityChange: potencjałHidden =" + document.potentialHidden + ", document.potentialHiddenSince =" + document.potentialHiddenSince + "s <br>";
});
// zarejestruj się w interfejsie API widoczności strony W3C
var hidden = null;
var visibilityChange = null;
if (typeof document.mozHidden! == "undefined") {
hidden = "mozHidden";
visibilityChange = "mozvisibilitychange";
} else if (typeof document.msHidden! == "undefined") {
hidden = "msHidden";
visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden! == "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
} else if (typeof document.hidden! == "hidden") {
hidden = "hidden";
visibilityChange = "visibilitychange";
}
if (hidden! = null && visibilityChange! = null) {
addEvent (dokument, widocznośćZmień, funkcja (zdarzenie) {
document.getElementById ("x"). innerHTML + = visibilityChange + ":" + hidden + "=" + document [ukryty] + "<br>";
});
}
var potencjałPageVisibility = {
pageVisibilityChangeThreshold: 3 * 3600, // w sekundach
init: function () {
funkcja setAsNotHidden () {
var dispatchEventRequired = document.potentialHidden;
document.potentialHidden = false;
document.potentialHiddenSince = 0;
if (dispatchEventRequired) dispatchPageVisibilityChangeEvent ();
}
funkcja initPotentialHiddenDetection () {
if (! hasFocusLocal) {
// okno nie ma fokusa => sprawdź aktywność użytkownika w oknie
lastActionDate = new Date ();
if (timeoutHandler! = null) {
clearTimeout (timeoutHandler);
}
timeoutHandler = setTimeout (checkPageVisibility, potencjałPageVisibility.pageVisibilityChangeThreshold * 1000 + 100); // +100 ms, aby uniknąć problemów z zaokrąglaniem w Firefoksie
}
}
funkcja dispatchPageVisibilityChangeEvent () {
unifiedVisilityChangeEventDispatchAllowed = false;
var evt = document.createEvent („Event”);
evt.initEvent („potencjałvisilitychange”, true, true);
document.dispatchEvent (evt);
}
funkcja checkPageVisibility () {
var potencjałHiddenDuration = (hasFocusLocal || lastActionDate == null? 0: Math.floor ((new Date (). getTime () - lastActionDate.getTime ()) / 1000));
document.potentialHiddenSince = potencjałHiddenDuration;
if (potencjałHiddenDuration> = potencjałPageVisibility.pageVisibilityChangeThreshold &&! document.potentialHidden) {
// próg zmiany widoczności strony raiched => podnieść parzystość
document.potentialHidden = true;
dispatchPageVisibilityChangeEvent ();
}
}
var lastActionDate = null;
var hasFocusLocal = true;
var hasMouseOver = true;
document.potentialHidden = false;
document.potentialHiddenSince = 0;
var timeoutHandler = null;
addEvent (dokument, „pokaz stron”, funkcja (zdarzenie) {
document.getElementById ("x"). innerHTML + = "pageshow / doc: <br>";
});
addEvent (dokument, „strona”, funkcja (zdarzenie) {
document.getElementById ("x"). innerHTML + = "pagehide / doc: <br>";
});
addEvent (okno, „przeglądanie stron”, funkcja (zdarzenie) {
document.getElementById ("x"). innerHTML + = "pageshow / win: <br>"; // podniesiony, gdy strona pokazuje się po raz pierwszy
});
addEvent (okno, „pagehide”, funkcja (zdarzenie) {
document.getElementById ("x"). innerHTML + = "pagehide / win: <br>"; // nie podniesiony
});
addEvent (dokument, „ruch myszy”, funkcja (zdarzenie) {
lastActionDate = new Date ();
});
addEvent (dokument, „wskaźnik myszy”, funkcja (zdarzenie) {
hasMouseOver = true;
setAsNotHidden ();
});
addEvent (dokument, „mouseout”, funkcja (zdarzenie) {
hasMouseOver = false;
initPotentialHiddenDetection ();
});
addEvent (okno, „rozmycie”, funkcja (zdarzenie) {
hasFocusLocal = false;
initPotentialHiddenDetection ();
});
addEvent (okno, „fokus”, funkcja (zdarzenie) {
hasFocusLocal = true;
setAsNotHidden ();
});
setAsNotHidden ();
}
}
potencjałPageVisibility.pageVisibilityChangeThreshold = 4; // 4 sekundy na testowanie
potencjałPageVisibility.init ();
</script>
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.
requestAnimationFrame
API lub skorzystaj z nowoczesnej funkcji zmniejszania częstotliwościsetTimeout
/,setInterval
gdy okno nie jest widoczne (na przykład 1 sekunda w Chrome).