Greasy Fork is available in English.
See View to Sentiment, View to Like, and other statistics.
/* This script should work in Tampermonkey, as a bookmarklet, or in the console. Have fun! */
/* Tested and known working in both Chrome and Firefox. */
/*
// ==UserScript==
// @name YTVTSview
// @license MIT
// @namespace http://tampermonkey.net/
// @version 1.3
// @description See View to Sentiment, View to Like, and other statistics.
// @author zegfarce
// @match https://www.youtube.com/watch?v=*
// @icon https://www.google.com/s2/favicons?domain=youtube.com
// @grant unsafeWindow
// ==/UserScript==
*/
/* The colors of the things. Change to whatever you want I guess. */
let colors = {
like_color: "#44ff44",
dislike_color: "#ff4444",
viewratio_unfilled: "#717171",
viewratio_partfilled: "#aaaaaa",
viewratio_fullfilled: "#ffffff",
};
/* Based on original work by Estus Flask on Stack Overflow, https://stackoverflow.com/a/44807594 */
/* Licensed under the CC BY-SA 3.0 license. https://creativecommons.org/licenses/by-sa/3.0/ */
/* Modified to make it look a little nicer and call my function */
let scriptPromise = new Promise((resolve, reject) => {
let script = document.createElement('script');
document.body.appendChild(script);
script.onload = resolve;
script.onerror = reject;
script.async = true;
script.src = 'https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js';
});
scriptPromise.then(runChecks);
let selectors = {
// Specific to YouTube that supports like bars
likebar: "#like-bar",
// Basic YouTube layout stuff
info: "#info-contents",
viewcount: ".ytd-video-view-count-renderer"
}
let ryd_selectors = {
likebar: "#ryd-bar"
}
// Enables Return YouTube Dislike support dynamically.
// really just there to work around bugs
let ryd;
/* yes i really did just comply with creative commons license for stack overflow code */
/* okay back to my code */
function runChecks()
{
/* tampermonkey support */
let window = (typeof unsafeWindow !== "undefined") ? unsafeWindow : globalThis;
let jQuery = window.$;
// no support by default -- detect if the bar is reenabled
ryd = false;
let interval = setInterval(() => {
// Return YouTube Dislike support.
if (jQuery(ryd_selectors.likebar).length)
{
selectors.likebar = ryd_selectors.likebar;
ryd = true; // well return-youtube-dislike exists
}
if (jQuery(selectors.likebar).length === 0)
return;
// hack because youtube didnt remove the html, just hid the element
if (jQuery(selectors.likebar)[0].parentElement.parentElement.hidden)
return;
clearInterval(interval);
init();
}, 100)
}
/* initialises the thing */
function init() {
/* tampermonkey support */
let window = (typeof unsafeWindow !== "undefined") ? unsafeWindow : globalThis;
let jQuery = window.$;
let likebar = jQuery(selectors.likebar)[0]; /* convenient */
let likebar_container = likebar.parentElement; /* less convenient */
let sentiment_section = likebar_container.parentElement;
if (ryd) // they wrapped it in another div -- annoying
sentiment_section = sentiment_section.parentElement;
let tooltip_container = sentiment_section.lastElementChild; /* even less convenient */
let tooltip = tooltip_container.children[0];
likebar.style.background = colors.like_color;
likebar_container.style.background = colors.dislike_color;
/* changing ID messes with the rendering */
let viewratiobar_container;
if (typeof window._yt_tampered_with === "undefined")
/* clone if first time */
viewratiobar_container = likebar_container.cloneNode(true);
else
/* otherwise, get existing one instead */
viewratiobar_container = sentiment_section.lastElementChild.previousElementSibling;
let viewratiobar = viewratiobar_container.children[0];
let viewratiobar_child;
if (typeof window._yt_tampered_with === "undefined")
/* clone if first time */
viewratiobar_child = viewratiobar.cloneNode(true);
else
/* otherwise, get existing one instead */
viewratiobar_child = viewratiobar.firstElementChild;
/* trim and remove commas */
let tooltip_str = tooltip.textContent.trim().replaceAll(',', '');
/* match the string representations of the likes and dislikes */
/* remove the commas too */
/* the .slice(1) removes the full string match */
let [orig, likes, dislikes] = tooltip_str.match(/^((\d+)[^\d]+(\d+))/).slice(1);
likes = parseInt(likes); /* get the number */
dislikes = parseInt(dislikes); /* same here */
let viewcount = jQuery(selectors.viewcount)[0]; /* grab view count html */
let views = viewcount.innerHTML.replaceAll(',', ''); /* grab and trim the html */
views = parseInt(views.match(/^\d+/)[0]); /* match the number and parse it */
let vts_percent = ((likes + dislikes) / views) * 100; /* do some actual math for once in my life */
let lts_percent = (likes / (likes + dislikes)) * 100; /* do some actual math for once in my life */
/* The full bar is the background -- it's colored between the bg and fg by default */
viewratiobar.style.width = vts_percent.toString() + "%";
viewratiobar.style.background = colors.viewratio_partfilled;
/* This bar is the likes percentage in the bar */
viewratiobar_child.style.width = lts_percent.toString() + "%";
viewratiobar_child.style.background = colors.viewratio_fullfilled;
viewratiobar_container.style.background = colors.viewratio_unfilled;
let spacerdiv;
if (typeof window._yt_tampered_with === "undefined")
/* create if first time */
spacerdiv = document.createElement("div");
else
/* otherwise, get existing one instead */
spacerdiv = likebar_container.nextElementSibling;
/* A little spacer that just visually seperates my bar and the original one */
spacerdiv.style.height = "4px";
/* Don't add the divs if we've already added them */
if (typeof window._yt_tampered_with === "undefined")
{
sentiment_section.insertBefore(spacerdiv, likebar_container.nextElementSibling);
sentiment_section.insertBefore(viewratiobar_container, spacerdiv.nextElementSibling);
viewratiobar.appendChild(viewratiobar_child);
}
/* Truncate percentages so you dont get annoyingly precise percentages */
let vts = vts_percent.toFixed(1);
let lts = lts_percent.toFixed(0);
let vtl = (likes/views * 100).toFixed(1);
/* NaN checks just so we dont have NaN show up. */
vts = isNaN(vts) ? 0 : vts;
lts = isNaN(lts) ? 0 : lts;
vtl = isNaN(vtl) ? 0 : vtl;
/* Edit the tooltip to be cooler */
tooltip.textContent = `${orig} (${lts}%) ${vts}% vts ${vtl}% vtl`;
/* The section where the video title, views, upload date, and buttons are. */
let info_contents = jQuery(selectors.info)[0].children[0];
info_contents.style.paddingBottom = "14px"; /* Just extend it a little more to fit my bar. */
/* we've tampered with youtube */
window._yt_tampered_with = true;
};