11

I am building an extension (some injected js) that adds some buttons to a youtube page, which works fine. My issue is that when a user clicks on another video (say in the right hand side list), the next video is loaded without an actual page reload. Is there any way to detect this change so that I can rerun my code?

I have already tried things like binding to the hashchange event, to no avail.

Matt Way
  • 32,319
  • 10
  • 79
  • 85
  • Looks like it uses `history.pushState()` to change the URL and the video. Read this answer to know how to proceed further: http://stackoverflow.com/a/5134732/921204 – techfoobar Feb 09 '14 at 09:24
  • Using the solution given by that link, it works when using the forward/back browser buttons, but I am still unable to trigger code when a video is clicked on. – Matt Way Feb 09 '14 at 09:42
  • 1
    Is popState not triggered when you open a new video? Even though its name is *pop*State, i think i read somewhere that it is triggered whenever the URL changes because of a pushState or replaceState operation. – techfoobar Feb 09 '14 at 10:50
  • Nope. If I click on a video nothing triggers. If I then click the browser back/forward buttons `onpopstate` triggers. – Matt Way Feb 09 '14 at 10:52
  • How about and interval checking the source of the video frame? – iAmOren Jun 25 '20 at 11:32

4 Answers4

13

The idea is simple:

  • Use background.js to listen for url changes to a specific youtube tab using chrome.tabs.onUpdated
  • Once tab change is detected, send the new URL to the content-script running in that tab

The background page listens for URL changes to other tabs also but I'm pretty sure you can figure out how to fix that.

manifest.json

{
    "manifest_version": 2,
    "name": "Tab url change detection",
    "version": "1.0",
    "background": {
        "persistent":true,
        "page":"bg.html"
    },
    "content_scripts": [{
            "matches": ["http://www.youtube.com/*"],
            "js": ["app.js"]
        }
    ],
    "permissions": [
        "tabs",
        "http://www.youtube.com/*"
    ]
}

background.html

<script src="background.js"></script>

background.js

//Listen for when a Tab changes state
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab){
    if(changeInfo && changeInfo.status == "complete"){
        console.log("Tab updated: " + tab.url);

        chrome.tabs.sendMessage(tabId, {data: tab}, function(response) {
            console.log(response);
        });

    }
});

app.js

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    //here we get the new 
    console.log("URL CHANGED: " + request.data.url);
});
1337holiday
  • 1,924
  • 1
  • 24
  • 42
  • Looks good. I'll mark as answer after i've had a bit of a trial of this method. – Matt Way Feb 10 '14 at 02:42
  • Test it out as a new app first then build on it. Lemme know if you find problems. – 1337holiday Feb 10 '14 at 02:52
  • @1337holiday you have the `tabId` as a parameter of your callback, you don't need to query to get a tab id. – rsanchez Feb 10 '14 at 22:23
  • @rsanchez yepp, thats something i was meaning to change, i was getting some weird error when i used `tabId` which is why i left it as that, ill verify that `tabId` works and change it – 1337holiday Feb 10 '14 at 22:28
  • 1
    I am getting `Tab updated: undefined` any chance metod is deprecated or something? – rohan-patel Nov 02 '15 at 23:32
  • @rohan-patel Dyou ever figure it out? Getting the same thing, and considering the official chrome-extension guide for google is out of date I don't have high hopes... – Laser Jun 21 '16 at 11:27
  • I do not think so. It was a group project for my course and can't recall if it worked or not. Maybe I have to open the project and see what I did. – rohan-patel Jun 25 '16 at 19:52
  • Nice and smooth as silk. Thank You. – Oleg Popov Jan 28 '17 at 17:42
8

I know it's an old thread but I hope someone else will be able to use this information.

I had a similar issue building a chrome extension for youtube. To be more specific I needed to detect the navigation within youtube.

TL;DR;
After going over most of the StackOverflow, I've ended with the following in the context.js file.

function run(){
// your youtube extention logic 
console.log('change');
}

window.onload = run;
window.addEventListener('yt-navigate-start', run,   true);

Explanation In case you wish to see all of the window events you can run getEventListeners(window).

youtube has a costume event when changing pages, the event is yt-navigate-start.

For the first time youtube loads, I used the window.onload and after that, add the event listener window.addEventListener('yt-navigate-start', run, true);

Good luck, I hope this could help.

Shahar
  • 2,101
  • 18
  • 23
3

I was recently struggling with this and I figured out what to do. I'm not sure if this is the best way to do it, but it doesn't rely on a background.js file.

var oldURL= ""

//window.setInterval takes a function and executes it after 
//a given time (defined by the second parmeter)in miliseconds

var urlChangeHandler = window.setInterval(checkUrlChange, 500)

function checkURLChange(){
  newURL = document.URL;
  if(newURL !== oldURL){
   doSomething();
   oldURL = newURL;
  }
}
Farai Gandiya
  • 79
  • 1
  • 4
2

I hope this will be helpful for somebody.

var old_url = '';
var mutationObserver = new MutationObserver(function (mutations) {
    mutations.forEach(function (mutation) {
            if (location.href != old_url) {
                old_url = location.href;
                console.log('URL was changed');
            }
    });
});

mutationObserver.observe(document.documentElement, {childList: true, subtree: true});