// ==UserScript== // @name RYM Combine Genres and Scenes // @namespace http://tampermonkey.net/ // @version 1.0 // @description Combines primary genres with scenes and movements on RateYourMusic album pages // @author FrnkPsycho // @match *://rateyourmusic.com/release/* // @license MIT // @grant none // @downloadURL https://update.greasyfork.icu/scripts/530727/RYM%20Combine%20Genres%20and%20Scenes.user.js // @updateURL https://update.greasyfork.icu/scripts/530727/RYM%20Combine%20Genres%20and%20Scenes.meta.js // ==/UserScript== (function() { 'use strict'; const DEBUG = false; // Set to true to enable logging const OPACITY = 0.75; // Set opacity of appending text, including slash separators const INLINE = true; // Set false to display scenes and movements in a new line function log(...args) { if (DEBUG) console.log("[RYM Script]", ...args); } function appendScenesAndMovements() { const genreRows = document.querySelectorAll("tr.release_genres"); let genreRow, scenesRow, movementsRow; genreRows.forEach(row => { const header = row.querySelector("th.info_hdr"); if (!header) return; const text = header.textContent.trim(); if (text === "Genres") genreRow = row; else if (text === "Scenes") scenesRow = row; else if (text === "Movements") movementsRow = row; }); if (!genreRow) { log("Genre row not found"); return; } const priGenres = genreRow.querySelector(".release_pri_genres"); if (!priGenres) { log("Primary genres not found"); return; } let additionalText = ""; let slash = ` / `; [scenesRow, movementsRow].forEach(row => { if (row) { const categorySpan = row.querySelector(".release_pri_genres"); if (categorySpan) { additionalText += (additionalText ? `${slash}` : "") + `${categorySpan.innerHTML}`; } row.remove(); } }); if (additionalText) { if (INLINE) { priGenres.innerHTML += `${slash}${additionalText}`; } else { priGenres.innerHTML += `
${additionalText}`; } log("Updated genres with scenes/movements:", priGenres.innerHTML); } else { log("No scenes or movements found"); } } function waitForElement(selector, callback, interval = 500, timeout = 5000) { const startTime = Date.now(); const check = setInterval(() => { const element = document.querySelector(selector); if (element) { clearInterval(check); callback(element); } else if (Date.now() - startTime > timeout) { clearInterval(check); log(`Timeout waiting for ${selector}`); } }, interval); } waitForElement("tr.release_genres", appendScenesAndMovements); })();