Skip to content

Instantly share code, notes, and snippets.

@alanrme
Last active September 14, 2026 06:39
Show Gist options
  • Select an option

  • Save alanrme/6dc32bfb67d61937d81d7bfbfdf15adf to your computer and use it in GitHub Desktop.

Select an option

Save alanrme/6dc32bfb67d61937d81d7bfbfdf15adf to your computer and use it in GitHub Desktop.
Userscript: VocaDB button to open PV thumbnail in new tab
// ==UserScript==
// @name VocaDB PV thumbnail button
// @namespace https://gist.github.com/alanrme/6dc32bfb67d61937d81d7bfbfdf15adf
// @icon
// @version 1.2.0
//
// @match *://vocadb.net/S/*
// @match *://www.vocadb.net/S/*
// @grant none
//
// @author Alan D'souza
// @description Adds a button to open PV thumbnails in a new tab on VocaDB
//
// @run-at document-idle
// ==/UserScript==
// This is really hacked together!!!!!
function addButton(thumb) {
// find original "play" button on pv thumbnail and make a clone
playButton = thumb.getElementsByTagName("button")[0];
imgButton = playButton.cloneNode(true);
// change the svg inside the clone button, give it an offset to not overlap with the play button
imgButton.getElementsByTagName("span")[0].innerHTML = `<svg aria-hidden="true" width="20" height="20" viewBox="0 0 16 16" fill="currentColor" class="___12fm75w f1w7gpdv fez10in fg4l7m0" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <path fill-rule="evenodd" clip-rule="evenodd" d="M1 1H15V15H1V1ZM6 9L8 11L13 6V13H3V12L6 9ZM6.5 7C7.32843 7 8 6.32843 8 5.5C8 4.67157 7.32843 4 6.5 4C5.67157 4 5 4.67157 5 5.5C5 6.32843 5.67157 7 6.5 7Z" fill="#000000"></path> </g></svg>`;
imgButton.style.left = "56px";
thumb.insertBefore(imgButton, playButton.nextSibling);
// open the thumbnail in a new tab when clone img button is pressed
imgButton.addEventListener('click', function() {
window.open(thumb.getElementsByTagName("div")[0].style.backgroundImage.slice(4, -1).replace(/"/g, ""));
});
}
// create observer to see if pv thumbnail element has loaded in
const observer = new MutationObserver((mutations, obs) => {
const target = document.getElementsByClassName('pv-embed-preview')[0];
if (target) {
obs.disconnect(); // stop watching
addButton(target);
}
});
// start observing the document body
observer.observe(document.body, {
childList: true,
subtree: true
});
@alanrme

alanrme commented Sep 8, 2026

Copy link
Copy Markdown
Author

I only tested this on Chromium 151

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment