3

Good day to everyone, as you can see I'm pretty new at Chrome extensions.

Can you run a script from content_scripts before and after the the DOM or page fully loads?

Like:

"content_scripts": [ {
    "matches": ["<all_url>"],
    "js": ["content.js"],
    "all_frames": true,
    "run_at": "document_start",
    "run_at": "document_end"
} ]

Or something like:

 "content_scripts": [ {
    "matches": ["<all_url>"],
    "js": ["content1.js"],
    "all_frames": true,
    "run_at": "document_start"
} ],
"content_scripts": [ {
    "matches": ["<all_url>"],
    "js": ["content2.js"],
    "all_frames": true,
    "run_at": "document_end"
} ]
Xan
  • 71,217
  • 14
  • 165
  • 189
  • i want it to be before the page and after, any method will be fine. – Francis ask question Mar 20 '19 at 07:52
  • I mean when after and before the page fully loaded. – Francis ask question Mar 20 '19 at 07:54
  • An important note: there is no general "all DOM is loaded now" state you can detect if the page dynamically creates more DOM (e.g. infinite scroll). This needs to be dealt with [different techniques](https://stackoverflow.com/questions/2844565/is-there-a-javascript-jquery-dom-change-listener). `document_end` (or `document_idle`) guarantees only that all static DOM has been parsed. – Xan Mar 20 '19 at 10:38
  • Xan, well for that case I run a script that run indefinitely. Well my only concern was to run a two different script before and after the page loaded. – Francis ask question Mar 21 '19 at 05:35

2 Answers2

2

You can have only one content_scripts entry, so it would be like:

"content_scripts": [{
    "matches": ["<all_urls>"],
    "js": ["content1.js"],
    "all_frames": true,
    "run_at": "document_start"
  },{
    "matches": ["<all_urls>"],
    "js": ["content2.js"],
    "all_frames": true,
    "run_at": "document_end"
}]

With this setting, content1.js would run at the beginning and content2.js at the end.

Iván Nokonoko
  • 4,463
  • 2
  • 14
  • 22
1

You are going in the right direction: You can use the run_at property, but your manifest needs to look something like this:

"content_scripts": [
{
    "matches": ["<all_url>"],
    "js": ["content1.js"],
    "all_frames": true,
    "run_at": "document_start"
},
{
    "matches": ["<all_url>"],
    "js": ["content2.js"],
    "all_frames": true,
    "run_at": "document_end"
}]

It should be an array of objects defining all content scripts instead to declaring the content_script property twice.


If you are using jQuery you can also use $(document).ready() like this:
const func1 = params => {
    // Stuff that will happen as soon as it can
};

$(document).ready(() => {
    // stuff that will happen when DOM is ready
});

If you are not using jQuery you can just do a quick google search to find alternatives for $(document).ready in vanilla js.


Other solution you can use it to inject content script programmatically from background script using chrome.tabs.executeScript() docs.
Vaibhav Vishal
  • 5,575
  • 7
  • 25
  • 43