0

When I make a chrome extension for youtube with userscript in Tampermonkey or as a Chrome Extension the extension doesn't recognize when it leaves the page that the extension should run on like it normally would because of the history.push function that has been implemented recently. So for example:

// @include     http://www.youtube.com/feed/subscriptions

I did this so it should only run when I go to my subscriptions but when I click a video it keeps loading the extension. When I turn it into a chrome extension the problem persists.

How can I see if it is on a certain youtube-page to then run my code?

Ruben Smit
  • 15
  • 1
  • 5

1 Answers1

2

The problem is caused by pages that modify the URL by history.pushState(). It only modifies the display URL and the contents without a page reload.

So when you run a script at Tampermonkey you need to force a reload on that manipulation.

Note: if you only want to make the script not run when you navigate away from the subscriptions page then just change the @match statement to your @include.

// ==UserScript==
// @name       YT pushState
// @namespace  http://tampermonkey.net/
// @version    0.1
// @match      *://*.youtube.com/*
// @grant      none
// ==/UserScript==

window.history.__proto__.pushState = function(a, b, url) {
    window.location.href = url;
}

if (window.location.href.match(/https?:\/\/www\.youtube\.com\/feed\/.*/)) {
    console.log("Put main function here!");                               
} else {
    console.log("Ignore this page");
}
derjanb
  • 1,020
  • 10
  • 13
  • FYI, on YouTube, the URL changes before the new page has really loaded. If your script relies on the structure of the document, then this general method does not help, because the document has not changed yet when the URL changes. – Rob W Mar 11 '14 at 12:35
  • This doesn't matter. It's my understanding that he want's to run a script at URL A but not URL B while B is set by history.pushState. The script above allows either to reload the complete page when a pushState call is detected or triggers an event that can signal the userscript to stop whatever it is doing. – derjanb Mar 11 '14 at 12:49
  • If you are at URL A, then the script should not run. When you are at URL B, then the script should run. However, in YouTube's implementation, the URL already changes to URL B even when the current page is still URL A. Hence if you try to detect navigation changes by intercepting pushState calls, then your script is run too early. – Rob W Mar 11 '14 at 15:05
  • "doesn't recognize it when it leaves the page that the extension should run" -> So the question author is on A (http://www.youtube.com/feed/subscriptions) and don't want to run scripts at B (http://www.youtube.com/watch?v=*). This can be achieved by intercepting pushState calls and make them set the window.location.href property. – derjanb Mar 12 '14 at 12:26
  • Did you understand my comment? Intercepting `pushState` only offers knowledge about the updated URL. When the URL is updated, the page is still not updated (e.g. the video player is still visible even though the URL has changed to /feed/subscriptions), so calling the script at that point makes no sense (because the script expects that the document looks like the feed page, not a video page). – Rob W Mar 12 '14 at 13:23
  • I do understand your comments. I break it down to a "flowchart": feed page is opened (script now is running because of its @include) -> a video is clicked -> the page uses pushState -> we intercept it and make the whole page reload -> the video page loads -> no script is running -> solved. You're right this doesn't work when a video page is opened and a link to the feed page is clicked, cause the script is not running at the video page, but this is _not_ part of the question. – derjanb Mar 13 '14 at 13:28
  • Thanks for answering my question :) Sorry for my late reply. I realised I had to really change up my script to make this work but it was much easier than I expected :) I basically turned 2 of my plugins into one plugin now which was much easier than it sounds ^^ So thank you very much! I didn't really need to reload the whole page, both of my plugins looked for specific elements on certain pages which they can still do without reloading the page now :D – Ruben Smit Mar 17 '14 at 17:26