web-dev-qa-db-fra.com

Identifier entre actualiser et fermer les actions du navigateur

Lorsque nous actualisons la page (F5, ou icône dans le navigateur), il déclenche en premier lieu l'événement ONUNLOAD. Lorsque nous fermons le navigateur (X sur l'icône en haut à droite), il déclenchera l'événement ONUNLOAD . Maintenant, lorsque l'événement ONUNLOAD est déclenché, il n'y a aucun moyen de distinguer entre actualiser la page ou fermer le navigateur. Si vous avez une solution alors donnez-moi.

33
ashish bhatt

Il y a une solution.

Je souhaitais déconnecter l'utilisateur du serveur lorsque l'onglet ou la fenêtre du navigateur était fermé, mais pas lorsque la page était rechargée (vous souhaiterez peut-être différencier les événements de rechargement/fermeture dans un but différent, mais vous pourrez bénéficier de ma solution). Je me suis retrouvé avec le processus suivant, basé sur le stockage local HTML5 et la communication client/serveur AJAX:

  1. sur votre page, ajoutez une onunload à la window au gestionnaire suivant (pseudo-javascript):

    function myUnload(event) {
        if (window.localStorage) {
            // flag the page as being unloading
            window.localStorage['myUnloadEventFlag']=new Date().getTime();
        }
    
        // notify the server that we want to disconnect the user in a few seconds (I used 5 seconds)
        askServerToDisconnectUserInAFewSeconds(); // synchronous AJAX call
    }
    
  2. sur votre page, ajoutez une onloadsur la body au gestionnaire suivant (pseudo-javascript):

    function myLoad(event) {
        if (window.localStorage) {
            var t0 = Number(window.localStorage['myUnloadEventFlag']);
            if (isNaN(t0)) t0=0;
            var t1=new Date().getTime();
            var duration=t1-t0;
            if (duration<10*1000) {
                // less than 10 seconds since the previous Unload event => it's a browser reload (so cancel the disconnection request)
                askServerToCancelDisconnectionRequest(); // asynchronous AJAX call
            } else {
                // last unload event was for a tab/window close => do whatever you want (I do nothing here)
            }
        }
    } 
    
  3. sur le serveur, rassemblez les demandes de déconnexion dans une liste et définissez un thread de minuterie qui inspecte la liste à intervalles réguliers (toutes les 20 secondes, je l'utilise). Une fois que le délai de demande de déconnexion a expiré (c’est-à-dire que les 5 secondes sont écoulées), déconnectez l’utilisateur du serveur. Si une annulation de demande de déconnexion est reçue entre-temps, la demande de déconnexion correspondante est supprimée de la liste afin que l'utilisateur ne soit pas déconnecté.

Cette approche est également applicable si vous souhaitez faire la différence entre un événement de fermeture d'onglet/fenêtre et des liens suivis ou un formulaire soumis. Il vous suffit de placer les deux gestionnaires d’événements sur chaque page contenant des liens et des formulaires et sur chaque page de destination lien/formulaire.

Notez que j’utilise l’événement unload au lieu de l’événement beforeUnload pour gérer correctement les liens vers les pièces jointes: lorsqu'un utilisateur clique sur un lien vers une pièce jointe (par exemple, un fichier PDF), l’événement beforeUnload est distribué, puis un message ouvert/save popup est levé, et rien de plus (le navigateur ne modifie pas la page affichée et n'envoie pas l'événement unload). Si j'utilisais l'événement beforeUnload (comme je le faisais auparavant), j'aurais détecté un changement de page s'il n'y en avait pas.

Cette approche étant limitée aux navigateurs prenant en charge le stockage local HTML5, vous utiliserez probablement des approches spécifiques pour les anciens navigateurs tels que MSIE7.

Les autres approches basées sur le event.clientY ne sont pas fiables car cette valeur est négative lorsque vous cliquez sur les boutons de rechargement ou de fermeture de la fenêtre et de l'onglet, et positive lorsque les raccourcis clavier sont utilisés pour recharger (par exemple, F5, Ctrl-R, ...) et la fermeture de la fenêtre. (par exemple Alt-F4). Le fait de s’en remettre à la position X de l’événement n’est pas non plus fiable car les boutons ne sont pas placés à la même position sur tous les navigateurs (par exemple, le bouton de fermeture à gauche).

42
Julien Kronegg

Malheureusement, l'inspection de la valeur clientY/pageY de l'événement, comme suggéré par certaines des réponses fournies ici, n'est pas un moyen fiable de déterminer si l'événement unload est déclenché suite à la fermeture de la page par l'utilisateur. 

La raison pour laquelle clientY/pageY est négative lorsque vous cliquez sur le bouton de fermeture du navigateur est que le bouton de fermeture est positionné au-dessus du haut du document (c'est-à-dire au-dessus du pixel 0). une valeur négative pour clientY/pageY.

Il est également problématique de consulter la coordonnée x de l'événement, car le bouton de fermeture du navigateur ne se trouve pas toujours à droite de la fenêtre (par exemple, il est à gauche dans OS X) et parce qu'une fenêtre peut être fermée. en fermant son onglet ou via le clavier.

6
Walter Rumsby

Aujourd'hui, j'ai eu le même problème et j'ai trouvé une solution que je souhaite partager avec vous. 

En pensant à ce qui pourrait aider à distinguer entre rafraîchir et fermer, des cookies me sont venus à l’esprit. Je me souviens que définir un cookie sans date d'expiration explicite ne le rend disponible que pour la session en cours. Et une session en cours est clairement valide jusqu'à la fermeture du navigateur. Cela ne comprend pas la fermeture d'un onglet, mais mon problème concernait l'authentification de l'utilisateur et je ne voulais pas le déconnecter uniquement pour avoir fermé un onglet (je pense que c'est la même approche que le cookie ASPXAUTH d'ASP.NET).

J'ai donc placé un simple cookie dans la collection document.cookies lorsque l'utilisateur s'est connecté et l'a vérifié au chargement de la page: si le cookie était toujours là, il s'agissait d'un onglet actualisé ou rouvert et les données de l'utilisateur étaient conservées; si le cookie n'était pas présent, la session avait expiré, les données utilisateur ont été effacées (comme une déconnexion explicite).

J'espère que cette approche pourra être utile à quelqu'un d'autre!

1
Alessandro

C'est une solution de travail

export class BootstrapComponent implements OnInit {

  validNavigation = 0;

  constructor(
    private auth: AuthenticationService
  ) { }

  ngOnInit() {
    const self = this;
    self.registerDOMEvents();
  }

  registerDOMEvents() {
    const self = this;
    window.addEventListener('unload', () => {
      if (self.validNavigation === 0) {
        self.endSession();
      }
    });
    document.addEventListener('keydown', (e) => {
      const key = e.which || e.keyCode;
      if (key === 116) {
        self.validNavigation = 1;
      }
    });
  }

  endSession() {
    const self = this;
    self.auth.clearStorage();
  }
}
0
blazehub

Utilisez l'événement window.onbeforeunload pour que le cas quitte la page, mais il inclut des balises d'actualisation ou d'ancrage. ) ou F5 vérifie en utilisant le code d'activation pour le rafraîchissement

Remarque * Le code peut causer des problèmes dans le cas de Chrome. 

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Test Page</title>

<style type='text/css'>
body {
    font-family: sans-serif;
}
</style>
<script src="jquery-1.9.1.js" type='text/javascript'></script>
<script type='text/javascript'>
var valid=false;
function wireUpEvents() {

if(valid){
alert("Page Refreshed or Redirected");
}else{

window.onbeforeunload = askWhetherToClose;

}
function askWhetherToClose(event) {

if(!valid){

    var msg;

    msg = "You're leaving the page, do you really want to?";
    event = event || window.event;
    event.returnValue = msg;
    return msg;
}}
$(document).bind('keypress', function(e) { 
 if (e.keyCode == 116){ 

 // or you can insert some code to check page refresh
 valid = true; 

//wireUpEvents();
 } 
 }); 
 $("a").bind("click", function() {
//To check redirection using Anchor tags  
 valid = true; 
 //wireUpEvents();
 }); 
 }
$(document).ready(function() { 
 wireUpEvents(); 

 });
</script>
</head>
<body>
<p>Close the browser window, or navigate to <a href="http://stackoverflow.com">StackOverflow</a></p>
</body>
</html>
0
krunal nanda