在覆盖页面上注入时,脚本如何在 HTML 模板中工作? (正在导入 jQuery)
How do I scripts work in HTML template on injection on the overriden page? (Importing jQuery)
显然,HTML 模板中的脚本仅适用于 HTML 模板本身,而不适用于 HTML 模板注入的页面。 (脚本仍然执行,但它们依赖于 jQuery,即使它在 之前 导入其他脚本,它也会吐出错误。)
详细说明,这是我的代码:
function cleanDocument(names) {
var element = document.documentElement;
for (var i = element.attributes.length - 1; i >= 0; i--) {
element.removeAttribute(element.attributes[i].name);
}
for (var i = 0; i < names.length; i++) {
var elements = document.getElementsByTagName(names[i]);
if (elements.length === 0)
document.documentElement.appendChild(document.createElement(names[i]));
}
window.stop();
}
var documentElements = ['html'];
cleanDocument(documentElements);
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// Typical action to be performed when the document is ready:
var PBSKPage = xhttp.responseText;
document.querySelector('html').innerHTML = "";
loadPBSKPage();
function loadPBSKPage() {
document.querySelector('html').innerHTML = PBSKPage;
}
}
};
var actualpage = chrome.runtime.getURL('/2015/wildkratts/wk_homepage.html')
xhttp.open("GET", actualpage, true);
xhttp.send();
function insertAndExecute() {
var scripts = Array.prototype.slice.call(document.getElementsByTagName("script"));
var jquery = document.createElement("script");
jquery.src = "https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js";
document.head.appendChild(jquery);
for (var i = 0; i < scripts.length; i++) {
if (scripts[i].src != "") {
var tag = document.createElement("script");
tag.src = scripts[i].src;
document.getElementsByTagName("head")[0].appendChild(tag);
}
else {
eval(scripts[i].innerHTML);
}
}
}
此代码适用于https://pbskids.org/wildkratts/。
基本上,它所做的是清除文档,然后使用 XMLHttpRequest,将扩展中的 HTML 模板注入页面。但是,HTML 模板中的所有脚本都需要 jQuery,并且在访问覆盖页面 (pbskids.org/wildkratts/) 时,由于未捕获的错误(即Uncaught ReferenceError: $ is not defined) 如果导入 jQuery 将被解决。
然后我访问了 HTML 模板 URL 本身,你知道吗,脚本实际上执行没有问题。
这是我的脚本标签在 HTML 模板中的顺序:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="chrome-extension://niabfndainielhgpcjenbpodannhfofj/jquery_libraries/1.11.0/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="chrome-extension://niabfndainielhgpcjenbpodannhfofj/2015/pbsk_resources/wildkratts/js/vendor/jquery-1.11.0.min.js"><\/script>')</script>
<script src="chrome-extension://niabfndainielhgpcjenbpodannhfofj/2015/pbsk_resources/wildkratts/js/vendor/jquery-1.11.0.min.js"></script>
<script src="chrome-extension://niabfndainielhgpcjenbpodannhfofj/2015/pbsk_resources/wildkratts/js/vendor/jquery.nivo.slider.pack.js" type="text/javascript"></script>
<script src="chrome-extension://niabfndainielhgpcjenbpodannhfofj/2015/pbsk_resources/wildkratts/js/vendor/jquery.touchSwipe.min.js" type="text/javascript"></script>
<script src="chrome-extension://niabfndainielhgpcjenbpodannhfofj/2015/pbsk_resources/wildkratts/js/vendor/retina.min.js"></script>
<script src="chrome-extension://niabfndainielhgpcjenbpodannhfofj/2015/pbsk_resources/wildkratts/js/plugins.js"></script>
<script type="text/javascript" src="chrome-extension://niabfndainielhgpcjenbpodannhfofj/2015/pbsk_resources/wildkratts/js/swfobject.js"></script>
<script type="text/javascript" src="chrome-extension://niabfndainielhgpcjenbpodannhfofj/2015/pbsk_resources/wildkratts/js/vendor/jquery.mobile.custom.min.js"></script>
<script type="text/javascript" src="chrome-extension://niabfndainielhgpcjenbpodannhfofj/2015/pbsk_resources/wildkratts/js/vendor/jquery.nivo.slider.3.2.plus.sliding.js"></script>
<script src="chrome-extension://niabfndainielhgpcjenbpodannhfofj/2015/pbsk_resources/wildkratts/js/pxaudio.min.js"></script>
<script type="text/javascript" src="https://www-tc.pbskids.org/includes/javascript/bridge.urls.js"></script>
<script type="text/javascript" src="https://www-tc.pbskids.org/includes/javascript/bridge.js"></script>
我想做到这一点,以便脚本在覆盖页面本身而不是 HTML 模板上时能够正常工作。我想我可以让它重定向到 HTML 模板,但我真的不想那样。
当通过 appendChild 或类似的 DOM 方法单独添加脚本元素时,每个带有 src
的脚本都是异步 运行ning 的,即它不等待前一个脚本,因此它可能运行 在 jQuery 运行 秒之前。解决方案是在 运行 下一个脚本之前等待 load
事件:
async function insertAndExecute() {
for (const orig of document.querySelectorAll('script')) {
const copy = document.createElement('script');
copy.textContent = orig.textContent;
copy.src = orig.src;
orig.replaceWith(copy);
if (copy.src) {
await new Promise(resolve => copy.addEventListener('load', resolve, {once: true}));
}
}
}
显然,HTML 模板中的脚本仅适用于 HTML 模板本身,而不适用于 HTML 模板注入的页面。 (脚本仍然执行,但它们依赖于 jQuery,即使它在 之前 导入其他脚本,它也会吐出错误。)
详细说明,这是我的代码:
function cleanDocument(names) {
var element = document.documentElement;
for (var i = element.attributes.length - 1; i >= 0; i--) {
element.removeAttribute(element.attributes[i].name);
}
for (var i = 0; i < names.length; i++) {
var elements = document.getElementsByTagName(names[i]);
if (elements.length === 0)
document.documentElement.appendChild(document.createElement(names[i]));
}
window.stop();
}
var documentElements = ['html'];
cleanDocument(documentElements);
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
// Typical action to be performed when the document is ready:
var PBSKPage = xhttp.responseText;
document.querySelector('html').innerHTML = "";
loadPBSKPage();
function loadPBSKPage() {
document.querySelector('html').innerHTML = PBSKPage;
}
}
};
var actualpage = chrome.runtime.getURL('/2015/wildkratts/wk_homepage.html')
xhttp.open("GET", actualpage, true);
xhttp.send();
function insertAndExecute() {
var scripts = Array.prototype.slice.call(document.getElementsByTagName("script"));
var jquery = document.createElement("script");
jquery.src = "https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js";
document.head.appendChild(jquery);
for (var i = 0; i < scripts.length; i++) {
if (scripts[i].src != "") {
var tag = document.createElement("script");
tag.src = scripts[i].src;
document.getElementsByTagName("head")[0].appendChild(tag);
}
else {
eval(scripts[i].innerHTML);
}
}
}
此代码适用于https://pbskids.org/wildkratts/。
基本上,它所做的是清除文档,然后使用 XMLHttpRequest,将扩展中的 HTML 模板注入页面。但是,HTML 模板中的所有脚本都需要 jQuery,并且在访问覆盖页面 (pbskids.org/wildkratts/) 时,由于未捕获的错误(即Uncaught ReferenceError: $ is not defined) 如果导入 jQuery 将被解决。
然后我访问了 HTML 模板 URL 本身,你知道吗,脚本实际上执行没有问题。
这是我的脚本标签在 HTML 模板中的顺序:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="chrome-extension://niabfndainielhgpcjenbpodannhfofj/jquery_libraries/1.11.0/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="chrome-extension://niabfndainielhgpcjenbpodannhfofj/2015/pbsk_resources/wildkratts/js/vendor/jquery-1.11.0.min.js"><\/script>')</script>
<script src="chrome-extension://niabfndainielhgpcjenbpodannhfofj/2015/pbsk_resources/wildkratts/js/vendor/jquery-1.11.0.min.js"></script>
<script src="chrome-extension://niabfndainielhgpcjenbpodannhfofj/2015/pbsk_resources/wildkratts/js/vendor/jquery.nivo.slider.pack.js" type="text/javascript"></script>
<script src="chrome-extension://niabfndainielhgpcjenbpodannhfofj/2015/pbsk_resources/wildkratts/js/vendor/jquery.touchSwipe.min.js" type="text/javascript"></script>
<script src="chrome-extension://niabfndainielhgpcjenbpodannhfofj/2015/pbsk_resources/wildkratts/js/vendor/retina.min.js"></script>
<script src="chrome-extension://niabfndainielhgpcjenbpodannhfofj/2015/pbsk_resources/wildkratts/js/plugins.js"></script>
<script type="text/javascript" src="chrome-extension://niabfndainielhgpcjenbpodannhfofj/2015/pbsk_resources/wildkratts/js/swfobject.js"></script>
<script type="text/javascript" src="chrome-extension://niabfndainielhgpcjenbpodannhfofj/2015/pbsk_resources/wildkratts/js/vendor/jquery.mobile.custom.min.js"></script>
<script type="text/javascript" src="chrome-extension://niabfndainielhgpcjenbpodannhfofj/2015/pbsk_resources/wildkratts/js/vendor/jquery.nivo.slider.3.2.plus.sliding.js"></script>
<script src="chrome-extension://niabfndainielhgpcjenbpodannhfofj/2015/pbsk_resources/wildkratts/js/pxaudio.min.js"></script>
<script type="text/javascript" src="https://www-tc.pbskids.org/includes/javascript/bridge.urls.js"></script>
<script type="text/javascript" src="https://www-tc.pbskids.org/includes/javascript/bridge.js"></script>
我想做到这一点,以便脚本在覆盖页面本身而不是 HTML 模板上时能够正常工作。我想我可以让它重定向到 HTML 模板,但我真的不想那样。
当通过 appendChild 或类似的 DOM 方法单独添加脚本元素时,每个带有 src
的脚本都是异步 运行ning 的,即它不等待前一个脚本,因此它可能运行 在 jQuery 运行 秒之前。解决方案是在 运行 下一个脚本之前等待 load
事件:
async function insertAndExecute() {
for (const orig of document.querySelectorAll('script')) {
const copy = document.createElement('script');
copy.textContent = orig.textContent;
copy.src = orig.src;
orig.replaceWith(copy);
if (copy.src) {
await new Promise(resolve => copy.addEventListener('load', resolve, {once: true}));
}
}
}