您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Click elements to get their CSS selector instantly
// ==UserScript== // @name CSS Selector Copy // @namespace https://gf.qytechs.cn/ // @version 1.0 // @description Click elements to get their CSS selector instantly // @author Bui Quoc Dung // @match *://*/* // @grant GM_setClipboard // @grant GM_addStyle // ==/UserScript== (function() { 'use strict'; // Add styles for our dialog GM_addStyle(` .instant-selector-dialog { position: fixed; z-index: 999999; background: white; border-radius: 8px; box-shadow: 0 4px 20px rgba(0,0,0,0.15); padding: 16px; max-width: 400px; width: 90%; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; animation: dialogFadeIn 0.15s ease-out; border: 1px solid #e0e0e0; } @keyframes dialogFadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } } .selector-header { font-size: 16px; font-weight: 600; margin-bottom: 12px; color: #202124; display: flex; align-items: center; gap: 8px; } .selector-header svg { width: 18px; height: 18px; fill: #5f6368; } .selector-display { background: #f8f9fa; border-radius: 6px; padding: 12px; font-family: 'Roboto Mono', monospace; font-size: 13px; line-height: 1.5; margin-bottom: 16px; max-height: 200px; overflow-y: auto; border: 1px solid #e0e0e0; white-space: pre-wrap; word-break: break-all; } .selector-options { display: flex; gap: 16px; margin-bottom: 16px; padding-bottom: 16px; border-bottom: 1px solid #f1f1f1; } .option-radio { display: flex; align-items: center; gap: 6px; cursor: pointer; font-size: 14px; } .selector-buttons { display: flex; justify-content: flex-end; gap: 8px; } .selector-button { padding: 8px 16px; border-radius: 4px; font-weight: 500; font-size: 14px; cursor: pointer; border: none; transition: all 0.2s; } .copy-button { background: #1a73e8; color: white; } .copy-button:hover { background: #1765cc; box-shadow: 0 1px 3px rgba(0,0,0,0.1); } .copy-button.copied { background: #34a853; } .close-button { background: transparent; color: #5f6368; border: 1px solid #dadce0; } .close-button:hover { background: #f8f9fa; } `); // Create dialog element const dialog = document.createElement('div'); dialog.className = 'instant-selector-dialog'; dialog.style.display = 'none'; document.body.appendChild(dialog); // Add dialog content dialog.innerHTML = ` <div class="selector-header"> <svg viewBox="0 0 24 24"><path d="M19 3h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-7 0c.55 0 1 .45 1 1s-.45 1-1 1-1-.45-1-1 .45-1 1-1zm4 12h-2v2c0 .55-.45 1-1 1s-1-.45-1-1v-2H9v-2h2v-2c0-.55.45-1 1-1s1 .45 1 1v2h2v2z"></path></svg> <span>CSS Selector</span> </div> <div class="selector-display" id="selector-display"></div> <div class="selector-options"> <label class="option-radio"> <input type="radio" name="selector-option" value="with" checked> With :nth-of-type </label> <label class="option-radio"> <input type="radio" name="selector-option" value="without"> Without :nth-of-type </label> </div> <div class="selector-buttons"> <button class="selector-button copy-button" id="copy-button">Copy</button> <button class="selector-button close-button" id="close-button">Close</button> </div> `; // Get references to dialog elements const selectorDisplay = dialog.querySelector('#selector-display'); const copyButton = dialog.querySelector('#copy-button'); const closeButton = dialog.querySelector('#close-button'); const optionRadios = dialog.querySelectorAll('input[name="selector-option"]'); // Your improved selector function function getFullCssSelector(el, includeNth = true) { if (!(el instanceof Element)) return; const path = []; while (el) { let selector = el.nodeName.toLowerCase(); if (el.id) { selector += "#" + el.id; path.unshift(selector); break; } else { if (el.className && typeof el.className === 'string') { const classes = el.className.trim().split(/\s+/).join("."); if (classes) selector += "." + classes; } if (includeNth) { let sibling = el, nth = 1; while ((sibling = sibling.previousElementSibling)) { if (sibling.nodeName === el.nodeName) nth++; } selector += `:nth-of-type(${nth})`; } path.unshift(selector); el = el.parentElement; } } return path.join(" > "); } // Position and show dialog function showDialog(element, event) { const includeNth = dialog.querySelector('input[name="selector-option"]:checked').value === 'with'; const selector = getFullCssSelector(element, includeNth); selectorDisplay.textContent = selector; // Position dialog near the click const x = event.clientX; const y = event.clientY; dialog.style.left = `${Math.min(x + 20, window.innerWidth - 420)}px`; dialog.style.top = `${Math.min(y + 20, window.innerHeight - dialog.offsetHeight - 20)}px`; dialog.style.display = 'block'; } // Hide dialog function hideDialog() { dialog.style.display = 'none'; } // Handle copy button click copyButton.addEventListener('click', () => { GM_setClipboard(selectorDisplay.textContent, 'text'); copyButton.textContent = 'Copied!'; copyButton.classList.add('copied'); setTimeout(() => { copyButton.textContent = 'Copy'; copyButton.classList.remove('copied'); }, 2000); }); // Handle close button click closeButton.addEventListener('click', hideDialog); // Close dialog when clicking outside document.addEventListener('click', (e) => { if (dialog.style.display === 'block' && !dialog.contains(e.target)) { hideDialog(); } }); // Close with Escape key document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && dialog.style.display === 'block') { hideDialog(); } }); // Handle Ctrl+Click or Alt+Click on elements document.addEventListener('click', (e) => { // Only activate with Ctrl+Click or Alt+Click to avoid conflict with normal clicks if (e.ctrlKey || e.altKey) { e.preventDefault(); e.stopPropagation(); showDialog(e.target, e); } }, true); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址