Javascript 如何检测YouTube上的页面导航并无缝修改其外观?
我正在制作一个简单的Chrome扩展,将YouTube播放列表中每个视频的长度相加,并将总长度插入页面。我已经成功地做到了这一点,但我的脚本只有在刷新页面后才能工作,而在导航站点时却无法工作。不过那不是很方便 是否可以检测YouTube上的页面导航,并在页面在浏览器中呈现之前将HTML插入该页面,以便立即显示添加的内容,而不需要任何延迟,也不需要刷新页面 示例链接: 另外,我的问题与其他问题不同,因为我尝试了MutationObserver,问题是相同的-需要刷新以显示对网页的更改:Javascript 如何检测YouTube上的页面导航并无缝修改其外观?,javascript,google-chrome,google-chrome-extension,Javascript,Google Chrome,Google Chrome Extension,我正在制作一个简单的Chrome扩展,将YouTube播放列表中每个视频的长度相加,并将总长度插入页面。我已经成功地做到了这一点,但我的脚本只有在刷新页面后才能工作,而在导航站点时却无法工作。不过那不是很方便 是否可以检测YouTube上的页面导航,并在页面在浏览器中呈现之前将HTML插入该页面,以便立即显示添加的内容,而不需要任何延迟,也不需要刷新页面 示例链接: 另外,我的问题与其他问题不同,因为我尝试了MutationObserver,问题是相同的-需要刷新以显示对网页的更改: var o
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});
var observer=新的突变观察者(函数(突变){
对于(var i=0;iYouTube站点,它不会在导航上重新加载页面,而是替换了
当URL更改而页面未重新加载时,扩展的内容脚本不会重新注入。当您手动重新加载页面时,内容脚本自然会执行
有几种方法可以检测Youtube网站上的页面转换:
- 使用后台页面脚本:
- 使用内容脚本:用于视频页面上的进度计
- 使用内容脚本和视频导航触发的特定于站点的事件:
在devtools控制台中运行
getEventListeners(document)
,并检查输出
yt导航开始是我们在这种情况下需要的
注:
- 对于其他任务,我们可能需要导航完成
- youtube的旧设计正在使用
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.addEventListener('yt-navigate-start', process);
if (document.body) process();
else document.addEventListener('DOMContentLoaded', process);
注意:匹配
键包含整个youtube.com域,因此当用户首先打开youtube主页,然后导航到监视页面时,内容脚本将运行
content.js:
{
"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.addEventListener('yt-navigate-start', process);
if (document.body) process();
else document.addEventListener('DOMContentLoaded', 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>');
}
函数过程(){
如果(!location.pathname.startsWith('/playlist')){
返回;
}
var seconds=[].reduce.call(
document.getElementsByClassName('timestamp'),
函数(和,ts){
var minsec=ts.textContent.split(“:”);
返回和+minsec[0]*60+minsec[1]*1;
},
0,
);
如果(!秒){
console.warn('没有时间戳。播放列表为空?');
返回;
}
var timeHMS=新日期(秒*1000).toutString().split(“”)[4]
.replace(//^[0://,'');//修剪前导零
document.querySelector(“.pl头详细信息”)
.insertAdjacentHTML('beforeend','长度:'+timeHMS+' );
}
2017答案:
我将此用于新材料设计版本Youtube
body.addEventListener("yt-navigate-finish", function(event) {
// code here
});
这是给老Youtube的
window.addEventListener("spfdone", function(e) {
// code here
});
代码来自我编写的2个脚本调用
“Youtube字幕下载器”和“Youtube自动字幕下载器”
我测试了一下,它们都能工作
如果您对我的脚本感兴趣并想了解更多详细信息:
Hmm,我试过了,但没有达到我的目的。在加载每个视频的时间戳时,我要插入组合视频长度的页面部分已经加载,因此我遇到了同样的问题,页面需要刷新以显示注入的HTML。更新了我的问题,因为它被标记为重复。只是尝试了t不,这没有解决问题。仍然需要刷新。感谢您迄今为止的帮助。以下是脚本,底部还有清单:作为参考,下面是一个背景脚本方法的示例:此解决方案工作正常,但不幸的是仅适用于YouTube旧设计。有一个新的yt导航开始
事件在展示给一些用户的网站上。另外,我稍微概括了一下答案,解释了如何找到实际事件。你确定他们使用了pushState
?几天前,因为一个问题,我快速浏览了一下(顺便说一句,我会发现它是VTC的翻版),但为了在这些方法中包含事件发射器而覆盖history.pushState
和history.replaceState
,根本不起作用,即使我在加载页面之前重写了它。@kaido,是的,他们只是通过iframe使用hack来恢复原始API绑定:注意,这些信息是红色的现有答案(虽然它使用了yt导航开始
)是的,这一个没有谈到原则,但给出了正确的代码,我认为这个答案仍然有一些价值,所以我仍然会保留这个答案。:D谢谢你提到它@Xan