您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds copy buttons to the VGMdb album pages to easily copy metadata.
- // ==UserScript==
- // @name VGMdb Metadata copy
- // @namespace https://vgmdb.net/
- // @version 1.8
- // @description Adds copy buttons to the VGMdb album pages to easily copy metadata.
- // @author kahpaibe
- // @match https://vgmdb.net/album/*
- // @grant none
- // @run-at document-end
- // @license MIT
- // ==/UserScript==
- (function() {
- 'use strict';
- const PREFIX = '';
- const SUFFIX = '';
- // Helper function to style buttons consistently
- const styleButton = (button) => {
- button.title = 'Copy this text to clipboard';
- button.style.marginLeft = '8px';
- button.style.padding = '1px 6px';
- button.style.fontSize = '0.75em';
- button.style.color = '#CEFFFF';
- button.style.background = 'transparent';
- button.style.border = '1px solid #CEFFFF';
- button.style.cursor = 'pointer';
- button.style.transition = 'background 0.3s, color 0.3s';
- button.style.verticalAlign = 'middle';
- };
- // Helper function to create and append a "COPY" button next to a field
- const addCopyButton = (innerText, labelText, selector, tooltipText, fieldValue) => {
- const rows = document.querySelectorAll('#album_infobit_large tr');
- rows.forEach(row => {
- const labelCell = row.querySelector('td span.label b');
- if (labelCell && labelCell.textContent.trim() === labelText) {
- const valueCell = row.cells[1];
- let field = fieldValue || valueCell.textContent.trim();
- if (selector) {
- const link = valueCell.querySelector(selector);
- if (link) {
- field = link.textContent.trim();
- }
- }
- const button = document.createElement('span');
- button.innerText = innerText; // Set innerText here
- button.title = tooltipText;
- styleButton(button);
- button.onclick = () => {
- navigator.clipboard.writeText(field).then(() => {
- const original = button.innerText;
- button.innerText = '✔ COPIED';
- setTimeout(() => button.innerText = original, 1500);
- });
- };
- labelCell.parentElement.appendChild(button);
- }
- });
- };
- // Function to handle Release Date buttons
- const addReleaseDateButtons = () => {
- const rows = document.querySelectorAll('#album_infobit_large tr');
- const releaseDateRow = Array.from(rows).find(row => {
- const labelCell = row.querySelector('td span.label b');
- return labelCell && labelCell.textContent.trim() === 'Release Date';
- });
- if (!releaseDateRow) return;
- const valueCell = releaseDateRow.cells[1];
- const dateLink = valueCell.querySelector('a[title^="View albums released on"]');
- const eventLink = valueCell.querySelector('a.link_event');
- let formattedDate = '';
- if (dateLink) {
- const releaseDateStr = dateLink.textContent.trim();
- const dateObj = new Date(releaseDateStr);
- formattedDate = `${dateObj.getFullYear()}.${('0' + (dateObj.getMonth() + 1)).slice(-2)}.${('0' + dateObj.getDate()).slice(-2)}`;
- addCopyButton('⎘', 'Release Date', null, 'Copy Release Date to clipboard', formattedDate);
- }
- let event = '';
- if (eventLink) {
- event = eventLink.textContent.trim();
- addCopyButton('⎘', 'Release Date', null, 'Copy Event to clipboard', event);
- }
- if (dateLink) {
- const combined = event ? `[${formattedDate}][${event}]` : `[${formattedDate}]`;
- addCopyButton('⎘', 'Release Date', null, 'Copy formatted release date to clipboard', combined);
- }
- };
- const addTitleCopyButtons = () => {
- const visibleTitles = document.querySelectorAll('.albumtitle');
- visibleTitles.forEach(span => {
- const computedStyle = window.getComputedStyle(span);
- if (computedStyle.display === 'none' || computedStyle.visibility === 'hidden') {
- return;
- }
- // Skip titles inside <a> tags (like in the album thumb list)
- if (span.closest('a')) {
- return;
- }
- const fragments = [];
- let currentText = '';
- // Break apart the nodes and <br> inside this span
- span.childNodes.forEach(node => {
- if (node.nodeName === 'BR') {
- if (currentText.trim()) fragments.push(currentText.trim());
- fragments.push('<br>');
- currentText = '';
- } else if (node.nodeType === Node.TEXT_NODE) {
- currentText += node.textContent;
- } else {
- currentText += node.outerHTML || node.textContent;
- }
- });
- if (currentText.trim()) {
- fragments.push(currentText.trim());
- }
- // Clear the span and re-inject each line with its own copy button
- span.innerHTML = '';
- fragments.forEach(fragment => {
- if (fragment === '<br>') {
- span.appendChild(document.createElement('br'));
- return;
- }
- const lineSpan = document.createElement('span');
- lineSpan.textContent = fragment;
- const button = document.createElement('button');
- styleButton(button);
- button.innerText = '⎘'; // Ensure button has text
- button.title = 'Copy this title to clipboard';
- button.addEventListener('click', () => {
- navigator.clipboard.writeText(fragment).then(() => {
- const original = button.innerText;
- button.innerText = '✔ COPIED!';
- setTimeout(() => button.innerText = original, 1000);
- });
- });
- span.appendChild(lineSpan);
- span.appendChild(button);
- // Add a second button for copying formatted string
- const formattedStringButton = document.createElement('button');
- styleButton(formattedStringButton);
- formattedStringButton.innerText = '⎘'; // Same button style
- formattedStringButton.title = 'Copy formatted album info to clipboard';
- // Fetch Publisher and Catalog Number dynamically within the context
- const publisherCell = Array.from(document.querySelectorAll('td span.label b')).find(b => b.textContent.trim() === 'Publisher');
- const publisher = publisherCell ? publisherCell.closest('tr').querySelector('td:nth-child(2)').textContent.trim() : '';
- const catalogNumberCell = Array.from(document.querySelectorAll('td span.label b')).find(b => b.textContent.trim() === 'Catalog Number');
- const catalogNumber = catalogNumberCell ? catalogNumberCell.closest('tr').querySelector('td:nth-child(2)').textContent.trim() : '';
- // Re-fetch Release Date and Event here to avoid assumptions
- const rows = document.querySelectorAll('#album_infobit_large tr');
- let formattedDate = '';
- let event = '';
- rows.forEach(row => {
- const labelCell = row.querySelector('td span.label b');
- if (labelCell && labelCell.textContent.trim() === 'Release Date') {
- const valueCell = row.cells[1];
- const dateLink = valueCell.querySelector('a[title^="View albums released on"]');
- const eventLink = valueCell.querySelector('a.link_event');
- if (dateLink) {
- const releaseDateStr = dateLink.textContent.trim();
- const dateObj = new Date(releaseDateStr);
- formattedDate = `${dateObj.getFullYear()}.${('0' + (dateObj.getMonth() + 1)).slice(-2)}.${('0' + dateObj.getDate()).slice(-2)}`;
- }
- if (eventLink) {
- event = eventLink.textContent.trim();
- }
- }
- });
- // Construct the formatted string
- let formattedString = PREFIX;
- formattedString += `[${formattedDate}]`;
- if (event) {
- formattedString += `[${event}]`;
- }
- if (publisher) {
- formattedString += ` ${publisher} -`;
- }
- formattedString += ` ${fragment}`;
- if (catalogNumber) {
- formattedString += ` {${catalogNumber}}`;
- } else {
- formattedString += ' {nocat#}';
- }
- formattedString += SUFFIX;
- formattedStringButton.addEventListener('click', () => {
- navigator.clipboard.writeText(formattedString).then(() => {
- const original = formattedStringButton.innerText;
- formattedStringButton.innerText = '✔ COPIED!';
- setTimeout(() => formattedStringButton.innerText = original, 1000);
- });
- });
- // Append button to the DOM (you can adjust where this button goes)
- document.body.appendChild(formattedStringButton);
- span.appendChild(formattedStringButton);
- });
- });
- };
- // Main function to initialize the copy buttons
- const initializeCopyButtons = () => {
- // Add metadata buttons
- addCopyButton('⎘', 'Catalog Number', null, 'Copy Catalog Number to clipboard');
- addCopyButton('⎘', 'Publisher', '.productname', 'Copy Publisher to clipboard');
- addReleaseDateButtons(); // Add the buttons for Release Date, Event, and Date+Event
- // Add inline copy buttons for album titles and secondary names
- addTitleCopyButtons();
- };
- // Initialize the script
- initializeCopyButtons();
- })();