Select elements, outline them in red, expand/shrink selection, and show a small copy box.
// ==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 ⚪');
}
});
}
})();