// ==UserScript==
// @name Space-efficient Youtube
// @namespace 1N07
// @author 1N07
// @icon https://i.imgur.com/VgEiyi3.png
// @description AKA: "Wide Youtube", AKA: "Wide video container" - Uses the page space on youtube more efficiently (especially good for high resolutions)
// @include https://www.youtube.com/*
// @version 1.9
// @grant GM_registerMenuCommand
// @grant GM_unregisterMenuCommand
// @grant GM_getValue
// @grant GM_setValue
// ==/UserScript==
(function() {
var FPPHandle;
var FPPCompOn = GM_getValue("FPPCompOn", false);
SetFPPHandle();
var ForceCSSHandle;
var ForceCSSOn = GM_getValue("ForceCSSOn", false);
SetForceCSSHandle();
//var HQTNHandle;
//var HQTN = GM_getValue("HQTN", false);
var HomeVideoContainerWidthHandle;
var HomeVideoContainerWidth = GM_getValue("HomeVideoContainerWidth", "360px");
SetHomeVideoContainerWidthHandle();
var SubVideoContainerWidthHandle;
var SubVideoContainerWidth = GM_getValue("SubVideoContainerWidth", "210px");
//SetHQTNHandle();
SetSubVideoContainerWidthHandle();
var TrendingVideoContainerWidthHandle;
var TrendingVideoContainerWidth = GM_getValue("TrendingVideoContainerWidth", "600px");
SetTrendingVideoContainerWidthHandle();
var VideoContainerHorMarginHandle;
var VideoContainerHorMargin = GM_getValue("VideoContainerHorMargin", "4px");
SetVideoContainerHorMarginHandle();
var VideoContainerVerMarginHandle;
var VideoContainerVerMargin = GM_getValue("VideoContainerVerMargin", "24px");
SetVideoContainerVerMarginHandle();
var ShowChannelIconNextToVideosOnHomePageHandle;
var ShowChannelIconNextToVideosOnHomePage = GM_getValue("ShowChannelIconNextToVideosOnHomePage", true);
SetShowChannelIconNextToVideosOnHomePageHandle();
var LessenVideoTitleTopMarginOnHomePage = true;
var screenWidth = screen.width;
if(!!document.getElementById("early-body")) { //if old youtube
document.getElementById("content").setAttribute("style", "width: 99%;");
} else { //new youtube
addGlobalStyle(`
ytd-app #page-manager > ytd-browse:not([page-subtype="playlist"]):not([page-subtype="home"]) ytd-two-column-browse-results-renderer.ytd-browse
{
box-sizing: border-box`+(ForceCSSOn ? `!important`:``)+`;
width: calc(100% - 25px) !important;
margin: 10px`+(ForceCSSOn ? `!important`:``)+`;
max-width: none;
}
#items.ytd-grid-renderer > ytd-grid-video-renderer.ytd-grid-renderer,
#items.ytd-grid-renderer > ytd-grid-radio-renderer.ytd-grid-renderer,
#items.ytd-grid-renderer > ytd-grid-channel-renderer.ytd-grid-renderer,
#items.ytd-grid-renderer > ytd-grid-playlist-renderer.ytd-grid-renderer,
#items.ytd-grid-renderer > ytd-grid-movie-playlist-renderer.ytd-grid-renderer,
#items.ytd-grid-renderer > ytd-grid-movie-renderer.ytd-grid-renderer,
#items.ytd-grid-renderer > ytd-grid-show-renderer.ytd-grid-renderer,
#items.ytd-grid-renderer > ytd-game-card-renderer.ytd-grid-renderer,
ytd-grid-video-renderer
{
width: `+SubVideoContainerWidth+`;
margin-left: 0;
margin-top: 0;
margin-right: `+VideoContainerHorMargin+`;
margin-bottom: `+VideoContainerVerMargin+`;
}
ytd-thumbnail.ytd-grid-video-renderer
{
width: `+SubVideoContainerWidth+`;
height: calc(`+SubVideoContainerWidth+` * 0.5625);
}
ytd-thumbnail #thumbnail.ytd-thumbnail yt-img-shadow.ytd-thumbnail
{
width: 100%;
height: 100%;
}
img.yt-img-shadow
{
max-width: 100%;
max-height: 100%;
margin-left: 0;
margin-right: 0;
width: 100%;
height: 100%;
}
/*channels page rules*/
ytd-app #page-manager > ytd-browse[page-subtype="channels"] ytd-two-column-browse-results-renderer.ytd-browse ytd-item-section-renderer.ytd-section-list-renderer
{
width: calc(100% - 20px);
max-width: none;
}
/*for some reason the arrows sometimes dont show up, so now forcing them to*/
ytd-app #page-manager > ytd-browse[page-subtype="channels"] ytd-two-column-browse-results-renderer.ytd-browse ytd-item-section-renderer.ytd-section-list-renderer ytd-button-renderer.yt-horizontal-list-renderer.arrow
{
opacity: 1;
display: flex;
}
/*trending page rules*/
ytd-app #page-manager > ytd-browse:not([page-subtype]) #grid-container.ytd-expanded-shelf-contents-renderer > .ytd-expanded-shelf-contents-renderer,
ytd-app #page-manager > ytd-browse:not([page-subtype]) #grid-container.ytd-expanded-shelf-contents-renderer > .ytd-expanded-shelf-contents-renderer > .ytd-video-renderer
{
max-width: `+TrendingVideoContainerWidth+`;
}
ytd-app #page-manager > ytd-browse:not([page-subtype]) ytd-video-renderer.ytd-expanded-shelf-contents-renderer,
ytd-app #page-manager > ytd-browse:not([page-subtype]) ytd-video-renderer.ytd-expanded-shelf-contents-renderer:not(:last-child)
{
padding-right: 3px;
margin-left: 0;
margin-top: 0;
margin-right: `+VideoContainerHorMargin+`;
margin-bottom: `+VideoContainerVerMargin+`;
}
ytd-app #page-manager > ytd-browse:not([page-subtype]) ytd-thumbnail.ytd-video-renderer
{
margin-right: 10px;
}
/*Playlist page rules*/
ytd-browse[page-subtype="playlist"] ytd-two-column-browse-results-renderer.ytd-browse
{
max-width: none;
}
/*home page rules*/
ytd-rich-item-renderer {
width: `+HomeVideoContainerWidth+`;
margin-left: 0;
margin-top: 0;
margin-right: `+VideoContainerHorMargin+`;
margin-bottom: `+VideoContainerVerMargin+`;
}
`);
console.log("Youtube Wide video container style added to DOM");
if(!ShowChannelIconNextToVideosOnHomePage)
{
addGlobalStyle(`
#avatar-link.ytd-rich-grid-video-renderer
{
display: none;
}
`);
}
if(LessenVideoTitleTopMarginOnHomePage)
{
addGlobalStyle(`
h3.ytd-rich-grid-video-renderer
{
margin-top: 6px;
}
`);
}
if(FPPCompOn) {
addGlobalStyle(`
/*========== Fade++ Compatibility ==========*/
ytd-app #page-manager > ytd-browse:not([page-subtype="playlist"]) {
display: block;
}
ytd-app[guide-persistent-and-visible] #page-manager > ytd-browse:not([page-subtype="playlist"]) ytd-two-column-browse-results-renderer.ytd-browse
{
margin-left: 250px !important;
}
`);
console.log("Youtube Wide video container Fade++ compatibilty style added to DOM");
}
}
/*=== load more videos for channel sections (experimental) ===*/
var lastCheckedURL = window.location.href;
URLChanged();
setInterval(function(){
if(lastCheckedURL != window.location.href)
{
lastCheckedURL = window.location.href;
//lol why am I doing this 3 times at different times here??? Should have probably commented this better huh?
//leaving it as is for now. Should probably figure out something better, this is a mess...
setTimeout(URLChanged, 500);
setTimeout(URLChanged, 2000);
setTimeout(URLChanged, 5000);
}
}, 200);
var waitForArrows;
function URLChanged()
{
//console.log("-urlchanged-");
clearInterval(waitForArrows);
let expandedEls = document.getElementsByClassName("expanded-wwc");
//console.log("expanded els found: " + expandedEls.length);
let numRemoved = 0;
//seems to always remove exactly half of them only, for some reason. So I guess do this until all have been removed
while(expandedEls.length > 0)
{
for(let x = 0; x < expandedEls.length; x++)
{
if(!!expandedEls[x])
{
expandedEls[x].classList.remove("expanded-wwc");
//console.log(++numRemoved + " cleared");
}
}
expandedEls = document.getElementsByClassName("expanded-wwc");
}
numRemoved = 0;
let clickedArrows = document.getElementsByClassName("clicked");
//console.log("clicked found: " + clickedArrows.length);
while(clickedArrows.length > 0)
{
for(let x = 0; x < clickedArrows.length; x++)
{
if(!!clickedArrows[x])
{
clickedArrows[x].classList.remove("clicked");
//console.log(++numRemoved + " cleared");
}
}
clickedArrows = document.getElementsByClassName("clicked");
}
//console.log("-expandedclear-");
if(lastCheckedURL.includes("/user/") || lastCheckedURL.includes("/channel/"))
{
waitForArrows = setInterval(function(){
//console.log("-searching...-");
let arrowsRight = document.querySelectorAll("yt-horizontal-list-renderer:not(.expanded-wwc) > #right-arrow > ytd-button-renderer.arrow");
let arrowsLeft = document.querySelectorAll("yt-horizontal-list-renderer:not(.expanded-wwc) > #left-arrow > ytd-button-renderer.arrow");
if(!!arrowsRight && arrowsRight.length > 0 && !!arrowsLeft && arrowsLeft.length > 0)
{
//console.log("-found-");
for(let i = 0; i < arrowsRight.length; i++)
{
if(!!arrowsRight[i] && arrowsRight[i].offsetParent !== null && !!arrowsLeft[i] && arrowsLeft[i].offsetParent !== null)
{
arrowsRight[i].parentElement.parentElement.classList.add("expanded-wwc");
arrowsRight[i].click();
//console.log("simulated click on right arrow");
arrowsRight[i].classList.add("clicked");
arrowsLeft[i].click();
//console.log("simulated click on left arrow");
arrowsLeft[i].classList.add("clicked");
}
}
}
}, 250);
}
}
/*============================================================*/
function SetFPPHandle() {
GM_unregisterMenuCommand(FPPHandle);
FPPHandle = GM_registerMenuCommand("Fade++ Compatibility mode (" + (FPPCompOn ? "On" : "Off") + ") -click to change-", function(){
FPPCompOn = !FPPCompOn;
GM_setValue("FPPCompOn", FPPCompOn);
SetFPPHandle();
if(confirm('Press "OK" to refresh the page to apply new settings'))
location.reload();
});
}
function SetForceCSSHandle() {
GM_unregisterMenuCommand(ForceCSSHandle);
ForceCSSHandle = GM_registerMenuCommand("CSS important rule mode (" + (ForceCSSOn ? "On" : "Off") + ") -click to change-", function(){
ForceCSSOn = !ForceCSSOn;
GM_setValue("ForceCSSOn", ForceCSSOn);
SetForceCSSHandle();
if(confirm('Press "OK" to refresh the page to apply new settings'))
location.reload();
});
}
function SetHomeVideoContainerWidthHandle() {
GM_unregisterMenuCommand(HomeVideoContainerWidthHandle);
HomeVideoContainerWidthHandle = GM_registerMenuCommand("[home-page] Video-renderer width (" + HomeVideoContainerWidth + ") -click to change-", function(){
HomeVideoContainerWidth = CleanCSSValue(prompt("Set the width of a single video renderer on the page (use CSS units)\nThe current value is: '" + HomeVideoContainerWidth + "'"));
GM_setValue("HomeVideoContainerWidth", HomeVideoContainerWidth);
SetHomeVideoContainerWidthHandle();
if(confirm('Press "OK" to refresh the page to apply new settings'))
location.reload();
});
}
/*function SetHQTNHandle() {
GM_unregisterMenuCommand(HQTNHandle);
HQTNHandle = GM_registerMenuCommand("[subs-page] Load HQ thumbnails (" + (HQTN ? "On" : "Off") + ") -click to change-", function(){
HQTN = !HQTN;
GM_setValue("HQTN", HQTN);
SetHQTNHandle();
if(confirm('Press "OK" to refresh the page to apply new settings'))
location.reload();
});
}*/
function SetSubVideoContainerWidthHandle() {
GM_unregisterMenuCommand(SubVideoContainerWidthHandle);
SubVideoContainerWidthHandle = GM_registerMenuCommand("[subs-page] Video-renderer width (" + SubVideoContainerWidth + ") -click to change-", function(){
SubVideoContainerWidth = CleanCSSValue(prompt("Set the width of a single video renderer on the page (use CSS units)\nNote: Currently values larger than the default (210px) make the thumbnails blurry, as youtube only loads 210px resolution images. I might make a workaround for this later.\nThe current value is: '" + SubVideoContainerWidth + "'"));
GM_setValue("SubVideoContainerWidth", SubVideoContainerWidth);
SetSubVideoContainerWidthHandle();
if(confirm('Press "OK" to refresh the page to apply new settings'))
location.reload();
});
}
function SetTrendingVideoContainerWidthHandle() {
GM_unregisterMenuCommand(TrendingVideoContainerWidthHandle);
TrendingVideoContainerWidthHandle = GM_registerMenuCommand("[trending-page] Video-renderer width (" + TrendingVideoContainerWidth + ") -click to change-", function(){
TrendingVideoContainerWidth = CleanCSSValue(prompt("Set the width of a single video renderer on the page (use CSS units)\nThe current value is: '" + TrendingVideoContainerWidth + "'"));
GM_setValue("TrendingVideoContainerWidth", TrendingVideoContainerWidth);
SetTrendingVideoContainerWidthHandle();
if(confirm('Press "OK" to refresh the page to apply new settings'))
location.reload();
});
}
function SetVideoContainerHorMarginHandle() {
GM_unregisterMenuCommand(VideoContainerHorMarginHandle);
VideoContainerHorMarginHandle = GM_registerMenuCommand("[all pages] Video-renderer horizontal margin (" + VideoContainerHorMargin + ") -click to change-", function(){
VideoContainerHorMargin = CleanCSSValue(prompt("Set the horizontal margin of a single video renderer on the page. i.e. the space between videos (use CSS units)\nThe current value is: '" + VideoContainerHorMargin + "'"));
GM_setValue("VideoContainerHorMargin", VideoContainerHorMargin);
SetVideoContainerHorMarginHandle();
if(confirm('Press "OK" to refresh the page to apply new settings'))
location.reload();
});
}
function SetVideoContainerVerMarginHandle() {
GM_unregisterMenuCommand(VideoContainerVerMarginHandle);
VideoContainerVerMarginHandle = GM_registerMenuCommand("[all pages] Video-renderer vertical margin (" + VideoContainerVerMargin + ") -click to change-", function(){
VideoContainerVerMargin = CleanCSSValue(prompt("Set the vertical margin of a single video renderer on the page. i.e. the space between videos (use CSS units)\nThe current value is: '" + VideoContainerVerMargin + "'"));
GM_setValue("VideoContainerVerMargin", VideoContainerVerMargin);
SetVideoContainerVerMarginHandle();
if(confirm('Press "OK" to refresh the page to apply new settings'))
location.reload();
});
}
function SetShowChannelIconNextToVideosOnHomePageHandle() {
GM_unregisterMenuCommand(ShowChannelIconNextToVideosOnHomePageHandle);
ShowChannelIconNextToVideosOnHomePageHandle = GM_registerMenuCommand("[homepage] Show channel icons next to videos (" + (ShowChannelIconNextToVideosOnHomePage ? "Yes" : "No") + ") -click to change-", function(){
ShowChannelIconNextToVideosOnHomePage = !ShowChannelIconNextToVideosOnHomePage;
GM_setValue("ShowChannelIconNextToVideosOnHomePage", ShowChannelIconNextToVideosOnHomePage);
SetShowChannelIconNextToVideosOnHomePageHandle();
if(confirm('Press "OK" to refresh the page to apply new settings'))
location.reload();
});
}
function CleanCSSValue(val)
{
val = val.trim();
//if only numbers...
if(/^\d+$/.test(val))
val += "px"; //...add px
return val;
}
function addGlobalStyle(css) {
var head, style;
head = document.getElementsByTagName('head')[0];
if (!head) { return; }
style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = css;
head.appendChild(style);
}
})();