Last active
June 20, 2025 06:39
-
-
Save stanley2058/472b3b9bd21d187e65e26b2fd71aa340 to your computer and use it in GitHub Desktop.
Highlight all `ui-` class on a web page
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name HackMD `ui-` classes highlighter | |
// @namespace http://hackmd.io/ | |
// @version 0.1.2 | |
// @description Show all `ui-` classes | |
// @author stanley2058, Yukaii | |
// @match https://hackmd.io/* | |
// @match https://local.localhost/* | |
// @icon https://www.google.com/s2/favicons?sz=64&domain=hackmd.io | |
// @grant GM.getValue | |
// @grant GM.setValue | |
// @require https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js | |
// ==/UserScript== | |
const setVal = (k, v) => typeof GM !== 'undefined' ? GM.setValue(k, v) : Promise.resolve(localStorage.setItem(k, v)); | |
const getVal = (k, v) => typeof GM !== 'undefined' ? GM.getValue(k, v) : Promise.resolve(localStorage.getItem(k) ?? v); | |
(async function() { | |
let highlighting = false; | |
let overlays = new Map(); | |
// Add tooltip styles | |
const style = document.createElement('style'); | |
style.textContent = ` | |
#highlight-toggle { | |
position: relative; | |
} | |
#highlight-toggle::after { | |
content: attr(title); | |
position: absolute; | |
background: #333; | |
color: white; | |
padding: 4px 8px; | |
border-radius: 4px; | |
font-size: 12px; | |
white-space: pre; | |
opacity: 0; | |
visibility: hidden; | |
transition: opacity 0.2s, visibility 0.2s; | |
pointer-events: none; | |
bottom: 120%; | |
left: 50%; | |
transform: translateX(-50%); | |
} | |
#highlight-toggle::before { | |
content: ''; | |
position: absolute; | |
border: 5px solid transparent; | |
border-top-color: #333; | |
opacity: 0; | |
visibility: hidden; | |
transition: opacity 0.2s, visibility 0.2s; | |
pointer-events: none; | |
bottom: calc(120% - 10px); | |
left: 50%; | |
transform: translateX(-50%); | |
} | |
#highlight-toggle:hover::after, | |
#highlight-toggle:hover::before { | |
opacity: 1; | |
visibility: visible; | |
} | |
`; | |
document.head.appendChild(style); | |
function validatePosition(position) { | |
const defaultPosition = { left: '10px', bottom: '10px' }; | |
if (!position) return defaultPosition; | |
const left = parseInt(position.left); | |
const bottom = parseInt(position.bottom); | |
if (isNaN(left) || isNaN(bottom) || | |
left < 0 || left > window.innerWidth - 40 || | |
bottom < 0 || bottom > window.innerHeight - 40) { | |
return defaultPosition; | |
} | |
return { | |
left: `${left}px`, | |
bottom: `${bottom}px` | |
}; | |
} | |
const savedPosition = validatePosition(JSON.parse(await getVal('highlightBtnPosition', null))); | |
const isVisible = await getVal('highlightBtnVisible') !== 'false'; | |
const toggleBtn = document.createElement('button'); | |
toggleBtn.id = 'highlight-toggle'; | |
toggleBtn.setAttribute('aria-label', 'Toggle UI Class Highlighter'); | |
toggleBtn.setAttribute('title', 'Toggle UI Class Highlighter\nLeft click: Toggle highlight\nRight click: Hide button\nCtrl+click: Remove overlay'); | |
toggleBtn.setAttribute('draggable', 'true'); | |
Object.assign(toggleBtn.style, { | |
position: 'fixed', | |
left: savedPosition.left, | |
bottom: savedPosition.bottom, | |
zIndex: '10002', | |
padding: '8px', | |
background: '#FFA500', | |
border: 'none', | |
borderRadius: '50%', | |
cursor: 'pointer', | |
width: '40px', | |
height: '40px', | |
display: isVisible ? 'flex' : 'none', | |
alignItems: 'center', | |
justifyContent: 'center', | |
opacity: '0.95', | |
}); | |
toggleBtn.innerHTML = '🔍'; | |
toggleBtn.addEventListener('mouseenter', () => { | |
toggleBtn.style.background = '#FF8C00'; | |
}); | |
toggleBtn.addEventListener('mouseleave', () => { | |
toggleBtn.style.background = '#FFA500'; | |
}); | |
const dropOverlay = document.createElement('div'); | |
Object.assign(dropOverlay.style, { | |
position: 'fixed', | |
left: 0, | |
top: 0, | |
zIndex: '10001', | |
width: '100dvw', | |
height: '100dvh', | |
display: 'none', | |
}); | |
let isDragging = false; | |
let currentX; | |
let currentY; | |
let initialX; | |
let initialY; | |
let xOffset = 0; | |
let yOffset = 0; | |
toggleBtn.addEventListener('dragstart', (e) => { | |
dropOverlay.style.display = 'block'; | |
initialX = e.clientX - xOffset; | |
initialY = e.clientY - yOffset; | |
}); | |
dropOverlay.addEventListener('dragover', (e) => { | |
e.preventDefault(); | |
}); | |
dropOverlay.addEventListener('drop', (e) => { | |
dropOverlay.style.display = 'none'; | |
currentX = e.clientX - initialX; | |
currentY = e.clientY - initialY; | |
xOffset = currentX; | |
yOffset = currentY; | |
const { width, height } = toggleBtn.getBoundingClientRect(); | |
const left = Math.max(0, Math.min(window.innerWidth - 40, e.clientX - width / 2)); | |
const bottom = Math.max(0, Math.min(window.innerHeight - 40, window.innerHeight - e.clientY - height / 2)); | |
toggleBtn.style.left = `${left}px`; | |
toggleBtn.style.bottom = `${bottom}px`; | |
setVal('highlightBtnPosition', JSON.stringify({ | |
left: toggleBtn.style.left, | |
bottom: toggleBtn.style.bottom | |
})); | |
}); | |
toggleBtn.addEventListener('contextmenu', (e) => { | |
e.preventDefault(); | |
toggleBtn.style.display = 'none'; | |
setVal('highlightBtnVisible', 'false'); | |
}); | |
async function enableUIClassDebug () { | |
const currentPosition = validatePosition(JSON.parse(await getVal('highlightBtnPosition', null))); | |
toggleBtn.style.left = currentPosition.left; | |
toggleBtn.style.bottom = currentPosition.bottom; | |
toggleBtn.style.display = 'flex'; | |
setVal('highlightBtnVisible', 'true'); | |
setVal('highlightBtnPosition', JSON.stringify(currentPosition)); | |
console.log('UI Class Debug enabled. The button has been restored to a valid position.'); | |
}; | |
window.enableUIClassDebug = enableUIClassDebug; | |
function getTrackingClasses(element) { | |
return Array.from(element.classList) | |
.filter(className => className.startsWith('ui-')); | |
} | |
function createOverlay(element) { | |
const rect = element.getBoundingClientRect(); | |
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft; | |
const scrollTop = window.pageYOffset || document.documentElement.scrollTop; | |
const overlay = document.createElement('div'); | |
Object.assign(overlay.style, { | |
position: 'absolute', | |
background: 'rgba(255, 255, 0, 0.3)', | |
border: '2px solid #FFA500', | |
zIndex: '10000', | |
left: (rect.left + scrollLeft) + 'px', | |
top: (rect.top + scrollTop) + 'px', | |
width: rect.width + 'px', | |
height: rect.height + 'px' | |
}); | |
const label = document.createElement('div'); | |
Object.assign(label.style, { | |
position: 'absolute', | |
background: '#FFA500', | |
color: 'black', | |
padding: '2px 6px', | |
borderRadius: '3px', | |
fontSize: '12px', | |
fontFamily: 'monospace', | |
zIndex: '10001', | |
display: 'none', | |
left: (rect.left + scrollLeft) + 'px', | |
whiteSpace: 'nowrap', | |
transform: '' | |
}); | |
const trackingClasses = getTrackingClasses(element).join(', '); | |
label.textContent = trackingClasses; | |
overlay.addEventListener('mouseenter', () => { | |
const viewportHeight = window.innerHeight; | |
const viewportWidth = window.innerWidth; | |
const elementCenterY = rect.top + (rect.height / 2); | |
const elementCenterX = rect.left + (rect.width / 2); | |
if (elementCenterY < viewportHeight / 2) { | |
label.style.top = (rect.bottom + scrollTop + 4) + 'px'; | |
} else { | |
label.style.top = (rect.top + scrollTop - 24) + 'px'; | |
} | |
if (elementCenterX < viewportWidth / 2) { | |
label.style.transform = ''; | |
} else { | |
label.style.transform = `translateX(calc(-100% + ${rect.width}px))`; | |
} | |
label.style.display = 'block'; | |
}); | |
overlay.addEventListener('mouseleave', () => { | |
label.style.display = 'none'; | |
}); | |
overlay.addEventListener('click', (e) => { | |
window.navigator.clipboard | |
.writeText(label.innerText) | |
.catch(console.error); | |
if (!e.ctrlKey && !e.metaKey) return; | |
document.body.removeChild(overlay); | |
document.body.removeChild(label); | |
e.preventDefault(); | |
e.stopPropagation(); | |
}); | |
document.body.appendChild(overlay); | |
document.body.appendChild(label); | |
return [overlay, label]; | |
} | |
function toggleHighlights() { | |
highlighting = !highlighting; | |
if (highlighting) { | |
$("[class^='ui-'],[class*=' ui-']").each((_, element) => { | |
const [overlay, label] = createOverlay(element); | |
overlays.set(element, [overlay, label]); | |
}); | |
} else { | |
for (const [overlay, label] of overlays.values()) { | |
overlay.remove(); | |
label.remove(); | |
} | |
overlays.clear(); | |
} | |
} | |
toggleBtn.addEventListener('click', toggleHighlights); | |
document.body.appendChild(dropOverlay); | |
document.body.appendChild(toggleBtn); | |
window.addEventListener('keydown', async (e) => { | |
const shouldTriggerToggle = | |
(e.ctrlKey && e.shiftKey && e.key === 'U') || | |
(e.metaKey && e.shiftKey && e.key === 'u'); | |
const shouldToggleButtonDisplay = | |
(e.ctrlKey && e.shiftKey && e.key === 'H') || | |
(e.metaKey && e.shiftKey && e.key === 'h'); | |
if (shouldTriggerToggle) { | |
e.preventDefault(); | |
toggleHighlights(); | |
} | |
if (shouldToggleButtonDisplay) { | |
e.preventDefault(); | |
const disabled = await getVal('highlightBtnVisible') === 'false'; | |
if (disabled) { | |
enableUIClassDebug(); | |
} else { | |
toggleBtn.style.display = 'none'; | |
setVal('highlightBtnVisible', 'false'); | |
} | |
} | |
}); | |
})(); |
Made some improvements
- Update the button UI style with tooltip and icon
- Right click to dismiss the button
- expose
enableUIClassDebug
to re-enable the UI

