Jouer avec les urls en javascript

De nombreux sites web ont fait le choix d'utiliser massivement de l'ajax. C'est le cas de Facebook par exemple. Le clic sur une photo affiche un popup chargé en ajax. Vous n'y avez peut-être jamais fait attention mais lors de l’affichage d'un de ces popup l'url est modifiée. Ceci n'est possible qu'avec les navigateurs récents et uniquement avec des url ayant le même nom de domaine. Je propose dans cette brève de présenter la solution pour modifier dynamiquement les urls des pages.

Modifier l'url de la page

L'objet history permet de modifier l'historique du navigateur. Pour ajouter un nouvel état on utilise la méthode pushState. Voici le prototype de la méthode :

  1. history.pushState(Object state, String title, String url);

L'objet "state" est un objet quelconque pouvant être sérialisé. Il est retourné lorsqu'un évènement popstate est levé. La chaîne title est le titre de l'évènement. Enfin le dernier argument est l'url associés au nouvel êtat.

Pour changer l'url on fera donc quelque chose comme :

  1. history.pushState({}, '', 'http://domain.com/page2.html');

Cas spécifique pour les anciens navigateurs

Les anciens navigateurs ne supportent pas ce comportement. Il faut donc utiliser une autre méthode moins sexy si on souhaite changer l'url de la page : les ancres.

Une ancre c'est ce qui se trouve après l'url préfixée d'un dièse. Par exemple : domain.com#page2. À l'origine, cela permet de scroller automatiquement la page au niveau de l’élément ayant pour l'ancre comme attribut id, dans notre exemple : page2.

Le code ressemblera alors à cela :

  1. if (typeof(history) != 'undefined' && typeof(history.pushState) != 'undefined') {
  2. history.pushState({}, '', 'http://domain.com/page2.html');
  3. } else {
  4. window.location = '#' + 'http://domain.com/page2.html' ;
  5. }

Les boutons précédant et suivant

L'évènement popstate est levé dès que l'on clique sur le bouton précédant ou suivant du navigateur. Il n'est normalement pas possible de savoir si c'est le bouton suivant ou précédant qui a été cliqué. Pour cela, il faut ruser un peu :)

Commençons donc par définir une variable globale nommée uid. Cette dernière nous permettra d’identifier de façon unique chaque nouvel état :

  1. var uid = 0;

À chaque pushState, il faut ajouter cet uid après l'avoir incrémenté :

  1. uid++;
  2. history.pushState({uid: uid}, '', 'http://domain.com/page2.html');

Maintenant, grâce à l'évènement popstate effectuons une action différente en fonction que l'on ait cliqué sur le bouton précédent ou suivant :

  1. $(window).bind('popstate', function(event) {
  2. // Si event.originalEvent.state n'existe pas, alors on est sur la première page (on a donc cliqué sur pécédent)
  3. // Si event.originalEvent.state.uid est inférieur au uid global, alors on a cliqué sur précedent
  4. if (!event.originalEvent.state || event.originalEvent.state.uid < uid) {
  5. // Il ne faut pas oublier de setter le nouvel uid
  6. if (event.originalEvent.state) {
  7. uid = event.originalEvent.state.uid;
  8. } else {
  9. uid = 0;
  10. }
  11. alert('Prev');
  12. } else {
  13. // Il ne faut pas oublier de setter le nouvel uid
  14. uid = event.originalEvent.state.uid;
  15. alert('Next');
  16. }
  17. });

Le cas de chrome

Si vous avez testé le code précédent sous chrome vous vous être certainement rendu compte d'un problème avec ce dernier. En effet, lors du chargement de la page, un évènement popstate est lancé. Notre script a donc cru que l'on avait cliqué sur le bouton "précédent". Pour corriger cela rapidement, il suffit d'ajouter un setTimeout :

  1. window.setTimeout(function() {
  2. $(window).bind('popstate', function(event) {
  3. // ...
  4. }
  5. }, 500);

Et pour les anciens navigateurs ?

Pour les navigateurs n’implémentant pas l'évènement "popstate", il faut ruser en analysant les urls ou en ajoutant l'uid dans l'ancre. Le code peut grandement changer en fonction de votre besoin, je ne détaillerai donc pas ici de solution.

 

Ajouter un commentaire

Le code HTML est affiché comme du texte et les adresses web sont automatiquement transformées.

À propos

Photographie

Maxence de Flotte

Développeur cœur PrestaShop

Passionné de nouvelles technologies

PHP, HTML5/CSS3, jQuery, Bootstrap, LESS CSS, ...

Voir mon CV

Mes projets