Javascript并不总是在Chrome扩展中运行,我应该在什么时候运行它? [英] Javascript not always working in Chrome Extension, when should I run it?
问题描述
我有一个Chrome扩展程序,它将CSS和Javascript注入到页面中,而CSS总是被注入,而JavaScript只是有时候而不是其他的。通过不工作,我认为它运行之前,它必须处理的东西存在。
Javascript只是移动 div
>另一个使用 insertBefore
但这并不总是发生,我认为这是因为何时加载。
我的清单目前是:
{
。 ..
content_scripts:[{
matches:[*://example.com/*],
js:[
js / jquery-1.8.3.min.js,js / myjavascript.js
],
run_at:document_end,
css:[
css / mycss.css
}]
}
我现在将 run_at
设置为 document_end
,因为它似乎运行更平滑(当它工作时),所以我认为这是什么需要改变。
如果有人有任何建议,他们将不胜感激。
编辑:关于这个问题的答案后续问题被添加这里,我觉得它可能对其他人有用,如果我将它添加到这个问题中。
如果代码不总是工作,则该表明元件(一个或多个)被创建/页面的javascript加载。因此,您需要使用标准的支持AJAX的技术来移动该div。
这些技术是:定时器,变异观察者,变异事件和拦截AJAX XHR(如果适用)。这些都在其他堆栈溢出问题中讨论过,但是:突变事件已被弃用/错误;拦截XHR变得混乱,可能不适用于此;并且突变观察者可能变得复杂。
我推荐下载并添加 waitForKeyElements()实用程序到您的清单。
然后移动< div> $ c的代码
waitForKeyElements(
jQuery选择器要移动的div(s)),
moveSelectDivs
);
function moveSelectDivs(jNode){
jNode.insertBefore(APPROPRIATE JQUERY SELECTOR);
}
<保持清单设置为运行于 document_end
。这相当于 DOMContentLoaded
- 这是在 $(document).ready()
时触发的。默认 run_at
在太晚和不可预知的时间点燃。 run_at
document_start
不会有任何好处,因为:定时器,突变观察者等都不会触发 DOMContentLoaded
事件 - 对于Chrome的当前版本(其他浏览器没有相同的限制)。
替代方法,用于最快的动作,但速度较慢的网页:
:
(页面正在加载,然后您可以看到div移动),这是我希望避免的。
在Chrome中使用 DOMContentLoaded
之前,只有两种方法可用:
- 您可以设置
mycss.css
来隐藏div,直到您移动它为止。这可能是性价比最高的方法。
- 或者,您可以覆盖
document.createElement()
。这将尽可能快地响应新元素(假设它是在 DOMContentLoaded
之前创建的),但它可能会使整个页面减慢一个明显量。
将内容脚本设置为在 document_start
处运行,并且必须注入覆盖代码。因此,该脚本将如下所示:
addJS_Node(null,null,scriptMain);
函数scriptMain(){
var _orig_createElement = document.createElement;
document.createElement = function(tag){
var element = _orig_createElement.call(document,tag);
var movingNode = document.querySelector(MOVING DIV SELECTOR);
if(movingNode){
var target = document.querySelector(TARGET DIV SELECTOR);
if(target){
target.parentNode.insertBefore(movingNode,target);
document.createElement = _orig_createElement;
}
}
返回元素;
};
}
function addJS_Node(text,s_URL,funcToRun){
var D = document;
var scriptNode = D.createElement('script');
scriptNode.type =text / javascript;
if(text)scriptNode.textContent = text;
if(s_URL)scriptNode.src = s_URL;
if(funcToRun)scriptNode.textContent ='('+ funcToRun.toString()+')()';
var targ = D.getElementsByTagName('head')[0] || D.body || D.documentElement;
targ.appendChild(scriptNode);
}
不要为此尝试使用jQuery。
I have a Chrome Extension which is injecting both CSS and Javascript into the page, and while the CSS is always being injected, the Javascript is only working sometimes and not others. By not working, I assume it's running before the stuff exists that it has to deal with.
The Javascript is simply moving a div
above another using insertBefore
but this isn't always happening, and I assume it's because of when it's loading.
My manifest is currently:
{
...
"content_scripts": [{
"matches": [ "*://example.com/*" ],
"js": [
"js/jquery-1.8.3.min.js", "js/myjavascript.js"
],
"run_at": "document_end",
"css": [
"css/mycss.css"
]
}]
}
I have run_at
set to document_end
currently because it seemed to run smoother (when it does work), so I figure that's what needs to be changed.
If anybody has any suggestions, they're greatly appreciated.
EDIT: A follow-up question regarding the answer to this question was added here, I felt it may be useful for others if I added it to this question.
解决方案 If the code is not always working, then that suggests that the element(s) are being created/loaded by the page's javascript. So, you need to use standard AJAX-aware techniques to move that div.
The techniques are: timers, mutation observers, mutation events, and intercepting AJAX XHR (if applicable). These are all discussed in other Stack Overflow questions, but: mutation events are deprecated/buggy; intercepting XHR gets messy and may not apply here; and mutation observers can get complicated.
I'd recommend downloading and adding the waitForKeyElements() utility to your manifest.
Then the code to move that <div>
becomes merely:
waitForKeyElements (
"jQuery selector for div(s) you want to move",
moveSelectDivs
);
function moveSelectDivs (jNode) {
jNode.insertBefore ("APPROPRIATE JQUERY SELECTOR");
}
Keep your manifest set to run at document_end
. This is equivalent to DOMContentLoaded
-- which is when $(document).ready()
fires. The default run_at
fires too late and at unpredictable times. run_at
document_start
won't do any good, since: timers, mutation observers, etc. all will not fire until after the DOMContentLoaded
event -- for current versions of Chrome anyway (Other browsers don't have the same limits).
Alternate method, for the fastest action but slower webpage:
Regarding:
(the page is loading and then you can see the div move), which is something I wish to avoid.
There are only two ways to do anything before DOMContentLoaded
that work in Chrome:
- You can set
mycss.css
to hide the div until after you've moved it. This might be the most cost-effective method, performance wise.
- Or, you can override
document.createElement()
. This will respond to the new element as fast as possible (assuming it's created before DOMContentLoaded
), but it might slow down the page overall, by a noticeable amount.
Set the content script to run at document_start
, and the override code must be injected. So, the script would look like:
addJS_Node (null, null, scriptMain);
function scriptMain () {
var _orig_createElement = document.createElement;
document.createElement = function (tag) {
var element = _orig_createElement.call (document, tag);
var movingNode = document.querySelector ("MOVING DIV SELECTOR");
if (movingNode) {
var target = document.querySelector ("TARGET DIV SELECTOR");
if (target) {
target.parentNode.insertBefore (movingNode, target);
document.createElement = _orig_createElement;
}
}
return element;
};
}
function addJS_Node (text, s_URL, funcToRun) {
var D = document;
var scriptNode = D.createElement ('script');
scriptNode.type = "text/javascript";
if (text) scriptNode.textContent = text;
if (s_URL) scriptNode.src = s_URL;
if (funcToRun) scriptNode.textContent = '(' + funcToRun.toString() + ')()';
var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement;
targ.appendChild (scriptNode);
}
Do not try to use jQuery for this.
这篇关于Javascript并不总是在Chrome扩展中运行,我应该在什么时候运行它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!