shadow root
This commit is contained in:
@@ -15,15 +15,58 @@
|
||||
max-height: 1.2em;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
(() => {
|
||||
var shadow = document.querySelector("#shadow1");
|
||||
var root = shadow.attachShadow({ mode: "open" });
|
||||
var newLine = document.createElement("p");
|
||||
newLine.innerText = "new line";
|
||||
root.appendChild(newLine);
|
||||
})();
|
||||
|
||||
setTimeout(function () {
|
||||
var shadow = document.querySelector("#shadow2");
|
||||
var root = shadow.attachShadow({ mode: "open" });
|
||||
}, 1000);
|
||||
|
||||
setTimeout(() => {
|
||||
var newLine = document.createElement("p");
|
||||
newLine.innerText = "new line";
|
||||
var shadow = document.querySelector("#shadow2");
|
||||
shadow.shadowRoot.appendChild(newLine);
|
||||
}, 2000);
|
||||
|
||||
setTimeout(() => {
|
||||
var newLine = document.createElement("div");
|
||||
newLine.innerHTML = "<p>second line</p><p>third line</p>";
|
||||
var shadow = document.querySelector("#shadow2");
|
||||
shadow.shadowRoot.appendChild(newLine);
|
||||
}, 3000);
|
||||
|
||||
setTimeout(function () {
|
||||
var el = document.querySelector("h2");
|
||||
el.innerText = "hello world";
|
||||
|
||||
var title = document.querySelector("#addtitle");
|
||||
title.innerHTML =
|
||||
"<div><p>second title</p><ul><li><p>second title</p></li></ul></div>";
|
||||
}, 1000);
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root">
|
||||
<h2>React is a JavaScript library for building user interfaces.</h2>
|
||||
<h2>
|
||||
<p>React is a JavaScript library for building user interfaces.</p>
|
||||
</h2>
|
||||
<div id="addtitle"></div>
|
||||
<h2>Shadow 1</h2>
|
||||
<div id="shadow1"></div>
|
||||
<h2>Shadow 2</h2>
|
||||
<div id="shadow2"></div>
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
@@ -102,8 +145,6 @@
|
||||
We’ve first shared our research on RSC in an introductory talk and an
|
||||
RFC.
|
||||
</h2>
|
||||
<h2>Shadow 2</h2>
|
||||
<div id="shadow2"></div>
|
||||
<br />
|
||||
<br />
|
||||
<br />
|
||||
@@ -236,29 +277,5 @@
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
<script>
|
||||
setTimeout(function () {
|
||||
for (var i = 1; i <= 2; i++) {
|
||||
var shadow = document.querySelector("#shadow" + i);
|
||||
var cont = document.querySelector(".cont" + i);
|
||||
var root = shadow.attachShadow({ mode: "open" });
|
||||
// root.appendChild(document.importNode(cont, true));
|
||||
root.appendChild(cont.cloneNode(true));
|
||||
|
||||
var newLine = document.createElement("p");
|
||||
newLine.innerText = "new line";
|
||||
root.appendChild(newLine);
|
||||
}
|
||||
}, 3000);
|
||||
</script>
|
||||
<script>
|
||||
setTimeout(function () {
|
||||
var el = document.querySelector("h2");
|
||||
el.innerText = "hello world";
|
||||
|
||||
var title = document.querySelector("#addtitle");
|
||||
title.innerHTML = "<p>second title</p>";
|
||||
}, 1000);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import {
|
||||
DEFAULT_SELECTOR,
|
||||
GLOBAL_KEY,
|
||||
SHADOW_KEY,
|
||||
DEFAULT_RULE,
|
||||
BUILTIN_RULES,
|
||||
} from "./rules";
|
||||
export { I18N, UI_LANGS } from "./i18n";
|
||||
export { GLOBAL_KEY, DEFAULT_RULE, BUILTIN_RULES };
|
||||
export { GLOBAL_KEY, SHADOW_KEY, DEFAULT_RULE, BUILTIN_RULES };
|
||||
|
||||
const APP_NAME = process.env.REACT_APP_NAME.trim().split(/\s+/).join("-");
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ export const DEFAULT_SELECTOR = `:is(${els})`;
|
||||
|
||||
export const GLOBAL_KEY = "*";
|
||||
|
||||
export const SHADOW_KEY = ">>>";
|
||||
|
||||
export const DEFAULT_RULE = {
|
||||
pattern: "",
|
||||
selector: "",
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
MSG_TRANS_CURRULE,
|
||||
OPT_STYLE_DASHLINE,
|
||||
OPT_STYLE_FUZZY,
|
||||
SHADOW_KEY,
|
||||
} from "../config";
|
||||
import Content from "../views/Content";
|
||||
import { fetchUpdate, fetchClear } from "./fetch";
|
||||
@@ -33,7 +34,10 @@ export class Translator {
|
||||
"option",
|
||||
"head",
|
||||
"script",
|
||||
"iframe",
|
||||
];
|
||||
_rootNodes = new Set();
|
||||
_tranNodes = new Set();
|
||||
|
||||
// 显示
|
||||
_interseObserver = new IntersectionObserver(
|
||||
@@ -57,7 +61,7 @@ export class Translator {
|
||||
!this._skipNodeNames.includes(mutation.target.localName) &&
|
||||
mutation.addedNodes.length > 0
|
||||
) {
|
||||
const addedNodes = Array.from(mutation.addedNodes).filter((node) => {
|
||||
const nodes = Array.from(mutation.addedNodes).filter((node) => {
|
||||
if (
|
||||
this._skipNodeNames.includes(node.localName) ||
|
||||
node.id === APP_LCNAME
|
||||
@@ -66,7 +70,9 @@ export class Translator {
|
||||
}
|
||||
return true;
|
||||
});
|
||||
if (addedNodes.length > 0) {
|
||||
if (nodes.length > 0) {
|
||||
// const rootNode = mutation.target.getRootNode();
|
||||
// todo
|
||||
this._reTranslate();
|
||||
}
|
||||
}
|
||||
@@ -136,27 +142,67 @@ export class Translator {
|
||||
this.rule = { ...this.rule, textStyle };
|
||||
};
|
||||
|
||||
_queryFilter = (selector, rootNode) => {
|
||||
return Array.from(rootNode.querySelectorAll(selector)).filter(
|
||||
(node) => this._queryFilter(selector, node).length === 0
|
||||
);
|
||||
};
|
||||
|
||||
_queryNodes = (rootNode = document) => {
|
||||
const childRoots = Array.from(rootNode.querySelectorAll("*"))
|
||||
.map((item) => item.shadowRoot)
|
||||
.filter(Boolean);
|
||||
const childNodes = childRoots.map((item) => this._queryNodes(item));
|
||||
const nodes = Array.from(rootNode.querySelectorAll(this.rule.selector));
|
||||
return nodes.concat(childNodes).flat();
|
||||
// const childRoots = Array.from(rootNode.querySelectorAll("*"))
|
||||
// .map((item) => item.shadowRoot)
|
||||
// .filter(Boolean);
|
||||
// const childNodes = childRoots.map((item) => this._queryNodes(item));
|
||||
// const nodes = Array.from(rootNode.querySelectorAll(this.rule.selector));
|
||||
// return nodes.concat(childNodes).flat();
|
||||
|
||||
this._rootNodes.add(rootNode);
|
||||
this._rule.selector
|
||||
.split(";")
|
||||
.map((item) => item.trim())
|
||||
.filter(Boolean)
|
||||
.forEach((selector) => {
|
||||
if (selector.includes(SHADOW_KEY)) {
|
||||
const [outSelector, inSelector] = selector
|
||||
.split(SHADOW_KEY)
|
||||
.map((item) => item.trim());
|
||||
if (outSelector && inSelector) {
|
||||
const outNodes = rootNode.querySelectorAll(outSelector);
|
||||
outNodes.forEach((outNode) => {
|
||||
if (outNode.shadowRoot) {
|
||||
this._rootNodes.add(outNode.shadowRoot);
|
||||
this._queryFilter(inSelector, outNode.shadowRoot).forEach(
|
||||
(item) => {
|
||||
this._tranNodes.add(item);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this._queryFilter(selector, rootNode).forEach((item) => {
|
||||
this._tranNodes.add(item);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
_register = () => {
|
||||
// 监听节点变化;
|
||||
this._mutaObserver.observe(document, {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
// characterData: true,
|
||||
// 搜索节点
|
||||
this._queryNodes();
|
||||
|
||||
this._rootNodes.forEach((node) => {
|
||||
// 监听节点变化;
|
||||
this._mutaObserver.observe(node, {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
// characterData: true,
|
||||
});
|
||||
});
|
||||
|
||||
// 监听节点显示
|
||||
this._queryNodes().forEach((el) => {
|
||||
this._interseObserver.unobserve(el);
|
||||
this._interseObserver.observe(el);
|
||||
this._tranNodes.forEach((node) => {
|
||||
// 监听节点显示
|
||||
this._interseObserver.observe(node);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -164,33 +210,29 @@ export class Translator {
|
||||
// 解除节点变化监听
|
||||
this._mutaObserver.disconnect();
|
||||
|
||||
// 解除节点显示监听
|
||||
this._queryNodes().forEach((el) => this._interseObserver.unobserve(el));
|
||||
this._tranNodes.forEach((node) => {
|
||||
// 解除节点显示监听
|
||||
this._interseObserver.unobserve(node);
|
||||
|
||||
// 移除已插入元素
|
||||
this._queryNodes().forEach((el) => {
|
||||
el?.querySelector(APP_LCNAME)?.remove();
|
||||
// 移除已插入元素
|
||||
node.querySelector(APP_LCNAME)?.remove();
|
||||
});
|
||||
|
||||
// 清空节点集合
|
||||
this._rootNodes.clear();
|
||||
this._tranNodes.clear();
|
||||
|
||||
// 清空任务池
|
||||
fetchClear();
|
||||
};
|
||||
|
||||
_reTranslate = debounce(() => {
|
||||
if (this.rule.transOpen === "true") {
|
||||
this._queryNodes().forEach((el) => {
|
||||
this._interseObserver.unobserve(el);
|
||||
this._interseObserver.observe(el);
|
||||
});
|
||||
if (this._rule.transOpen === "true") {
|
||||
this._register();
|
||||
}
|
||||
}, 500);
|
||||
|
||||
_render = (el) => {
|
||||
// 含子元素
|
||||
if (this._queryNodes(el).length > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 已翻译
|
||||
if (el.querySelector(APP_LCNAME)) {
|
||||
return;
|
||||
@@ -202,7 +244,7 @@ export class Translator {
|
||||
return;
|
||||
}
|
||||
|
||||
// console.log("---> ", q);
|
||||
// console.log("---> ", el);
|
||||
|
||||
const span = document.createElement(APP_LCNAME);
|
||||
span.style.visibility = "visible";
|
||||
|
||||
Reference in New Issue
Block a user