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