web-dev-qa-db-fra.com

Existe-t-il un événement de chargement inter-navigateur lorsque vous cliquez sur le bouton Précédent?

Pour tous les principaux navigateurs (sauf IE), l’événement JavaScript onload ne se déclenche pas lors du chargement de la page à la suite d’une opération du bouton Précédent: il ne se déclenche que lors du premier chargement de la page.

Quelqu'un peut-il m'indiquer un exemple de code inter-navigateurs (Firefox, Opera, Safari, IE,…) qui résout ce problème? Je connais l’événement pageshow de Firefox, mais malheureusement, ni Opera ni Safari ne l’implémentent.

177
Bill

Les gars, j'ai trouvé que JQuery n'a qu'un seul effet: la page est rechargée lorsque le bouton Précédent est enfoncé. Cela n'a rien à voir avec " ready ".

Comment cela marche-t-il? Eh bien, JQuery ajoute un écouteur d’événement onunload .

// http://code.jquery.com/jquery-latest.js
jQuery(window).bind("unload", function() { // ...

Par défaut, cela ne fait rien. Toutefois, cela semble déclencher un rechargement dans Safari, Opera et Mozilla - quel que soit le contenu du gestionnaire d'événements.

[ edit (Nickolay) : voici pourquoi cela fonctionne de cette façon: webkit.org , developer.mozilla.org . Veuillez lire ces articles (ou mon résumé dans une réponse séparée ci-dessous) et déterminer si vous vraiment avez besoin de le faire et ralentissez le chargement de votre page pour vos utilisateurs.]

Vous ne pouvez pas y croire? Essaye ça:

<body onunload=""><!-- This does the trick -->
<script type="text/javascript">
    alert('first load / reload');
    window.onload = function(){alert('onload')};
</script>
<a href="http://stackoverflow.com">click me, then press the back button</a>
</body>

Vous verrez des résultats similaires avec JQuery.

Vous voudrez peut-être comparer à celui-ci sans onunload

<body><!-- Will not reload on back button -->
<script type="text/javascript">
    alert('first load / reload');
    window.onload = function(){alert('onload')};
</script>
<a href="http://stackoverflow.com">click me, then press the back button</a>
</body>
115
user123444555621

Certains navigateurs modernes (Firefox, Safari et Opera, mais pas Chrome) prennent en charge le cache spécial "précédent/suivant" (je l'appellerai bfcache, terme inventé par Mozilla), impliqué lorsque l'utilisateur navigue à l'arrière. Contrairement au cache standard (HTTP), il capture l'état complet de la page (y compris l'état de JS, DOM). Cela lui permet de recharger la page plus rapidement et exactement comme l'utilisateur l'a laissée.

L'événement load n'est pas censé se déclencher lorsque la page est chargée à partir de ce bfcache. Par exemple, si vous avez créé votre interface utilisateur dans le gestionnaire "load" et que l'événement "load" a été déclenché une fois lors du chargement initial, et la deuxième fois lorsque la page a été rechargée à partir de bfcache, la page se retrouverait doubler les éléments de l'interface utilisateur.

C’est aussi pourquoi l’ajout du gestionnaire "unload" empêche la page d’être stockée dans le bfcache (ce qui ralentit la navigation): le gestionnaire de déchargement peut effectuer des tâches de nettoyage, ce qui peut laisser la page dans un état impraticable.

Pour les pages qui ont besoin de savoir quand elles sont renvoyées, Firefox 1.5+ et la version de Safari avec le correctif pour bug 28758 prennent en charge des événements spéciaux appelés "pageshow" et "pagehide".

Références:

73
Nickolay

J'ai rencontré un problème que mon js ne s'exécutait pas lorsque l'utilisateur avait cliqué en arrière ou en avant. J'ai d'abord essayé d'empêcher le navigateur de mettre en cache, mais cela ne semblait pas être le problème. Mon javascript a été configuré pour s'exécuter après le chargement de toutes les bibliothèques, etc. J'ai vérifié ceux-ci avec l'événement readyStateChange.

Après quelques tests, j'ai découvert que le readyState d'un élément d'une page sur laquelle vous avez cliqué en arrière n'est pas "chargé" mais "complet". L'ajout de || element.readyState == 'complete' à mon instruction conditionnelle a résolu mes problèmes.

Je pensais partager mes découvertes, espérons-le, ils aideront quelqu'un d'autre.

Editer pour compléter

Mon code ressemblait à ceci:

script.onreadystatechange(function(){ 
   if(script.readyState == 'loaded' || script.readyState == 'complete') {
      // call code to execute here.
   } 
});

Dans l'exemple de code ci-dessus, la variable de script était un élément de script nouvellement créé qui avait été ajouté au DOM.

31
Brian Heese

OK, voici une solution finale basée sur la solution initiale de ckramer et l'exemple de palehorse qui fonctionne dans tous les navigateurs, y compris Opera. Si vous définissez history.navigationMode sur 'compatible', la fonction Ready de jQuery se déclenchera lors des opérations du bouton Précédent dans Opera ainsi que dans les autres navigateurs principaux.

Cette page a plus d'informations .

Exemple:

history.navigationMode = 'compatible';
$(document).ready(function(){
  alert('test');
});

J'ai testé cela dans Opera 9.5, IE7, FF3 et Safari, et cela fonctionne dans tous.

21
Bill

Je ne pouvais pas faire fonctionner les exemples ci-dessus. Je voulais simplement déclencher un rafraîchissement de certaines zones div modifiées lorsque je revenais à la page via le bouton Précédent. Le truc que j’avais utilisé était de définir un champ de saisie caché (appelé "bit sale") sur 1 dès que les zones div étaient modifiées par rapport à l’original. Le champ de saisie masqué conserve en fait sa valeur lorsque je clique en arrière. Par conséquent, je peux vérifier ce bit. Si c'est le cas, j'actualise la page (ou actualise simplement les divs). Sur le chargement d'origine, cependant, le bit n'est pas défini, je ne perds donc pas de temps à charger la page deux fois.

<input type='hidden' id='dirty'>

<script>
$(document).ready(function() {
  if ($('#dirty').val()) {
    // ... reload the page or specific divs only
  }
  // when something modifies a div that needs to be refreshed, set dirty=1
  $('#dirty').val('1');
});
</script>

Et cela se déclencherait correctement chaque fois que je clique sur le bouton Retour.

6
thorie

Je pensais que ce serait pour "onunload", pas pour le chargement de pages, puisque ne parlons-nous pas de déclencher un événement en frappant "Back"? $ document.ready () est pour les événements souhaités lors du chargement de la page, quelle que soit la façon dont vous accédez à cette page (par exemple, redirection, ouverture directe du navigateur vers l'URL, etc.), pas lorsque vous cliquez sur "Retour", sauf si vous parlez à propos de quoi tirer sur la page précédente quand il charge à nouveau. Et je ne suis pas sûr que la page ne soit pas mise en cache car j'ai constaté que les javascripts le sont toujours, même si $ document.ready () y est inclus. Nous avons dû appuyer sur Ctrl + F5 lors de l'édition de nos scripts contenant cet événement chaque fois que nous les révisons et que nous voulons tester les résultats dans nos pages.

$(window).unload(function(){ alert('do unload stuff here'); }); 

est ce que vous souhaitez pour un événement onunload lorsque vous cliquez sur "Précédent" et déchargez la page en cours. Il se déclenche également lorsqu'un utilisateur ferme la fenêtre du navigateur. Cela ressemblait davantage à ce qui était souhaité, même si les réponses $ document.ready () me dépassaient en nombre. Fondamentalement, la différence est entre un événement qui se déclenche sur la page en cours lors de la fermeture ou sur celui qui se charge lorsque vous cliquez sur "Retour" pendant le chargement. Testé dans IE 7 bien, ne peut pas parler pour les autres navigateurs car ils ne sont pas autorisés là où nous sommes. Mais cela pourrait être une autre option.

4
Tom

pour les personnes qui ne veulent pas utiliser toute la bibliothèque jquery, j'ai extrait l'implémentation dans un code séparé. C'est seulement 0,4 KB grand.

Vous pouvez trouver le code ainsi qu'un tutoriel en allemand sur ce wiki: http://www.easy-coding.de/wiki/html-ajax-und-co/onload-event-cross-browser-kompatibler -domcontentloaded.html

4
Torben Brodt

Si je me souviens bien, ajouter un événement unload () signifie que la page ne peut pas être mise en cache (dans le cache en avant/en arrière), car son état change/peut changer lorsque l'utilisateur navigue. Donc, il n'est pas sûr de restaurer l'état de la dernière seconde de la page lorsque vous y revenez en naviguant dans l'objet historique.

4
arcijsg

Je peux confirmer à ckramer que l'événement ready de jQuery fonctionne dans IE et FireFox. Voici un exemple:

<html>
<head>
    <title>Test Page</title>
    <script src="http://code.jquery.com/jquery-latest.js" type="text/javascript"></script>
    <script type="text/javascript">
            $(document).ready(function () {
               var d = new Date();
               $('#test').html( "Hi at " + d.toString() );
            });
    </script>
</head>
<body>
    <div id="test"></div>
    <div>
        <a href="http://www.google.com">Go!</a>
    </div>
</body>
</html>
4
palehorse

jQuery'sprêt l'événement a été créé pour ce type de problème. Vous voudrez peut-être creuser dans la mise en œuvre pour voir ce qui se passe sous les couvertures.

3
ckramer

Bill, j'ose répondre à votre question, mais je ne suis pas sûr à 100% de mes suppositions. Je pense que les autres navigateurs, puis IE, lorsqu’un utilisateur accède à une page de l’historique, chargeront non seulement la page et ses ressources à partir de la mémoire cache, mais ils restaureront également l’intégralité de son état DOM (lecture de session). IE ne fait pas de restauration DOM (ou au moins ne le fait pas) et donc l'événement onload semble être nécessaire pour une réinitialisation correcte de la page.

2
Sergey Ilinsky

J'ai essayé la solution de Bill en utilisant $ (document) .ready ... mais au début cela n'a pas fonctionné. J'ai découvert que si le script est placé après la section html, cela ne fonctionnera pas. Si c'est la section head, cela fonctionnera, mais seulement dans IE. Le script ne fonctionne pas dans Firefox.

2
Johann

L'événement de déchargement ne fonctionne pas correctement sur IE 9. Je l'ai essayé avec l'événement de chargement (onload ()), il fonctionne correctement sur IE 9 et FF5 =.

Exemple:

<%@ page language="Java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
    jQuery(window).bind("load", function() {
        $("[name=customerName]").val('');
    });
</script>
</head>
<body>
    <h1>body.jsp</h1>
    <form action="success.jsp">
        <div id="myDiv">

        Your Full Name: <input name="yourName" id="fullName"
            value="Your Full Name" /><br> <br> <input type="submit"><br>

        </div>

    </form>
</body>
</html>
1
mallesham

OK, j'ai essayé ceci et cela fonctionne dans Firefox 3, Safari 3.1.1 et IE7 mais pas dans Opera 9.52.
Si vous utilisez l'exemple ci-dessous (basé sur l'exemple de palehorse), vous obtenez une boîte d'alerte lors du premier chargement de la page. Mais si vous passez ensuite à une autre URL, puis cliquez sur le bouton Précédent pour revenir à cette page, vous ne verrez pas de boîte d’alerte s’ouvrir dans Opera (mais vous le ferez dans les autres navigateurs). .

Quoi qu'il en soit, je pense que c'est assez proche pour l'instant. Merci tout le monde!

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Untitled Document</title>
<meta http-equiv="expires" content="0">
<script src="jquery.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready( 
                    function(){
                      alert('test');
                    }
                 );
</script>
</head>
<body>
<h1>Test of the page load event and the Back button using jQuery</h1>
</body>
</html>
1
Bill

J'ai utilisé un modèle HTML. Dans le fichier custom.js de ce modèle, il y avait une fonction comme celle-ci:

    jQuery(document).ready(function($) {

       $(window).on('load', function() {
          //...
       });

    });

Mais cette fonction ne fonctionnait pas quand je reviens à la page précédente.

Alors j'ai essayé et ça a marché:

    jQuery(document).ready(function($) {
       //...
    });

   //Window Load Start
   window.addEventListener('load', function() {
       jQuery(document).ready(function($) {
          //...
       });
   });

Maintenant, j'ai 2 "prêt" fonction, mais il ne donne aucune erreur et la page fonctionne très bien.

Néanmoins, je dois déclarer qu'il a testé sur Windows 10 - Opera v53 et Edge v42 mais pas d'autres navigateurs. Gardez à l'esprit ceci ...

Remarque: la version de jquery était 3.3.1 et la version de migration était 3.0.0

0
bafsar