简体   繁体   English

Javascript并不总是在Chrome扩展程序中运行,我应该何时运行它?

[英]Javascript not always working in Chrome Extension, when should I run it?

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. 我有一个Chrome扩展程序,它将CSS和Javascript注入页面,虽然CSS总是被注入,但Javascript只在有时工作而不是其他工作。 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. Javascript只是使用insertBeforediv移到另一个上面,但这并不总是发生,我认为这是因为它正在加载。

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. 我当前将run_at设置为document_end因为它似乎运行run_at顺畅(当它工作时),所以我认为这是需要更改的内容。

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. 如果代码并不总是有效,则表明该元素是由页面的javascript创建/加载的。 So, you need to use standard AJAX-aware techniques to move that div. 因此,您需要使用标准的AJAX感知技术来移动该div。

The techniques are: timers, mutation observers, mutation events, and intercepting AJAX XHR (if applicable). 这些技术包括:定时器,变异观察器,突变事件和拦截AJAX XHR(如果适用)。 These are all discussed in other Stack Overflow questions, but: mutation events are deprecated/buggy; 这些都在其他Stack Overflow问题中讨论过,但是:变异事件被弃用/错误; intercepting XHR gets messy and may not apply here; 拦截XHR变得混乱,可能不适用于此; and mutation observers can get complicated. 和变异观察者会变得复杂。

I'd recommend downloading and adding the waitForKeyElements() utility to your manifest. 我建议下载并将waitForKeyElements()实用程序添加到清单中。

Then the code to move that <div> becomes merely: 然后移动<div>的代码变成了:

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 . 保持清单集document_end运行 This is equivalent to DOMContentLoaded -- which is when $(document).ready() fires. 这相当于DOMContentLoaded - 这是$(document).ready()触发的时间。 The default run_at fires too late and at unpredictable times. 默认的run_at触发太晚且不可预测的时间。 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). run_at document_start不会有任何好处,因为:定时器,变异观察器等都不会在DOMContentLoaded事件之后才会触发 - 无论如何对于当前版本的Chrome(其他浏览器没有相同的限制)。



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. (页面正在加载,然后你可以看到div移动),这是我希望避免的。

There are only two ways to do anything before DOMContentLoaded that work in Chrome: DOMContentLoaded之前,只有两种方法可以在Chrome中运行:

  1. You can set mycss.css to hide the div until after you've moved it. 您可以设置mycss.css以隐藏div,直到您移动它为止。 This might be the most cost-effective method, performance wise. 这可能是最具成本效益的方法,性能明智。
  2. Or, you can override document.createElement() . 或者,您可以覆盖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. 这将尽可能快地响应新元素(假设它是在DOMContentLoaded之前创建的),但它可能会使页面整体减慢一个明显的数量。

Set the content script to run at document_start , and the override code must be injected. 将内容脚本设置为在document_start运行,并且必须注入覆盖代码。 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. 不要试图使用jQuery。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM