如何在YouTube每次加载新页面时运行脚本?

时间:2021-02-19 01:03:55

Since some time last year, YouTube made it so that every page is not actually loading an entirely new page, but primarily just re-loading the contents in div#content. You can notice this when you click on a link in YouTube and see the red loading bar at the top of the page.

从去年的某个时候开始,YouTube让每个页面都不实际加载一个全新的页面,而主要是重新加载div#内容中的内容。当你点击YouTube上的一个链接,看到页面顶部的红色加载栏时,你会注意到这一点。

I have a Greasemonkey script that modified elements on YouTube, but now that YouTube doesn't reload the entire page, the Greasemonkey script no longer fires on every "new" page. How can I make the Greasemonkey script fire on every "new" page that I load on YouTube?

我有一个Greasemonkey脚本,在YouTube上修改了元素,但是现在YouTube没有重新加载整个页面,Greasemonkey脚本不再在每个“新”页面上触发。如何让Greasemonkey脚本在我在YouTube上加载的每个“新”页面上启动?

I'm using jQuery in this Greasemonkey script. I tried using functions like .on() with DOMNodeInserted but I can't find the right combination to make it work properly. With the event listeners that I've been using, I end up running my script hundreds of times for each page load, such as with the following:

我在这个Greasemonkey脚本中使用jQuery。我尝试过使用诸如。on()和domnodeinsert这样的函数,但是我找不到合适的组合来让它正常工作。在我使用的事件监听器中,我为每个页面加载运行了几百次脚本,例如:

$('div#page').on('DOMNodeInserted', 'div#content', function() { });

