Esistono 3 metodi tipici utilizzati per determinare se l'utente può visualizzare la pagina HTML, tuttavia nessuno di questi funziona perfettamente:
L' API W3C Page Visibility dovrebbe eseguire questa operazione (supportata da: Firefox 10, MSIE 10, Chrome 13). Tuttavia, questa API genera eventi solo quando la scheda del browser è completamente sostituita (ad es. Quando l'utente passa da una scheda all'altra). L'API non genera eventi quando la visibilità non può essere determinata con una precisione del 100% (ad esempio Alt + Tab per passare a un'altra applicazione).
L'uso di metodi basati sulla messa a fuoco / sfocatura offre molti falsi positivi. Ad esempio, se l'utente visualizza una finestra più piccola nella parte superiore della finestra del browser, la finestra del browser perderà il focus (in onblur
rilievo) ma l'utente sarà ancora in grado di vederlo (quindi deve ancora essere aggiornato). Vedi anche http://javascript.info/tutorial/focus
- Affidarsi all'attività dell'utente (spostamento del mouse, clic, digitazione dei tasti) ti dà anche molti falsi positivi. Pensa allo stesso caso sopra o a un utente che guarda un video.
Al fine di migliorare i comportamenti imperfetti sopra descritti, utilizzo una combinazione dei 3 metodi: W3C Visibility API, quindi focus / blur e metodi di attività dell'utente al fine di ridurre il tasso di falsi positivi. Ciò consente di gestire i seguenti eventi:
- Modifica della scheda del browser in un'altra (precisione del 100%, grazie all'API di visibilità della pagina del W3C)
- Pagina potenzialmente nascosta da un'altra finestra, ad esempio a causa di Alt + Tab (probabilistico = non preciso al 100%)
- Attenzione dell'utente potenzialmente non focalizzata sulla pagina HTML (probabilistica = non accurata al 100%)
Funziona così: quando il documento perde lo stato attivo, l'attività dell'utente (come lo spostamento del mouse) sul documento viene monitorata per determinare se la finestra è visibile o meno. La probabilità di visibilità della pagina è inversamente proporzionale al tempo dell'ultima attività dell'utente sulla pagina: se l'utente non fa attività sul documento per un lungo periodo, molto probabilmente la pagina non è visibile. Il codice seguente imita l'API di visibilità della pagina del W3C: si comporta allo stesso modo ma ha una piccola percentuale di falsi positivi. Ha il vantaggio di essere multibrowser (testato su Firefox 5, Firefox 10, MSIE 9, MSIE 7, Safari 5, Chrome 9).
<div id = "x"> </div>
<Script>
/ **
Registra il gestore all'evento per l'oggetto specificato.
@param obj l'oggetto che genererà l'evento
@param ev Digitare il tipo di evento: clic, pressione dei tasti, passaggio del mouse, ...
@param fn la funzione del gestore eventi
@param isCapturing imposta la modalità evento (true = evento di acquisizione, false = evento di bubbling)
@return true se il gestore eventi è stato collegato correttamente
* /
funzione addEvent (obj, evType, fn, isCapturing) {
if (isCapturing == null) isCapturing = false;
if (obj.addEventListener) {
// Firefox
obj.addEventListener (evType, fn, isCapturing);
ritorno vero;
} else if (obj.attachEvent) {
// MSIE
var r = obj.attachEvent ('on' + evType, fn);
ritorno r;
} altro {
restituire false;
}
}
// registra la potenziale modifica della visibilità della pagina
addEvent (documento, "entialvisilitychange ", funzione (evento) {
document.getElementById ("x"). innerHTML + = "entialVisilityChange: potentialHidden = "+ document.potentialHidden +", document.potentiallyHiddenSince = "+ document.potentiallyHiddenSince +" s <br> ";
});
// registrati all'API di visibilità della pagina del W3C
var nascosto = null;
var visibleChange = 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 (nascosto! = null && visibleChange! = null) {
addEvent (documento, visibilitàCambia, funzione (evento) {
document.getElementById ("x"). innerHTML + = visibleChange + ":" + hidden + "=" + document [nascosto] + "<br>";
});
}
var potenzialePageVisibility = {
pageVisibilityChangeThreshold: 3 * 3600, // in secondi
init: function () {
function setAsNotHidden () {
var dispatchEventRequired = document.potentialHidden;
document.potentialHidden = false;
document.potentiallyHiddenSince = 0;
if (dispatchEventRequired) dispatchPageVisibilityChangeEvent ();
}
funzione initPotentiallyHiddenDetection () {
if (! hasFocusLocal) {
// la finestra non ha lo stato attivo => controlla l'attività dell'utente nella finestra
lastActionDate = new Date ();
if (timeoutHandler! = null) {
clearTimeout (timeoutHandler);
}
timeoutHandler = setTimeout (checkPageVisibility ,entialPageVisibility.pageVisibilityChangeThreshold * 1000 + 100); // +100 ms per evitare problemi di arrotondamento in Firefox
}
}
function dispatchPageVisibilityChangeEvent () {
unifiedVisilityChangeEventDispatchAllowed = false;
var evt = document.createEvent ("Event");
evt.initEvent ("entialvisilitychange ", true, true);
document.dispatchEvent (EVT);
}
function checkPageVisibility () {
varentialHiddenDuration = (hasFocusLocal || lastActionDate == null? 0: Math.floor ((new Date (). getTime () - lastActionDate.getTime ()) / 1000));
document.potentiallyHiddenSince = potentialHiddenDuration;
if (entialHiddenDuration> = potentialPageVisibility.pageVisibilityChangeThreshold &&! document.potentialHidden) {
// soglia di modifica della visibilità della pagina raiched => aumenta il pari
document.potentialHidden = true;
dispatchPageVisibilityChangeEvent ();
}
}
var lastActionDate = null;
var hasFocusLocal = true;
var hasMouseOver = true;
document.potentialHidden = false;
document.potentiallyHiddenSince = 0;
var timeoutHandler = null;
addEvent (documento, "pageshow", funzione (evento) {
document.getElementById ( "x") innerHTML + = "pageshow / doc: <br>.";
});
addEvent (documento, "pagehide", funzione (evento) {
document.getElementById ( "x") innerHTML + = "pagehide / doc: <br>.";
});
addEvent (finestra, "pageshow", funzione (evento) {
document.getElementById ( "x") innerHTML + = "pageshow / win: <br>."; // sollevato alla prima visualizzazione della pagina
});
addEvent (finestra, "pagehide", funzione (evento) {
document.getElementById ( "x") innerHTML + = "pagehide / win: <br>."; // non sollevato
});
addEvent (documento, "mousemove", funzione (evento) {
lastActionDate = new Date ();
});
addEvent (documento, "passaggio del mouse", funzione (evento) {
hasMouseOver = true;
setAsNotHidden ();
});
addEvent (documento, "mouseout", funzione (evento) {
hasMouseOver = false;
initPotentiallyHiddenDetection ();
});
addEvent (finestra, "sfocatura", funzione (evento) {
hasFocusLocal = false;
initPotentiallyHiddenDetection ();
});
addEvent (finestra, "focus", funzione (evento) {
hasFocusLocal = true;
setAsNotHidden ();
});
setAsNotHidden ();
}
}
potentialPageVisibility.pageVisibilityChangeThreshold = 4; // 4 secondi per il test
potentialPageVisibility.init ();
</ Script>
Poiché al momento non esiste una soluzione cross-browser funzionante senza falsi positivi, è meglio pensarci due volte sulla disabilitazione dell'attività periodica sul proprio sito Web.
requestAnimationFrame
API o utilizza la moderna funzionalità che riduce la frequenza disetTimeout
/setInterval
quando la finestra non è visibile (1 secondo in Chrome, ad esempio).