4

我有一个 Chrome 扩展程序,它将 CSS 和 Javascript 都注入到页面中,虽然 CSS 总是被注入,但 Javascript 有时只能工作,有时不能工作。通过不工作,我假设它在它必须处理的东西存在之前运行。

Javascript 只是简单地将 a 移到div另一个 using 之上,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目前,因为它似乎运行得更顺畅(当它确实工作时),所以我认为这就是需要改变的地方。

如果有人有任何建议,他们将不胜感激。

编辑:关于这个问题的答案的后续问题被添加在这里,我觉得如果我将它添加到这个问题中可能对其他人有用。

4

1 回答 1

4

如果代码并非始终有效,则表明元素正在由页面的 javascript 创建/加载。因此,您需要使用标准的 AJAX 感知技术来移动该 div。

这些技术是:计时器、突变观察者、突变事件和拦截 AJAX XHR(如果适用)。这些都在其他 Stack Overflow 问题中讨论过,但是: 突变事件已被弃用/错误;拦截 XHR 变得混乱,可能不适用于这里;突变观察者可能会变得复杂。

我建议下载waitForKeyElements() 实用程序并将其添加到您的清单中。

那么移动的代码就<div>变成了:

waitForKeyElements (
    "jQuery selector for div(s) you want to move",
    moveSelectDivs
);
function moveSelectDivs (jNode) {
    jNode.insertBefore ("APPROPRIATE JQUERY SELECTOR");
}


保持您的清单设置为document_end. 这相当于DOMContentLoaded-- 即$(document).ready()发生火灾时。默认run_at触发太晚且时间不可预测。run_at document_start不会有任何好处,因为:计时器、突变观察者等在DOMContentLoaded事件发生之前都不会触发——无论如何,对于当前版本的 Chrome(其他浏览器没有相同的限制)。



替代方法,用于最快的操作但较慢的网页:

关于:

(页面正在加载,然后您可以看到 div 移动),这是我希望避免的。

DOMContentLoaded在 Chrome 中工作之前,只有两种方法可以做任何事情:

  1. 您可以设置mycss.css隐藏 div 直到您移动它。从性能角度来看,这可能是最具成本效益的方法。
  2. 或者,您可以覆盖document.createElement(). 这将尽可能快地响应新元素(假设它是在之前创建的DOMContentLoaded),但它可能会显着降低整个页面的速度。

将内容脚本设置为在 运行document_start,并且必须注入覆盖代码。所以,脚本看起来像:

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);
}


不要尝试为此使用 jQuery。

于 2013-01-01T22:50:26.417 回答