$(' div#页面”)。on(' domnodeinsert ', 'div#content', function() {});

Another solution I was thinking of was making all links on YouTube load pages like normal, without the new way that they are doing it.

我想到的另一个解决方案是让YouTube上的所有链接都像正常的一样,没有新的方式。

3 个解决方案

#1


6  

I figured it out myself after some research. First off, I don't like solutions that use setTimeout. This is often one method suggested in favor over the deprecated DOMNodeInserted for instance (which I use in some of my scripts, but try to avoid as much as possible), but if possible, I always prefer a solution where the script actually executes after a specific event. I've posted the solution I initially used in the first section below, then the final solution I used in the second section. All code below requires jQuery.

我自己做了一些调查才弄明白的。首先,我不喜欢使用setTimeout的解决方案。这通常是一种方法,建议您使用已弃用的domnodeinsert,例如(我在一些脚本中使用它,但是尽量避免),但是如果可能的话,我总是倾向于在某个特定事件之后,脚本实际执行的解决方案。我已经发布了最初在第一部分中使用的解决方案,然后是我在第二部分使用的最终解决方案。下面的所有代码都需要jQuery。

Decent solution, but not the best

At first, I had a solution where I added a click event to all A elements, which would run a timer that ran my script after 2 seconds. This isn't elegant, because if the page loads quickly, then there's a split second where the script hasn't run. And if the page loads for more than two seconds, then the script doesn't run at all. Script below:

首先,我有一个解决方案,在所有元素中添加一个click事件,它将运行一个计时器,在2秒后运行我的脚本。这并不优雅,因为如果页面加载速度很快,那么会有一秒钟的时间脚本没有运行。如果页面加载超过两秒,那么脚本就根本不会运行。脚本如下:

$('a').click(function()
{
    setTimeout(youtubeFunction, 2000);
});

Much better solution

So I began looking for a solution that was related to what I wanted to accomplish. I eventually found other people with a similar problem to mine (such as people wanting to create a Chrome script that modifies YouTube pages). This led me to this particular Stack Overflow solution, which basically says that the red loading bar at the top of YouTube pages was a CSS transition element, and that it created a transitionend (case sensitive) event when it was finished. The code in the linked solution wasn't complete (for me anyway), but it did explain how to achieve a working solution. The code I have runs only once per page, which is perfect. So here's what I have now:

所以我开始寻找一个与我想要实现的目标相关的解决方案。我最终找到了和我有类似问题的人(比如想要创建一个修改YouTube页面的Chrome脚本的人)。这让我想到了这个特殊的Stack Overflow解决方案,它基本上说YouTube页面顶部的红色加载条是一个CSS转换元素,并且它在完成时创建了一个transitionend(区分大小写)事件。链接解决方案中的代码并不完整(对我来说),但它确实解释了如何实现一个有效的解决方案。我的代码每一页只运行一次,这是完美的。这就是我现在的内容:

function youtubePageChange()
{
    youtubeFunction();
    $('body').on('transitionend', function(event)
    {
        if (event.target.id != 'progress') return false;
        youtubeFunction();
    });
}

$(youtubePageChange);

To explain the code above, basically I run the code once for when you first load a YouTube page (such as by typing the URL in the address bar). Then for every subsequent click that requires the progress bar, the code runs again.

为了解释上面的代码,我基本上只在首次加载YouTube页面时运行一次代码(比如在地址栏中输入URL)。然后,对于需要进度条的每一次后续单击,代码将再次运行。

Red progress bar code

Oh, and for future reference, when the red progress bar appears at the top of YouTube pages, the site temporarily adds a new DIV to the end of BODY, with the following code:

哦,作为将来的参考,当红色的进度条出现在YouTube页面的顶部时,网站会临时在正文的末尾添加一个新的DIV,代码如下:

<div id="progress" class="waiting" style="transition-duration: 400ms; width: 99%;"><dt></dt><dd></dd></div>

#2


0  

Hooking into the popstate might be an option, but i was unable to make that work correctly for some reason (youtube may be preventing it from propagating), so i came up with this that shows the concept:

连接到popstate可能是一种选择,但是由于某种原因,我无法使其正确工作(youtube可能阻止它传播),所以我想到了这个概念:

var currentState = "";
setInterval(function(){
    if (currentState != history.state["spf-referer"]) {
        currentState = history.state["spf-referer"];
        console.log("Do Stuff!");
    }
},250)

Just watches for the history.state to change, at which point it will log. The state should change any time the url changes, even if it wasn't due to a page reload.

只看历史。状态改变,在这一点它会记录。无论url何时更改,状态都应该更改,即使不是由于页面重载造成的。

#3


0  

You can set a listener which gets called when the page has finished loading.

您可以设置一个侦听器,当页面完成加载时调用该侦听器。

This is for the new YouTube material design:

这是新的YouTube材料设计:

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

And this for the old:

对于老年人来说:

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

(if you are using *monkey, you'll need to use unsafeWindow)

(如果你使用*monkey,你需要使用unsafeWindow)

Keep in mind that the old design will be discontinued, so your script may not work after that.

请记住,旧的设计将被停止,因此您的脚本在那之后可能无法工作。

#1


6  

I figured it out myself after some research. First off, I don't like solutions that use setTimeout. This is often one method suggested in favor over the deprecated DOMNodeInserted for instance (which I use in some of my scripts, but try to avoid as much as possible), but if possible, I always prefer a solution where the script actually executes after a specific event. I've posted the solution I initially used in the first section below, then the final solution I used in the second section. All code below requires jQuery.

我自己做了一些调查才弄明白的。首先,我不喜欢使用setTimeout的解决方案。这通常是一种方法,建议您使用已弃用的domnodeinsert,例如(我在一些脚本中使用它,但是尽量避免),但是如果可能的话,我总是倾向于在某个特定事件之后,脚本实际执行的解决方案。我已经发布了最初在第一部分中使用的解决方案,然后是我在第二部分使用的最终解决方案。下面的所有代码都需要jQuery。

Decent solution, but not the best

At first, I had a solution where I added a click event to all A elements, which would run a timer that ran my script after 2 seconds. This isn't elegant, because if the page loads quickly, then there's a split second where the script hasn't run. And if the page loads for more than two seconds, then the script doesn't run at all. Script below:

首先,我有一个解决方案,在所有元素中添加一个click事件,它将运行一个计时器,在2秒后运行我的脚本。这并不优雅,因为如果页面加载速度很快,那么会有一秒钟的时间脚本没有运行。如果页面加载超过两秒,那么脚本就根本不会运行。脚本如下:

$('a').click(function()
{
    setTimeout(youtubeFunction, 2000);
});

Much better solution

So I began looking for a solution that was related to what I wanted to accomplish. I eventually found other people with a similar problem to mine (such as people wanting to create a Chrome script that modifies YouTube pages). This led me to this particular Stack Overflow solution, which basically says that the red loading bar at the top of YouTube pages was a CSS transition element, and that it created a transitionend (case sensitive) event when it was finished. The code in the linked solution wasn't complete (for me anyway), but it did explain how to achieve a working solution. The code I have runs only once per page, which is perfect. So here's what I have now:

所以我开始寻找一个与我想要实现的目标相关的解决方案。我最终找到了和我有类似问题的人(比如想要创建一个修改YouTube页面的Chrome脚本的人)。这让我想到了这个特殊的Stack Overflow解决方案,它基本上说YouTube页面顶部的红色加载条是一个CSS转换元素,并且它在完成时创建了一个transitionend(区分大小写)事件。链接解决方案中的代码并不完整(对我来说),但它确实解释了如何实现一个有效的解决方案。我的代码每一页只运行一次,这是完美的。这就是我现在的内容:

function youtubePageChange()
{
    youtubeFunction();
    $('body').on('transitionend', function(event)
    {
        if (event.target.id != 'progress') return false;
        youtubeFunction();
    });
}

$(youtubePageChange);

To explain the code above, basically I run the code once for when you first load a YouTube page (such as by typing the URL in the address bar). Then for every subsequent click that requires the progress bar, the code runs again.

为了解释上面的代码,我基本上只在首次加载YouTube页面时运行一次代码(比如在地址栏中输入URL)。然后,对于需要进度条的每一次后续单击,代码将再次运行。

Red progress bar code

Oh, and for future reference, when the red progress bar appears at the top of YouTube pages, the site temporarily adds a new DIV to the end of BODY, with the following code:

哦,作为将来的参考,当红色的进度条出现在YouTube页面的顶部时,网站会临时在正文的末尾添加一个新的DIV,代码如下:

<div id="progress" class="waiting" style="transition-duration: 400ms; width: 99%;"><dt></dt><dd></dd></div>

#2


0  

Hooking into the popstate might be an option, but i was unable to make that work correctly for some reason (youtube may be preventing it from propagating), so i came up with this that shows the concept:

连接到popstate可能是一种选择,但是由于某种原因,我无法使其正确工作(youtube可能阻止它传播),所以我想到了这个概念:

var currentState = "";
setInterval(function(){
    if (currentState != history.state["spf-referer"]) {
        currentState = history.state["spf-referer"];
        console.log("Do Stuff!");
    }
},250)

Just watches for the history.state to change, at which point it will log. The state should change any time the url changes, even if it wasn't due to a page reload.

只看历史。状态改变,在这一点它会记录。无论url何时更改,状态都应该更改,即使不是由于页面重载造成的。

#3


0  

You can set a listener which gets called when the page has finished loading.

您可以设置一个侦听器,当页面完成加载时调用该侦听器。

This is for the new YouTube material design:

这是新的YouTube材料设计:

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

And this for the old:

对于老年人来说:

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

(if you are using *monkey, you'll need to use unsafeWindow)

(如果你使用*monkey,你需要使用unsafeWindow)

Keep in mind that the old design will be discontinued, so your script may not work after that.

请记住,旧的设计将被停止,因此您的脚本在那之后可能无法工作。