Why doesn't this script work with successive p

2020-08-01 06:32发布

问题:

I am currently using the following script in Tampermonkey in Google Chrome:

// ==UserScript==
// @name        Youtube opt in Ads per channel
// @namespace   schippi
// @include     http://www.youtube.com/watch*
// @version     1
// ==/UserScript==

var u = window.location.href;
if (u.search("user=") == -1) {
   var cont = document.getElementById("watch7-user-header").innerHTML;
   var user=cont.replace(/.+\/user\//i,'').replace(/\?(?:.|\s)*/m,'');
   window.location.href = u+"&user="+user;
}

It seems to work perfectly in Firefox with Greasemonkey but in Google Chrome, it seems that it only works on the first click on a YouTube video.

More specifically, if I click on a YouTube video:
   youtube.com/watch?v=MijmeoH9LT4,
it redirects me to:
   youtube.com/watch?v=MijmeoH9LT4&user=Computerphile

However, if I click on a video from the related videos vertical bar, it doesn't seem to do any further redirection.

回答1:

Alas, there is still no really "neat" way to do this in Chrome. (Firefox has more options.)

Your best bet is just to poll location.search; see below.

Your other options in Chrome, currently, are not recommended -- but here they are for reference:

  • Hack into the history.pushState function. This gives faster notice of page changes, BUT fires before you can run your code, so it will still need a timer. Plus, it brings in cross-scope problems, in a userscript environment.
  • Use Mutation Observers to monitor changes to the <title> tag. this may work okay, but may fire after you want it to, causing delays and pronounced "flicker". Also may not work on poorly designed pages (YouTube is okay).


Also note that the replace() statements, from the question, will blow up the URL and 404 the script in several cases. Use DOM methods to get the user (see below).


Polling code (Simple, robust, cross-browser):

// ==UserScript==
// @name        Youtube opt in Ads per channel
// @namespace   schippi
// @include     http://www.youtube.com/watch*
// @version     1
// @grant       GM_addStyle
// ==/UserScript==
/*- The @grant directive is needed to work around a design change
    introduced in GM 1.0.   It restores the sandbox.
*/
var elemCheckTimer      = null;
var pageURLCheckTimer   = setInterval (
    function () {
        if (this.lastQueryStr !== location.search) {
            this.lastQueryStr = location.search;
            gmMain ();
        }
    }
    , 111   //-- Nine times a second. Plenty fast w/o bogging page
);

function gmMain () {
    if ( ! /user=/.test (window.location.href) ) {
       elemCheckTimer = setInterval (checkUserAndRelocate, 24);
    }
}

function checkUserAndRelocate () {
    var elem        = document.querySelector (
        "#watch7-user-header a[href*='/user/']"
    );
    if (elem) {
        clearInterval (elemCheckTimer);
        var user    = elem.href.match (/\/user\/(\w+)\W?/);
        if (user  &&  user.length > 1) {
            location.replace (location.href + "&user=" + user[1]);
        }
    }
}