Demander confirmation à la fermeture d’un onglet en javascript


Votre utilisateur est en train d’écrire un commentaire, upload un ficher ou fait un truc quelconque qui n’est pas terminé. Puis il clique sur “fermer l’onglet”.

Dans certains cas, vous voulez lui demander confirmation pour éviter qu’il perde tout son travail.

var confirmOnLeave = function(msg) {
 
    window.onbeforeunload = function (e) {
        e = e || window.event;
        msg = msg || '';
 
        // For IE and Firefox
        if (e) {e.returnValue = msg;}
 
        // For Chrome and Safari
        return msg;
    };
 
};
 
// message de confirmation générique du navigateur
confirmOnLeave();
 
// message de confirmation personnalisé
confirmOnLeave('Vous allez perdre votre travail, êtes vous sûr(e) de vouloir quitter la page ?');

Quand vous appelez la fonction confirmOnLeave(), le callback de l’événement ‘onbeforeunload’ va être remplacé par une nouvelle fonction. Vous pouvez appeler cette fonction n’importe quand, l’événement ne se déclenche que quand l’utilisateur quitte la page de toute façon.

Cette fonction ne fait que retourner un message et assigner le message à l’attribut returnValue.

La navigateur va réagir ainsi:

  • À la fermeture de la page, il va déclencher l’événement ‘onbeforeunload’.
  • Au déclenchement de l’événement, il va appeler le callback.
  • Le navigateur va ensuite regarder la valeur de returnValue. Si elle n’est pas undefined, il va demander confirmation à l’utilisateur avec une pop up.
  • Le contenu de la pop up dépend de returnValue. Si c’est une chaîne vide, c’est un message générique, sinon, c’est le contenu de la chaîne qui est affiché.

Dans la plupart des cas, cette fonction suffit. Mais si vous utilisez d’autres codes JS qui ont besoin aussi de réagir à ‘onbeforeunload’ (comme par exemple pour faire un autosave), dans ce cas il vaut mieux utiliser utiliser une gestion avancée d’attachement de callback a des événements (pour qu’ils ne s’écrasent pas les uns les autres). Vous pouvez coder ça à la main, ou juste utiliser celui de jQuery qui fait ça très bien:

$(window).bind('beforeunload', function(){
    ...
});

