2010-08-19 18 views
27

Sto scrivendo uno script Greasemonkey per un sito che ad un certo punto modifica location.href.Evento quando window.location.href cambia

Come posso ottenere un evento (tramite window.addEventListener o qualcosa di simile) quando le modifiche di window.location.href in una pagina? Ho anche bisogno di accedere al DOM del documento che punta all'URL nuovo/modificato.

Ho visto altre soluzioni che riguardano timeout e polling, ma vorrei evitarlo se possibile.

risposta

31

popstate event:

L'evento popstate viene generato quando cambia ingresso storia attivi. [...] L'evento popstate viene attivato solo facendo un'azione di browser come un clic sul pulsante Indietro (o chiamando history.back() in JavaScript)

Così, ascoltando popstate evento e invio di un popstate evento quando si utilizza history.pushState() dovrebbe essere sufficiente per agire sui cambiamenti href:

window.addEventListener('popstate', listener); 

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

Ma il popstate sparerà prima che il contenuto sia caricato? – user2782001

14

Non è possibile evitare il polling, non c'è alcun evento per il cambio href.

L'utilizzo di intervalli è comunque abbastanza leggero se non si va in mare. Controllare l'href ogni 50ms circa non avrà alcun effetto significativo sulle prestazioni se sei preoccupato per questo.

+10

Yikes che non è buona –

+1

@AlexanderMills: fortunatamente ci sono queste nuove soluzioni di 'popstate' e' hashchange'. –

6

Hai provato prima di scaricare? Questo evento si attiva immediatamente prima che la pagina risponda a una richiesta di navigazione e questo dovrebbe includere la modifica di 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> 

Attenzione, però, che il vostro evento verrà generato ogni volta si esce dalla pagina, se questo è a causa della sceneggiatura, o qualcuno cliccando su un link. La tua vera sfida, è scoprire i diversi motivi per cui l'evento è stato licenziato. (Se questo è importante per la vostra logica)

+0

Non sono sicuro che funzionerà perché spesso le modifiche all'hash non comportano il ricaricamento di una pagina. – samandmoore

+0

Ho bisogno di accedere anche al nuovo DOM, ho aggiornato la domanda per chiarire che. –

+0

OK - non considera la situazione di 'hash' - penserà a questo. Per quanto riguarda la possibilità di accedere al nuovo DOM, non si ha fortuna (per quanto riguarda l'accesso da un gestore di eventi interessato) poiché l'evento si attiva prima che il nuovo DOM sia stato caricato. Potresti essere in grado di incorporare la logica nell'evento onload della nuova pagina, ma potresti avere gli stessi problemi rispetto a identificare se è necessario eseguire la logica per ogni carico di tale pagina. Puoi fornire ulteriori dettagli su ciò che stai cercando di ottenere, incluso il flusso della pagina? – belugabob

2

c'è un evento di default onhashchange che è possibile utilizzare.

Documented HERE

e può essere utilizzato in questo modo:

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

window.onhashchange = locationHashChanged; 

Se il browser non supporta oldURL e newURL si può legare in questo modo:

//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

Io uso questo script nella mia estensione "Prendi tutti i media" e funziona bene (come caso youtube)

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); 

}; 
0

Attraverso Jquery, basta provare

$(window).on('beforeunload', function() { 
    //your code goes here on location change 
}); 

Utilizzando javascript:

window.addEventListener("beforeunload", function (event) { 
    //your code goes here on location change 
}); 

Fare riferimento del documento: https://developer.mozilla.org/en-US/docs/Web/Events/beforeunload

Problemi correlati