GWT et l’historique de navigation

Notre navigateur fait correspondre une url à une page et réciproquement. Or, avec AJAX, tout se passe dans la même page…
Par exemple : notre client visite une page de notre boutique virtuelle, ajoute un article à son caddie, visualise son caddie puis appuie sur le bouton « Précédent » du navigateur pour retourner à la page de la boutique qu’il était en train de visiter. Comment va-t-on gérer ça avec GWT ?

Liens et ancres

Dans certaines url, on distingues deux éléments :

La première partie définit l’adresse physique de la page. C’est donc au serveur de traiter cette partie.
La seconde, par contre, représente un élément dans la page. C’est le client, c’est-à-dire le navigateur, qui se charge d’afficher l’élément en question. Si cet élément n’existe pas, la page est quand même affichée par le navigateur et le nom de l’ancre reste un élément du contexte du document : le DOM.
Vous trouverez ici plus d’information sur les liens et les ancres, qui ne sont pas le sujet de mon billet.

Une requête, une page, mais plusieurs affichages

Vous voulez comprendre le mécanisme ? Alors c’est parti : installez Firebug pour Firefox ou utilisez les outils de développement de Chrome. Dans un premier temps, affichez l’onglet « Réseau ».
Lancez l’url suivante : http://256.com/gray/docs/rfc2616/13.html#13.13.
Cette url contient une ancre : #13.13, qui correspond à la section 13.13 du document. Dans la capture ci-dessous, on voit bien que la ressource demandée au serveur est la page html, l’ancre n’apparait pas dans la requête :

Maintenant effaçons l’onglet console de Firebug, puis changeons l’url, dans la barre d’adresse, pour demander la section 13.5 :

L’onglet réseau de Firebug reste vide : tout se passe côté client. C’est-à-dire que la page est chargée entièrement, puis quelque chose se passe dans le navigateur, pour modifier l’affichage lorsque l’on modifie l’ancre.

Appuyons sur le bouton « Précédent » : on affiche bien la section 13.13 du document, et toujours aucune requête ne circule dans l’onglet réseau.

Enregistrer l’état de la page dans le navigateur

On a donc trouvé un mécanisme qui va permettre de modifier l’état de la page côté client. C’est pratique, car GWT tourne essentiellement côté client. Mais cela ne nous dit toujours pas comment il gère l’historique. Pour cela, il va falloir être capable de sauvegarder et de restaurer l’état d’une page.
Et bien je n’ai pas choisi ce lien au hasard. En effet, la section 13.13 de la RFC2616 spécifie que le bouton « précédent » du navigateur doit restaurer la page telle qu’elle a été chargée. Cela inclut donc le contexte de la page, alias le DOM. Or le DOM contient, outre les balises HTML de la page, toutes les variables que l’on manipule avec Javascript.
Pour comprendre, affichez maintenant l’onglet « DOM » de firebug ou Chrome, puis recommencez l’expérience ci-dessus, en observant les variables de l’objet Document (dans ma version, il faut forcer l’actualisation des données du DOM : clic-droit, puis « actualiser »). On voit que celui-ci contient l’ancre qui permet de gérer l’affichage (« 13.13″, « 13.05 » , etc.)…
Enfin, saisissons une ancre qui n’est pas dans la page (« 13.16″, par exemple). La page reste visiblement dans le même état, mais Firebug nous indique que le DOM a changé. Et si l’on fait précédent… le navigateur recharge l’état antérieur du DOM !
Bref, chaque nouvelle ancre permet d’indiquer au navigateur qu’il doit sauvegarder l’état actuel du DOM et le restaurer lorsque l’utilisateur appuiera sur « précédent ».

En pratique, la classe History de GWT

En pratique, la classe History fournit plusieurs méthodes statiques, pour gérer ce mécanisme via des « token ». Les « token » sont des ancres générées par le développeur et correspondant à un état de l’application.
Pour créer un token, il faut utiliser la méthode :

1
History.newItem(token);

Où token est une chaîne de texte générée pour sauvegarder et restaurer l’état de l’application. C’est lui que l’on verra après le # dans l’url.

1
2
3
4
5
6
History.addValueChangeHandler(new ValueChangeHandler() {
      public void onValueChange(ValueChangeEvent event) {
        String historyToken = event.getValue();
        //Du code pour restaurer l'état de l'application: masquer des composant, recharger des données, changer un onglet...
      }
}

Conclusion

Sur un petit module, cela est largement suffisant pour gérer l’appuie sur le bouton « précédent » du navigateur. Mais le « token » peut être modifié à la main par l’utilisateur… et puis je n’ai pas parlé des évolutions de l’application qui impacteraient la syntaxe du « token »… Bref, il existe des méthodes plus compliquées pour des problématiques plus compliquées.

Pour en savoir plus sur le mécanisme History de GWT : https://developers.google.com/web-toolkit/doc/latest/DevGuideCodingBasicsHistory

Une réflexion au sujet de « GWT et l’historique de navigation »

  1. Ping : Blog de la rubrique java

Les commentaires sont fermés.