2015-12-03 5 views
9

Sto creando una semplice estensione di Chrome per sommare la lunghezza di ciascun video in una playlist di YouTube e inserire la lunghezza totale nella pagina. Ci sono riuscito, ma il mio script funziona solo dopo aver aggiornato una pagina ma non quando il sito è stato navigato. Non è molto comodo però.Come rilevare la navigazione della pagina su Youtube e modificare l'HTML prima che la pagina venga visualizzata?

È possibile rilevare la navigazione della pagina su Youtube e inserire HTML nella pagina prima di essere visualizzato nel browser in modo che il contenuto aggiunto venga visualizzato immediatamente senza alcun ritardo e non sia necessario aggiornare la pagina? Link

Esempio: https://www.youtube.com/playlist?list=PL_8APVyhfhpdgMJ3J80YQxWBMUhbwXw8B

P.S. La mia domanda non è lo stesso di Modify elements immediately after they are displayed (not after page completely loads) in greasemonkey script? perché ho provato MutationObserver e il problema è lo stesso - un aggiornamento è necessario per mostrare le modifiche alla pagina web:

var observer = new MutationObserver(function(mutations) { 
    for (var i=0; i<mutations.length; i++) { 
     var mutationAddedNodes = mutations[i].addedNodes; 
     for (var j=0; j<mutationAddedNodes.length; j++) { 
      var node = mutationAddedNodes[j]; 
      if (node.classList && node.classList.contains("timestamp")) { 
       var videoLength = node.firstElementChild.innerText; 
       observer.disconnect();  

       var lengthNode = document.createElement("li"); 
       var lengthNodeText = document.createTextNode(videoLength); 
       lengthNode.appendChild(lengthNodeText); 
       document.getElementsByClassName("pl-header-details")[0].appendChild(lengthNode); 

       return; 
      } 
     } 
    } 
}); 
observer.observe(document, {childList: true, subtree: true}); 
+0

Hmm, ho provato ma non funziona per il mio scopo. La parte della pagina in cui voglio inserire la lunghezza video combinata è già caricata dal momento in cui viene caricata la data/ora per ogni video, quindi ho lo stesso problema, la pagina deve essere aggiornata per mostrare l'HTML iniettato. Aggiornata la mia domanda poiché è stata contrassegnata come duplicata. – Lauren

+0

Ho appena provato e no, non è stato risolto. È ancora necessario un aggiornamento. – Lauren

+0

Grazie per aver cercato di aiutare finora. Ecco lo script, con il manifest anche in basso: http://pastie.org/private/yyc7piosnsna4yq7oymia – Lauren

risposta

12

sito Youtube non ricarica le pagine di navigazione, sostituisce lo history state.

Gli script di contenuto dell'estensione non vengono reintrodotti quando l'URL cambia senza che una pagina venga ricaricata. Naturalmente quando si ricarica una pagina manualmente viene eseguito lo script di contenuto.

Sono disponibili diversi metodi per rilevare transizioni di pagina sul sito Youtube:

  • utilizzando uno script di sfondo della pagina: webNavigation API, tabs API
  • utilizzando uno script di contenuti: transitionend event per la barra di avanzamento sulle pagine di video
  • utilizzando uno script di contenuti e un evento site specific attivato sulla navigazione del video:

    Eseguire getEventListeners(window) nella console devtools e ispezionare l'uscita.

    enter image description here

    YT da navigare-start è quello che ci serve.
    nota, il vecchio design youtube ancora dimostrato in alcuni casi utilizza spfdone event


manifest.json:

{ 
    "name": "YouTube Playlist Length", 
    "version": "0.0.1", 
    "manifest_version": 2, 
    "description": ".............", 
    "content_scripts": [{ 
     "matches": [ "*://*.youtube.com/*" ], 
     "js": [ "content.js" ], 
     "run_at": "document_start" 
    }] 
} 

nota, quando si carica lo script contenuto in document_start lo farà rendere il nostro listener DOMContentLoaded eseguito leggermente prima rispetto al comportamento predefinito quando gli script di contenuto vengono iniettati leggermente dopoDOMContentLoaded. Con document_start lo script del contenuto viene eseguito quando non c'è nulla nel documento body e nemmeno l'elemento head. Allegare un listener a document è comunque possibile.

contenuto.js:

window.addEventListener("spfdone", process); // old youtube design 
window.addEventListener("yt-navigate-start", process); // new youtube design 

document.addEventListener("DOMContentLoaded", process); // one-time early processing 
window.addEventListener("load", postProcess); // one-time late postprocessing 

La funzione process altererà il pagina.
Nota, le classi e la struttura dell'elemento specificato cambieranno in futuro.

function process() { 
    if (location.pathname != "/playlist") { 
     return; 
    } 
    var seconds = [].reduce.call(
     document.getElementsByClassName("timestamp"), 
     function(sum, ts) { 
      var minsec = ts.textContent.split(":"); 
      return sum + minsec[0]*60 + minsec[1]*1; 
     }, 
     0 
    ); 
    if (!seconds) { 
     console.warn("Got no timestamps. Empty playlist?"); 
     return; 
    } 
    var timeHMS = new Date(seconds * 1000).toUTCString().split(" ")[4] 
     .replace(/^[0:]+/, ""); // trim leading zeroes 
    document.querySelector(".pl-header-details") 
     .insertAdjacentHTML("beforeend", "<li>Length: " + timeHMS + "</li>"); 
} 

La funzione postProcess che abbiamo attaccato su load verrà eseguito solo una volta quando il sito viene aperto. Usalo per l'elaborazione una volta della pagina dopo che tutti i suoi script sono stati caricati.

+0

Per riferimento, ecco un esempio dell'approccio dello script in background: http://stackoverflow.com/a/21071357/72321 – Dennis

+0

Questa soluzione funziona bene, ma purtroppo solo per YouTube vecchio design. –

+0

C'è un nuovo evento 'yt-navigate-start' sul sito mostrato ad alcuni utenti. Inoltre, ho leggermente generalizzato la risposta per spiegare come si può trovare l'evento reale. – wOxxOm

3

2017 risposta:

Io lo uso per nuovo Materiale design versione Youtube

body.addEventListener("yt-navigate-finish", function(event) { 
    // code here 
}); 

e questo per il vecchio Youtube

window.addEventListener("spfdone", function(e) { 
    // code here 
}); 

codice provengono da 2 script che ho scritto chiamata
" Downloader sottotitoli di Youtube "e" Downloader sottotitoli Youtube ".

entrambi funzionano, ho provato.

se siete interessati nel mio script e volete conoscere più particolare:
https://github.com/1c7/Youtube-Auto-Subtitle-Download

+0

Da notare che questa informazione è coperta dalla risposta esistente (sebbene usi 'yt-navigate-start') – Xan

+0

sì, questo non parlava di principio ma distribuiva il codice giusto, penso che questa risposta abbia ancora qualche valore, quindi terrei comunque questa risposta. : D grazie per averlo detto @ Xan – NamNamNam