I'm trying to load jQuery into content script when page is loaded.
All works great until couple days ago when some users started to get errors.
Uncaught ReferenceError: $ is not defined
I was thinking what can cause this problem, because all works great.
Part of manifest file:
"content_scripts": [
{
"all_frames": true,
"js": [
"js/jquery-3.6.0.min.js"
],
"css": [
"css/overlay.css"
],
"matches": [
"https://coolsite.com/*"
],
"runAt": "document_start"
},
{
"all_frames": true,
"js": [
"content/content1.js"
],
"matches": [
"https://coolsite.com/*",
],
"runAt": "document_end"
}]
Code of content1.js
$(document).ready(function () {
// Broadcast runner loaded
chrome.runtime.sendMessage({
callback: true,
runnerLoaded: true
});
});
The problem is something about jQuery, couldn't find out why.
I will be so thankful for some help.
Thank you,
Ori
Related
I'm using chrome extension to automate my few tasks, one of them is to select the date from datepicker. but i'm unable to perform actions on Jquery UI datepicker by using its methods such as:
$(".hasDatepicker").datepicker("setDate", new Date("01/03/2022"));
or getting date:
$(".hasDatepicker").datepicker("getDate");
i display the result in console and it returns undefine.
Inside manifest file, i also included the jquery-ui.js file, here it is:
{
"manifest_version": 3,
"name": "Auto Cart",
"version": "1.0",
"content_scripts": [
{
"matches": [
"https://www.billetterie-parismusees.paris.fr/*"
],
"js": [
"jquery.js",
"jquery-ui.js",
"content.js"
]
}
],
"action": {
"default_popup": "popup.html"
},
"permissions": ["storage","activeTab"]
}
Important:
I can get and set values of datepicker from console but it doesn't work from content-script.js file.
Can anyone pls help me in resolving this issue?
I had defined a content script in the manifest.json as:
"content_scripts": [
{
"matches": [
"https://*/*"
],
"js": [
"cs.js"
]
}
]
And in cs.js I would like to load another JS (mark.js) as module:
// cs.js
import Mark from './lib/mark.es6.min.js'
window.onload = (event) => {
console.log(Mark)
}
and when I am visiting any page, there is an error in the console
Uncaught SyntaxError: Cannot use import statement outside a module
The directory structure looks like:
manifest.json
cs.js
lib/mark.es6.min.js
What is the best way in which I can load the mark.js to be able to use in my content script?
Not exactly what you asked for, but be aware that you can spawn different scripts from the background page:
chrome.tabs.executeScript(tabId, {
file: "./content_scripts/script1.js",
});
chrome.tabs.executeScript(tabId, {
file: "./content_scripts/script2.js",
});
And then, the functions you declare in script1.js can be used in script2.js
Thanks to 1j01, woxxom and nicola-scionti for good suggestions (Can I share code between different parts of Chrome Extension?, How to import ES6 modules in content script for Chrome Extension and https://stackoverflow.com/a/70359345/725306 respectively).
I ended up using content_scripts only as:
"content_scripts": [
{
"matches": [
"https://*/*"
],
"js": [
"lib/mark.es6.min.js",
"cs.js"
]
}
]
and then simply use that in my cs.js
// cs.js
window.onload = (event) => {
console.log(Mark)
}
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"
} ]
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.
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.
I'm trying to write Chrome Extension in pure javascript to fetch a collection of nodes and make some changes to it. So, I started off with:
var list = document.getElementsByClassName("testclass");
console.log(list); //1
console.log(list.length); //2
console.log(list[0]); //3
The output for this comes up as:
1. An object [item:function, namedItem:function], which has all the elements and a length: <number of elements> and __proto___: HTMLCollection (As Expected)
2. 0
3. undefined
The same thing, which I give in jsfiddle, I get proper outputs:
1. HTMLCollection object with all elements and length: <no of elements> and __proto__: HTMLCollection
2. <no of elements>
3. First Element
Why am I unable to iterate when the javascript used is them same? Is there something else to do when we are using a Chrome extension?'
Heres my manifest.json in case it helps:
{
"manifest_version": 2,
"name": "Something",
"description": "Something something...",
"version": "1.0",
"permissions": [
"tabs",
"notifications",
"http://*/",
"https://*/"
],
"content_scripts": [{
"matches": ["https://*","http://*"],
"js": ["testscript.js"],
"run_at": "document_end"
}],
"web_accessible_resources": ["samplejs.js"],
"browser_action": {
"default_popup": "popup.html"
}
}
My javascript code is in testscript.js
Well, I did some modifications in your manifest file and it worked for me. Here is the updated version:
{
"manifest_version": 2,
"name": "Something",
"description": "Something something...",
"version": "1.0",
"permissions": [
"tabs",
"notifications",
"http://*/",
"http://*/*",
"https://*/*"
],
"content_scripts": [{
"matches": ["https://*/*", "http://*/*"],
"js": ["testscript.js"],
"run_at": "document_end"
}],
"web_accessible_resources": ["samplejs.js"],
"browser_action": {
"default_popup": "popup.html"
}
}
I have changed the permissions and matches sections.
Found a solution. The problem was that the DOM was not getting loaded fully, hence my script which executed before DOM got loaded, could not fetch data properly is what I am guessing.
I tried using
document.onload=function(){}
and
window.onload=function(){}
window.onload had trouble fetching the output, and document.onload never triggered at all.
So, tried using a delay:
setTimeout(function(){
<javascript code>
},3000);
And this works fine. Not sure if its the best method.
As an alternative, added jquery to the extension and used:
$(document).ready(function(){
<javascript code>
});
And this works even better.
When specifying parameters in the manifest file of a chrome extension there is an option all_frames. This allows the content scripts to be embedded in all frames of a page or not.
An example of what I want to achieve is have a.js running with all_frames=false and b.js with all_frames=true.
The content_scripts manifest property is an array, so you can define multiple content script specification objects:
"content_scripts": [
{
"matches": ["http://www.google.com/*"],
"css": ["mystyles.css"],
"js": ["a.js"],
"all_frames": false
},
{
"matches": ["http://www.yahoo.com/*"],
"js": ["b.js"],
"all_frames": true
}
],