Custom search and highlighting aka (Ctrl+F)

search and highlight tool

当前为 2025-11-01 提交的版本,查看 最新版本

// ==UserScript==
// @name          Custom search and highlighting aka (Ctrl+F)
// @namespace     http://tampermonkey.net/
// @version       2025-10-31
// @description    search and highlight  tool
// @author        kr6r5kugkkgk
// @match         *://*/*
// @license       MIT
// @run-at        document-idle
// @icon          https://i.pinimg.com/originals/79/09/89/7909897ceea2691e5a4942766c678ff3.png
// ==/UserScript==
 

(function() {
    'use strict';
    // Переменные для функционала
    let matches = [];
    let currentIndex = -1;
    // Создание wrapper (всегда видимый)
    const wrapper = document.createElement('div');
    wrapper.id = 'modifiedcstm-page-searcher-wrapper-r6ujr5jre5';
    wrapper.style.cssText = `
        position: fixed;
        top: 10px;
        right: 10px;
        z-index: 555555;
        display: flex;
        flex-direction: column;
        gap: 2px;
    `;
    // Кнопка сворачивания (всегда видна)
    const btnToggle = document.createElement('button');
    btnToggle.id = 'searche4nmx7hjn-toggle8nme5h-btnjre6';
    btnToggle.style.cssText = `
           width: 30px;
           height: 30px;
           background: rgb(13, 61, 63);
           border: 1px solid rgb(139, 248, 194);
           border-radius: 5px;
           cursor: pointer;
           display: flex;
           align-items: center;
           justify-content: center;
           box-shadow: rgba(0, 0, 0, 0.2) 0px 2px 10px;
           transition: background 0.3s;
           position: fixed;
           top: 10px;
           left: 1081px;
    `;
    btnToggle.addEventListener('click', () => {
        wrapper.classList.toggle('collapsed');
    });
 
    const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
    svg.setAttribute('viewBox', '0 0 24 24');
    svg.setAttribute('width', '16');
    svg.setAttribute('height', '16');
    svg.style.transition = 'transform 0.3s ease';
    const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
    path.setAttribute('d', 'M7 10l5 5 5-5z');
    path.setAttribute('fill', 'rgb(139, 248, 194)');
    svg.appendChild(path);
    btnToggle.appendChild(svg);
    // Стили для анимации и скрытия
    const style = document.createElement('style');
    style.textContent = `
 #modifiedcstm-page-searcher-wrapper-r6ujr5jre5.collapsed #modifiedcstm-page-search-container-r6ujr5jre5 {
       display: none !important;
 }
 #searche4nmx7hjn-toggle8nme5h-btnjre6:hover {
      background: rgb(20, 80, 82);
 }
 #modifiedcstm-page-searcher-wrapper-r6ujr5jre5.collapsed #searche4nmx7hjn-toggle8nme5h-btnjre6 svg {
      transform: rotate(180deg);
 }
 input#input-searcj-on-paggeweb-text {
    background: #1f2a2f !important;
    border: 2px solid #46968d !important;
    color: antiquewhite !important;
 }
 #modifiedcstm-page-search-container-r6ujr5jre5 {
    display: flex !important;
}
 
 #markSearch-he5ngw4n-webpagebody {
     background-color: rgb(52 22 86) !important;
     color: rgb(232 248 101) !important;
     font-weight: bold !important;
     padding: 5px !important;
     border: 2px solid !important;
     border-radius: 12px !important;
}
 #searcherUp-btnUp-5en8h4w5en8m {
    padding: 5px !important;
    background: rgb(20 29 43) !important;
    color: rgb(139, 248, 194) !important;
    border: 1px solid rgb(139, 248, 194) !important;
    border-radius: 5px !important;
    border-radius: 3px !important;
    cursor: pointer !important;
    width: 28px !important;
    height: 28px !important;
}

#searcherDown-btnDown-5en8h4w5en8m {
    padding: 5px !important;
    background: rgb(20 29 43) !important;
    color: rgb(139, 248, 194) !important;
    border: 1px solid rgb(139, 248, 194) !important;
    border-radius: 3px !important;
    cursor: pointer !important;
    width: 28px !important;
    height: 28px !important;
}
  
 #searche4nmx7hjn-toggle8nme5h-btnjre6:hover,
#searcherUp-btnUp-5en8h4w5en8m:hover,
#closeSsearchWrapper-8n5e85egh8n-he5hedhe5d:hover,
#searcherDown-btnDown-5en8h4w5en8m:hover {
     background-color: #775993  !important;
    transform: scale(1.3)  !important;
    transition: all 0.3s ease  !important;
}

    `;
    document.head.appendChild(style);
    // Создание контейнера (внутри wrapper)
    const container = document.createElement('div');
    container.id = 'modifiedcstm-page-search-container-r6ujr5jre5';
    container.style.cssText = `
        background: rgb(13, 61, 63);
        border: 1px solid rgb(139, 248, 194);
        border-radius: 5px;
        padding: 5px;
        display: flex;
        align-items: center;
        gap: 5px;
        font-family: Arial, sans-serif;
        font-size: 14px;
        box-shadow: 0 2px 10px rgba(0,0,0,0.2);
        position: relative;
        top: 45px;
        left: -150px;
    `;
 
    // Поле поиска
    const input = document.createElement('input');
    input.id = 'input-searcj-on-paggeweb-text';
    input.type = 'text';
    input.placeholder = 'Поиск по странице...';
    input.style.cssText = 'padding: 5px; border: 1px solid #ccc; border-radius: 3px; width: 150px;';
 
      // Кнопки
    const btnNext = document.createElement('button');
    btnNext.id = 'searcherDown-btnDown-5en8h4w5en8m';
    btnNext.innerHTML = '↓';
    btnNext.style.cssText = 'padding: 5px; background: #dc35dc; color: white; border: none; border-radius: 3px; cursor: pointer;';
 
    const btnPrev = document.createElement('button');
    btnPrev.id = 'searcherUp-btnUp-5en8h4w5en8m';
    btnPrev.innerHTML = '↑';
    btnPrev.style.cssText = 'padding: 5px; background: #dc35dc; color: white; border: none; border-radius: 3px; cursor: pointer;';
 
    const btnClose = document.createElement('button');
     btnClose.id = 'closeSsearchWrapper-8n5e85egh8n-he5hedhe5d';
    btnClose.innerHTML = '×';
    btnClose.style.cssText = 'padding: 5px 8px; background: #dc3545; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 16px;';
 
    container.appendChild(input);
    container.appendChild(btnPrev);
    container.appendChild(btnNext);
    container.appendChild(btnClose);
    wrapper.appendChild(btnToggle);
    wrapper.appendChild(container);
    document.body.appendChild(wrapper);
 
      // Функция очистки подсветки
    function clearHighlights() {
        matches.forEach(mark => {
            const parent = mark.parentNode;
            if (!parent) return;
            parent.replaceChild(document.createTextNode(mark.textContent), mark);
            parent.normalize();
        });
        matches = [];
        currentIndex = -1;
    }
 
     // Функция поиска и подсветки
    function searchAndHighlight(query) {
        clearHighlights();
        if (!query.trim()) return;
        const regex = new RegExp(`(${query})`, 'gi');
 
        function walk(node) {
            if (node.nodeType === Node.TEXT_NODE && node.parentNode.tagName !== 'SCRIPT' && node.parentNode.tagName !== 'STYLE') {
                const text = node.textContent;
                const frag = document.createDocumentFragment();
                let lastIndex = 0;
                let match;
                while ((match = regex.exec(text)) !== null) {
                    if (match.index > lastIndex) {
                        frag.appendChild(document.createTextNode(text.slice(lastIndex, match.index)));
                    }
                    // Mark для совпадения
                    const mark = document.createElement('mark');
                    mark.id = 'markSearch-he5ngw4n-webpagebody';
                    mark.textContent = match[1];
                    mark.style.fontWeight = 'bold';
                    frag.appendChild(mark);
                    matches.push(mark);
                    lastIndex = match.index + match[1].length;
                }
                // Остаток текста
                if (lastIndex < text.length) {
                    frag.appendChild(document.createTextNode(text.slice(lastIndex)));
                }
                if (matches.length) node.parentNode.replaceChild(frag, node);
            } else if (node.nodeType === Node.ELEMENT_NODE) {
                Array.from(node.childNodes).forEach(child => walk(child));
            }
        }
 
        walk(document.body);
    }
 
 
    // Функция навигации
    function navigate(direction) {
        if (!matches.length) return;
        currentIndex += direction;
        if (currentIndex >= matches.length) currentIndex = 0;
        if (currentIndex < 0) currentIndex = matches.length - 1;
        matches.forEach((m, i) => {
            m.style.backgroundColor = i === currentIndex ? 'rgb(179,117,238)' : 'rgb(57, 92, 18)';
        });
        matches[currentIndex].scrollIntoView({ behavior: 'smooth', block: 'center' });
    }
 
     // Обработчики событий
    input.addEventListener('input', e => searchAndHighlight(e.target.value));
    btnNext.addEventListener('click', () => navigate(1));
    btnPrev.addEventListener('click', () => navigate(-1));
    btnClose.addEventListener('click', () => {
        clearHighlights();
        wrapper.classList.add('collapsed');
        container.style.display = 'none';
    });
 
 // Горячие клавиши
    document.addEventListener('keydown', e => {
        if (e.ctrlKey && e.key === 'f') {
            e.preventDefault();
            wrapper.classList.remove('collapsed');
            input.focus();
        }
        if (!wrapper.classList.contains('collapsed') && container.style.display !== 'none' && input === document.activeElement) {
            if (e.key === 'Enter') navigate(e.shiftKey ? -1 : 1);
            if (e.key === 'Escape') btnClose.click();
        }
    });
 
    container.style.display = 'flex';
})();