web-dev-qa-db-fra.com

Détecter le navigateur ou la fermeture de l'onglet

Existe-t-il un code JavaScript/jQuery inter-navigateurs permettant de détecter si le navigateur ou un onglet de navigateur est en cours de fermeture, mais pas en raison du clic sur un lien?

236
cometta

Si je vous ai bien compris, vous voulez savoir quand un onglet/une fenêtre est effectivement fermé. Pour autant que je sache, le seul moyen dans Javascript de détecter ce genre de choses est les événements onunload & onbeforeunload.

Malheureusement (ou heureusement?), Ces événements sont également déclenchés lorsque vous quittez un site avec un bouton link ou le bouton de retour de votre navigateur. Donc, c’est la meilleure réponse que je puisse donner, je ne pense pas que vous puissiez détecter nativement une pure close en Javascript. Corrigez-moi si je me trompe ici.

226
jAndy

Depuis Documentation Firefox

Pour certaines raisons, les navigateurs Webkit ne suivent pas les spécifications de la boîte de dialogue. Un exemple presque transversal serait proche de l'exemple ci-dessous.

window.addEventListener("beforeunload", function (e) {
  var confirmationMessage = "\o/";

  (e || window.event).returnValue = confirmationMessage; //Gecko + IE
  return confirmationMessage;                            //Webkit, Safari, Chrome
});

Cet exemple pour gérer tous les navigateurs.

104
mohamed-ibrahim

Solution simple

window.onbeforeunload = function () {
    return "Do you really want to close?";
};
39
user1760979
<body onbeforeunload="ConfirmClose()" onunload="HandleOnClose()">

var myclose = false;

function ConfirmClose()
{
    if (event.clientY < 0)
    {
        event.returnValue = 'You have closed the browser. Do you want to logout from your application?';
        setTimeout('myclose=false',10);
        myclose=true;
    }
}

function HandleOnClose()
{
    if (myclose==true) 
    {
        //the url of your logout page which invalidate session on logout 
        location.replace('/contextpath/j_spring_security_logout') ;
    }   
}

// Cela fonctionne dans IE7, si vous fermez l'onglet ou le navigateur avec un seul onglet

17
jyothis

Désolé, je n’ai pas pu ajouter de commentaire à l’une des réponses existantes, mais si vous souhaitez implémenter une sorte de boîte de dialogue d’avertissement, je voulais simplement mentionner que toute fonction de gestionnaire d’événements a un argument - événement. Dans votre cas, vous pouvez appeler event.preventDefault () pour interdire de quitter la page automatiquement, puis ouvrir votre propre boîte de dialogue. Je considère cela comme une meilleure option que d’utiliser une alerte standard moche et peu sûre (). J'ai personnellement mis en place mon propre ensemble de boîtes de dialogue basées sur l'objet kendoWindow (l'interface utilisateur Kendo de Telerik, qui est presque entièrement à source ouverte, à l'exception de kendoGrid et de kendoEditor). Vous pouvez également utiliser des boîtes de dialogue à partir de l'interface utilisateur jQuery. Notez cependant que ces éléments sont asynchrones et que vous aurez besoin de lier un gestionnaire à l'événement onclick de chaque bouton, mais cette opération est relativement simple à mettre en œuvre. 

Cependant, je conviens que le manque d'événement de fermeture réelle est terrible: si vous souhaitez, par exemple, réinitialiser l'état de votre session sur le back-end uniquement en cas de fermeture réelle, c'est un problème.

6
Alex Iurovetski

J'avais besoin de déconnecter automatiquement l'utilisateur lorsque le navigateur ou l'onglet était fermé, mais pas lorsque l'utilisateur accédait à d'autres liens. Je ne souhaitais pas non plus qu'un message de confirmation s'affiche lorsque cela se produit. Après avoir lutté avec cela pendant un certain temps, en particulier avec IE et Edge, voici ce que j'ai fini de faire (vérifié en travaillant avec IE 11, Edge, Chrome et Firefox) après avoir calé l'approche par cette réponse .

Commencez par démarrer un compte à rebours sur le serveur dans le gestionnaire d'événements beforeunload de JS. Les appels ajax doivent être synchrones pour que IE et Edge fonctionnent correctement. Vous devez également utiliser return; pour empêcher la boîte de dialogue de confirmation de s'afficher comme ceci:

    window.addEventListener("beforeunload", function (e) {        
      $.ajax({
          type: "POST",
          url: startTimerUrl,
          async: false           
      });
      return;
    });

Le démarrage de la minuterie définit l'indicateur cancelLogout sur false. Si l'utilisateur actualise la page ou navigue vers un autre lien interne, l'indicateur cancelLogout sur le serveur est défini sur true. Une fois que l'événement timer s'est écoulé, il vérifie l'indicateur cancelLogout pour voir si l'événement de déconnexion a été annulé. Si le chronomètre a été annulé, le chronomètre sera arrêté. Si le navigateur ou l'onglet était fermé, l'indicateur cancelLogout resterait false et le gestionnaire d'événements déconnecterait l'utilisateur.

