Greasy Fork is available in English.
Mark episodes as watched/unwatched on All Seasons pages on TheTVDB.com
// ==UserScript==
// @name TheTVDB All Seasons - Mark as Watched
// @namespace http://tampermonkey.net/
// @version 1.1
// @description Mark episodes as watched/unwatched on All Seasons pages on TheTVDB.com
// @author xdpirate
// @license GPLv3
// @match https://thetvdb.com/series/*/allseasons/*
// @match https://www.thetvdb.com/series/*/allseasons/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=thetvdb.com
// @grant GM_getValue
// @grant GM_setValue
// @run-at document-end
// ==/UserScript==
function colorEpisodes() {
for(let i = 0; i < episodeListItems.length; i++) {
let id = episodeListItems[i].querySelector("a").href.match(/\/([0-9]+)$/)[1];
if(seriesArr.includes(id)) {
episodeListItems[i].style.backgroundColor = "darkgreen";
} else {
episodeListItems[i].style.backgroundColor = "maroon";
}
}
}
function isEntireShowWatched() {
for(let i = 0; i < episodeListItems.length; i++) {
let id = episodeListItems[i].querySelector("a").href.match(/\/([0-9]+)$/)[1];
if(!seriesArr.includes(id)) {
return false;
}
}
return true;
}
function isEntireSeasonWatched(seasonHeader) {
let seasonEps = seasonHeader.nextElementSibling.querySelectorAll("li.list-group-item");
for(let i = 0; i < seasonEps.length; i++) {
let id = seasonEps[i].querySelector("a").href.match(/\/([0-9]+)$/)[1];
if(!seriesArr.includes(id)) {
return false;
}
}
return true;
}
function populateCheckboxes() {
for(let i = 0; i < episodeListItems.length; i++) {
let checkbox = document.createElement("span");
checkbox.classList.add("aomaw-episode-checkbox");
checkbox.style.cursor = "pointer";
checkbox.title = "Click to mark this episode as watched";
checkbox.innerText = "👀";
checkbox.style.marginRight = "0.5em";
checkbox.episodeID = episodeListItems[i].querySelector("a").href.match(/\/([0-9]+)$/)[1];
if(seriesArr.includes(checkbox.episodeID)) {
checkbox.innerText = "✅";
checkbox.title = "Click to mark this episode as unwatched";
}
checkbox.addEventListener("click", function() {
if(seriesArr.includes(this.episodeID)) {
seriesArr.splice(seriesArr.indexOf(this.episodeID), 1);
this.closest("li").style.backgroundColor = "maroon";
this.innerText = "👀";
this.title = "Click to mark this episode as watched";
} else {
seriesArr.push(this.episodeID);
this.closest("li").style.backgroundColor = "darkgreen";
checkbox.innerText = "✅";
this.title = "Click to mark this episode as unwatched";
}
let completeCheckbox = document.querySelector("span#aomaw-show-checkbox");
if(isEntireShowWatched()) {
completeCheckbox.innerText = "✅";
completeCheckbox.title = "Click to mark every episode in this show as unwatched";
} else {
completeCheckbox.innerText = "👀";
completeCheckbox.title = "Click to mark every episode in this show as watched";
}
let seasonCheckbox = this.closest("ul.list-group").previousElementSibling.querySelector("span.aomaw-season-checkbox");
if(isEntireSeasonWatched(this.closest("ul.list-group").previousElementSibling)) {
seasonCheckbox.innerText = "✅";
seasonCheckbox.title = "Click to mark this season as unwatched";
} else {
seasonCheckbox.innerText = "👀";
seasonCheckbox.title = "Click to mark this season as watched";
}
GM_setValue(seriesID, seriesArr);
});
let headerElement = episodeListItems[i].querySelector("h4.list-group-item-heading");
headerElement.insertAdjacentElement("afterbegin", checkbox);
}
}
function populateBatchElements() {
let showHeader = document.querySelector("div.page-toolbar > h1");
let completeCheckbox = document.createElement("span");
completeCheckbox.id = "aomaw-show-checkbox";
completeCheckbox.style.cursor = "pointer";
completeCheckbox.style.marginRight = "0.4em";
if(isEntireShowWatched()) {
completeCheckbox.innerText = "✅";
completeCheckbox.title = "Click to mark every episode in this show as unwatched";
} else {
completeCheckbox.innerText = "👀";
completeCheckbox.title = "Click to mark every episode in this show as watched";
}
completeCheckbox.addEventListener("click", function() {
if(isEntireShowWatched()) {
seriesArr = [];
let episodeCheckboxes = document.querySelectorAll("span.aomaw-episode-checkbox");
for(let i = 0; i < episodeCheckboxes.length; i++) {
episodeCheckboxes[i].innerText = "👀";
episodeCheckboxes[i].title = "Click to mark this episode as watched";
episodeCheckboxes[i].closest("li").style.backgroundColor = "maroon";
}
let seasonCheckboxes = document.querySelectorAll("span.aomaw-season-checkbox");
for(let i = 0; i < seasonCheckboxes.length; i++) {
seasonCheckboxes[i].innerText = "👀";
seasonCheckboxes[i].title = "Click to mark this season as watched";
}
this.innerText = "👀";
this.title = "Click to mark every episode in this show as watched";
} else {
let episodeCheckboxes = document.querySelectorAll("span.aomaw-episode-checkbox");
for(let i = 0; i < episodeCheckboxes.length; i++) {
if(!seriesArr.includes(episodeCheckboxes[i].episodeID)) {
seriesArr.push(episodeCheckboxes[i].episodeID);
}
episodeCheckboxes[i].innerText = "✅";
episodeCheckboxes[i].closest("li").style.backgroundColor = "darkgreen";
}
let seasonCheckboxes = document.querySelectorAll("span.aomaw-season-checkbox");
for(let i = 0; i < seasonCheckboxes.length; i++) {
seasonCheckboxes[i].innerText = "✅";
seasonCheckboxes[i].title = "Click to mark this season as unwatched";
}
this.innerText = "✅";
this.title = "Click to mark every episode in this show as unwatched";
}
GM_setValue(seriesID, seriesArr);
});
showHeader.insertAdjacentElement("afterbegin", completeCheckbox);
let seasonHeaders = document.querySelectorAll("h3.mt-4");
for(let i = 0; i < seasonHeaders.length; i++) {
let seasonCheckbox = document.createElement("span");
seasonCheckbox.classList.add("aomaw-season-checkbox");
seasonCheckbox.style.cursor = "pointer";
seasonCheckbox.style.marginRight = "0.4em";
if(isEntireSeasonWatched(seasonHeaders[i])) {
seasonCheckbox.innerText = "✅";
seasonCheckbox.title = "Click to mark this season as unwatched";
} else {
seasonCheckbox.innerText = "👀";
seasonCheckbox.title = "Click to mark this season as watched";
}
seasonCheckbox.addEventListener("click", function() {
let seasonEps = this.closest("h3.mt-4").nextElementSibling.querySelectorAll("li.list-group-item");
if(isEntireSeasonWatched(this.closest("h3.mt-4"))) {
for(let i = 0; i < seasonEps.length; i++) {
let id = seasonEps[i].querySelector("a").href.match(/\/([0-9]+)$/)[1];
if(seriesArr.includes(id)) {
seriesArr.splice(seriesArr.indexOf(id), 1);
}
}
let episodeCheckboxes = this.closest("h3.mt-4").nextElementSibling.querySelectorAll("span.aomaw-episode-checkbox");
for(let i = 0; i < episodeCheckboxes.length; i++) {
episodeCheckboxes[i].innerText = "👀";
episodeCheckboxes[i].title = "Click to mark this episode as watched";
episodeCheckboxes[i].closest("li").style.backgroundColor = "maroon";
}
this.innerText = "👀";
this.title = "Click to mark this season as watched";
} else {
for(let i = 0; i < seasonEps.length; i++) {
let id = seasonEps[i].querySelector("a").href.match(/\/([0-9]+)$/)[1];
if(!seriesArr.includes(id)) {
seriesArr.push(id);
}
}
let episodeCheckboxes = this.closest("h3.mt-4").nextElementSibling.querySelectorAll("span.aomaw-episode-checkbox");
for(let i = 0; i < episodeCheckboxes.length; i++) {
episodeCheckboxes[i].innerText = "✅";
episodeCheckboxes[i].title = "Click to mark this episode as unwatched";
episodeCheckboxes[i].closest("li").style.backgroundColor = "darkgreen";
}
this.innerText = "✅";
this.title = "Click to mark this season as unwatched";
}
let completeCheckbox = document.querySelector("span#aomaw-show-checkbox");
if(isEntireShowWatched()) {
completeCheckbox.innerText = "✅";
completeCheckbox.title = "Click to mark every episode in this show as unwatched";
} else {
completeCheckbox.innerText = "👀";
completeCheckbox.title = "Click to mark every episode in this show as watched";
}
GM_setValue(seriesID, seriesArr);
});
seasonHeaders[i].insertAdjacentElement("afterbegin", seasonCheckbox);
}
}
let seriesID = location.href.match(/^https:\/\/(?:www\.)?thetvdb\.com\/series\/(.+)\/allseasons\/(.+)/)[1];
let seriesArr = GM_getValue(seriesID, []);
let episodeListItems = document.querySelectorAll("li.list-group-item");
populateBatchElements();
populateCheckboxes();
colorEpisodes();