2010-08-19 5 views
27

J'écris un script Greasemonkey pour un site qui modifie à un moment donné location.href.Événement lorsque window.location.href change

Comment puis-je obtenir un événement (via window.addEventListener ou quelque chose de similaire) lorsque window.location.href change sur une page? J'ai également besoin d'accéder au DOM du document pointant vers l'URL nouvelle/modifiée.

J'ai vu d'autres solutions qui impliquent des délais et des interrogations, mais j'aimerais éviter cela si possible.

Répondre

31

popstate event:

L'événement popstate est déclenché lorsque les changements d'entrée de l'histoire active. [...] L'événement popstate ne se déclenche en faisant une action du navigateur, comme un clic sur le bouton de retour (ou en appelant history.back() en JavaScript)

Alors, en écoutant popstate événement et l'envoi d'une popstate événement lors de l'utilisation history.pushState() devrait être suffisant pour prendre des mesures sur le changement href:

window.addEventListener('popstate', listener); 

const pushUrl = (href) => { 
    history.pushState({}, '', href); 
    window.dispatchEvent(new Event('popstate')); 
}; 
+0

Mais le popstate va-t-il tirer avant que le contenu ne soit chargé? – user2782001

14

Vous ne pouvez pas éviter l'interrogation, il n'y a pas d'événement pour le changement de href. L'utilisation des intervalles est assez légère de toute façon si vous ne dépassez pas les limites. Vérifier le href toutes les 50 ms environ n'aura aucun effet significatif sur la performance si vous vous inquiétez de cela.

+10

beurk qui est pas bon –

+1

@AlexanderMills: heureusement, il y a ces nouvelles solutions de 'popstate' et' hashchange'. –

6

Avez-vous essayé avant de charger? Cet événement se déclenche immédiatement avant que la page ne réponde à une demande de navigation, et cela doit inclure la modification du href.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> 
    <HTML> 
    <HEAD> 
    <TITLE></TITLE> 
    <META NAME="Generator" CONTENT="TextPad 4.6"> 
    <META NAME="Author" CONTENT="?"> 
    <META NAME="Keywords" CONTENT="?"> 
    <META NAME="Description" CONTENT="?"> 
    </HEAD> 

     <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript"></script> 
      <script type="text/javascript"> 
      $(document).ready(function(){ 
       $(window).unload(
         function(event) { 
          alert("navigating"); 
         } 
       ); 
       $("#theButton").click(
        function(event){ 
         alert("Starting navigation"); 
         window.location.href = "http://www.bbc.co.uk"; 
        } 
       ); 

      }); 
      </script> 


    <BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#FF0000" VLINK="#800000" ALINK="#FF00FF" BACKGROUND="?"> 

     <button id="theButton">Click to navigate</button> 

     <a href="http://www.google.co.uk"> Google</a> 
    </BODY> 
    </HTML> 

Prenez garde, cependant, que votre événement se déclenche chaque fois que vous quittez la page, que ce soit à cause du script, ou quelqu'un d'autre en cliquant sur un lien. Votre véritable défi consiste à détecter les différentes raisons de l'événement. (Si cela est important pour votre logique)

+0

Je ne suis pas sûr si cela fonctionnera parce que souvent les changements de hachage n'impliquent pas un rechargement de page. – samandmoore

+0

J'ai aussi besoin d'accéder au nouveau DOM, j'ai mis à jour la question pour clarifier cela. –

+0

OK - n'a pas considéré la situation de «hachage» - va penser à celui-là. En ce qui concerne l'accès au nouveau DOM, vous n'avez pas de chance (en ce qui concerne l'accès à partir d'un gestionnaire d'événement) car l'événement se déclenchera avant le chargement du nouveau DOM. Vous pourriez être en mesure d'incorporer la logique dans l'événement onload de la nouvelle page, mais vous pouvez avoir les mêmes problèmes en ce qui concerne l'identification si vous devez exécuter la logique pour chaque chargement de cette page. Pouvez-vous fournir plus de détails sur ce que vous essayez d'accomplir, y compris le flux de la page? – belugabob

2

Il y a un événement par défaut onhashchange que vous pouvez utiliser.

Documented HERE

et peut être utilisé comme ceci:

function locationHashChanged(e) { 
    console.log(location.hash); 
    console.log(e.oldURL, e.newURL); 
    if (location.hash === "#pageX") { 
     pageX(); 
    } 
} 

window.onhashchange = locationHashChanged; 

Si le navigateur ne supporte pas oldURL et newURL vous pouvez lier comme ceci:

//let this snippet run before your hashChange event binding code 
if(!window.HashChangeEvent)(function() { 
    let lastURL = document.URL; 
    window.addEventListener("hashchange", function(event) { 
     Object.defineProperty(event, "oldURL", { enumerable: true, configurable: true, value: lastURL }); 
     Object.defineProperty(event, "newURL", { enumerable: true, configurable: true, value: document.URL }); 
     lastURL = document.URL; 
    }); 
}()); 
1

J'utilise cette script dans mon extension "Grab Any Media" et fonctionne bien (comme youtube cas)

var oldHref = document.location.href; 

window.onload = function() { 

    var 
     bodyList = document.querySelector("body") 

     ,observer = new MutationObserver(function(mutations) { 

      mutations.forEach(function(mutation) { 

       if (oldHref != document.location.href) { 

        oldHref = document.location.href; 

        /* Changed ! your code here */ 

       } 

      }); 

     }); 

    var config = { 
     childList: true, 
     subtree: true 
    }; 

    observer.observe(bodyList, config); 

}; 
Questions connexes