您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Automatically scrolls to a specified text within a YouTube grid. Search box in masthead, search on button click only, and stop button.
当前为
// ==UserScript== // @name YouTube Grid Auto-Scroll & Search (Ultra Optimized - Instant) // @match https://www.youtube.com/* // @grant GM_addStyle // @version 1.9 // @description Automatically scrolls to a specified text within a YouTube grid. Search box in masthead, search on button click only, and stop button. // @author You (with further optimization) // @license MIT // @run-at document-end // @namespace https://gf.qytechs.cn/users/1435316 // ==/UserScript== (function() { 'use strict'; let targetText = ""; let searchBox; let isScrolling = false; let searchInput; let searchButton; let stopButton; // Added stop button let observer; // Store the observer so we can disconnect it. // --- Styling (CSS) --- GM_addStyle(` #floating-search-box { background-color: #222; padding: 5px; border: 1px solid #444; border-radius: 5px; display: flex; align-items: center; margin-left: 10px; } #floating-search-box input[type="text"] { background-color: #333; color: #fff; border: 1px solid #555; padding: 3px 5px; border-radius: 3px; margin-right: 5px; width: 200px; height: 30px; } #floating-search-box input[type="text"]:focus { outline: none; border-color: #065fd4; } #floating-search-box button { background-color: #065fd4; color: white; border: none; padding: 3px 8px; border-radius: 3px; cursor: pointer; height: 30px; } #floating-search-box button:hover { background-color: #0549a8; } #floating-search-box button:focus { outline: none; } #stop-search-button { /* Style for the stop button */ background-color: #aa0000; /* Red color */ } #stop-search-button:hover { background-color: #800000; } .highlighted-text { background-color: yellow; } `); // --- Create the Search Box --- function createSearchBox() { searchBox = document.createElement('div'); searchBox.id = 'floating-search-box'; searchInput = document.createElement('input'); searchInput.type = 'text'; searchInput.placeholder = 'Search to scroll...'; // NO input event listener here. We only search on button click. searchButton = document.createElement('button'); searchButton.textContent = 'Search'; searchButton.addEventListener('click', searchAndScroll); stopButton = document.createElement('button'); // Create the stop button stopButton.textContent = 'Stop'; stopButton.id = 'stop-search-button'; // Give it an ID for styling stopButton.addEventListener('click', stopSearch); // Add the stop function searchBox.appendChild(searchInput); searchBox.appendChild(searchButton); searchBox.appendChild(stopButton); // Add stop button to the box const mastheadEnd = document.querySelector('#end.ytd-masthead'); const buttonsContainer = document.querySelector('#end #buttons'); if (mastheadEnd) { if(buttonsContainer){ mastheadEnd.insertBefore(searchBox, buttonsContainer); } else{ mastheadEnd.appendChild(searchBox); } } else { console.error("Could not find the YouTube masthead's end element."); document.body.appendChild(searchBox); // Fallback } } // --- Stop Search Function --- function stopSearch() { if (observer) { observer.disconnect(); // Stop observing } isScrolling = false; const prevHighlighted = document.querySelector('.highlighted-text'); if (prevHighlighted) { prevHighlighted.classList.remove('highlighted-text'); } } // --- Optimized Search and Scroll Function --- function searchAndScroll() { if (isScrolling) return; isScrolling = true; //disconnect any prior observer, to avoid multiple observers if(observer) { observer.disconnect(); } targetText = searchInput.value.trim().toLowerCase(); if (!targetText) { isScrolling = false; return; } // Remove previous highlights const prevHighlighted = document.querySelector('.highlighted-text'); if (prevHighlighted) { prevHighlighted.classList.remove('highlighted-text'); } // Intersection Observer for optimized searching observer = new IntersectionObserver((entries) => { // Store the observer for (const entry of entries) { if (entry.isIntersecting) { const titleElement = entry.target.querySelector('#video-title'); // Target title directly if (titleElement && titleElement.textContent.toLowerCase().includes(targetText)) { entry.target.scrollIntoView({ behavior: 'auto', block: 'center' }); // Instant scroll entry.target.classList.add('highlighted-text'); observer.disconnect(); // Stop observing once found. VERY IMPORTANT. isScrolling = false; // Reset flag return; // Exit early } } } }); // Observe initial set of grid items document.querySelectorAll('ytd-rich-grid-media').forEach(item => { observer.observe(item); }); // Immediate scroll to bottom, but with a *very* short delay. setTimeout(() => { if (!document.querySelector('.highlighted-text')) { window.scrollTo({ top: document.documentElement.scrollHeight, behavior: 'auto' }); //instant scroll //shorter delay, before searching again setTimeout(() => { if(!isScrolling) return; // Check again, in case stop was pressed isScrolling = false; searchAndScroll(); }, 750); }else{ isScrolling = false; // Reset the flag even if found by observer. } }, 100); } // --- Initialization --- createSearchBox(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址