element parse

Select elements, outline them in red, expand/shrink selection, and show a small copy box.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na inštaláciu tohto skriptu budete musieť nainštalovať rozšírenie, ako je napríklad Tampermonkey alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==UserScript==
// @name element parse
// @namespace https://viayoo.com/
// @version 0.1
// @description Select elements, outline them in red, expand/shrink selection, and show a small copy box.
// @author You
// @run-at document-end
// @license me
// @match *://*/*
// @grant GM_registerMenuCommand
// @grant GM_setClipboard
// ==/UserScript==

(function() {
    'use strict';

    let isActive = false; // State of the selector (Active / Inactive)
    let currentElement = null;
    let elementHistory = [];

    // Inject CSS for the panel, outline, and the small Copy Box
    const style = document.createElement('style');
    style.innerHTML = `
        /* Top control panel */
        .custom-selector-panel {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            background: rgba(255, 255, 255, 0.95);
            box-shadow: 0 2px 10px rgba(0,0,0,0.2);
            z-index: 999999;
            display: flex;
            flex-direction: column;
            align-items: center;
            padding: 8px 0;
            font-family: Arial, sans-serif;
            font-size: 14px;
        }
        .custom-selector-info {
            color: #555;
            margin-bottom: 6px;
            font-weight: bold;
            font-size: 12px;
            max-width: 90%;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }
        .custom-selector-buttons {
            display: flex;
            gap: 15px;
        }
        .custom-selector-btn {
            background: none;
            border: none;
            font-size: 16px;
            font-weight: bold;
            color: #333;
            cursor: pointer;
            padding: 5px 10px;
        }
        .custom-selector-btn:active {
            color: red;
        }

        /* Small Copy Box Modal */
        .custom-copy-box {
            position: fixed;
            bottom: 20px;
            left: 50%;
            transform: translateX(-50%);
            width: 90%;
            max-width: 400px;
            background: rgba(30, 30, 30, 0.95);
            color: #f4f4f4;
            border-radius: 8px;
            box-shadow: 0 4px 15px rgba(0,0,0,0.4);
            z-index: 1000000;
            display: flex;
            flex-direction: column;
            padding: 10px;
            gap: 8px;
            font-family: Arial, sans-serif;
            border: 1px solid #444;
        }
        .custom-copy-input {
            width: 100%;
            background: #121212;
            color: #a5d6a7;
            border: 1px solid #333;
            border-radius: 4px;
            padding: 6px;
            font-size: 12px;
            font-family: monospace;
            box-sizing: border-box;
        }
        .custom-copy-actions {
            display: flex;
            justify-content: flex-end;
            gap: 8px;
        }
        .custom-copy-btn {
            background: #00e676;
            color: #121212;
            border: none;
            padding: 6px 12px;
            border-radius: 4px;
            font-size: 12px;
            cursor: pointer;
            font-weight: bold;
        }
        .custom-copy-btn:active {
            background: #00b555;
        }
        .custom-close-btn {
            background: #ff5252;
            color: white;
            border: none;
            padding: 6px 12px;
            border-radius: 4px;
            font-size: 12px;
            cursor: pointer;
            font-weight: bold;
        }
        .custom-close-btn:active {
            background: #d32f2f;
        }
    `;
    document.head.appendChild(style);

    // Create physical external outline box
    const outline = document.createElement('div');
    outline.style.cssText = `
        position: absolute;
        border: 4px solid red;
        outline: none;
        pointer-events: none;
        z-index: 999998;
        display: none;
        box-sizing: border-box;
        transition: all 0.1s ease;
    `;
    document.body.appendChild(outline);

    // Create top control panel
    const panel = document.createElement('div');
    panel.className = 'custom-selector-panel';
    panel.style.display = 'none';

    const infoLabel = document.createElement('div');
    infoLabel.className = 'custom-selector-info';

    const btnContainer = document.createElement('div');
    btnContainer.className = 'custom-selector-buttons';

    const expandBtn = document.createElement('button');
    expandBtn.className = 'custom-selector-btn';
    expandBtn.innerText = 'Expand';

    const shrinkBtn = document.createElement('button');
    shrinkBtn.className = 'custom-selector-btn';
    shrinkBtn.innerText = 'Shrink';

    const saveBtn = document.createElement('button');
    saveBtn.className = 'custom-selector-btn';
    saveBtn.innerText = 'Save';

    const cancelBtn = document.createElement('button');
    cancelBtn.className = 'custom-selector-btn';
    cancelBtn.innerText = 'Cancel';

    btnContainer.appendChild(expandBtn);
    btnContainer.appendChild(shrinkBtn);
    btnContainer.appendChild(saveBtn);
    btnContainer.appendChild(cancelBtn);
    panel.appendChild(infoLabel);
    panel.appendChild(btnContainer);
    document.body.appendChild(panel);

    // Create Small Copy Box
    const copyBox = document.createElement('div');
    copyBox.className = 'custom-copy-box';
    copyBox.style.display = 'none';

    const copyInput = document.createElement('input');
    copyInput.type = 'text';
    copyInput.className = 'custom-copy-input';
    copyInput.readOnly = true;

    const actionContainer = document.createElement('div');
    actionContainer.className = 'custom-copy-actions';

    const copyBtn = document.createElement('button');
    copyBtn.className = 'custom-copy-btn';
    copyBtn.innerText = 'Copy to Clipboard';

    const closeBtn = document.createElement('button');
    closeBtn.className = 'custom-close-btn';
    closeBtn.innerText = 'Close';

    actionContainer.appendChild(copyBtn);
    actionContainer.appendChild(closeBtn);
    copyBox.appendChild(copyInput);
    copyBox.appendChild(actionContainer);
    document.body.appendChild(copyBox);

    // Close Copy Box
    function hideCopyBox() {
        copyBox.style.display = 'none';
        copyInput.value = '';
    }
    closeBtn.addEventListener('click', hideCopyBox);

    // Clipboard Copy Helper
    function secureCopy(text) {
        function fallbackCopy(str) {
            const textArea = document.createElement('textarea');
            textArea.value = str;
            textArea.style.position = 'fixed';
            textArea.style.top = '0';
            textArea.style.left = '0';
            textArea.style.opacity = '0';
            document.body.appendChild(textArea);
            textArea.focus();
            textArea.select();
            try {
                document.execCommand('copy');
            } catch (err) {
                console.error('Fallback copy failed: ', err);
            }
            document.body.removeChild(textArea);
        }

        if (typeof GM_setClipboard !== 'undefined') {
            try {
                GM_setClipboard(text);
                return;
            } catch (e) {}
        }

        if (navigator.clipboard && navigator.clipboard.writeText) {
            navigator.clipboard.writeText(text).catch(function() {
                fallbackCopy(text);
            });
        } else {
            fallbackCopy(text);
        }
    }

    copyBtn.addEventListener('click', function() {
        if (copyInput.value) {
            secureCopy(copyInput.value);
            alert('HTML Copied! 🎉');
            hideCopyBox();
        }
    });

    // Positions our external outline directly over the targeted element
    function highlightElement(el) {
        if (el && el !== document.body && el !== document.documentElement && !panel.contains(el) && !copyBox.contains(el)) {
            currentElement = el;
            
            const rect = el.getBoundingClientRect();
            const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
            const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
            
            outline.style.top = (rect.top + scrollTop) + 'px';
            outline.style.left = (rect.left + scrollLeft) + 'px';
            outline.style.width = rect.width + 'px';
            outline.style.height = rect.height + 'px';
            outline.style.display = 'block';
            
            let className = el.className && typeof el.className === 'string' ? '.' + Array.from(el.classList).join('.') : '';
            infoLabel.innerText = `${el.tagName.toLowerCase()}${className}`;
            panel.style.display = 'flex';
        } else {
            outline.style.display = 'none';
            panel.style.display = 'none';
        }
    }

    // Keep outline aligned with the element during scrolls
    window.addEventListener('scroll', function() {
        if (isActive && currentElement) {
            highlightElement(currentElement);
        }
    }, { passive: true });

    // Capture and highlight clicked element instantly if script is active
    document.addEventListener('click', function(e) {
        if (!isActive) return;
        if (panel.contains(e.target) || copyBox.contains(e.target)) return;

        e.preventDefault();
        e.stopPropagation();

        elementHistory = []; 
        highlightElement(e.target);
    }, true);

    // Expand button
    expandBtn.addEventListener('click', function() {
        if (currentElement && currentElement.parentElement && currentElement.parentElement !== document.body) {
            elementHistory.push(currentElement);
            highlightElement(currentElement.parentElement);
        }
    });

    // Shrink button
    shrinkBtn.addEventListener('click', function() {
        if (elementHistory.length > 0) {
            const previousElement = elementHistory.pop();
            highlightElement(previousElement);
        }
    });

    // Save button (Now opens the small, neat copy box)
    saveBtn.addEventListener('click', function() {
        if (currentElement) {
            const htmlContent = currentElement.outerHTML;
            copyInput.value = htmlContent;
            copyBox.style.display = 'flex';
            clearSelection();
        }
    });

    // Cancel button
    cancelBtn.addEventListener('click', function() {
        clearSelection();
    });

    function clearSelection() {
        outline.style.display = 'none';
        panel.style.display = 'none';
        currentElement = null;
        elementHistory = [];
        isActive = false;
    }

    // Register a static, crash-proof menu command for Via Browser
    if (typeof GM_registerMenuCommand !== 'undefined') {
        GM_registerMenuCommand('🔍 Toggle Element Selector', function() {
            isActive = !isActive;
            if (isActive) {
                alert('Element Selector: ACTIVE 🟢\nClick any element on the page to highlight it.');
            } else {
                clearSelection();
                alert('Element Selector: INACTIVE ⚪');
            }
        });
    }
})();