web-dev-qa-db-fra.com

Comment capturer l'événement de fermeture de la fenêtre du navigateur?

Je souhaite capturer l'événement de fermeture de la fenêtre/du navigateur du navigateur. J'ai essayé ce qui suit avec jQuery:

jQuery(window).bind(
    "beforeunload", 
    function() { 
        return confirm("Do you really want to close?") 
    }
)

Mais cela fonctionne aussi sur la soumission de formulaire, ce qui n'est pas ce que je veux. Je veux un événement qui se déclenche uniquement lorsque l'utilisateur ferme la fenêtre.

141
khelll

L'événement beforeunload se déclenche chaque fois que l'utilisateur quitte votre page pour une raison quelconque.

Par exemple, il sera déclenché si l'utilisateur soumet un formulaire, clique sur un lien, ferme la fenêtre (ou un onglet) ou affiche une nouvelle page à l'aide de la barre d'adresse, du champ de recherche ou d'un signet.

Vous pouvez exclure les envois de formulaire et les liens hypertexte (à l'exception des autres cadres) à l'aide du code suivant:

var inFormOrLink;
$('a').on('click', function() { inFormOrLink = true; });
$('form').on('submit', function() { inFormOrLink = true; });

$(window).on("beforeunload", function() { 
    return inFormOrLink ? "Do you really want to close?" : null; 
})

Pour les versions de jQuery antérieures à 1.7, essayez ceci:

var inFormOrLink;
$('a').live('click', function() { inFormOrLink = true; });
$('form').bind('submit', function() { inFormOrLink = true; });

$(window).bind("beforeunload", function() { 
    return inFormOrLink ? "Do you really want to close?" : null; 
})

La méthode live ne fonctionne pas avec l'événement submit. Par conséquent, si vous ajoutez un nouveau formulaire, vous devez également y associer le gestionnaire.

Notez que si un autre gestionnaire d'événements annule la soumission ou la navigation, vous perdrez l'invite de confirmation si la fenêtre est réellement fermée ultérieurement. Vous pouvez résoudre ce problème en enregistrant l'heure dans les événements submit et click, et en vérifiant si la beforeunload se produit plus de quelques secondes plus tard.

198
SLaks

Peut-être simplement dissocier le gestionnaire d'événement beforeunload dans le gestionnaire d'événement submit du formulaire:

jQuery('form').submit(function() {
    jQuery(window).unbind("beforeunload");
    ...
});
44
karim79

Pour une solution inter-navigateur (testé dans Chrome 21, IE9, FF15), envisagez d'utiliser le code suivant, qui est une version légèrement modifiée du code de Slaks:

var inFormOrLink;
$('a').live('click', function() { inFormOrLink = true; });
$('form').bind('submit', function() { inFormOrLink = true; });

$(window).bind('beforeunload', function(eventObject) {
    var returnValue = undefined;
    if (! inFormOrLink) {
        returnValue = "Do you really want to close?";
    }
    eventObject.returnValue = returnValue;
    return returnValue;
}); 

Notez que depuis Firefox 4, le message "Voulez-vous vraiment fermer?" n'est pas affiché. FF affiche simplement un message générique. Voir la note dans https://developer.mozilla.org/en-US/docs/DOM/window.onbeforeunload

15
desm
window.onbeforeunload = function () {
    return "Do you really want to close?";
};
11
Behnam Mohammadi

Pour une solution qui fonctionne bien avec des contrôles tiers tels que Telerik (ex: RadComboBox) et DevExpress qui utilisent les balises Anchor pour diverses raisons, envisagez d'utiliser le code suivant, qui est une version légèrement modifiée du code de desm avec un meilleur sélecteur pour soi. ciblage des balises d'ancrage:

var inFormOrLink;
$('a[href]:not([target]), a[href][target=_self]').live('click', function() { inFormOrLink = true; });
$('form').bind('submit', function() { inFormOrLink = true; });

$(window).bind('beforeunload', function(eventObject) {
    var returnValue = undefined;
    if (! inFormOrLink) {
        returnValue = "Do you really want to close?";
    }
    eventObject.returnValue = returnValue;
    return returnValue;
});
4
PLT

Ma réponse vise à fournir des repères simples.

COMMENT

Voir @ SLaks answer .

$(window).on("beforeunload", function() { 
    return inFormOrLink ? "Do you really want to close?" : null; 
})

Combien de temps faut-il au navigateur pour fermer définitivement votre page?

Lorsqu'un utilisateur ferme la page (x bouton ou CTRL + W), le navigateur exécute le code beforeunload donné, mais pas indéfiniment. La seule exception est la boîte de confirmation (return 'Do you really want to close?) qui attendra la réponse de l'utilisateur.

Chrome : 2 secondes.
Firefox : (ou double-cliquez ou forcez la fermeture)
Edge : (ou double-cliquez)
Explorer 11 : 0 seconde.
Safari : TODO

Ce que nous avons utilisé pour tester ceci:

  • Un serveur Node.js Express avec journal des requêtes
  • Le court fichier HTML suivant

Ce qu’il fait est d’envoyer autant de demandes qu’il le peut avant que le navigateur ne ferme sa page (de manière synchrone).

<html>
<body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script>
    function request() {
        return $.ajax({
            type: "GET",
            url: "http://localhost:3030/" + Date.now(),
            async: true
        }).responseText;
    }
    window.onbeforeunload = () => {
        while (true) {
            request();
        }
        return null;
    }
    </script>
</body>
</html>

Sortie de chrome:

