web-dev-qa-db-fra.com

Modifier l'URL dans le navigateur sans charger la nouvelle page à l'aide de JavaScript

Comment pourrais-je avoir une action JavaScript qui pourrait avoir des effets sur la page en cours mais modifierait également l'URL dans le navigateur; ainsi, si l'utilisateur clique sur recharger ou mettre en favori la nouvelle URL est utilisée? 

Il serait également agréable que le bouton Précédent recharge l'URL d'origine.

J'essaie d'enregistrer l'état JavaScript dans l'URL.

291
Steven Noble

Si vous voulez que cela fonctionne dans les navigateurs ne supportant pas encore history.pushState et history.popState, la "vieille" méthode consiste à définir l'identifiant de fragment, ce qui ne provoquera pas de rechargement de page.

L'idée de base est de définir la propriété window.location.hash sur une valeur contenant toutes les informations d'état nécessaires, puis d'utiliser l'événement window.onhashchange ou les anciens navigateurs qui ne prennent pas en charge onhashchange (IE <8, Firefox < 3.6), vérifiez périodiquement si le hachage a changé (en utilisant setInterval par exemple) et mettez à jour la page. Vous devrez également vérifier la valeur de hachage au chargement de la page pour configurer le contenu initial.

Si vous utilisez jQuery, un plugin hashchange utilisera la méthode prise en charge par le navigateur. Je suis sûr qu'il existe également des plugins pour d'autres bibliothèques.

Une chose à ne pas oublier est la collision avec les identifiants de la page, car le navigateur fait défiler tous les éléments dont l'identifiant correspond.

187
Matthew Crumley

Avec HTML 5, utilisez la fonction history.pushState . Par exemple:

<script type="text/javascript">
var stateObj = { foo: "bar" };
function change_my_url()
{
   history.pushState(stateObj, "page 2", "bar.html");
}
var link = document.getElementById('click');
link.addEventListener('click', change_my_url, false);
</script>

et un href:

<a href="#" id='click'>Click to change url to bar.html</a>

Si vous souhaitez modifier l'URL sans ajouter une entrée à la liste du bouton Précédent, utilisez plutôt history.replaceState.

111
clu3

window.location.href contient l'URL actuelle. Vous pouvez en lire, en ajouter, et le remplacer, ce qui peut provoquer un rechargement de page.

Si, comme cela semble être le cas, vous souhaitez enregistrer l'état JavaScript dans l'URL afin de pouvoir l'ajouter à un signet, sans recharger la page, ajoutez-la à l'URL actuelle après un # et laissez un morceau de JavaScript déclenché par l'événement onload URL pour voir si elle contient l'état sauvegardé.

Si vous utilisez un? au lieu d'un #, vous forcerez un rechargement de la page, mais comme vous allez analyser l'état sauvegardé au chargement, cela peut ne pas être un problème; De plus, les boutons avant et arrière fonctionnent correctement.

37
moonshadow

Je soupçonne fortement que ce n'est pas possible, car ce serait un problème de sécurité incroyable s'il en était ainsi. Par exemple, je pourrais créer une page qui ressemblerait à une page de connexion à une banque et donner à l'URL de la barre d'adresse l'aspect tout comme la vraie banque!

Peut-être que si vous expliquez pourquoi vous voulez faire cela, les gens pourraient peut-être suggérer des approches alternatives ...