Note d'implémentation: J'utilise ASP.NET MVC 5 et j'annule la déconnexion d'une méthode Controller.OnActionExecuted() remplacée.

6
Ionian316
$(window).unload( function () { alert("Bye now!"); } );
4
Poonam Bhatt

Pour des tâches similaires, vous pouvez utiliser sessionStorage pour stocker les données localement jusqu'à la fermeture de l'onglet du navigateur.

L'objet sessionStorage ne stocke les données que pour une session (les données sont supprimées à la fermeture de l'onglet du navigateur). ( W3Schools )

C'est mon stylo .

<div id="Notice">
    <span title="remove this until browser tab is closed"><u>dismiss</u>.</span>
</div>
<script>
    $("#Notice").click(function() {
     //set sessionStorage on click
        sessionStorage.setItem("dismissNotice", "Hello");
        $("#Notice").remove();
    });
    if (sessionStorage.getItem("dismissNotice"))
    //When sessionStorage is set Do stuff...
        $("#Notice").remove();
</script>
3
csandreas1

Il est possible de le vérifier à l’aide de window.closed dans un gestionnaire d’événements lors d’un événement «unload» comme celui-ci, mais l’utilisation du délai d’expiration est obligatoire (le résultat ne peut donc pas être garanti si le délai ou la fenêtre ne se ferme pas):

Exemple de JSFiddle (testé sur les dernières versions de Safari, FF, Chrome, Edge et IE11)

var win = window.open('', '', 'width=200,height=50,left=200,top=50');
win.document.write(`<html>
   <head><title>CHILD WINDOW/TAB</title></head>
   <body><h2>CHILD WINDOW/TAB</h2></body>
</html>`);
win.addEventListener('load',() => {
    document.querySelector('.status').innerHTML += '<p>Child was loaded!</p>';
});
win.addEventListener('unload',() => {
    document.querySelector('.status').innerHTML += '<p>Child was unloaded!</p>';
    setTimeout(()=>{
        document.querySelector('.status').innerHTML +=  getChildWindowStatus();
    },1000);
});
win.document.close()
document.querySelector('.check-child-window').onclick = ()=> {
    alert(getChildWindowStatus());
}
function getChildWindowStatus() {
  if (win.closed) { 
      return 'Child window has been closed!';
  } else {
      return 'Child window has not been closed!';
  }
}
1
Rvach.Flyver

Comme @jAndy l'a mentionné, il n'y a pas de code javascript adéquat pour détecter une fenêtre en cours de fermeture ..__J'ai commencé avec ce que @Syno avait proposé.

Je suis passé par une telle situation et à condition de suivre ces étapes, vous serez en mesure de la détecter .
Je l'ai testé sur Chrome 67+ et Firefox 61+.

var wrapper = function () { //ignore this

var closing_window = false;
$(window).on('focus', function () {
    closing_window = false; 
   //if the user interacts with the window, then the window is not being 
   //closed
});

$(window).on('blur', function () {

    closing_window = true;
    if (!document.hidden) { //when the window is being minimized
        closing_window = false;
    }
    $(window).on('resize', function (e) { //when the window is being maximized
        closing_window = false;
    });
    $(window).off('resize'); //avoid multiple listening
});

$('html').on('mouseleave', function () {
    closing_window = true; 
    //if the user is leaving html, we have more reasons to believe that he's 
    //leaving or thinking about closing the window
});

$('html').on('mouseenter', function () {
    closing_window = false; 
    //if the user's mouse its on the page, it means you don't need to logout 
    //them, didn't it?
});

$(document).on('keydown', function (e) {

    if (e.keyCode == 91 || e.keyCode == 18) {
        closing_window = false; //shortcuts for ALT+TAB and Window key
    }

    if (e.keyCode == 116 || (e.ctrlKey && e.keyCode == 82)) {
        closing_window = false; //shortcuts for F5 and CTRL+F5 and CTRL+R
    }
});

// Prevent logout when clicking in a hiperlink
$(document).on("click", "a", function () {
    closing_window = false;
});

// Prevent logout when clicking in a button (if these buttons rediret to some page)
$(document).on("click", "button", function () {
    closing_window = false;

});
// Prevent logout when submiting
$(document).on("submit", "form", function () {
    closing_window = false;
});
// Prevent logout when submiting
$(document).on("click", "input[type=submit]", function () {
    closing_window = false;
});

var toDoWhenClosing = function() {

    //write a code here likes a user logout, example: 
    //$.ajax({
    //    url: '/MyController/MyLogOutAction',
    //    async: false,
    //    data: {

    //    },
    //    error: function () {
    //    },
    //    success: function (data) {
    //    },
    //});
};


window.onbeforeunload = function () {
    if (closing_window) {
        toDoWhenClosing();
    }
};

};

