Risposte:
Prova l' onbeforeunloadevento: viene generato appena prima che la pagina venga scaricata. Ti permette anche di chiedere se l'utente vuole davvero andarsene. Guarda la demo prima di scaricare Demo .
In alternativa, puoi inviare una richiesta Ajax quando lascia.
Mozilla Developer Network ha una bella descrizione ed esempio di onbeforeunload .
Se vuoi avvisare l'utente prima di lasciare la pagina se la tua pagina è sporca (ovvero se l'utente ha inserito alcuni dati):
window.addEventListener('beforeunload', function(e) {
var myPageIsDirty = ...; //you implement this logic...
if(myPageIsDirty) {
//following two lines will cause the browser to ask the user if they
//want to leave. The text of this dialog is controlled by the browser.
e.preventDefault(); //per the standard
e.returnValue = ''; //required for Chrome
}
//else: user is allowed to leave without a warning dialog
});
Ecco una soluzione alternativa: poiché nella maggior parte dei browser i controlli di navigazione (barra di navigazione, schede, ecc.) Si trovano sopra l'area del contenuto della pagina, puoi rilevare il puntatore del mouse che lascia la pagina in alto e visualizzare un " prima di uscire " dialogo. È completamente discreto e ti consente di interagire con l'utente prima che eseguano effettivamente l'azione per uscire.
$(document).bind("mouseleave", function(e) {
if (e.pageY - $(window).scrollTop() <= 1) {
$('#BeforeYouLeaveDiv').show();
}
});
Il rovescio della medaglia è che ovviamente si tratta di un'ipotesi che l'utente intende effettivamente lasciare, ma nella stragrande maggioranza dei casi è corretto.
Per questo sto usando:
window.onbeforeunload = function (e) {
}
Viene generato appena prima che la pagina venga scaricata.
onbeforeunload?
So che a questa domanda è stata data una risposta, ma nel caso in cui si desideri attivare qualcosa solo quando il BROWSER effettivo è chiuso e non solo quando si verifica un pageload, è possibile utilizzare questo codice:
window.onbeforeunload = function (e) {
if ((window.event.clientY < 0)) {
//window.localStorage.clear();
//alert("Y coords: " + window.event.clientY)
}
};
Nel mio esempio, sto cancellando l'archiviazione locale e avvisando l'utente con i mouse y coords, solo quando il browser è chiuso, questo verrà ignorato su tutti i caricamenti di pagine dall'interno del programma.
edovrebbe essere usato il parametro evento (la variabile in questo caso): stackoverflow.com/questions/9813445/ …
This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. developer.mozilla.org/en-US/docs/Web/API/Window/event
Un modo (leggermente confuso) per farlo è la sostituzione e i collegamenti che portano via dal tuo sito con una chiamata AJAX sul lato server, indicando che l'utente sta uscendo, quindi usa lo stesso blocco javascript per portarlo sul sito esterno che ha ho richiesto.
Ovviamente questo non funzionerà se l'utente semplicemente chiude la finestra del browser o digita un nuovo URL.
Per ovviare a questo, dovresti potenzialmente utilizzare il setTimeout () di Javascript sulla pagina, effettuare una chiamata AJAX ogni pochi secondi (a seconda di quanto velocemente vuoi sapere se l'utente è partito).
Grazie a Service Workers , è possibile implementare una soluzione simile a quella di Adam esclusivamente sul lato client, a condizione che il browser la supporti. Basta eludere le richieste di battito cardiaco:
// The delay should be longer than the heartbeat by a significant enough amount that there won't be false positives
const liveTimeoutDelay = 10000
let liveTimeout = null
global.self.addEventListener('fetch', event => {
clearTimeout(liveTimeout)
liveTimeout = setTimeout(() => {
console.log('User left page')
// handle page leave
}, liveTimeoutDelay)
// Forward any events except for hearbeat events
if (event.request.url.endsWith('/heartbeat')) {
event.respondWith(
new global.Response('Still here')
)
}
})
setInterval(() => fetch('/heartbeat'), 5000)?
Nel caso in cui sia necessario eseguire un codice asincrono (come l'invio di un messaggio al server che l'utente non è focalizzato sulla propria pagina in questo momento), l'evento beforeunloadnon darà il tempo per l'esecuzione del codice asincrono. Nel caso di asincrono ho scoperto che gli eventi visibilitychangee mouseleavesono le migliori opzioni. Questi eventi si attivano quando l'utente cambia scheda o nasconde il browser o estrae il cursore dall'ambito della finestra.
document.addEventListener('mouseleave', e=>{
//do some async code
})
document.addEventListener('visibilitychange', e=>{
if (document.visibilityState === 'visible') {
//report that user is in focus
} else {
//report that user is out of focus
}
})
Per quello che vale, questo è quello che ho fatto e forse può aiutare gli altri anche se l'articolo è vecchio.
PHP:
session_start();
$_SESSION['ipaddress'] = $_SERVER['REMOTE_ADDR'];
if(isset($_SESSION['userID'])){
if(!strpos($_SESSION['activeID'], '-')){
$_SESSION['activeID'] = $_SESSION['userID'].'-'.$_SESSION['activeID'];
}
}elseif(!isset($_SESSION['activeID'])){
$_SESSION['activeID'] = time();
}
JS
window.setInterval(function(){
var userid = '<?php echo $_SESSION['activeID']; ?>';
var ipaddress = '<?php echo $_SESSION['ipaddress']; ?>';
var action = 'data';
$.ajax({
url:'activeUser.php',
method:'POST',
data:{action:action,userid:userid,ipaddress:ipaddress},
success:function(response){
//alert(response);
}
});
}, 5000);
Chiamata Ajax a activeUser.php
if(isset($_POST['action'])){
if(isset($_POST['userid'])){
$stamp = time();
$activeid = $_POST['userid'];
$ip = $_POST['ipaddress'];
$query = "SELECT stamp FROM activeusers WHERE activeid = '".$activeid."' LIMIT 1";
$results = RUNSIMPLEDB($query);
if($results->num_rows > 0){
$query = "UPDATE activeusers SET stamp = '$stamp' WHERE activeid = '".$activeid."' AND ip = '$ip' LIMIT 1";
RUNSIMPLEDB($query);
}else{
$query = "INSERT INTO activeusers (activeid,stamp,ip)
VALUES ('".$activeid."','$stamp','$ip')";
RUNSIMPLEDB($query);
}
}
}
Banca dati:
CREATE TABLE `activeusers` (
`id` int(11) NOT NULL,
`activeid` varchar(20) NOT NULL,
`stamp` int(11) NOT NULL,
`ip` text
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Praticamente ogni 5 secondi js invierà un file php che traccia l'utente e l'indirizzo IP dell'utente. Gli utenti attivi sono semplicemente un record di database che ha un aggiornamento al timestamp del database entro 5 secondi. I vecchi utenti interrompono l'aggiornamento al database. L'indirizzo IP viene utilizzato solo per garantire che un utente sia univoco, quindi 2 persone sul sito contemporaneamente non si registrano come 1 utente.
Probabilmente non è la soluzione più efficiente ma fa il lavoro.