diff --git a/scripts/content.js b/scripts/content.js index 9cf089a..2378169 100644 --- a/scripts/content.js +++ b/scripts/content.js @@ -59,37 +59,88 @@ return message; } + // 创建启用复制模式消息提示 + function createCopyModeMessage() { + const message = document.createElement('div'); + message.innerHTML = '复制模式已启用'; + message.style.position = 'fixed'; + message.style.top = '10px'; + message.style.left = '50%'; + message.style.transform = 'translateX(-50%)'; + message.style.background = '#1E3A8A'; + message.style.color = '#F9FAFB'; + message.style.padding = '10px'; + message.style.borderRadius = '5px'; + message.style.display = 'none'; + message.style.zIndex = '1001'; + message.style.fontSize = '16px'; + document.body.appendChild(message); + return message; + } + // 获取元素的 XPath function getElementXPath(element) { - if (element.id) { - return `//*[@id="${element.id}"]`; + if (!element) { + return ''; } - - const parts = []; - while (element && element.nodeType === Node.ELEMENT_NODE) { - let selector = element.nodeName.toLowerCase(); - if (element.className) { - selector += `[@class="${element.className}"]`; - } else if (element.textContent.trim()) { - selector += `[text()="${element.textContent.trim()}"]`; - } else if (element.id) { - selector += `[@id="${element.id}"]`; - } else { - let sibling = element; - let index = 1; - while (sibling.previousElementSibling) { - sibling = sibling.previousElementSibling; - if (sibling.nodeName.toLowerCase() === selector) { - index++; - } - } - selector += `[${index}]`; + if (!element.parentNode) { + return '/' + (element.tagName ? element.tagName.toLowerCase() : ''); + } + let ix = 0; + const siblings = element.parentNode.childNodes; + for (let i = 0; i < siblings.length; i++) { + const sibling = siblings[i]; + if (sibling === element) { + return getElementXPath(element.parentNode) + '/' + (element.tagName ? element.tagName.toLowerCase() : '') + '[' + (ix + 1) + ']'; + } + if (sibling.nodeType === 1 && sibling.tagName === element.tagName) { + ix++; } - parts.unshift(selector); - element = element.parentNode; } - // return parts.length ? '/' + parts.join('/') : null; - return "/xpath"; + } + + // Function to check if the current node is inside an iframe + function isInsideIframe() { + try { + return window.self !== window.top; + } catch (e) { + return true; + } + } + + // Function to get the index of the iframe containing the current node + function getIframeIndex() { + if (!isInsideIframe()) return -1; + const iframes = window.top.document.querySelectorAll('iframe'); + for (let i = 0; i < iframes.length; i++) { + try { + if (iframes[i].contentWindow === window.self) { + return i; + } + } catch (e) { + continue; + } + } + return -1; + } + + // Function to get the XPath of an iframe + function getIframeXPath(iframe) { + if (!iframe) return ''; + let xpath = ''; + while (iframe && iframe !== document) { + let index = 0; + let sibling = iframe.previousSibling; + while (sibling) { + if (sibling.nodeType === 1 && sibling.tagName === iframe.tagName) { + index++; + } + sibling = sibling.previousSibling; + } + xpath = '/' + iframe.tagName.toLowerCase() + '[' + (index + 1) + ']' + xpath; + iframe = iframe.parentNode ? iframe.parentNode : null; + } + return xpath; } // 监听鼠标移动事件 @@ -130,6 +181,21 @@ const xpath = getElementXPath(element); console.log('Element XPath:', xpath); } + + // Check if the current node is inside an iframe and get its index + if (isInsideIframe()) { + const iframeIndex = getIframeIndex(); + console.log('Current node is inside an iframe with index:', iframeIndex); + const iframes = window.top.document.querySelectorAll('iframe'); + if (iframeIndex !== -1) { + const iframeXPath = getElementXPath(iframes[iframeIndex]); + + console.log('Iframe XPath:', iframeXPath); + } else { + console.log('Iframe not found'); + } + } + console.log("=".repeat(50)); }); // Function to remove highlight effect @@ -148,11 +214,11 @@ function addIframeMouseListeners() { const iframes = document.querySelectorAll('iframe'); iframes.forEach(iframe => { - iframe.addEventListener('mouseenter', function() { + iframe.addEventListener('mouseenter', function () { console.log('Mouse entered iframe:', iframe.src); removeHighlightEffect(); }, true); - iframe.addEventListener('mouseleave', function() { + iframe.addEventListener('mouseleave', function () { console.log('Mouse left iframe:', iframe.src); removeHighlightEffect(); }, true); @@ -173,13 +239,21 @@ function enableCopyModeInAllFrames() { isCopyModeEnabled = true; console.log('Copy mode enabled in main window'); + copyModeMessage.style.display = 'block'; + setTimeout(() => { + copyModeMessage.style.display = 'none'; + }, 3000); const iframes = document.querySelectorAll('iframe'); iframes.forEach(iframe => { - iframe.contentWindow.postMessage({ action: 'enableCopyMode' }, '*'); - iframe.contentWindow.addEventListener('mouseleave', function() { - console.log('Mouse left iframe:', iframe.src); - removeHighlightEffect(); - }); + try { + iframe.contentWindow.postMessage({ action: 'enableCopyMode' }, '*'); + iframe.contentWindow.addEventListener('mouseleave', function () { + console.log('Mouse left iframe:', iframe.src); + removeHighlightEffect(); + }); + } catch (error) { + console.error('Error accessing iframe:', error); + } }); } @@ -190,7 +264,11 @@ console.log('Copy mode disabled in main window'); const iframes = document.querySelectorAll('iframe'); iframes.forEach(iframe => { - iframe.contentWindow.postMessage({ action: 'disableCopyMode' }, '*'); + try { + iframe.contentWindow.postMessage({ action: 'disableCopyMode' }, '*'); + } catch (error) { + console.error('Error accessing iframe:', error); + } }); } @@ -256,4 +334,5 @@ copyButton = createCopyButton(); copyMessage = createCopyMessage(); + const copyModeMessage = createCopyModeMessage(); })(); diff --git a/scripts/utils.js b/scripts/utils.js new file mode 100644 index 0000000..7c75090 --- /dev/null +++ b/scripts/utils.js @@ -0,0 +1,47 @@ +function getElementXPath(element) { + if (element.id) { + return `//*[@id="${element.id}"]`; + } + + // 判断元素是否在iframe中 + let currentElement = element; + let iframe = null; + while (currentElement) { + if (currentElement.tagName && currentElement.tagName.toLowerCase() === 'iframe') { + iframe = currentElement; + break; + } + currentElement = currentElement.parentNode; + } + + if (iframe) { + const iframeXPath = getElementXPath(iframe); + const elementXPath = getElementXPath(element); + return iframeXPath + elementXPath; + } + + const parts = []; + while (element && element.nodeType === Node.ELEMENT_NODE) { + let selector = element.nodeName.toLowerCase(); + if (element.className) { + selector += `[@class="${element.className}"]`; + } else if (element.textContent.trim()) { + selector += `[text()="${element.textContent.trim()}"]`; + } else if (element.id) { + selector += `[@id="${element.id}"]`; + } else { + let sibling = element; + let index = 1; + while (sibling.previousElementSibling) { + sibling = sibling.previousElementSibling; + if (sibling.nodeName.toLowerCase() === selector) { + index++; + } + } + selector += `[${index}]`; + } + parts.unshift(selector); + element = element.parentNode; + } + return parts.length ? '/' + parts.join('/') : null; +} diff --git a/test/html/local-page.html b/test/html/local-page.html new file mode 100644 index 0000000..240ea0c --- /dev/null +++ b/test/html/local-page.html @@ -0,0 +1,21 @@ + + + + + + Document + + + +
+ + +
+
+ + + diff --git a/test/html/local-page2.html b/test/html/local-page2.html new file mode 100644 index 0000000..7308e95 --- /dev/null +++ b/test/html/local-page2.html @@ -0,0 +1,19 @@ + + + + + + Document + + + +
+ + +
+ + diff --git a/test/html/test-ifream.html b/test/html/test-ifream.html new file mode 100644 index 0000000..29988c0 --- /dev/null +++ b/test/html/test-ifream.html @@ -0,0 +1,35 @@ + + + + + + + Document + + + + +
+ + +
+ +
+ +
+ +
+ +
+ +
+ + + + +