514 lines
18 KiB
HTML
514 lines
18 KiB
HTML
|
|
<!DOCTYPE html>
|
|||
|
|
<html lang="en">
|
|||
|
|
<head>
|
|||
|
|
<meta charset="UTF-8">
|
|||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|||
|
|
<title>Analog Clock</title>
|
|||
|
|
<link rel="stylesheet" href="style.css">
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
<div class="clock-container">
|
|||
|
|
<div class="clock">
|
|||
|
|
<!-- Clock face numbers -->
|
|||
|
|
<div class="number number-1"><span>1</span></div>
|
|||
|
|
<div class="number number-2"><span>2</span></div>
|
|||
|
|
<div class="number number-3"><span>3</span></div>
|
|||
|
|
<div class="number number-4"><span>4</span></div>
|
|||
|
|
<div class="number number-5"><span>5</span></div>
|
|||
|
|
<div class="number number-6"><span>6</span></div>
|
|||
|
|
<div class="number number-7"><span>7</span></div>
|
|||
|
|
<div class="number number-8"><span>8</span></div>
|
|||
|
|
<div class="number number-9"><span>9</span></div>
|
|||
|
|
<div class="number number-10"><span>10</span></div>
|
|||
|
|
<div class="number number-11"><span>11</span></div>
|
|||
|
|
<div class="number number-12"><span>12</span></div>
|
|||
|
|
|
|||
|
|
<!-- Clock hands -->
|
|||
|
|
<div class="hand hour-hand" id="hour-hand"></div>
|
|||
|
|
<div class="hand minute-hand" id="minute-hand"></div>
|
|||
|
|
<div class="hand second-hand" id="second-hand"></div>
|
|||
|
|
|
|||
|
|
<!-- Center pivot -->
|
|||
|
|
<div class="center-pivot"></div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<script src="script.js"></script>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
/**
|
|||
|
|
* Iframe 元素高亮注入脚本
|
|||
|
|
* 需要在目标网站中引入此脚本来支持跨域 iframe 高亮功能
|
|||
|
|
*
|
|||
|
|
* 使用方法:
|
|||
|
|
* 1. 将此脚本添加到目标网站的 HTML 中
|
|||
|
|
* 2. 或通过浏览器扩展、用户脚本等方式注入
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
(function () {
|
|||
|
|
"use strict";
|
|||
|
|
|
|||
|
|
// 检查是否在 iframe 中
|
|||
|
|
if (window.self === window.top) {
|
|||
|
|
return; // 不在 iframe 中,不执行
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 检查是否已经初始化过
|
|||
|
|
if (window.__iframeHighlightInitialized) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
window.__iframeHighlightInitialized = true;
|
|||
|
|
console.log("Iframe 高亮脚本已加载");
|
|||
|
|
|
|||
|
|
// 创建高亮覆盖层
|
|||
|
|
var overlay = document.createElement("div");
|
|||
|
|
overlay.id = "iframe-highlight-overlay";
|
|||
|
|
overlay.style.cssText = "\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n pointer-events: none;\n z-index: 999999;\n overflow: hidden;\n ";
|
|||
|
|
|
|||
|
|
// 创建悬停高亮框(虚线边框)
|
|||
|
|
var highlightBox = document.createElement("div");
|
|||
|
|
highlightBox.id = "iframe-highlight-box";
|
|||
|
|
highlightBox.style.cssText = "\n position: absolute;\n border: 2px dashed #007AFF;\n background: rgba(0, 122, 255, 0.08);\n pointer-events: none;\n display: none;\n transition: all 0.1s ease;\n box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.8);\n border-radius: 2px;\n ";
|
|||
|
|
|
|||
|
|
// 创建选中节点的常驻高亮框(实线边框)
|
|||
|
|
var selectedBox = document.createElement("div");
|
|||
|
|
selectedBox.id = "iframe-selected-box";
|
|||
|
|
selectedBox.style.cssText = "\n position: absolute;\n border: 2px solid #007AFF;\n pointer-events: none;\n display: none;\n box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.9), 0 0 8px rgba(255, 107, 53, 0.4);\n border-radius: 2px;\n z-index: 1000000;\n ";
|
|||
|
|
|
|||
|
|
// 创建悬停标签显示
|
|||
|
|
var tagLabel = document.createElement("div");
|
|||
|
|
tagLabel.id = "iframe-tag-label";
|
|||
|
|
tagLabel.style.cssText = "\n position: absolute;\n background: #007AFF;\n color: white;\n padding: 2px 6px;\n font-size: 11px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n border-radius: 2px;\n pointer-events: none;\n display: none;\n white-space: nowrap;\n z-index: 1000001;\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);\n font-weight: 500;\n ";
|
|||
|
|
|
|||
|
|
// 创建选中节点标签
|
|||
|
|
var selectedLabel = document.createElement("div");
|
|||
|
|
selectedLabel.id = "iframe-selected-label";
|
|||
|
|
selectedLabel.style.cssText = "\n position: absolute;\n background: #007AFF;\n color: white;\n padding: 3px 8px;\n font-size: 11px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n border-radius: 3px;\n pointer-events: none;\n display: none;\n white-space: nowrap;\n z-index: 1000002;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);\n font-weight: 600;\n ";
|
|||
|
|
overlay.appendChild(highlightBox);
|
|||
|
|
overlay.appendChild(selectedBox);
|
|||
|
|
overlay.appendChild(tagLabel);
|
|||
|
|
overlay.appendChild(selectedLabel);
|
|||
|
|
document.body.appendChild(overlay);
|
|||
|
|
|
|||
|
|
// 存储当前选中的元素
|
|||
|
|
var selectedElement = null;
|
|||
|
|
var highlightEnabled = false;
|
|||
|
|
|
|||
|
|
// 更新选中元素的高亮显示
|
|||
|
|
function updateSelectedHighlight(element) {
|
|||
|
|
console.log("updateSelectedHighlight called with:", element);
|
|||
|
|
if (!element) {
|
|||
|
|
selectedBox.style.display = "none";
|
|||
|
|
selectedLabel.style.display = "none";
|
|||
|
|
selectedElement = null;
|
|||
|
|
console.log("Cleared selected highlight");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
selectedElement = element;
|
|||
|
|
var rect = element.getBoundingClientRect();
|
|||
|
|
console.log("Selected element rect:", rect);
|
|||
|
|
|
|||
|
|
// 更新选中高亮框位置
|
|||
|
|
selectedBox.style.display = "block";
|
|||
|
|
selectedBox.style.left = "".concat(rect.left - 2, "px");
|
|||
|
|
selectedBox.style.top = "".concat(rect.top - 2, "px");
|
|||
|
|
selectedBox.style.width = "".concat(rect.width + 4, "px");
|
|||
|
|
selectedBox.style.height = "".concat(rect.height + 4, "px");
|
|||
|
|
|
|||
|
|
// 更新选中标签位置和内容
|
|||
|
|
selectedLabel.style.display = "block";
|
|||
|
|
selectedLabel.textContent = "\u2713 <".concat(element.tagName.toLowerCase(), ">");
|
|||
|
|
|
|||
|
|
// 计算标签位置,确保不超出视窗
|
|||
|
|
var labelTop = rect.top - 28;
|
|||
|
|
var labelLeft = rect.left;
|
|||
|
|
|
|||
|
|
// 如果标签会超出顶部,显示在元素下方
|
|||
|
|
if (labelTop < 5) {
|
|||
|
|
labelTop = rect.bottom + 5;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 如果标签会超出右侧,向左调整
|
|||
|
|
var labelWidth = selectedLabel.offsetWidth || 100; // 预估宽度
|
|||
|
|
if (labelLeft + labelWidth > window.innerWidth - 10) {
|
|||
|
|
labelLeft = window.innerWidth - labelWidth - 10;
|
|||
|
|
}
|
|||
|
|
selectedLabel.style.left = "".concat(Math.max(5, labelLeft), "px");
|
|||
|
|
selectedLabel.style.top = "".concat(labelTop, "px");
|
|||
|
|
console.log("Selected highlight positioned at:", {
|
|||
|
|
left: selectedBox.style.left,
|
|||
|
|
top: selectedBox.style.top,
|
|||
|
|
width: selectedBox.style.width,
|
|||
|
|
height: selectedBox.style.height
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
function getElementSelector(element) {
|
|||
|
|
if (!(element instanceof Element)) throw new Error('Argument must be a DOM element');
|
|||
|
|
var segments = [];
|
|||
|
|
var current = element;
|
|||
|
|
while (current !== document.documentElement) {
|
|||
|
|
var selector = '';
|
|||
|
|
// 优先检查唯一ID
|
|||
|
|
if (current.id && document.querySelectorAll("#".concat(current.id)).length === 1) {
|
|||
|
|
segments.unshift("#".concat(current.id));
|
|||
|
|
break; // ID唯一,无需继续向上
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 生成类名选择器(取第一个有效类名)
|
|||
|
|
var classes = Array.from(current.classList).filter(function (c) {
|
|||
|
|
return !c.startsWith('js-');
|
|||
|
|
});
|
|||
|
|
var className = classes.length > 0 ? ".".concat(classes[0]) : '';
|
|||
|
|
|
|||
|
|
// 生成位置索引(nth-child)
|
|||
|
|
var tag = current.tagName.toLowerCase();
|
|||
|
|
if (!className) {
|
|||
|
|
var siblings = Array.from(current.parentNode.children);
|
|||
|
|
var index = siblings.findIndex(function (el) {
|
|||
|
|
return el === current;
|
|||
|
|
}) + 1;
|
|||
|
|
selector = "".concat(tag, ":nth-child(").concat(index, ")");
|
|||
|
|
} else {
|
|||
|
|
selector = className;
|
|||
|
|
}
|
|||
|
|
segments.unshift(selector);
|
|||
|
|
current = current.parentElement;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 处理根元素
|
|||
|
|
if (current === document.documentElement) {
|
|||
|
|
segments.unshift('html');
|
|||
|
|
}
|
|||
|
|
return segments.join(' > ');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取元素文本内容
|
|||
|
|
function getElementText(element) {
|
|||
|
|
var _element$textContent;
|
|||
|
|
if (element.tagName === "INPUT") {
|
|||
|
|
return element.value || element.placeholder || "";
|
|||
|
|
}
|
|||
|
|
if (element.tagName === "TEXTAREA") {
|
|||
|
|
return element.value || element.placeholder || "";
|
|||
|
|
}
|
|||
|
|
var text = ((_element$textContent = element.textContent) === null || _element$textContent === void 0 ? void 0 : _element$textContent.trim()) || "";
|
|||
|
|
return text.length > 50 ? text.substring(0, 50) + "..." : text;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 获取元素属性信息
|
|||
|
|
function getElementAttributes(element) {
|
|||
|
|
var attrs = {};
|
|||
|
|
for (var i = 0; i < element.attributes.length; i++) {
|
|||
|
|
var attr = element.attributes[i];
|
|||
|
|
attrs[attr.name] = attr.value;
|
|||
|
|
}
|
|||
|
|
return attrs;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 鼠标悬停事件处理
|
|||
|
|
function handleMouseOver(e) {
|
|||
|
|
if (!highlightEnabled) return;
|
|||
|
|
var target = e.target;
|
|||
|
|
if (!target || target === overlay || target === highlightBox || target === tagLabel || target === selectedBox || target === selectedLabel) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 避免高亮 html 和 body 元素
|
|||
|
|
if (target === document.documentElement || target === document.body) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 如果是已选中的元素,不显示悬停高亮
|
|||
|
|
if (target === selectedElement) {
|
|||
|
|
highlightBox.style.display = "none";
|
|||
|
|
tagLabel.style.display = "none";
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
var rect = target.getBoundingClientRect();
|
|||
|
|
var selector = getElementSelector(target);
|
|||
|
|
var text = getElementText(target);
|
|||
|
|
var attributes = getElementAttributes(target);
|
|||
|
|
|
|||
|
|
// 更新悬停高亮框位置
|
|||
|
|
highlightBox.style.display = "block";
|
|||
|
|
highlightBox.style.left = "".concat(rect.left - 2, "px");
|
|||
|
|
highlightBox.style.top = "".concat(rect.top - 2, "px");
|
|||
|
|
highlightBox.style.width = "".concat(rect.width + 4, "px");
|
|||
|
|
highlightBox.style.height = "".concat(rect.height + 4, "px");
|
|||
|
|
|
|||
|
|
// 更新标签位置和内容
|
|||
|
|
tagLabel.style.display = "block";
|
|||
|
|
tagLabel.textContent = "<".concat(target.tagName.toLowerCase(), ">");
|
|||
|
|
|
|||
|
|
// 计算标签位置,确保不超出视窗
|
|||
|
|
var labelTop = rect.top - 22;
|
|||
|
|
var labelLeft = rect.left;
|
|||
|
|
|
|||
|
|
// 如果标签会超出顶部,显示在元素下方
|
|||
|
|
if (labelTop < 0) {
|
|||
|
|
labelTop = rect.bottom + 5;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 如果标签会超出右侧,向左调整
|
|||
|
|
if (labelLeft + tagLabel.offsetWidth > window.innerWidth) {
|
|||
|
|
labelLeft = window.innerWidth - tagLabel.offsetWidth - 5;
|
|||
|
|
}
|
|||
|
|
tagLabel.style.left = "".concat(Math.max(0, labelLeft), "px");
|
|||
|
|
tagLabel.style.top = "".concat(labelTop, "px");
|
|||
|
|
|
|||
|
|
// 发送消息到父窗口
|
|||
|
|
var elementInfo = {
|
|||
|
|
tagName: target.tagName.toLowerCase(),
|
|||
|
|
rect: {
|
|||
|
|
left: rect.left,
|
|||
|
|
top: rect.top,
|
|||
|
|
right: rect.right,
|
|||
|
|
bottom: rect.bottom,
|
|||
|
|
width: rect.width,
|
|||
|
|
height: rect.height,
|
|||
|
|
x: rect.x,
|
|||
|
|
y: rect.y
|
|||
|
|
},
|
|||
|
|
selector: selector,
|
|||
|
|
text: text,
|
|||
|
|
attributes: attributes,
|
|||
|
|
url: window.location.href,
|
|||
|
|
path: window.location.pathname,
|
|||
|
|
timestamp: Date.now()
|
|||
|
|
};
|
|||
|
|
try {
|
|||
|
|
window.parent.postMessage({
|
|||
|
|
type: "iframe-element-hover",
|
|||
|
|
data: elementInfo,
|
|||
|
|
source: "iframe-highlight-injector"
|
|||
|
|
}, "*");
|
|||
|
|
} catch (error) {
|
|||
|
|
console.warn("无法发送消息到父窗口:", error);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 鼠标离开事件处理
|
|||
|
|
function handleMouseOut(e) {
|
|||
|
|
if (!highlightEnabled) return;
|
|||
|
|
var relatedTarget = e.relatedTarget;
|
|||
|
|
|
|||
|
|
// 如果鼠标移动到高亮相关元素上,不隐藏高亮
|
|||
|
|
if (relatedTarget && (relatedTarget === highlightBox || relatedTarget === tagLabel || relatedTarget === overlay || relatedTarget === selectedBox || relatedTarget === selectedLabel)) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
highlightBox.style.display = "none";
|
|||
|
|
tagLabel.style.display = "none";
|
|||
|
|
try {
|
|||
|
|
window.parent.postMessage({
|
|||
|
|
type: "iframe-element-hover",
|
|||
|
|
data: null,
|
|||
|
|
source: "iframe-highlight-injector"
|
|||
|
|
}, "*");
|
|||
|
|
} catch (error) {
|
|||
|
|
console.warn("无法发送消息到父窗口:", error);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 点击事件处理
|
|||
|
|
function handleClick(e) {
|
|||
|
|
var target = e.target;
|
|||
|
|
if (!target || target === overlay || target === highlightBox || target === tagLabel || target === selectedBox || target === selectedLabel) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 避免处理 html 和 body 元素
|
|||
|
|
if (target === document.documentElement || target === document.body) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 检查是否是交互元素,这些元素需要保留默认行为
|
|||
|
|
var isInteractiveElement = ['input', 'textarea', 'select', 'button', 'a'].includes(target.tagName.toLowerCase());
|
|||
|
|
|
|||
|
|
// 如果高亮功能启用,对于非交互元素阻止默认行为和事件传播
|
|||
|
|
if (highlightEnabled) {
|
|||
|
|
e.preventDefault();
|
|||
|
|
e.stopPropagation();
|
|||
|
|
}
|
|||
|
|
var rect = target.getBoundingClientRect();
|
|||
|
|
var selector = getElementSelector(target);
|
|||
|
|
var text = getElementText(target);
|
|||
|
|
var attributes = getElementAttributes(target);
|
|||
|
|
console.log("Element clicked:", {
|
|||
|
|
tagName: target.tagName,
|
|||
|
|
selector: selector,
|
|||
|
|
rect: rect
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
// 立即更新选中高亮
|
|||
|
|
updateSelectedHighlight(target);
|
|||
|
|
|
|||
|
|
// 隐藏悬停高亮,因为现在是选中状态
|
|||
|
|
highlightBox.style.display = "none";
|
|||
|
|
tagLabel.style.display = "none";
|
|||
|
|
var elementInfo = {
|
|||
|
|
tagName: target.tagName.toLowerCase(),
|
|||
|
|
rect: {
|
|||
|
|
left: rect.left,
|
|||
|
|
top: rect.top,
|
|||
|
|
right: rect.right,
|
|||
|
|
bottom: rect.bottom,
|
|||
|
|
width: rect.width,
|
|||
|
|
height: rect.height,
|
|||
|
|
x: rect.x,
|
|||
|
|
y: rect.y
|
|||
|
|
},
|
|||
|
|
selector: selector,
|
|||
|
|
text: text,
|
|||
|
|
attributes: attributes,
|
|||
|
|
url: window.location.href,
|
|||
|
|
path: window.location.pathname,
|
|||
|
|
timestamp: Date.now()
|
|||
|
|
};
|
|||
|
|
try {
|
|||
|
|
window.parent.postMessage({
|
|||
|
|
type: "iframe-element-click",
|
|||
|
|
data: elementInfo,
|
|||
|
|
source: "iframe-highlight-injector"
|
|||
|
|
}, "*");
|
|||
|
|
} catch (error) {
|
|||
|
|
console.warn("无法发送消息到父窗口:", error);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 监听来自父窗口的消息
|
|||
|
|
function handleParentMessage(event) {
|
|||
|
|
console.log("Received message from parent:", event.data);
|
|||
|
|
if (event.data.type === "iframe-highlight-toggle") {
|
|||
|
|
var enabled = event.data.enabled;
|
|||
|
|
console.log("Highlight toggle:", enabled);
|
|||
|
|
if (enabled) {
|
|||
|
|
enableHighlight();
|
|||
|
|
} else {
|
|||
|
|
disableHighlight();
|
|||
|
|
}
|
|||
|
|
} else if (event.data.type === "enable-iframe-highlight") {
|
|||
|
|
console.log("Enable iframe highlight");
|
|||
|
|
enableHighlight();
|
|||
|
|
} else if (event.data.type === "disable-iframe-highlight") {
|
|||
|
|
console.log("Disable iframe highlight");
|
|||
|
|
disableHighlight();
|
|||
|
|
} else if (event.data.type === "toggle-iframe-highlight") {
|
|||
|
|
var _enabled = event.data.enabled !== undefined ? event.data.enabled : !highlightEnabled;
|
|||
|
|
console.log("Toggle iframe highlight to:", _enabled);
|
|||
|
|
if (_enabled) {
|
|||
|
|
enableHighlight();
|
|||
|
|
} else {
|
|||
|
|
disableHighlight();
|
|||
|
|
}
|
|||
|
|
} else if (event.data.type === "update-selected-element") {
|
|||
|
|
var selector = event.data.selector;
|
|||
|
|
console.log("Update selected element with selector:", selector);
|
|||
|
|
if (selector) {
|
|||
|
|
try {
|
|||
|
|
var element = document.querySelector(selector);
|
|||
|
|
console.log("Found element by selector:", element);
|
|||
|
|
updateSelectedHighlight(element);
|
|||
|
|
} catch (error) {
|
|||
|
|
console.warn("Failed to select element:", error);
|
|||
|
|
updateSelectedHighlight(null);
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
updateSelectedHighlight(null);
|
|||
|
|
}
|
|||
|
|
} else if (event.data.type === "clear-selected-element") {
|
|||
|
|
console.log("Clear selected element");
|
|||
|
|
updateSelectedHighlight(null);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 启用高亮功能
|
|||
|
|
function enableHighlight() {
|
|||
|
|
console.log("Enabling highlight");
|
|||
|
|
document.addEventListener("mouseover", handleMouseOver, true);
|
|||
|
|
document.addEventListener("mouseout", handleMouseOut, true);
|
|||
|
|
document.addEventListener("click", handleClick, true);
|
|||
|
|
highlightEnabled = true;
|
|||
|
|
overlay.style.display = "block";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 禁用高亮功能
|
|||
|
|
function disableHighlight() {
|
|||
|
|
console.log("Disabling highlight");
|
|||
|
|
highlightEnabled = false;
|
|||
|
|
// 保持事件监听器,但通过 highlightEnabled 变量控制行为
|
|||
|
|
// 这样可以保留选中状态的显示
|
|||
|
|
highlightBox.style.display = "none";
|
|||
|
|
tagLabel.style.display = "none";
|
|||
|
|
// 不隐藏 selectedBox 和 selectedLabel,保留选中状态
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 完全禁用高亮功能(移除所有监听器)
|
|||
|
|
function fullyDisableHighlight() {
|
|||
|
|
console.log("Fully disabling highlight");
|
|||
|
|
highlightEnabled = false;
|
|||
|
|
document.removeEventListener("mouseover", handleMouseOver, true);
|
|||
|
|
document.removeEventListener("mouseout", handleMouseOut, true);
|
|||
|
|
document.removeEventListener("click", handleClick, true);
|
|||
|
|
overlay.style.display = "none";
|
|||
|
|
highlightBox.style.display = "none";
|
|||
|
|
tagLabel.style.display = "none";
|
|||
|
|
selectedBox.style.display = "none";
|
|||
|
|
selectedLabel.style.display = "none";
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 添加事件监听
|
|||
|
|
enableHighlight();
|
|||
|
|
window.addEventListener("message", handleParentMessage);
|
|||
|
|
|
|||
|
|
// 暴露全局函数供外部调用
|
|||
|
|
window.__iframeHighlightControl = {
|
|||
|
|
enable: enableHighlight,
|
|||
|
|
disable: disableHighlight,
|
|||
|
|
fullyDisable: fullyDisableHighlight,
|
|||
|
|
isEnabled: function isEnabled() {
|
|||
|
|
return highlightEnabled;
|
|||
|
|
},
|
|||
|
|
getSelectedElement: function getSelectedElement() {
|
|||
|
|
return selectedElement;
|
|||
|
|
},
|
|||
|
|
updateSelected: updateSelectedHighlight,
|
|||
|
|
// 通过消息发送开关控制
|
|||
|
|
sendToggleMessage: function sendToggleMessage(enabled) {
|
|||
|
|
window.parent.postMessage({
|
|||
|
|
type: 'iframe-highlight-status',
|
|||
|
|
enabled: enabled || highlightEnabled,
|
|||
|
|
source: 'iframe-highlight-injector'
|
|||
|
|
}, '*');
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
// 通知父窗口脚本已加载
|
|||
|
|
try {
|
|||
|
|
window.parent.postMessage({
|
|||
|
|
type: "iframe-highlight-ready",
|
|||
|
|
data: {
|
|||
|
|
url: window.location.href,
|
|||
|
|
userAgent: navigator.userAgent,
|
|||
|
|
timestamp: Date.now()
|
|||
|
|
},
|
|||
|
|
source: "iframe-highlight-injector"
|
|||
|
|
}, "*");
|
|||
|
|
} catch (error) {
|
|||
|
|
console.warn("无法发送就绪消息到父窗口:", error);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 清理函数
|
|||
|
|
window.__iframeHighlightCleanup = function () {
|
|||
|
|
fullyDisableHighlight();
|
|||
|
|
window.removeEventListener("message", handleParentMessage);
|
|||
|
|
if (overlay.parentElement) {
|
|||
|
|
overlay.parentElement.removeChild(overlay);
|
|||
|
|
}
|
|||
|
|
delete window.__iframeHighlightInitialized;
|
|||
|
|
delete window.__iframeHighlightCleanup;
|
|||
|
|
};
|
|||
|
|
})();
|
|||
|
|
|
|||
|
|
</script>
|
|||
|
|
</body>
|
|||
|
|
</html>
|