// ==UserScript== // @name XPath工具 // @namespace http://tampermonkey.net/ // @version 1.3 // @description 按Shift+X在鼠标位置显示输入框,并提供实时反馈和高级配置选项操作XPath元素 // @author Ace // @match *://*/* // @grant none // @downloadURL none // ==/UserScript== (function () { 'use strict'; let toolbar = null; let currentElement = null; let isShiftPressed = false; let originalBackgroundColor = ''; const SHOW_KEY = 'KeyX'; const SELECT_KEY = 'ShiftLeft'; function getXPath(element) { if (element.id) { return `//*[@id="${element.id}"]`; } if (element === document.body) { return '/html/body'; } let ix = 0; const siblings = element.parentNode.childNodes; for (let i = 0; siblings[i]; i++) { const sibling = siblings[i]; if (sibling === element) { return `${getXPath(element.parentNode)}/${element.tagName.toLowerCase()}[${ix + 1}]`; } if (sibling.nodeType === 1 && sibling.tagName === element.tagName) { ix++; } } } function highlightElement(element) { if (currentElement) { currentElement.style.backgroundColor = originalBackgroundColor; } originalBackgroundColor = element.style.backgroundColor; element.style.backgroundColor = 'yellow'; currentElement = element; } function clearHighlight() { if (currentElement) { currentElement.style.backgroundColor = originalBackgroundColor; currentElement = null; } } document.addEventListener('keydown', (event) => { if (event.key === 'Shift') { isShiftPressed = true; } }); document.addEventListener('keyup', (event) => { if (event.key === 'Shift') { isShiftPressed = false; clearHighlight(); } }); document.addEventListener('mouseover', (event) => { if (isShiftPressed) { highlightElement(event.target); } }); document.addEventListener('mouseout', (event) => { if (isShiftPressed && currentElement === event.target) { clearHighlight(); } }); document.addEventListener('click', (event) => { if (isShiftPressed) { event.preventDefault(); const xpath = getXPath(event.target); document.getElementById('custom-xpath-input').value = xpath; } }); function createToolbar() { if (document.getElementById('custom-toolbar')) return; toolbar = document.createElement('div'); toolbar.id = 'custom-toolbar'; toolbar.style.position = 'fixed'; toolbar.style.zIndex = '9999'; toolbar.style.backgroundColor = 'rgba(33, 33, 33, 0.95)'; toolbar.style.color = '#fff'; toolbar.style.padding = '15px'; toolbar.style.borderRadius = '8px'; toolbar.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.2)'; toolbar.style.display = 'none'; const input = document.createElement('input'); input.id = 'custom-xpath-input'; input.type = 'text'; input.placeholder = '输入XPath'; input.style.width = '250px'; input.style.padding = '8px'; input.style.border = '1px solid #ccc'; input.style.borderRadius = '4px'; input.style.color = '#000'; input.style.backgroundColor = '#fff'; toolbar.appendChild(input); const button = document.createElement('button'); button.innerText = '删除'; button.style.marginLeft = '10px'; button.style.padding = '8px 12px'; button.style.backgroundColor = '#e74c3c'; button.style.color = '#fff'; button.style.border = 'none'; button.style.borderRadius = '4px'; button.style.cursor = 'pointer'; button.style.transition = 'background-color 0.3s'; button.onmouseover = function () { button.style.backgroundColor = '#c0392b'; }; button.onmouseout = function () { button.style.backgroundColor = '#e74c3c'; }; button.onclick = function () { const userXPath = input.value; if (!userXPath) { alert('请输入XPath'); return; } const element = document.evaluate( userXPath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue; if (element) { if (document.getElementById('style-checkbox').checked) { element.style.display = 'none'; alert(`已隐藏元素: ${userXPath}`); } else { element.remove(); alert(`已删除元素: ${userXPath}`); } } else { alert('未找到匹配的元素'); } }; toolbar.appendChild(button); const styleCheckbox = document.createElement('div'); styleCheckbox.innerHTML = ` `; styleCheckbox.querySelector('input').addEventListener('change', (event) => { button.innerText = event.target.checked ? '隐藏' : '删除'; }); toolbar.appendChild(styleCheckbox); const highlightCheckbox = document.createElement('div'); highlightCheckbox.innerHTML = ` `; toolbar.appendChild(highlightCheckbox); input.addEventListener('input', () => { if (document.getElementById('highlight-checkbox').checked) { highlightMatchingElements(input.value); } }); highlightCheckbox.addEventListener('change', () => { const userXPath = input.value; if (highlightCheckbox.querySelector('input').checked && userXPath) { highlightMatchingElements(userXPath); } else { document.querySelectorAll('.highlighted-element').forEach((el) => { el.style.backgroundColor = ''; el.classList.remove('highlighted-element'); }); } }); document.body.appendChild(toolbar); function toggleToolbarAtMouse(event) { const mouseX = event.clientX; const mouseY = event.clientY; toolbar.style.left = `${mouseX}px`; toolbar.style.top = `${mouseY}px`; toolbar.style.display = toolbar.style.display === 'none' ? 'block' : 'none'; } document.addEventListener('keydown', (event) => { if (event.shiftKey && event.code === 'KeyX') { document.addEventListener('mousemove', (mouseEvent) => { toggleToolbarAtMouse(mouseEvent); }, { once: true }); } }); const observer = new MutationObserver((mutations) => { const userXPath = input.value; if (document.getElementById('highlight-checkbox').checked && userXPath) { highlightMatchingElements(userXPath); } }); observer.observe(document.body, { childList: true, subtree: true }); } function highlightMatchingElements(xpath) { const elements = document.evaluate(xpath, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); for (let i = 0; i < elements.snapshotLength; i++) { const element = elements.snapshotItem(i); element.style.backgroundColor = 'yellow'; element.classList.add('highlighted-element'); } } createToolbar(); })();