GET /1480451321041 404 0.389 ms - 32  
GET /1480451321052 404 0.219 ms - 32  
...  
GET /hello/1480451322998 404 0.328 ms - 32

1957ms ≈ 2 seconds // we assume it's 2 seconds since requests can take few milliseconds to be sent.
4
zurfyx

J'ai utilisé Slaks answer mais cela ne fonctionnait pas tel quel, car onbeforeunload returnValue est analysé sous forme de chaîne, puis affiché dans la zone de confirmation du navigateur. Donc, la valeur true a été affichée, comme "true".

Juste en utilisant le retour a fonctionné. Voici mon code

var preventUnloadPrompt;
var messageBeforeUnload = "my message here - Are you sure you want to leave this page?";
//var redirectAfterPrompt = "http://www.google.co.in";
$('a').live('click', function() { preventUnloadPrompt = true; });
$('form').live('submit', function() { preventUnloadPrompt = true; });
$(window).bind("beforeunload", function(e) { 
    var rval;
    if(preventUnloadPrompt) {
        return;
    } else {
        //location.replace(redirectAfterPrompt);
        return messageBeforeUnload;
    }
    return rval;
})
3
kapad

Malheureusement, qu’il s’agisse d’un rechargement, d’une nouvelle redirection de page ou de la fermeture du navigateur, l’événement sera déclenché. Une alternative consiste à intercepter l'identifiant déclenchant l'événement. S'il s'agit d'un formulaire, il ne déclenche aucune fonction. S'il ne s'agit pas de l'identifiant du formulaire, faites ce que vous souhaitez faire à la fermeture de la page. Je ne sais pas si cela est également possible directement et fastidieux.

Vous pouvez faire quelques petites choses avant que le client ferme l'onglet. onglet fermer le navigateur javascript/fermer le navigateur mais si votre liste d'actions est longue et que l'onglet se ferme avant la fin, vous êtes impuissant. Vous pouvez l'essayer, mais avec mon expérience, n'en dépendez pas.

window.addEventListener("beforeunload", function (e) {
  var confirmationMessage = "\o/";
  /* Do you small action code here */
  (e || window.event).returnValue = confirmationMessage; //Gecko + IE
  return confirmationMessage;                            //Webkit, Safari, Chrome
});

https://developer.mozilla.org/en-US/docs/Web/Reference/Events/beforeunload?redirectlocale=en-US&redirectslug=DOM/Mozilla_event_reference/beforeunload

1
Gary
jQuery(window).bind(
                    "beforeunload",
                      function (e) {
                          var activeElementTagName = e.target.activeElement.tagName;
                          if (activeElementTagName != "A" && activeElementTagName != "INPUT") {
                              return "Do you really want to close?";
                          }
                      })
1
Coding man

Vous pourriez peut-être gérer OnSubmit et définir un indicateur à vérifier ultérieurement dans votre gestionnaire OnBeforeUnload.

1
i_am_jorf

Si votre soumission de formulaire les amène à une autre page (comme je le suppose, d'où le déclenchement de beforeunload), vous pouvez essayer de modifier la soumission de votre formulaire en un appel ajax. De cette façon, ils ne quitteront pas votre page lorsqu'ils soumettront le formulaire et vous pourrez utiliser votre code de liaison beforeunload à votre guise.

0
idrumgood

Mon problème: L'événement 'onbeforeunload' ne serait déclenché que s'il y avait un nombre impair de soumissions (clics). J'ai eu une combinaison de solutions de threads similaires dans SO pour que ma solution fonctionne. bien mon code va parler.

<!--The definition of event and initializing the trigger flag--->


$(document).ready(function() {
updatefgallowPrompt(true);
window.onbeforeunload = WarnUser;   
}

function WarnUser() {
var allowPrompt = getfgallowPrompt();
    if(allowPrompt) {
    saveIndexedDataAlert();
    return null;
    } else {
        updatefgallowPrompt(true);
        event.stopPropagation
    }
}

<!--The method responsible for deciding weather the unload event is triggered from submit or not--->
function saveIndexedDataAlert() {
    var allowPrompt = getfgallowPrompt();
    var lenIndexedDocs = parseInt($('#sortable3 > li').size()) + parseInt($('#sortable3 > ul').size());

    if(allowPrompt && $.trim(lenIndexedDocs) > 0) {
        event.returnValue = "Your message";
    } else {
        event.returnValue = "   ";
        updatefgallowPrompt(true);
    }
}

<!---Function responsible to reset the trigger flag---->
$(document).click(function(event) {  
$('a').live('click', function() { updatefgallowPrompt(false); });
 });

<!--getter and setter for the flag---->
function updatefgallowPrompt (allowPrompt){ //exit msg dfds
    $('body').data('allowPrompt', allowPrompt); 
}   

function getfgallowPrompt(){        
    return $('body').data('allowPrompt');   
}
0
Yoosaf Abdulla

Essayez ceci aussi

window.onbeforeunload = function ()
{       
    if (pasteEditorChange) {
        var btn = confirm('Do You Want to Save the Changess?');
           if(btn === true ){
               SavetoEdit();//your function call
           }
           else{
                windowClose();//your function call
           }
    }  else { 
        windowClose();//your function call
    }
};
0
Bhaskara Arani

Depuis jQuery 1.7, la méthode .live () est obsolète. Utilisez .on () pour attacher des gestionnaires d’événements. Les utilisateurs d'anciennes versions de jQuery doivent utiliser .delegate () plutôt que .live ()

$(window).bind("beforeunload", function() {
    return true || confirm("Do you really want to close?"); 
}); 

sur complet ou lien

$(window).unbind();
0
Tom