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:Keep your manifest set to run at
document_end. This is equivalent toDOMContentLoaded— which is when$(document).ready()fires. The defaultrun_atfires too late and at unpredictable times.run_atdocument_startwon’t do any good, since: timers, mutation observers, etc. all will not fire until after theDOMContentLoadedevent — for current versions of Chrome anyway (Other browsers don’t have the same limits).Alternate method, for the fastest action but slower webpage:
Regarding:
There are only two ways to do anything before
DOMContentLoadedthat work in Chrome:mycss.cssto hide the div until after you’ve moved it. This might be the most cost-effective method, performance wise.document.createElement(). This will respond to the new element as fast as possible (assuming it’s created beforeDOMContentLoaded), 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:Do not try to use jQuery for this.