// ==UserScript==
// @name HackMD `ui-` classes highlighter
// @namespace http://hackmd.io/
// @version 0.1.0
// @description Show all `ui-` classes
// @author stanley2058
// @match https://hackmd.io/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=hackmd.io
// @require https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js
// @grant none
// ==/UserScript==
(function() {
let highlighting = false;
let overlays = new Map();
// Add tooltip styles
const style = document.createElement('style');
style.textContent = `
#highlight-toggle {
position: relative;
}
#highlight-toggle::after {
content: attr(title);
position: absolute;
background: #333;
color: white;
padding: 4px 8px;
border-radius: 4px;
font-size: 12px;
white-space: pre;
opacity: 0;
visibility: hidden;
transition: opacity 0.2s, visibility 0.2s;
pointer-events: none;
bottom: 120%;
left: 50%;
transform: translateX(-50%);
}
#highlight-toggle::before {
content: '';
position: absolute;
border: 5px solid transparent;
border-top-color: #333;
opacity: 0;
visibility: hidden;
transition: opacity 0.2s, visibility 0.2s;
pointer-events: none;
bottom: calc(120% - 10px);
left: 50%;
transform: translateX(-50%);
}
#highlight-toggle:hover::after,
#highlight-toggle:hover::before {
opacity: 1;
visibility: visible;
}
`;
document.head.appendChild(style);
function validatePosition(position) {
const defaultPosition = { left: '10px', bottom: '10px' };
if (!position) return defaultPosition;
const left = parseInt(position.left);
const bottom = parseInt(position.bottom);
if (isNaN(left) || isNaN(bottom) ||
left < 0 || left > window.innerWidth - 40 ||
bottom < 0 || bottom > window.innerHeight - 40) {
return defaultPosition;
}
return {
left: `${left}px`,
bottom: `${bottom}px`
};
}
const savedPosition = validatePosition(JSON.parse(localStorage.getItem('highlightBtnPosition')));
const isVisible = localStorage.getItem('highlightBtnVisible') !== 'false';
const toggleBtn = document.createElement('button');
toggleBtn.id = 'highlight-toggle';
toggleBtn.setAttribute('aria-label', 'Toggle UI Class Highlighter');
toggleBtn.setAttribute('title', 'Toggle UI Class Highlighter\nLeft click: Toggle highlight\nRight click: Hide button\nCtrl+click: Remove overlay');
Object.assign(toggleBtn.style, {
position: 'fixed',
left: savedPosition.left,
bottom: savedPosition.bottom,
zIndex: '10002',
padding: '8px',
background: '#FFA500',
border: 'none',
borderRadius: '50%',
cursor: 'pointer',
width: '40px',
height: '40px',
display: isVisible ? 'flex' : 'none',
alignItems: 'center',
justifyContent: 'center',
opacity: '0.95',
});
toggleBtn.innerHTML = '🔍';
toggleBtn.addEventListener('mouseenter', () => {
toggleBtn.style.background = '#FF8C00';
});
toggleBtn.addEventListener('mouseleave', () => {
toggleBtn.style.background = '#FFA500';
});
let isDragging = false;
let currentX;
let currentY;
let initialX;
let initialY;
let xOffset = 0;
let yOffset = 0;
toggleBtn.addEventListener('mousedown', dragStart);
document.addEventListener('mousemove', drag);
document.addEventListener('mouseup', dragEnd);
function dragStart(e) {
if (e.button === 2) return;
initialX = e.clientX - xOffset;
initialY = e.clientY - yOffset;
if (e.target === toggleBtn) {
isDragging = true;
}
}
function drag(e) {
if (isDragging) {
e.preventDefault();
currentX = e.clientX - initialX;
currentY = e.clientY - initialY;
xOffset = currentX;
yOffset = currentY;
const left = Math.max(0, Math.min(window.innerWidth - 40, e.clientX));
const bottom = Math.max(0, Math.min(window.innerHeight - 40, window.innerHeight - e.clientY));
toggleBtn.style.left = `${left}px`;
toggleBtn.style.bottom = `${bottom}px`;
}
}
function dragEnd() {
if (!isDragging) return;
isDragging = false;
localStorage.setItem('highlightBtnPosition', JSON.stringify({
left: toggleBtn.style.left,
bottom: toggleBtn.style.bottom
}));
}
toggleBtn.addEventListener('contextmenu', (e) => {
e.preventDefault();
toggleBtn.style.display = 'none';
localStorage.setItem('highlightBtnVisible', 'false');
});
window.enableUIClassDebug = function() {
const currentPosition = validatePosition(JSON.parse(localStorage.getItem('highlightBtnPosition')));
toggleBtn.style.left = currentPosition.left;
toggleBtn.style.bottom = currentPosition.bottom;
toggleBtn.style.display = 'flex';
localStorage.setItem('highlightBtnVisible', 'true');
localStorage.setItem('highlightBtnPosition', JSON.stringify(currentPosition));
console.log('UI Class Debug enabled. The button has been restored to a valid position.');
};
function getTrackingClasses(element) {
return Array.from(element.classList)
.filter(className => className.startsWith('ui-'));
}
function createOverlay(element) {
const rect = element.getBoundingClientRect();
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
const overlay = document.createElement('div');
Object.assign(overlay.style, {
position: 'absolute',
background: 'rgba(255, 255, 0, 0.3)',
border: '2px solid #FFA500',
zIndex: '10000',
left: (rect.left + scrollLeft) + 'px',
top: (rect.top + scrollTop) + 'px',
width: rect.width + 'px',
height: rect.height + 'px'
});
const label = document.createElement('div');
Object.assign(label.style, {
position: 'absolute',
background: '#FFA500',
color: 'black',
padding: '2px 6px',
borderRadius: '3px',
fontSize: '12px',
fontFamily: 'monospace',
zIndex: '10001',
display: 'none',
left: (rect.left + scrollLeft) + 'px',
whiteSpace: 'nowrap',
transform: ''
});
const trackingClasses = getTrackingClasses(element).join(', ');
label.textContent = trackingClasses;
overlay.addEventListener('mouseenter', () => {
const viewportHeight = window.innerHeight;
const viewportWidth = window.innerWidth;
const elementCenterY = rect.top + (rect.height / 2);
const elementCenterX = rect.left + (rect.width / 2);
if (elementCenterY < viewportHeight / 2) {
label.style.top = (rect.bottom + scrollTop + 4) + 'px';
} else {
label.style.top = (rect.top + scrollTop - 24) + 'px';
}
if (elementCenterX < viewportWidth / 2) {
label.style.transform = '';
} else {
label.style.transform = `translateX(calc(-100% + ${rect.width}px))`;
}
label.style.display = 'block';
});
overlay.addEventListener('mouseleave', () => {
label.style.display = 'none';
});
overlay.addEventListener('click', (e) => {
window.navigator.clipboard
.writeText(label.innerText)
.catch(console.error);
if (!e.ctrlKey && !e.metaKey) return;
document.body.removeChild(overlay);
document.body.removeChild(label);
e.preventDefault();
e.stopPropagation();
});
document.body.appendChild(overlay);
document.body.appendChild(label);
return [overlay, label];
}
function toggleHighlights() {
highlighting = !highlighting;
if (highlighting) {
$("[class^='ui-'],[class*=' ui-']").each((_, element) => {
const [overlay, label] = createOverlay(element);
overlays.set(element, [overlay, label]);
});
} else {
for (const [overlay, label] of overlays.values()) {
overlay.remove();
label.remove();
}
overlays.clear();
}
}
toggleBtn.addEventListener('click', toggleHighlights);
document.body.appendChild(toggleBtn);
window.addEventListener('keydown', (e) => {
const shouldTriggerToggle =
(e.ctrlKey && e.shiftKey && e.key === 'U') ||
(e.metaKey && e.shiftKey && e.key === 'u');
const shouldToggleButtonDisplay =
(e.ctrlKey && e.shiftKey && e.key === 'H') ||
(e.metaKey && e.shiftKey && e.key === 'h');
if (shouldTriggerToggle) {
e.preventDefault();
toggleHighlights();
}
if (shouldToggleButtonDisplay) {
e.preventDefault();
const disabled = toggleBtn.getAttribute('data-clickable') === 'false';
if (disabled) {
toggleBtn.style.opacity = '0.95';
toggleBtn.style.pointerEvents = 'auto';
toggleBtn.setAttribute('data-clickable', 'true');
} else {
toggleBtn.style.opacity = '0.3';
toggleBtn.style.pointerEvents = 'none';
toggleBtn.setAttribute('data-clickable', 'false');
}
}
});
})();
Made some improvements
* Update the button UI style with tooltip and icon * Right click to dismiss the button * expose `enableUIClassDebug` to re-enable the UI
![]()
I've changed it up a bit:
- Use GM setValue/getValue APIs for userscript users.
- The
Ctrl
/Cmd
+Shift
+U
shortcut now binds to toggle hide or show the button. - Relocation now uses drag & drop event instead of mouse event to prevent triggering highlight on drop.
Minified bookmarklet of v0.1.2 and instructions generated by Gemini 2.5 Pro:
How to use:
- Create a new bookmark in your browser.
- Name it something descriptive (e.g., "UI Class Highlighter").
- Paste the entire
javascript:...
code block into the URL/Location field of the bookmark. - Save the bookmark.
- Navigate to a page you want to inspect (like HackMD).
- Click the bookmarklet. The orange button should appear.
javascript:void(async function(){const setVal=(k,v)=>Promise.resolve(localStorage.setItem(k,v));const getVal=(k,v)=>Promise.resolve(localStorage.getItem(k)??v);let h=!1,ov=new Map;const st=document.createElement('style');st.textContent=`#highlight-toggle{position:relative;}#highlight-toggle::after{content:attr(title);position:absolute;background:#333;color:white;padding:4px 8px;border-radius:4px;font-size:12px;white-space:pre;opacity:0;visibility:hidden;transition:opacity .2s,visibility .2s;pointer-events:none;bottom:120%;left:50%;transform:translateX(-50%);}#highlight-toggle::before{content:'';position:absolute;border:5px solid transparent;border-top-color:#333;opacity:0;visibility:hidden;transition:opacity .2s,visibility .2s;pointer-events:none;bottom:calc(120% - 10px);left:50%;transform:translateX(-50%);}#highlight-toggle:hover::after,#highlight-toggle:hover::before{opacity:1;visibility:visible;}`;document.head.appendChild(st);function validatePos(p){const d={left:'10px',bottom:'10px'};if(!p)return d;const l=parseInt(p.left),b=parseInt(p.bottom);return isNaN(l)||isNaN(b)||l<0||l>window.innerWidth-40||b<0||b>window.innerHeight-40?d:{left:`${l}px`,bottom:`${b}px`}}const sp=validatePos(JSON.parse(await getVal('highlightBtnPosition',null)));const vis=await getVal('highlightBtnVisible')!=='false';const b=document.createElement('button');b.id='highlight-toggle';b.setAttribute('aria-label','Toggle UI Class Highlighter');b.setAttribute('title','Toggle UI Class Highlighter\nLeft click: Toggle highlight\nRight click: Hide button\nCtrl+click: Remove overlay');b.setAttribute('draggable','true');Object.assign(b.style,{position:'fixed',left:sp.left,bottom:sp.bottom,zIndex:'10002',padding:'8px',background:'#FFA500',border:'none',borderRadius:'50%',cursor:'pointer',width:'40px',height:'40px',display:vis?'flex':'none',alignItems:'center',justifyContent:'center',opacity:'0.95'});b.innerHTML='🔍';b.addEventListener('mouseenter',()=>b.style.background='#FF8C00');b.addEventListener('mouseleave',()=>b.style.background='#FFA500');const drp=document.createElement('div');Object.assign(drp.style,{position:'fixed',left:0,top:0,zIndex:'10001',width:'100dvw',height:'100dvh',display:'none'});let isDragging=!1,cx,cy,ix,iy,xo=0,yo=0;b.addEventListener('dragstart',e=>{drp.style.display='block';ix=e.clientX-xo;iy=e.clientY-yo});drp.addEventListener('dragover',e=>e.preventDefault());drp.addEventListener('drop',e=>{drp.style.display='none';cx=e.clientX-ix;cy=e.clientY-iy;xo=cx;yo=cy;const{width:w,height:ht}=b.getBoundingClientRect(),l=Math.max(0,Math.min(window.innerWidth-40,e.clientX-w/2)),bt=Math.max(0,Math.min(window.innerHeight-40,window.innerHeight-e.clientY-ht/2));b.style.left=`${l}px`;b.style.bottom=`${bt}px`;setVal('highlightBtnPosition',JSON.stringify({left:b.style.left,bottom:b.style.bottom}))});b.addEventListener('contextmenu',e=>{e.preventDefault();b.style.display='none';setVal('highlightBtnVisible','false')});async function enableDebug(){const cp=validatePos(JSON.parse(await getVal('highlightBtnPosition',null)));b.style.left=cp.left;b.style.bottom=cp.bottom;b.style.display='flex';setVal('highlightBtnVisible','true');setVal('highlightBtnPosition',JSON.stringify(cp));console.log('UI Class Debug enabled. Button restored.')};window.enableUIClassDebug=enableDebug;function getCls(el){return Array.from(el.classList).filter(c=>c.startsWith('ui-'))}function createOv(el){const r=el.getBoundingClientRect(),sl=window.pageXOffset||document.documentElement.scrollLeft,st=window.pageYOffset||document.documentElement.scrollTop,ol=document.createElement('div');Object.assign(ol.style,{position:'absolute',background:'rgba(255,255,0,.3)',border:'2px solid #FFA500',zIndex:'10000',left:r.left+sl+'px',top:r.top+st+'px',width:r.width+'px',height:r.height+'px'});const lb=document.createElement('div');Object.assign(lb.style,{position:'absolute',background:'#FFA500',color:'black',padding:'2px 6px',borderRadius:'3px',fontSize:'12px',fontFamily:'monospace',zIndex:'10001',display:'none',left:r.left+sl+'px',whiteSpace:'nowrap',transform:''});const tc=getCls(el).join(', ');lb.textContent=tc;ol.addEventListener('mouseenter',()=>{const vh=window.innerHeight,vw=window.innerWidth,ecy=r.top+r.height/2,ecx=r.left+r.width/2;lb.style.top=ecy<vh/2?r.bottom+st+4+'px':r.top+st-24+'px';lb.style.transform=ecx<vw/2?'':`translateX(calc(-100% + ${r.width}px))`;lb.style.display='block'});ol.addEventListener('mouseleave',()=>{lb.style.display='none'});ol.addEventListener('click',e=>{window.navigator.clipboard.writeText(lb.innerText).catch(console.error);if(!e.ctrlKey&&!e.metaKey)return;document.body.removeChild(ol);document.body.removeChild(lb);e.preventDefault();e.stopPropagation()});document.body.appendChild(ol);document.body.appendChild(lb);return[ol,lb]}function toggleHl(){h=!h;if(h){document.querySelectorAll("[class^='ui-'],[class*=' ui-']").forEach(el=>{const[ol,lb]=createOv(el);ov.set(el,[ol,lb])})}else{for(const[ol,lb]of ov.values()){ol.remove();lb.remove()}ov.clear()}}b.addEventListener('click',toggleHl);document.body.appendChild(drp);document.body.appendChild(b);window.addEventListener('keydown',async e=>{const t1=(e.ctrlKey&&e.shiftKey&&e.key==='U')||(e.metaKey&&e.shiftKey&&e.key==='u');const t2=(e.ctrlKey&&e.shiftKey&&e.key==='H')||(e.metaKey&&e.shiftKey&&e.key==='h');if(t1){e.preventDefault();toggleHl()}if(t2){e.preventDefault();const d=await getVal('highlightBtnVisible')==='false';if(d){enableDebug()}else{b.style.display='none';setVal('highlightBtnVisible','false')}}})})();
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Ctrl
/Cmd
+ Left click to temporarily remove an overlayCtrl
+Shift
+u
to toggle (Cmd
+Shift
+u
on Mac)