[Modifier en 2011: depuis que j'ai écrit cette réponse en 2008, plus d'informations ont été découvertes concernant une technique HTML5 qui permet de modifier l'URL tant qu'il s'agit de la même origine]

22
Paul Dixon

jQuery a un excellent plugin pour changer l'URL des navigateurs, appelé jQuery-pusher.

JavaScript pushState et jQuery peuvent être utilisés ensemble, comme:

history.pushState(null, null, $(this).attr('href'));

Exemple:

$('a').click(function (event) {

  // Prevent default click action
  event.preventDefault();     

  // Detect if pushState is available
  if(history.pushState) {
    history.pushState(null, null, $(this).attr('href'));
  }
  return false;
});


Utiliser uniquement JavaScript history.pushState(), qui modifie le référant, qui est utilisé dans l'en-tête HTTP pour les objets XMLHttpRequest créés après la modification de l'état.

Exemple:

window.history.pushState("object", "Your New Title", "/new-url");

La méthode pushState ():

pushState() accepte trois paramètres: un objet state, un titre (actuellement ignoré) et (éventuellement) une URL. Examinons chacun de ces trois paramètres plus en détail:

  1. objet d'état - L'objet d'état est un objet JavaScript associé à la nouvelle entrée d'historique créée par pushState(). Chaque fois que l'utilisateur accède au nouvel état, un événement popstate est déclenché et la propriété state de l'événement contient une copie de l'objet state de l'entrée d'historique.

    L'objet d'état peut être tout ce qui peut être sérialisé. Étant donné que Firefox enregistre les objets d'état sur le disque de l'utilisateur afin qu'ils puissent être restaurés après le redémarrage de son navigateur, nous imposons une taille maximale de 640 000 caractères à la représentation sérialisée d'un objet d'état. Si vous transmettez à pushState() un objet d'état dont la représentation sérialisée est supérieure à celle-ci, la méthode lève une exception. Si vous avez besoin de plus d’espace, nous vous recommandons d’utiliser sessionStorage et/ou localStorage.

  2. title - Firefox ignore actuellement ce paramètre, bien qu'il puisse l'utiliser ultérieurement. Passer la chaîne vide ici devrait être sûr contre les modifications futures de la méthode. Vous pouvez également attribuer un titre abrégé à l’État dans lequel vous vous déplacez.

  3. URL - L'URL de la nouvelle entrée d'historique est donnée par ce paramètre. Notez que le navigateur ne tentera pas de charger cette URL après un appel à pushState(), mais il pourrait tenter de charger l'URL ultérieurement, par exemple après le redémarrage de son navigateur par l'utilisateur. La nouvelle URL n'a pas besoin d'être absolue. s'il est relatif, il est résolu par rapport à l'URL actuelle. La nouvelle URL doit être de même origine que l'URL actuelle. sinon, pushState() lève une exception. Ce paramètre est facultatif. s'il n'est pas spécifié, il est défini sur l'URL actuelle du document.

8
Ilia Rostovtsev

Les paramètres de sécurité du navigateur empêchent les utilisateurs de modifier directement l’URL affichée. Vous pouvez imaginer les vulnérabilités d'hameçonnage que cela causerait.

Le seul moyen fiable de modifier l’URL sans changer de page est d’utiliser un lien interne ou un hachage. Par exemple: http://site.com/page.html devient http://site.com/page.html#item1 . Cette technique est souvent utilisée en hijax (AJAX + préserver l'historique). 

En faisant cela, je vais souvent simplement utiliser des liens pour les actions avec le hachage comme href, puis ajouter des événements click avec jquery qui utilisent le hachage demandé pour déterminer et déléguer l'action. 

J'espère que cela vous met sur la bonne voie. 

8
Jethro Larson

Il existe un composant Yahoo YUI (Browser History Manager) qui peut gérer cela: http://developer.yahoo.com/yui/history/

4
powtac

La galerie de photos de Facebook utilise un #hash dans l'URL. Voici quelques exemples d'URL:

Avant de cliquer sur 'suivant':

/photo.php?fbid=496429237507&set=a.218088072507.133423.681812507&pid=5887027&id=681812507

Après avoir cliqué sur 'suivant':

/photo.php?fbid=496429237507&set=a.218088072507.133423.681812507&pid=5887027&id=681812507#!/photo.php?fbid=496435457507&set=a.218088072507.133423.681812507&pid=5887085&id=681812507

Notez le hash-bang (#!) Immédiatement suivi de la nouvelle URL.

3
Jonathon Hill

Il existe un plugin jquery http://www.asual.com/jquery/address/

Je pense que c'est ce dont vous avez besoin.

2
Hash

mon code est:

//change address bar
function setLocation(curLoc){
    try {
        history.pushState(null, null, curLoc);
        return false;
    } catch(e) {}
        location.hash = '#' + curLoc;
}

et action:

setLocation('http://example.com/your-url-here');

et exemple

$(document).ready(function(){
    $('nav li a').on('click', function(){
        if($(this).hasClass('active')) {

        } else {
            setLocation($(this).attr('href'));
        }
            return false;
    });
});

C'est tout :)

2
Tusko Trush

Ce qui fonctionne pour moi est - la fonction history.replaceState() qui est la suivante - 

history.replaceState(data,"Title of page"[,'url-of-the-page']);

Cela ne rechargera pas la page, vous pouvez l'utiliser avec event of javascript

2
Veshraj Joshi

Je me demandais si cela serait possible tant que le chemin parent dans la page est le même, seul quelque chose de nouveau y est ajouté.

Donc, disons que l'utilisateur est à la page: http://domain.com/site/page.html Ensuite, le navigateur peut me laisser faire location.append = new.html.__ et la page devient: http://domain.com/site/page.htmlnew.html et le navigateur ne la modifie pas. 

Ou simplement autoriser la personne à changer le paramètre get, alors prenons location.get = me=1&page=1.

Ainsi, la page d'origine devient http://domain.com/site/page.html?me=1&page=1 et ne s'actualise pas. 

Le problème avec # est que les données ne sont pas mises en cache (du moins, je ne le pense pas) lorsque le hachage est modifié. C'est donc comme chaque fois qu'une nouvelle page est chargée, alors que les boutons Précédent/Suivant d'une page non- Ajax sont capables de mettre en cache des données et ne perdent pas de temps à les recharger.

D'après ce que j'ai vu, l'historique de Yahoo charge déjà toutes les données en même temps. Il ne semble pas faire de demandes Ajax. Ainsi, lorsqu'une variable div est utilisée pour traiter différentes heures supplémentaires de méthode, ces données ne sont pas stockées pour chaque état de l'historique.

1
user58670

Une réponse plus simple que je présente,

window.history.pushState(null, null, "/abc")

ceci ajoutera /abc après le nom de domaine dans l'URL du navigateur. Il vous suffit de copier ce code et de le coller dans la console du navigateur pour afficher l'URL qui devient " https://stackoverflow.com/abc ".

0
Samim

J'ai eu du succès avec:

location.hash="myValue";

Il ajoute simplement #myValue à l'URL actuelle. Si vous devez déclencher un événement sur la page Load, vous pouvez utiliser le même location.hash pour vérifier la valeur pertinente. N'oubliez pas de supprimer le # de la valeur renvoyée par location.hash, par exemple.

var articleId = window.location.hash.replace("#","");
0
Adam Hey