Keeps YouTube progressbar visible all the time.
目前為
// ==UserScript==
// @name YouTube Permanent ProgressBar
// @namespace http://tampermonkey.net/
// @version 0.1
// @description Keeps YouTube progressbar visible all the time.
// @author Can Kurt
// @match *://www.youtube.com/*
// @license MIT
// ==/UserScript==
var permanentProgressBar = {
setup : function(){
// keep progressBar visible with css
document.querySelector(".ytp-chrome-bottom").style.cssText = "opacity: 1 !important;";
},
prettifyVideoTime : function(video){
let seconds = "" + Math.floor(video.currentTime%60);
let minutes = "" + Math.floor((video.currentTime%3600)/60);
let hours = "" + Math.floor(video.currentTime/3600);
if(video.currentTime/60 > 60){
return `${hours}:${minutes.padStart(2, '0')}:${seconds.padStart(2, '0')}`;
}
else{
return `${minutes}:${seconds.padStart(2, '0')}`;
}
},
getDuration : function(video, type){
if(type === "PROGRESSBAR"){
return video.currentTime;
}
else if(type === "BUFFERBAR"){
return video.buffered.end(video.buffered.length-1);
}
},
updateCurrentTimeField : function(player){
const video = player.querySelector("video");
const currentTime = player.querySelector(".ytp-time-current");
if (!video || !currentTime) {
return;
}
currentTime.innerText = permanentProgressBar.prettifyVideoTime(video);
},
updateProgressBar : function(player){
// works only on chapterless (old) videos
const video = player.querySelector("video");
const progressBar = player.querySelector(".ytp-play-progress");
const bufferBar = player.querySelector(".ytp-load-progress");
if (!video || !progressBar || !bufferBar) {
return;
}
progressBar.style.transform = `scaleX(${video.currentTime/video.duration})`;
bufferBar.style.transform = `scaleX(${video.buffered.end(video.buffered.length-1)/video.duration})`;
},
updateProgressBarWithChapters : function(player, type){
// YouTube api does not provides current time in chapters
// this function finds current time in the chapter by finding the ratio between total video duration and total width of the chapters div
const video = player.querySelector("video");
// there can be multiple chapters
const progressBarWidthsCollection = player.getElementsByClassName("ytp-progress-bar-padding");
// select progress or bufferBar
let progressBarChaptersCollection;
if(type === "PROGRESSBAR"){
progressBarChaptersCollection = player.getElementsByClassName("ytp-play-progress");
}
if(type === "BUFFERBAR"){
progressBarChaptersCollection = player.getElementsByClassName("ytp-load-progress");
}
// quit if elements does not exists
if (!video || !progressBarWidthsCollection || !progressBarChaptersCollection) {
return;
}
// find the ratio between total video duration and total width of the chapters div
let totalProgressBarWidth = 0;
for (let i = 0; i < progressBarWidthsCollection.length; i++) {
totalProgressBarWidth += progressBarWidthsCollection[i].offsetWidth;
}
const durationWidthRatio = video.duration/totalProgressBarWidth;
// loop inside chapters
let chaptersPixelWidthUntilCurrentChapter = 0;
for (let i = 0; i < progressBarWidthsCollection.length; i++) {
// if current time is bigger than durationWidthRatio * (chapters pixel width including current one) scale the current chapter to 1 because we passed it
if(permanentProgressBar.getDuration(video, type) > durationWidthRatio*(chaptersPixelWidthUntilCurrentChapter + progressBarWidthsCollection[i].offsetWidth)){
progressBarChaptersCollection[i].style.transform = "scaleX(1)";
// increase the current chapters location by adding last watched chapter
chaptersPixelWidthUntilCurrentChapter += progressBarWidthsCollection[i].offsetWidth;
}
// If not, it means that we are on this chapter.
// Find the appropriate size for the chapter and scale it
else{
// current time
let currentTimeInChapterInSeconds = permanentProgressBar.getDuration(video, type) - (durationWidthRatio*chaptersPixelWidthUntilCurrentChapter);
// total chapter time
let currentChapterLengthInSeconds = durationWidthRatio*progressBarWidthsCollection[i].offsetWidth;
let currentChapterTimeRatio = currentTimeInChapterInSeconds / currentChapterLengthInSeconds
progressBarChaptersCollection[i].style.transform = `scaleX(${currentChapterTimeRatio})`;
break;
}
}
},
update : function(){
const player = document.querySelector(".html5-video-player");
if (!player) {
return;
}
// update video timer
permanentProgressBar.updateCurrentTimeField(player);
// update progressBars
permanentProgressBar.updateProgressBarWithChapters(player, "PROGRESSBAR");
permanentProgressBar.updateProgressBarWithChapters(player, "BUFFERBAR");
},
start : function(){
permanentProgressBar.setup();
setInterval(permanentProgressBar.update, 500);
}
}
permanentProgressBar.start();