How to detect page navigation on YouTube and modify its appearance seamlessly?

Solution 1:

YouTube site doesn't reload pages on navigation, it replaces the history state.

The extension's content scripts aren't reinjected when URL changes without a page being reloaded. Naturally when you reload a page manually the content script is executed.

There are several methods to detect page transitions on Youtube site:

  • using a background page script: webNavigation API, tabs API

  • using a content script: transitionend event for the progress meter on video pages

  • using a content script and a site-specific event triggered on video navigation:

    Run getEventListeners(document) in devtools console and inspect the output.

    enter image description here

    yt-navigate-start is what we need in this case.

    Notes:

    • for other tasks we might want yt-navigate-finish
    • the old youtube design was using 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"
  }]
}

Note: the matches key encompasses the entire youtube.com domain so that the content script runs when the user first opens the home youtube page then navigates to a watch page.

content.js:

document.addEventListener('yt-navigate-start', process);

if (document.body) process();
else document.addEventListener('DOMContentLoaded', process);

The process function will alter the page.
Note, the specified element classes and structure will change in the future.

function process() {
  if (!location.pathname.startsWith('/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>');
}

Solution 2:

2017 answer:

I use this for new Material Design version Youtube

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

and this for old Youtube

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

code come from 2 script I wrote call
"Youtube subtitle downloader" and "Youtube auto subtitle downloader".

both of them work, I tested.

if you are interested in my script and want know more detail:
https://github.com/1c7/Youtube-Auto-Subtitle-Download