18 thoughts on “Demander confirmation à la fermeture d’un onglet en javascript

  • kontre

    Mais par pitié, sortez une popup uniquement quand c’est absolument indispensable !

    Grmbll…

    • Max

      Voyons les choses positivement :)

      Tu fais un site qui permet à tes utilisateurs de téléverser un fichier image.
      L’utilisateur commence à remplir ses finos, etc puis téléverse l’image.
      Comme ça prend du temps car l’image est grosse et que la cnx est pourrit il se balade sur un autre site puise revient voir de temps en temps où ça en est.
      Et là encore un peu dans le gaz de la cuite de la veille il ferme l’onglet malancontreusement ! Mais ouf voilà qu’une popup le bloque et lui indique que si il se tire son téléversement sera perdu avec toutes les infos entrées, etc. Il peut donc annuler sa connerie et conserver son boulot.

  • r4is3

    Alors là, sorry mais je ne peux absoluement pas blairer les pages web qui refusent de se fermer sans confirmation. L’utilisateur clique par “megarde” sur la croix et il perd son contenu, tant pis pour lui! ca m’est deja arrivé, c’est rageant mais devoir chercher ou se trouve cette putain de popup de merde qui empeche mon navigateur de se fermer (voir carrement mon OS,ca m’agace vraiment fort!

  • kontre

    @r4is3 Les navigateurs modernes affichent l’onglet sur lequel l’alerte s’est ouverte. Tu n’as rien à chercher normalement.

  • pika822

    salut
    Sujet intéressant, un de mes collègues avaient exactement cette problématique. Malheureusement, cette méthode ne marche pas bien avec tous les navigateurs :
    – opera s’en tamponne le coquillard, il ferme l’onglet
    – firefox n’affiche pas le message personnalisé
    – ie … ça marche
    Je viens de tester rapidement, j’ai manqué peut être quelque chose

  • Sam Post author

    Le support est en effet inégal selon les browsers (quelle surprise !). Pas de message pour FF. Pas de gestion de onunload sur opera. Marche correctement sur webkit et IE.

    Enfin, on a quand même un confirmation à la fermeture pour ie, ff, chrome et safari. C’est plutot pas mal, ça couvre pas mal d’utilisateur, pour une feature qui a une forte valeur ajoutée sur les contenus user generated en ligne.

  • pika822

    Effectivement, ça couvre pas mal. C’est dommage qu’il n’y ait pas d’onunload dans opera. J’ai déja rencontré des applis web où la session coté serveur devait se cloturer si l’utilisateur se déconnectait/fermait la page où autre. Ca n’aurait pas été possible avec opera. Heureusement, le navigateur cible était ie6 … mon dieu, qu’est ce que je viens d’écrire !!

  • Sam Post author

    Je n’ai pas de tampon approprié pour cette dernière phrase…

  • r4is3

    @kontre ouais mais quand c’est dans un autre bureau et sur un autre ecran (ce qui m’arrive 99% du temps) bah c’est relou.
    Trés franchement mon avis est de laisser à l’utilisateur la responsabilité sinon on se retrouve avec des users debiles profonds qui ne savent même pas que le truc qu’ils utilisent là s’appelle un “NA-VI-GA-TEUR”. Et trés franchment, ca dans ma vie de sysadmin ca me donne envie de tuer des gens! xD

  • Sam Post author

    @r4is3: j’ai été longtemps de ton avis, mais Max m’a ramené à la réalité. La plupart, que dis-je, l’immense majorité des utilisateurs ne savent pas se servir de leur ordinateur. Même pas un petit peu. Ils ne lisent rien. Ne comprennent rien. Et ne sont pas patient.

    Si tu fais un site grand publique, il faut donc tabler sur des utilisateurs lambda, qui ne savent pas ouvrir dans un nouvel onglet, qui ne vérifient pas si le traitement est toujours en cours et ferment la page, qui ne cherchent pas à comprendre quelque chose qui ne marche pas et passe tout de suite à autre chose.

    Si tu veux que ton site soit utilisé, tu n’as pas le choix. C’est comme target="_blank". J’étais archi contre par principe. Mais tu te rends vite compte après test sur ta cible que tes utilisateurs ne font pas de différence entre ton site et un autre, et qu’ils sortent très souvent de ton site sans le vouloir en cliquant sur un lien externe, pour ne jamais revenir (ils ne s’en rendent même pas compte). Ouvrir certains liens de manière forcée dans un nouvel onglet devient alors indispensable si tu ne veut pas voir 10 % de ta user base qui disparaît mystérieusement. Je suis d’accord, c’est hyper chiant pour quelqu’un qui sait utiliser “click milieu” sur sa souris, moi le premier. Mais nous ne sommes pas ceux qui rapportent le fric qui paie les serveurs et les salaires.

    Nous vivons entre geeks, mais les gens qui paient sur internet, ce sont massivement des non geeks. Si le fait qu’ils paient est ce qui te nourrit, tu n’as pas le choix, tu dois faire en fonction d’eux.

    Souvent on me dit “mais c’est pas parcequ’il sont non geek qu’ils sont débiles”. Vous n’avez pas idée. Vous n’avez juste aucune idée du niveau des gens qui utilisent internet. Il est bas. TRES, TRES bas.

    Je suis pour éduquer les gens. Les informer. Ne pas les prendre pour des cons. Mais en attendant il faut faire avec leur comportement ACTUEL, et il est ainsi, que vous le vouliez de toute votre force n’y change rien.

    Faudra que je fasse un article là dessus.

  • Teocali

    @sam

    Gros, très gros pluzin.

    @r4is3
    “Et trés franchment, ca dans ma vie de sysadmin ca me donne envie de tuer des gens! xD”
    Moi, ce qui me donne envie de tuer des gens, dans ma vie de développeur, c’est les développeurs qui ne font aucun effort pour rendre leur application utilisable, qui développent selon leur paradigme, sans jamais se remettre en question, ni essayer d’adapter leur travail à leur cible. Accessoirement, c’est aussi ce genre de développeur qui à le plus de chances d’opposer une résistance a tout changement et de se scléroser dans ces pratiques, emmenant tout un projet avec lui…
    Bon, les utilisateurs qui ne font aucun effort pour remonter les bug correctement me donnent aussi envie de sortir le shotgun. Mais moins (mais beaucoup quand même)

    Tout ça pour dire que de mon point de vue, ce qui fait un bon développeur, c’est pas la capacité à te faire tenir un algorithme de voyageur de commerce sur deux lignes, ni a être capable de livrer un ERP complet en deux jours. Non, ce qui fait la plus grande qualité d’un développeur, à mes yeux, c’est l’adaptation. Adaptation au client, adaptation a l’environnement de travail, Adaptation au besoin. Les principes, dans tout ce qui concerne la technique (“je bosserais jamais pour une boite qui utilise des logiciels propriétaire”… déjà entendu de la part d’un chômeur longue durée), c’est bien joli, mais ça n’a jamais suffit a remplir l’assiette, ni même a faire des software efficaces.

  • r4is3

    @sam : Je comprend tout à fait la problematique mais là on entre dans un autre domaine que celui de la pure utilisabilité. Ca devient plus strategique ou commercial peut-être. Au final ca ne change rien au fond du probleme : vaut-il mieux avoir des utilisateurs avertis plutôt que passer son temps a essayer d’avertir les utilisateurs?

    @Teocali : Je ne developpe pas, j’ai horreur de ca, je suis architecte systeme et hormis ca, je suis trés proche de l’utilisateur standard, je veux des choses qui font ce que je leur demande sans me casser la tête, mais la base de l’informatique ca reste l’interaction! Si on reduit l’interaction il reste quoi?
    Je suis d’accord avec toi, un bon developpeur doit savoir s’adapter, sortir de son carcan et surtout ne pas être refractaire au changement.
    Je reste fermement convaincu de la necessité d’eduquer les utilisateurs! L’alternative reste a accepter qu’il y a ceux qui fabriquent/concoivent/savent et ceux qui subissent ce qu’il ne veulent pas apprendre. Et ca, pour moi ce n’est pas acceptable.

  • Teocali

    “Eduquer l’utilisateur”… c’est bien joli, et je suis tout a fait d’accord avec toi… pour une application dont le public cible est relativement limité. Typiquement, les application B2B. Par contre, quand tu développes un site (par exemple) dont la cible idéale constitue 100 % de la population (dont la plupart auront une main occupée, en plus. Coucou max). ben désolé, si tu veux bouffer, tu obliges pas ton utilisateur à s’adapter à toi, parce que sinon, il ira voir ailleurs. Les principes, c’est bien joli, mais ça n’a jamais suffit à remplir l’assiette, ni payer les capotes.

    • Max

      J’ai un pote qui voulait faire le bien comme ça aussi, asser déterminé et il pensait qu’il fallait faire “réfléchir” l’utilisateur.
      A ce jour il n’a toujours pas de site à lui qui brasse du trafic malgrès sa supériorité évidente à tous programmeurs que j’ai pu rencontrer.

      Si apple a cartonné avec son iphone c’est bien parceque “une application, une fonction” et ça doit marcher de suite, être rapide et avec un minimum d’options.
      D’ailleurs bcp de geeks se sont foutus de leur geule quand ils ont annoncé le copier/coller sur l’iPhone, ces geeks avaient oubliés que l’utilisateur d’iPhone ne connait que word sur son PC, et en plus ça a permis de faire passer le nouvel Os et surtout de monter graduellement, pas de tout balancer d’un coup.
      Certes on peut croire qu’apple a pris ses users pour des cons, mais moi je trouve ça simplement génial.

  • Teocali

    je suis d’accord. Jusqu’à la sortie de Android 4, ça m’arrachait la gueule, mais pour le grand public, y’avait pas photo : l’Iphone était le meilleur smartphone disponible. Avec le 4.0, Android commence touuuut juste a se mettre a niveau en terme d’usabilité.

  • Retep

    @pika822: “firefox n’affiche pas le message personnalisé”

    Pour le message personnalisé sur Firefox il faut remplacer :

    // For IE and Firefox
    if (e) {e.returnValue = msg;}

    // For Chrome and Safari
    return msg;

    Par :

    if(/Firefox[\/\s](\d+)/.test(navigator.userAgent) && new Number(RegExp.$1) >= 4) {
    if(confirm(msg)) {
    history.go();
    } else {
    window.setTimeout(function() {
    window.stop();
    }, 1);
    }
    } else {
    return msg;
    }

Comments are closed.

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.