您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Add a button to copy book information from the Médiathèque de Roubaix
// ==UserScript== // @name MediathequeRoubaix Book Info Copier // @namespace http://tampermonkey.net/ // @version 2025-04-29 // @description Add a button to copy book information from the Médiathèque de Roubaix // @author Tom // @license MIT // @match http*://www.mediathequederoubaix.fr/osiros/result/notice.php* // @icon http://www.mediathequederoubaix.fr/favicon.ico // @grant GM_setClipboard // @run-at document-end // ==/UserScript== (function() { 'use strict'; // First check if this is actually a book page by looking for key elements const titleElement = document.querySelector('h1'); const authorElement = document.querySelector('.col-md-12 a b'); const descriptionElement = document.querySelector('.col-md-12 > p'); // Only proceed if we have the essential elements that indicate this is a book page if (titleElement && (authorElement || descriptionElement)) { // Create a button element const button = document.createElement('button'); button.textContent = '📋'; button.title = 'Copy Book Info'; button.style.cssText = 'margin-left: 10px; padding: 5px 8px; background-color: transparent; color: #333; border: none; border-radius: 4px; cursor: pointer; vertical-align: middle; font-size: 32px; transition: background-color 0.2s;'; // Add hover effect button.addEventListener('mouseover', function() { this.style.backgroundColor = 'rgba(0, 0, 0, 0.1)'; }); button.addEventListener('mouseout', function() { this.style.backgroundColor = 'transparent'; }); // Add click event handler button.addEventListener('click', function() { try { // Extract book information const bookInfo = extractBookInfo(); // Copy to clipboard (notification will be shown by the callback) copyToClipboard(bookInfo); } catch (error) { console.error('Error in book info extraction:', error); showNotification('Error: Failed to extract book information!', true); } }); // Append the button next to the title titleElement.appendChild(button); } // Function to extract book information function extractBookInfo() { let title = ''; let author = ''; let description = ''; let link = ''; try { // Extract title (only text subelements, removing the icon and extra spaces) const titleElement = document.querySelector('h1'); if (titleElement) { for (let node of titleElement.childNodes) { if (node.nodeType === Node.TEXT_NODE) { title += node.textContent; } } title = title.replace(/^\s+|\s+$/g, '').replace(/\s+/g, ' '); } // Extract author (remove dates and extra info in parentheses) const authorElement = document.querySelector('.col-md-12 a b'); if (authorElement) { author = authorElement.textContent.replace(/\(\d{4}-....\)/, '').trim(); } // Extract description const descriptionElement = document.querySelector('.col-md-12 > p'); if (descriptionElement) { description = descriptionElement.textContent.replaceAll("", "").trim(); } // Extract permalink const permalinkElement = document.getElementById('contain_permalien'); if (permalinkElement) { link = permalinkElement.textContent.trim(); } } catch (error) { console.error('Error extracting book information:', error); } // Format the extracted information const formattedInfo = `${title} - ${author}\n` + `[Roubaix](${link})\n` + `> ${description}\n`; return formattedInfo; } // Function to copy text to clipboard and show notification function copyToClipboard(text) { // Use GM_setClipboard with callback for notification GM_setClipboard(text, "text", function() { showNotification('Copied!'); }); } // Function to show a notification function showNotification(message, isError = false) { // Get button position to place notification next to it const button = document.querySelector('h1 button'); if (!button) return; const buttonRect = button.getBoundingClientRect(); const notification = document.createElement('div'); notification.textContent = message; const bgColor = isError ? 'rgba(200, 50, 50, 0.8)' : 'rgba(50, 200, 50, 0.8)'; notification.style.cssText = ` position: absolute; left: ${buttonRect.right + 10}px; top: ${buttonRect.top}px; z-index: 9999; padding: 4px 8px; background-color: ${bgColor}; color: white; border-radius: 4px; transition: opacity 0.5s; font-size: 14px; `; document.body.appendChild(notification); // Fade out setTimeout(function() { notification.style.opacity = '0'; setTimeout(function() { if (notification.parentNode) { notification.parentNode.removeChild(notification); } }, 500); }, 1000); } })();