A simple aid for collecting ScummVM and ResidualVM-supported games
// ==UserScript==
// @name Mark owned ScummVM/ResidualVM Games
// @namespace ssokolow.com
// @description A simple aid for collecting ScummVM and ResidualVM-supported games
// @license MIT
// @version 6
//
// @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
//
// @match *://scummvm.org/compatibility
// @match *://scummvm.org/compatibility/*
// @match *://residualvm.org/compatibility
// @match *://residualvm.org/compatibility/*
// @match *://www.scummvm.org/compatibility
// @match *://www.scummvm.org/compatibility/*
// @match *://www.residualvm.org/compatibility
// @match *://www.residualvm.org/compatibility/*
//
// @grant GM_setValue
// @grant GM.setValue
// @grant GM_getValue
// @grant GM.getValue
// @grant GM_deleteValue
// @grant GM.deleteValue
// @grant GM_listValues
// @grant GM.listValues
// ==/UserScript==
const OWNED_OPACITY = 0.3;
var hide_owned;
var owned_games;
/// Code shared between initial setup and the click handler
var mark_owned = function(node, state) {
let row = node.closest('tr');
if (state) {
row.style.opacity = OWNED_OPACITY;
row.classList.add('owned');
} else {
row.style.opacity = 1.0;
row.classList.remove('owned');
}
};
// TODO: Finish factoring out jQuery
/// click() handler for the per-game toggle button
var toggleOwnership = function(e) {
e.preventDefault();
let game_id = this.dataset.gameId;
// Toggle based on what's displayed so that it will always act as the
// user expects, regardless of changes since last reload
if (this.textContent == '+') {
this.textContent = '-';
mark_owned(this, true);
GM.setValue(game_id, true);
} else {
this.textContent = '+';
mark_owned(this, false);
GM.deleteValue(game_id);
}
};
/// click() handler for the whole-table hide/show button
var toggleVisible = function(e) {
document.querySelectorAll('tr.owned').forEach(function(node) {
node.style.display = hide_owned ? '' : 'none';
});
this.textContent = hide_owned ? '-' : '+';
GM.setValue('__HIDE_OWNED', hide_owned = !hide_owned);
};
/// Shared code to generate a toggle button
var makeButton = function(initial_state, label) {
let button = document.createElement("div");
button.setAttribute('class', 'toggle_btn');
button.setAttribute('title', label);
button.textContent = initial_state ? '+' : '-'
button.style.cssText = "" +
"background: #c0c0c0; " +
"border-radius: 3px; " +
"color: black; " +
"display: inline-block; " +
"margin-right: 5px; " +
"padding: 0 2px; " +
"text-align: center; " +
"width: 1em; " +
"cursor: pointer";
return button;
};
(async function() {
let state = await Promise.all([
GM.getValue('__HIDE_OWNED', false),
GM.listValues()
]);
hide_owned = state[0];
owned_games = state[1];
// Per-entry code
document.querySelectorAll('table.chart a').forEach(function(node) {
console.log(node);
// Extract the game ID for use in record-keeping
let site_id = location.hostname.split('.');
site_id = site_id[site_id.length - 2]; // "scummvm" or "residualvm"
let url = node.getAttribute('href').split('/');
let game_id = url[url.length-1] ? url[url.length-1] : url[url.length-2];
game_id = site_id + "_" + game_id;
// Craft a button to toggle ownership status
let togglebutton = makeButton(owned_games.indexOf(game_id) == -1,
"Toggle Owned")
togglebutton.addEventListener("click", toggleOwnership);
togglebutton.dataset.gameId = game_id;
node.closest('td').prepend(togglebutton);
// TODO: Profile alternatives like an x|y|z regexp or a popping iteration
if (owned_games.indexOf(game_id) !== -1){ mark_owned(node, true); }
});
// Global toggle-button code
let g_button = makeButton(hide_owned, "Show/Hide Owned Games")
g_button.id = 'gm_visible_toggle';
g_button.style.position = 'relative';
g_button.style.marginRight = '-100%';
g_button.style.top = '14px';
g_button.style.left = '0';
g_button.addEventListener("click", toggleVisible);
let container = document.querySelector("#content .content");
if (!container) {
container = document.querySelector("section.intro ~ section.content");
}
container.prepend(g_button);
if (hide_owned) {
document.querySelectorAll('tr.owned').forEach(function(node) {
node.style.display = 'none';
});
}
// Hover-style the buttons and add a better print stylesheet to
// make "thrifting TODO" printouts easier
let style_elem = document.createElement("style");
style_elem.textContent = "td > .toggle_btn { visibility: hidden; }\n\n" +
"td:hover > .toggle_btn { visibility: visible; }\n\n" +
"@media print { " +
"section.box section.content, #content, .rbwrapper > .box > .content { " +
"position: absolute !important; " +
"top: 0 !important; " +
"left: 0 !important; " +
"right: 0 !important; " +
"z-index: 9999 !important; " +
"margin: 0 !important; " +
"padding: 0 !important; " +
"background: white !important; " +
"} " +
"table.chart, #container { width: 100% !important; } " +
"#header, #menu, #footer, .intro, .cookie-consent, .toggle_btn { " +
"display: none !important; " +
"} " +
"html, body, #container { background: white !important; } " +
"}";
document.head.appendChild(style_elem);
})();