Javascript doesn't always work in Chrome Extension, when to run it?

I have a Chrome extension that inserts CSS and Javascript into the page, and although CSS is always injected, Javascript only works occasionally, not others. Without working, I assume that he works before there is material that he has to deal with.

Javascript just moves the div on top of the other using insertBefore , but this does not always happen, and I assume this is due to 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 at the moment, because it seemed smoother (when it works), so I think that needs to be changed.

If anyone has any suggestions, they are very much appreciated.

EDIT: The next question on the answer to this question was added here , I felt this could be useful to others if I added it to this question.

+4
source share
1 answer

If the code does not always work, then this indicates that the element is being created / loaded on the javascript page. So you need to use standard AJAX methods to move this div.

The methods are: timers, mutation observers, mutation events, and AJAX XHR interception (if applicable). All of them are discussed in other issues, but: mutation events are outdated / erroneous; XHR interception becomes erratic and may not apply here; and mutation observers can be complicated.

I would recommend downloading and adding the waitForKeyElements () utility to your manifest.

Then the code for moving that <div> becomes simple:

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


Save your manifest in run document_end . This is equivalent to DOMContentLoaded - that is, when $(document).ready() fired. By default, run_at fires too late and at unpredictable times. run_at document_start will not do any good, because: timers, mutation observers, etc. all will not fire until the DOMContentLoaded event is for current versions of Chrome anyway (other browsers do not have the same limits).



An alternative method for quick action but a slower web page:

Regarding

(the page loads, and then you can see the movement of the div), which I want 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 you move it. This may be the most cost-effective method in terms of performance.
  • Or you can override document.createElement() . This will respond to the new element as quickly as possible (provided that it is created before DOMContentLoaded ), but it can slow down the overall page by a noticeable amount.

Set the contents of the script to run in document_start , and the override code must be entered. So the script will look like this:

 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.

+4
source

All Articles