我正在制作一个简单的Chrome扩展程序,以在YouTube播放列表中添加每个视频的长度,并在页面中插入总长度.我已经成功了,但我的脚本仅在刷新页面后才起作用,但在网站导航时却不起作用.但这不是很方便.
是否有可能在Youtube上检测页面导航并在浏览器中呈现之前将HTML插入到页面中,以便立即显示添加的内容而不会有任何延迟并且不需要刷新页面?
示例链接:https://www.youtube.com/playlist?list = PL_8APVyhfhpdgMJ3J80YQxWBMUhbwXw8B
PS我的问题与在greasemonkey脚本中显示后立即修改元素(不是在页面完全加载后)后的问题不同?因为我已经尝试过MutationObserver并且问题是相同的 - 需要刷新才能显示对网页的更改:
var observer = new MutationObserver(function(mutations) { for (var i=0; i
wOxxOm.. 19
Youtube网站不会在导航上重新加载页面,它会替换历史状态.
在没有重新加载页面的情况下更改URL时,不会重新注入扩展的内容脚本.当然,当您手动重新加载页面时,将执行内容脚本.
有几种方法可以检测Youtube网站上的页面转换:
使用后台页面脚本:webNavigation API,tabs API
使用内容脚本:视频页面上的进度表
transitionend
事件使用内容脚本和视频导航触发的特定于站点的事件:
getEventListeners(window)
在devtools控制台中运行并检查输出.yt-navigate-start是我们所需要的.
请注意,在某些情况下仍然显示旧的youtube设计使用spfdone
事件
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
收听稍早些的运行相比,在内容脚本注入的默认行为后小幅DOMContentLoaded
.随着document_start
内容脚本时没有什么文件中运行body
,甚至没有任何head
元素.document
但是,附加一个监听器是可能的.content.js:
window.addEventListener("spfdone", process); // old youtube design, just in case 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.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', 'Length: ' + timeHMS + ' '); }
postProcess
我们附加的功能在load
打开网站时只运行一次.在加载所有脚本后,将其用于页面的一次性处理.
Youtube网站不会在导航上重新加载页面,它会替换历史状态.
在没有重新加载页面的情况下更改URL时,不会重新注入扩展的内容脚本.当然,当您手动重新加载页面时,将执行内容脚本.
有几种方法可以检测Youtube网站上的页面转换:
使用后台页面脚本:webNavigation API,tabs API
使用内容脚本:视频页面上的进度表transitionend
事件
使用内容脚本和视频导航触发的特定于站点的事件:
getEventListeners(window)
在devtools控制台中运行并检查输出.
yt-navigate-start是我们所需要的.
请注意,在某些情况下仍然显示旧的youtube设计使用spfdone
事件
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
收听稍早些的运行相比,在内容脚本注入的默认行为后小幅 DOMContentLoaded
.随着document_start
内容脚本时没有什么文件中运行body
,甚至没有任何head
元素.document
但是,附加一个监听器是可能的.
content.js:
window.addEventListener("spfdone", process); // old youtube design, just in case 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.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', '
postProcess
我们附加的功能在load
打开网站时只运行一次.在加载所有脚本后,将其用于页面的一次性处理.
2017答案:
我将它用于新的Material Design版本Youtube
body.addEventListener("yt-navigate-finish", function(event) { // code here });
这对于老Youtube来说
window.addEventListener("spfdone", function(e) { // code here });
代码来自2个脚本我写了
"Youtube字幕下载器"和"Youtube自动字幕下载器".
我测试过它们都有效.
如果您对我的脚本感兴趣并想了解更多详细信息:https:
//github.com/1c7/Youtube-Auto-Subtitle-Download