0
Bruno Henrique

essayez ceci, Je suis sûr que cela fonctionnera pour vous.

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type='text/javascript'>
    $(function() {

        try{
            opera.setOverrideHistoryNavigationMode('compatible');
            history.navigationMode = 'compatible';
        }catch(e){}

        function ReturnMessage()
        {
            return "wait";
        }

        function UnBindWindow()
        {
            $(window).unbind('beforeunload', ReturnMessage);
        }

        $(window).bind('beforeunload',ReturnMessage );
    });
</script>
0

J'ai trouvé un moyen, que fonctionne sur tous mes navigateurs}. 

Testé sur les versions suivantes: Firefox 57, Internet Explorer 11, Edge 41, l’un des derniers Chrome (il n’affiche pas ma version) 

Note: onbeforeunload se déclenche si vous quittez la page de toutes les manières possibles (rafraîchissement, fermeture du navigateur, redirection, lien, soumission, etc.). Si vous souhaitez que cela se produise à la fermeture du navigateur, il vous suffit de lier les gestionnaires d'événements.

  $(document).ready(function(){         

        var validNavigation = false;

        // Attach the event keypress to exclude the F5 refresh (includes normal refresh)
        $(document).bind('keypress', function(e) {
            if (e.keyCode == 116){
                validNavigation = true;
            }
        });

        // Attach the event click for all links in the page
        $("a").bind("click", function() {
            validNavigation = true;
        });

        // Attach the event submit for all forms in the page
        $("form").bind("submit", function() {
          validNavigation = true;
        });

        // Attach the event click for all inputs in the page
        $("input[type=submit]").bind("click", function() {
          validNavigation = true;
        }); 

        window.onbeforeunload = function() {                
            if (!validNavigation) {     
                // ------->  code comes here
            }
        };

  });
0
Syno

Essayez de l'utiliser:

window.onbeforeunload = function (event) {
    var message = 'Important: Please click on \'Save\' button to leave this page.';
    if (typeof event == 'undefined') {
        event = window.event;
    }
    if (event) {
        event.returnValue = message;
    }
    return message;
};

$(function () {
    $("a").not('#lnkLogOut').click(function () {
        window.onbeforeunload = null;
    });
    $(".btn").click(function () {
        window.onbeforeunload = null;
});
});
0
Fezal halai
window.addEventListener("beforeunload", function (e) {
 var confirmationMessage = "tab close";

 (e || window.event).returnValue = confirmationMessage;     //Gecko + IE
 sendkeylog(confirmationMessage);
 return confirmationMessage;                                //Webkit, Safari, Chrome etc.
}); 
0
user3098847

Comme personne ne l’a encore mentionné (plus de 8 ans plus tard): Un WebSocket peut être un autre moyen efficace de détecter un onglet fermé. Tant que l'onglet est ouvert et dirigé vers l'hôte, le client est capable de maintenir une connexion WebSocket active avec l'hôte.

Mise en garde: Veuillez noter que cette solution n'est réellement viable pour un projet que si WebSocket ne nécessite pas de temps système supplémentaire important.

Dans un délai raisonnable (par exemple, 2 minutes), le serveur peut déterminer que le client a disparu après la déconnexion de WebSocket et effectuer toute action souhaitée, telle que la suppression des fichiers temporaires téléchargés. (Dans mon cas d'utilisation extrêmement spécialisé, mon objectif était de terminer un serveur d'application localhost trois secondes après la perte de la connexion WebSocket et la fin de toute activité CGI/FastCGI - aucune autre connexion persistante ne m'affecte.)

J'ai eu des problèmes à faire en sorte que le gestionnaire d'événements onunload fonctionne correctement avec les balises (comme recommandé par cette réponse ). La fermeture de l'onglet ne semblait pas déclencher la balise et les onglets ouverts l'ont déclenchée d'une manière pouvant potentiellement poser problème. Un WebSocket a résolu le problème que je rencontrais plus proprement parce que la connexion se ferme à peu près au même moment que la fermeture de l'onglet et que le changement de page dans l'application ouvre simplement une nouvelle connexion WebSocket dans la fenêtre de délai.

0
CubicleSoft
window.onbeforeunload = function() {
  console.log('event');
  return false; //here also can be string, that will be shown to the user
}
0
IvanM
window.onbeforeunload = function ()
{       

    if (isProcess > 0) 
    {
        return true;       
    }   

    else
    { 
        //do something      
    }
}; 

Cette fonction affiche une boîte de dialogue de confirmation si vous fermez la fenêtre ou actualisez la page au cours d’un processus dans le navigateur.

0
Hari