Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 80 additions & 40 deletions colourTableCellsByCategory.user.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
// ==UserScript==
// @name Coloured Categories
// @description Adds category colours to Category column sb.ltn.fi
// @version 1.1.2
// @author ChatGPT, AcesFullOfKings, TheJzoli
// @grant none
// @version 1.3.3
// @author ChatGPT, AcesFullOfKings, TheJzoli, mini_bomba
// @grant GM_setValue
// @grant GM_getValue
// @match https://sb.ltn.fi/*
// @updateURL https://raw.githubusercontent.com/AcesFullOfKings/SponsorBlock-UserScripts/main/colourTableCellsByCategory.user.js
// @downloadURL https://raw.githubusercontent.com/AcesFullOfKings/SponsorBlock-UserScripts/main/colourTableCellsByCategory.user.js
// @updateURL https://raw.githubusercontent.com/mini-bomba/AcesFullOfKings-SponsorBlock-UserScripts/rewrite/colourTableCellsByCategory.user.js
// @downloadURL https://raw.githubusercontent.com/mini-bomba/AcesFullOfKings-SponsorBlock-UserScripts/rewrite/colourTableCellsByCategory.user.js
// @icon https://sb.ltn.fi/static/browser/logo.png
// ==/UserScript==

/* eslint-disable no-multi-spaces */

(function() {
'use strict';

Expand All @@ -26,49 +25,90 @@
poi_highlight: '#ff1684', // kinda salmon-y pink idk
exclusive_access: '#008a5c',// kinda murky greeny grey ish
chapter: '#ffd679',
hook: '#395699',
};

// Find the Category column, save its index
const columnHeads = document.querySelector("table thead tr").children;
let categoryColIndex = -1;
for (const i in columnHeads) {
if (columnHeads[i].innerText == "Category") {
categoryColIndex = Number(i); // i love javascript
break;
}
}
if (categoryColIndex == -1) {
throw Error("Coloured Categories: Failed to find the Category column");
}

// Generate and install CSS styles for the squares
let cssCode = `
#sbbcc-radius {
order: 1;
display: flex;
flex-direction: column;
}
.categoryCell::before {
content: " ";
width: 0.75em;
height: 0.75em;
margin-right: 0.25em;
border-radius: var(--sbbcc-radius, 0);
display: inline-block;
}
`
for (const [name, color] of Object.entries(COLOURS)) {
cssCode += `
.categoryCell[data-category="${name}"]::before {
background-color: ${color};
}
`
}
const styleElement = document.createElement("style");
styleElement.innerHTML = cssCode;
styleElement.id = "sbbcc-styles";
document.head.appendChild(styleElement);

const table = document.querySelector('.table');
const headerRow = table.querySelector('thead tr');
const headerCells = headerRow.querySelectorAll('th');

// The columns aren't always in a fixed order, e.g. they're different on user pages vs video pages
// And also the order can be changed with userscripts etc. So instead of using column 7 (the default on video pages),
// we find the correct column number from the table header:

var columnNumber = 0;
var found = false;
// Create a global slider for border radius in the navbar
const sliderContainer = document.createElement('div');
sliderContainer.id = "sbbcc-radius";
const sliderLabel = document.createElement("label");
sliderLabel.for = "sbbcc-radius-slider";
sliderLabel.innerText = "Category label radius:"
sliderContainer.appendChild(sliderLabel);
const slider = document.createElement("input");
slider.type="range";
slider.id="sbbcc-radius-slider";
slider.value = GM_getValue("radius", 0); // read previous stored radius preference from storage
slider.min = 0;
slider.max = 50;
slider.step = 0.5;
sliderContainer.appendChild(slider);
document.querySelector('nav > div').appendChild(sliderContainer);
document.body.style.setProperty("--sbbcc-radius", `${slider.value}%`); // set the radius variable for the first time

headerCells.forEach((cell) => {
if (!found){
if (cell.innerText == "Category") {
found = true;
} else {
columnNumber += 1;
}
}
slider.addEventListener('input', () => {
document.body.style.setProperty("--sbbcc-radius", `${slider.value}%`);
GM_setValue("radius", slider.value); // save radius preference
});

addSquare();

function addSquare() {
const rows = table.querySelectorAll('tbody tr'); // a list of the table rows

rows.forEach((row) => {
const categoryCell = row.querySelectorAll('td')[columnNumber]; // select the correct column
let category = categoryCell.innerText.split("\n")[0]; // sometimes userscripts add a line below the category text, e.g. for a button
if (category.charAt(0) === "■") category = category.substring(1);

if (category in COLOURS) {
var newSpan = document.createElement('span');
newSpan.id = "colorSquare";
newSpan.innerHTML = "■"; // cute lil square
newSpan.setAttribute('style', 'color:' + COLOURS[category]);
categoryCell.querySelector('#colorSquare')?.remove();
categoryCell.prepend(newSpan); // add to beginning of cell
function markCells() {
// Find all category cells with CSS selectors
for (const cell of document.querySelectorAll(`td:nth-child(${categoryColIndex+1})`)) {
cell.classList.add("categoryCell");
for (const node of cell.childNodes) {
if (node.nodeName != "#text") continue; // search for the first child text node, to avoid extracting strings from other userscripts
cell.setAttribute("data-category", node.textContent);
break;
}
});
}
}

document.addEventListener('forceRefresh', () => addSquare());
// Mark category cells with appropriate classes and attributes
markCells();
document.addEventListener('forceRefresh', markCells);
})();