javascript - 如何检测 YouTube 上的页面导航并无缝修改其外观?

标签 javascript google-chrome google-chrome-extension

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

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

示例链接:https://www.youtube.com/playlist?list=PL_8APVyhfhpdgMJ3J80YQxWBMUhbwXw8B

附言我的问题与Modify elements immediately after they are displayed (not after page completely loads) in greasemonkey script?不一样因为我已经尝试过 MutationObserver 并且问题是相同的 - 需要刷新以显示对网页的更改:

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 网站不会在导航时重新加载页面,它会替换 history state .

当 URL 在没有重新加载页面的情况下更改时,不会重新注入(inject)扩展的内容脚本。当然,当您手动重新加载页面时,内容脚本会被执行。

有几种方法可以检测 Youtube 网站上的页面转换:

  • 使用后台页面脚本:webNavigation API , tabs API

  • 使用内容脚本:transitionend event用于视频页面上的进度表

  • 使用内容脚本和在视频导航时触发的网站特定事件:

    在 devtools 控制台中运行 getEventListeners(document) 并检查输出。

    enter image description here

    yt-navigate-start 是我们在这种情况下所需要的。

    注意事项:

    • 对于我们可能需要的其他任务yt-navigate-finish
    • 旧的 youtube 设计使用了 spfdone event

list .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"
  }]
}

注意:matches 键包含整个 youtube.com 域,因此内容脚本会在用户首次打开 youtube 主页然后导航到观看页面时运行。

content.js:

document.addEventListener('yt-navigate-start', process);
// Choose a different event depending on when you want to apply the change
// document.addEventListener('yt-navigate-finish', process);

if (document.body) process();
else document.addEventListener('DOMContentLoaded', process);

process 函数将改变页面。
请注意,指定的元素类和结构将来会发生变化。

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

关于javascript - 如何检测 YouTube 上的页面导航并无缝修改其外观?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34077641/

相关文章:

javascript - Firefox 允许将桌面图像文件拖入 CKEditor

javascript - 如何将消息发布到 iFrame 中?

javascript - Chrome 扩展程序 : Clicking notification opens multiple tabs

javascript - 使用单个 DOM 内容加载调用

javascript - ECMAScript6 类中的碰撞函数

javascript - 如何最好地从数据模型动态渲染 react 组件

google-chrome - 我可以在不使用 chromedriver.exe 的情况下为 Chrome 使用 Selenium (webdriver) 吗?

javascript - 在 chrome 中使用 session 和本地存储时不加载 Angular JS 页面

google-chrome - 当 transport=serverSentEvents 时不调用 SignalR 客户端函数

javascript - addEventListener ("beforeload") 缺少事件