您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Automatically selects text in specific Strava elements and displays a notification near the cursor. Also allows right-click to copy text.
当前为
// ==UserScript== // @name Strava Text Auto-Selector // @namespace typpi.online // @version 1.0.8 // @description Automatically selects text in specific Strava elements and displays a notification near the cursor. Also allows right-click to copy text. // @author Nick2bad4u // @license UnLicense // @homepageURL https://github.com/Nick2bad4u/UserScripts // @grant none // @include *://*.strava.com/activities/* // @include *://*.strava.com/athlete/training // @icon https://www.google.com/s2/favicons?sz=64&domain=strava.com // ==/UserScript== (function () { 'use strict'; // Log when the script starts console.log( 'Strava Text Auto-Selector script loaded.', ); // Wait for the page to fully load window.addEventListener('load', function () { console.log( 'Page fully loaded, initializing script.', ); // Delay script execution for 500 ms setTimeout(initializeScript, 500); }); function initializeScript() { console.log( 'Initializing script after delay.', ); const selectors = [ '#search-results > tbody > tr:nth-child(n) > td.view-col.col-title > a', '.summaryGrid .summaryGridDataContainer, .inline-stats strong, .inline-stats b', '#heading > div > div.row.no-margins.activity-summary-container > div.spans8.activity-summary.mt-md.mb-md > div.details-container > div > h1', '.ride .segment-effort-detail .effort-details table, .swim .segment-effort-detail .effort-details table', '.activity-description p:only-child', ]; const summarySelector = '.summaryGridDataContainer'; // Function to add the event listener to target elements function addContextMenuListener(element) { console.log( 'Adding right-click event listener to element:', element, ); element.addEventListener( 'contextmenu', function (event) { console.log( 'Right-click detected on element:', element, ); event.preventDefault(); console.log( 'Default right-click menu prevented.', ); const range = document.createRange(); if ( element.classList.contains( 'summaryGridDataContainer', ) ) { const textNode = element.childNodes[0]; range.selectNodeContents(textNode); console.log( 'Text range selected:', textNode.textContent, ); } else { range.selectNodeContents(element); console.log( 'Text range selected:', element.textContent, ); } const selection = window.getSelection(); selection.removeAllRanges(); selection.addRange(range); console.log('Text added to selection.'); const copiedText = selection.toString(); console.log( 'Text copied to clipboard:', copiedText, ); navigator.clipboard .writeText(copiedText) .then(() => { console.log( 'Clipboard write successful.', ); showNotification( event.clientX, event.clientY, 'Text Copied!', ); }) .catch(() => { console.log( 'Clipboard write failed.', ); showNotification( event.clientX, event.clientY, 'Failed to Copy!', ); }); }, ); } // Query elements and add event listeners initially for the first three selectors selectors.forEach((selector) => { const elements = document.querySelectorAll(selector); console.log( `Found ${elements.length} elements for selector: ${selector}`, ); elements.forEach(addContextMenuListener); }); // Function to handle the summaryGridDataContainer elements separately function handleSummaryGridDataContainer() { const elements = document.querySelectorAll( summarySelector, ); console.log( `Found ${elements.length} elements for selector: ${summarySelector}`, ); elements.forEach(addContextMenuListener); } // MutationObserver to detect changes in the DOM and add event listeners to new summaryGridDataContainer elements const observer = new MutationObserver( (mutations) => { mutations.forEach((mutation) => { mutation.addedNodes.forEach((node) => { if ( node.nodeType === Node.ELEMENT_NODE ) { if (node.matches(summarySelector)) { addContextMenuListener(node); } node .querySelectorAll(summarySelector) .forEach(addContextMenuListener); } }); }); }, ); observer.observe(document.body, { childList: true, subtree: true, }); console.log( 'MutationObserver set up to monitor the DOM for summaryGridDataContainer.', ); // Handle existing summaryGridDataContainer elements initially handleSummaryGridDataContainer(); } function showNotification(x, y, message) { console.log( 'Displaying notification:', message, ); const notification = document.createElement('div'); notification.textContent = message; notification.style.position = 'absolute'; notification.style.left = `${x + 10}px`; notification.style.top = `${y + 10}px`; notification.style.background = 'rgba(0, 0, 0, 0.8)'; notification.style.color = 'white'; notification.style.padding = '5px 10px'; notification.style.borderRadius = '5px'; notification.style.fontSize = '12px'; notification.style.zIndex = '1000'; notification.style.pointerEvents = 'none'; document.body.appendChild(notification); console.log('Notification added to DOM.'); setTimeout(() => { notification.remove(); console.log( 'Notification removed from DOM.', ); }, 2000); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址