YouTube Grid Auto-Scroll & Search (Ultra Optimized - Instant)

Automatically scrolls to a specified text within a YouTube grid. Search box in masthead, search on button click only, and stop button.

目前為 2025-03-02 提交的版本,檢視 最新版本

// ==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或关注我们的公众号极客氢云获取最新地址