如何检测Youtube上的页面导航并在页面呈现之前修改HTML? [英] How to detect page navigation on Youtube and modify HTML before page is rendered?

查看:149
本文介绍了如何检测Youtube上的页面导航并在页面呈现之前修改HTML?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作一个简单的Chrome扩展程序,将YouTube播放列表中每个视频的长度加起来,并在页面中插入总长度。我已经成功了,但是我的脚本只在刷新页面后才起作用,但在站点导航时不起作用。这不是很方便。



是否可以在浏览器中呈现之前检测Youtube上的页面导航并将HTML插入到页面中添加的内容会立即显示,不会有任何延迟,并且不需要刷新页面?



示例链接:



yt-navigate-start 是我们需要的。在某些情况下仍会显示YouTube设计使用 spfdone 事件






$ b manifest.json

  {
name:YouTube Playlist Length,
version:0.0.1,
manifest_version:2,
description:.............,
content_scripts:[{
与 :[*://*.youtube.com/*],
js:[content.js],
run_at:document_start
}]
}

请注意,当我们将内容脚本加载到 document_start 与内容脚本稍后注入时的默认行为相比,它会使我们的 DOMContentLoaded 侦听器稍微运行一些。 DOMContentLoaded 。使用 document_start 时,内容脚本在文档 body 中甚至没有 head 元素。将侦听器添加到文档是可能的,但也是一样的。



content.js strong>:

  window.addEventListener(spfdone,process); //旧的youtube设计
window.addEventListener(yt-navigate-start,process); //新的youtube设计

document.addEventListener(DOMContentLoaded,process); //一次性提前处理
window.addEventListener(load,postProcess); //一次性后期处理

进程函数将改变页面。

注意,指定的元素类和结构将在未来发生变化。

  if(location.pathname!=/ 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:] + /, ); //修剪前导零
document.querySelector(。pl-header-details)
.insertAdjacentHTML(beforeend,< li>长度:+ timeHMS +< / li> );

postProcess 函数我们附加在 load 上的附件只会在网站打开时运行一次。在加载所有脚本后,将其用于一次性页面处理。


I'm making a simple Chrome extension to add up the length of each video in a YouTube playlist and insert the total length in the page. I've succeeded at that, but my script only works after refreshing a page but not when the site is navigated. That's not very convenient though.

Is it possible to detect page navigation on Youtube and insert HTML into the page before it's rendered in the browser so that the added content is shown immediately without any delay and no page refresh is required?

Example link: https://www.youtube.com/playlist?list=PL_8APVyhfhpdgMJ3J80YQxWBMUhbwXw8B

P.S. My question is not the same as Modify elements immediately after they are displayed (not after page completely loads) in greasemonkey script? because I've tried MutationObserver and the problem is the same - a refresh is needed to show changes to the web page:

var observer = new MutationObserver(function(mutations) {
    for (var i=0; i<mutations.length; i++) {
        var mutationAddedNodes = mutations[i].addedNodes;
        for (var j=0; j<mutationAddedNodes.length; j++) {
            var node = mutationAddedNodes[j];
            if (node.classList && node.classList.contains("timestamp")) {
                var videoLength = node.firstElementChild.innerText;
                observer.disconnect();    

                var lengthNode = document.createElement("li");
                var lengthNodeText = document.createTextNode(videoLength);
                lengthNode.appendChild(lengthNodeText);
                document.getElementsByClassName("pl-header-details")[0].appendChild(lengthNode);

                return;
            }
        }
    }
});
observer.observe(document, {childList: true, subtree: true});

解决方案

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(window) in devtools console and inspect the output.

    yt-navigate-start is what we need.
    Note, the old youtube design still shown in some cases uses 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, when we load the content script at document_start it will make our DOMContentLoaded listener run slightly sooner compared to the default behavior when content scripts are injected slightly after DOMContentLoaded. With document_start the content script runs when there's nothing in the document body and even no head element. Attaching a listener to document is possible, though, just the same.

content.js:

window.addEventListener("spfdone", process); // old youtube design
window.addEventListener("yt-navigate-start", process); // new youtube design

document.addEventListener("DOMContentLoaded", process); // one-time early processing
window.addEventListener("load", postProcess); // one-time late postprocessing 

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

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

The postProcess function that we attached on load will run only one time when the site is opened. Use it for one-time processing of the page after all of its scripts are loaded.

这篇关于如何检测Youtube上的页面导航并在页面呈现之前修改HTML?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