我正在制作一个简单的Chrome扩展程序,以在YouTube播放列表中添加每个视频的长度,并在页面中插入总长度。我已经成功了,但我的脚本仅在刷新页面后才起作用,但在网站导航时却不起作用。但这不太方便。
是否可以在浏览器中呈现之前检测Youtube上的页面导航并将HTML插入页面,以便立即显示添加的内容而不会有任何延迟并且不需要刷新页面?< / p>
示例链接:https://www.youtube.com/playlist?list=PL_8APVyhfhpdgMJ3J80YQxWBMUhbwXw8B
P.S。我的问题与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});
答案 0 :(得分:18)
Youtube网站不会在导航时重新加载页面,而是取代history state。
在没有重新加载页面的情况下更改URL时,不会重新注入扩展程序的内容脚本。当然,当您手动重新加载页面时,将执行内容脚本。
有几种方法可以检测Youtube网站上的页面转换:
transitionend
event用于视频页面上的进度表使用内容脚本和在视频导航中触发的特定于网站的事件:
在devtools控制台中运行getEventListeners(window)
并检查输出。
yt-navigate-start
请注意,在某些情况下仍会显示旧的YouTube设计使用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"
}]
}
请注意,当我们在document_start
加载内容脚本时,与 {之后稍微注入内容脚本时的默认行为相比,它会使我们的DOMContentLoaded
侦听器稍早运行一下{1}}。使用DOMContentLoaded
时,如果文档document_start
中没有任何内容,甚至没有body
元素,则会运行内容脚本。但是,将听众附加到head
也是可能的。
content.js :
document
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
功能会改变页面
注意,指定的元素类和结构将来会发生变化。
process
我们在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>");
}
上附加的postProcess
功能只会在网站打开时运行一次。在加载所有脚本后,将其用于页面的一次性处理。
答案 1 :(得分:10)
2017回答:
我将它用于新的Material Design版本Youtube
body.addEventListener("yt-navigate-finish", function(event) {
// code here
});
和旧的Youtube
window.addEventListener("spfdone", function(e) {
// code here
});
代码来自我编写的2个脚本 &#34; Youtube字幕下载&#34;和&#34; Youtube自动字幕下载器&#34;。
这两个都有效,我测试了。
如果您对我的剧本感兴趣并想了解更多细节:
https://github.com/1c7/Youtube-Auto-Subtitle-Download