339 lines
13 KiB
JavaScript
339 lines
13 KiB
JavaScript
(function () {
|
|
|
|
console.log("Content script injected into:", window.location.href);
|
|
|
|
// 清除之前的高亮样式
|
|
let previousHighlight = null;
|
|
let copyButton = null;
|
|
let isCopyModeEnabled = false;
|
|
let copyMessage = null;
|
|
|
|
// 创建复制按钮
|
|
function createCopyButton() {
|
|
const button = document.createElement('button');
|
|
button.innerHTML = '📋'; // 使用图标展示拷贝
|
|
button.style.position = 'absolute';
|
|
button.style.zIndex = '1000';
|
|
button.style.display = 'none';
|
|
button.style.background = 'transparent';
|
|
button.style.border = 'none';
|
|
button.style.cursor = 'pointer';
|
|
button.style.fontSize = '16px';
|
|
button.addEventListener('click', function () {
|
|
if (previousHighlight) {
|
|
const xpath = getElementXPath(previousHighlight);
|
|
const action = previousHighlight.tagName.toLowerCase() === 'input' ? 'input("your_text")' : 'click()';
|
|
const command = `web.find_by_xpath("${xpath}").${action}`;
|
|
navigator.clipboard.writeText(command).then(() => {
|
|
console.log('Command copied to clipboard:', command);
|
|
copyMessage.style.display = 'block';
|
|
setTimeout(() => {
|
|
copyMessage.style.display = 'none';
|
|
}, 3000);
|
|
});
|
|
}
|
|
});
|
|
document.body.appendChild(button);
|
|
return button;
|
|
}
|
|
|
|
// 创建复制消息提示
|
|
function createCopyMessage() {
|
|
const message = document.createElement('div');
|
|
message.innerHTML = '已拷贝! <span id="copied-xpath" style="color:rgb(191, 201, 214);"></span><span style="cursor: pointer;">x</span> ';
|
|
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'; // 增大字体
|
|
message.querySelector('span').addEventListener('click', function () {
|
|
message.style.display = 'none';
|
|
});
|
|
document.body.appendChild(message);
|
|
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) {
|
|
return '';
|
|
}
|
|
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++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
// 监听鼠标移动事件
|
|
document.addEventListener('mousemove', function (event) {
|
|
if (!isCopyModeEnabled) return;
|
|
|
|
// 移除上一次高亮
|
|
if (previousHighlight) {
|
|
previousHighlight.style.background = '';
|
|
previousHighlight.style.backgroundImage = '';
|
|
previousHighlight.style.border = '';
|
|
copyButton.style.display = 'none';
|
|
}
|
|
|
|
// 获取鼠标位置
|
|
const mouseX = event.clientX;
|
|
const mouseY = event.clientY;
|
|
|
|
// 获取鼠标下的元素
|
|
const element = document.elementFromPoint(mouseX, mouseY);
|
|
|
|
// 如果有元素,添加高亮样式并输出对应的 XPath
|
|
if (element && element !== document.body) {
|
|
previousHighlight = element;
|
|
element.style.background = 'rgba(255, 182, 193, 0.5)'; // 浅红色背景
|
|
element.style.backgroundImage = 'linear-gradient(45deg, rgba(255, 182, 193, 0.5) 25%, transparent 25%, transparent 50%, rgba(255, 182, 193, 0.5) 50%, rgba(255, 182, 193, 0.5) 75%, transparent 75%, transparent)'; // 浅红色斜线
|
|
element.style.backgroundSize = '10px 10px';
|
|
element.style.border = '2px solid rgba(255, 105, 135, 0.8)'; // 边框颜色稍深
|
|
element.style.borderRadius = '5px';
|
|
|
|
// 设置复制按钮位置并显示
|
|
const rect = element.getBoundingClientRect();
|
|
copyButton.style.left = `${rect.right + window.scrollX - 20}px`;
|
|
copyButton.style.top = `${rect.top + window.scrollY}px`;
|
|
copyButton.style.display = 'block';
|
|
|
|
// 输出 XPath
|
|
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
|
|
function removeHighlightEffect() {
|
|
|
|
if (previousHighlight) {
|
|
previousHighlight.style.background = '';
|
|
previousHighlight.style.backgroundImage = '';
|
|
previousHighlight.style.border = '';
|
|
copyButton.style.display = 'none';
|
|
previousHighlight = null;
|
|
}
|
|
}
|
|
|
|
// Listen for mouse entering and leaving iframes
|
|
function addIframeMouseListeners() {
|
|
const iframes = document.querySelectorAll('iframe');
|
|
iframes.forEach(iframe => {
|
|
iframe.addEventListener('mouseenter', function () {
|
|
console.log('Mouse entered iframe:', iframe.src);
|
|
removeHighlightEffect();
|
|
}, true);
|
|
iframe.addEventListener('mouseleave', function () {
|
|
console.log('Mouse left iframe:', iframe.src);
|
|
removeHighlightEffect();
|
|
}, true);
|
|
});
|
|
}
|
|
|
|
// Call the function to add listeners to existing iframes
|
|
addIframeMouseListeners();
|
|
|
|
// Also add listeners to any new iframes that are added to the DOM
|
|
const observer = new MutationObserver(() => {
|
|
addIframeMouseListeners();
|
|
});
|
|
|
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
|
|
// Function to enable copy mode in the current window and all iframes
|
|
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 => {
|
|
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);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Function to disable copy mode in the current window and all iframes
|
|
function disableCopyModeInAllFrames() {
|
|
isCopyModeEnabled = false;
|
|
removeHighlightEffect();
|
|
console.log('Copy mode disabled in main window');
|
|
const iframes = document.querySelectorAll('iframe');
|
|
iframes.forEach(iframe => {
|
|
try {
|
|
iframe.contentWindow.postMessage({ action: 'disableCopyMode' }, '*');
|
|
} catch (error) {
|
|
console.error('Error accessing iframe:', error);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Listen for messages from iframes to enable or disable copy mode
|
|
window.addEventListener('message', function (event) {
|
|
if (event.data.action === 'enableCopyMode') {
|
|
isCopyModeEnabled = true;
|
|
console.log('Copy mode enabled in iframe');
|
|
} else if (event.data.action === 'disableCopyMode') {
|
|
isCopyModeEnabled = false;
|
|
removeHighlightEffect();
|
|
console.log('Copy mode disabled in iframe');
|
|
}
|
|
console.log('Message received from iframe:', event.origin);
|
|
});
|
|
|
|
// 监听消息以启用或禁用拷贝模式
|
|
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
|
|
if (request.action === 'toggleCopyMode') {
|
|
isCopyModeEnabled = !isCopyModeEnabled;
|
|
if (!isCopyModeEnabled && previousHighlight) {
|
|
previousHighlight.style.border = '';
|
|
previousHighlight.style.borderRadius = '';
|
|
previousHighlight.style.boxShadow = '';
|
|
copyButton.style.display = 'none';
|
|
}
|
|
sendResponse({ copyModeEnabled: isCopyModeEnabled });
|
|
}
|
|
});
|
|
|
|
// 监听键盘事件以启用或禁用拷贝模式
|
|
document.addEventListener('keydown', function (event) {
|
|
console.log(event.key);
|
|
if (event.altKey && event.key === 'r') {
|
|
enableCopyModeInAllFrames();
|
|
} else if (event.key === 'Escape') {
|
|
disableCopyModeInAllFrames();
|
|
} else if (event.ctrlKey && event.key === 'c' && previousHighlight) {
|
|
const xpath = getElementXPath(previousHighlight);
|
|
const action = previousHighlight.tagName.toLowerCase() === 'input' ? 'input("your_text")' : 'click()';
|
|
|
|
const command = `web.find_by_xpath("${xpath}").${action}`;
|
|
navigator.clipboard.writeText(command).then(() => {
|
|
console.log('Command copied to clipboard:', command);
|
|
const truncatedXPath = xpath.length > 20 ? xpath.substring(0, 20) + '...' : xpath;
|
|
document.getElementById('copied-xpath').innerText = truncatedXPath;
|
|
copyMessage.style.display = 'block';
|
|
setTimeout(() => {
|
|
copyMessage.style.display = 'none';
|
|
}, 3000);
|
|
isCopyModeEnabled = false;
|
|
if (previousHighlight) {
|
|
previousHighlight.style.background = '';
|
|
previousHighlight.style.backgroundImage = '';
|
|
previousHighlight.style.border = '';
|
|
copyButton.style.display = 'none';
|
|
previousHighlight = null;
|
|
}
|
|
console.log('Copy mode disabled');
|
|
});
|
|
}
|
|
});
|
|
|
|
copyButton = createCopyButton();
|
|
copyMessage = createCopyMessage();
|
|
const copyModeMessage = createCopyModeMessage();
|
|
})();
|