element parse

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

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==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 ⚪');
            }
        });
    }
})();