Can't access DOM via functions in Chrome Extension - javascript

I'm trying to write a Chrome extension that highlights certain words that were entered in extension's textfield
For example: I enter "web" in extension's area, press the button. On active tab all "web" words are should be highlighted.
I've found a nice web-pagethat has all the functions I need.
In my code, when I try to use them in my Extension, nothing works.
manifest file
{
"manifest_version": 2,
"name": "Word search & highlight",
"version": "1.0",
"icons": {
"16": "16x16.png",
"32": "32x32.png",
"48": "48x48.png",
"128": "128x128.png"
},
"content_scripts": [
{
"matches": [ "*://*/*" ],
"js": [ "popup.js"],
"run_at": "document_end"
}
],
"permissions": [
"tabs", "activeTab"
],
"browser_action": {
"default_title": "Start searching",
"default_icon": "48x48.png",
"default_popup": "popup.html"
}
}
popup.html
<!DOCTYPE html>
<html>
<head>
<script src="popup.js"></script>
<title></title>
</head>
<body>
<input type="text" id="searchtextfield"><br>
<input id="btn_save" value="Save" type="button">
<input id="btn_search" value="Search" type="button"><br>
</body>
</html>
And here's popup.js file: it's too long, so I made a pastebin document:
http://pastebin.com/g5ZenE48
I can't get innerHTML of webpage from these functions and I don't really understand how to make this all work.

sean-adams is correct, your browser action (popup.html) cannot communicate directly with your content script (popup.js). You can think of a content script as being an addition to whatever page the user is visiting, whereas the browser action is directly integrated as part of your chrome extension.
So, you will indeed need to use message passing to communicate. It's simple though. First, I recommend renaming your browser action popup to something like browser_popup.html. I'll use a stripped down example for brevity:
//browser_popup.html
<input type="button" id="my_button" value="Click Me">
<script src='browser_popup.js'></script>
You'll also want another file browser_popup.js for handling events.
//browser_popup.js
var button = document.querySelector('#my_button');
button.addEventListener('click', function() {
// Send message to active tab
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, 'button_clicked');
});
});
In your content script (let's call it content.js) you need to listen for the message:
//content.js
chrome.runtime.onMessage.addListener(function(message) {
if (message == 'button_clicked') {
// code to modify page...
}
});

Related

Chrome Extension addEventListener null

I just started learning JS a few weeks ago and am trying to build a Chrome Extension. I've build a manifest.json, popup.html, popup.js, and content.js file.
When I try running the background page console on Chrome to see if the popup.js is working I keep getting the error:
Uncaught TypeError: Cannot read property 'addEventListener' of null
at popup.js:8
I've tried moving the script in the html to the bottom of the body, but it still ends in an error and have tried implementing:
document.addEventListener('DOMContentLoaded', function () {
// My code here.. ( Your code here )
});
in my popup.js and the windows.onload method, but still haven't been able to get rid of the error.
If someone could please point out any errors in my code and tell me what is wrong I would really appreciate it. Thanks
POPUP HTML
<!DOCTYPE html>
<html>
<head>
<title>Like IG Links</title>
</head>
<body>
<h3><center>Paste Links Below</center></h3>
<hr>
<textarea rows="10" cols="60" id="urls"></textarea>
<br>
<textarea rows="1" cols="5" id="counter" disabled></textarea>
<br>
<br>
<button type="submit" align="center" style="width:60px;"
id="start">Start</button>
<br>
<br>
<button type="submit" align="right" style="width:60px;"
id="stop">Stop</button>
<script type="text/javascript" src="popup.js"></script>
</body>
</html>
CONTENT JS
console.log('CHROME');
POPUP JS
console.log('background running');
function loadUrls() {
console.log("123");
}
var startbutton = document.getElementById("start");
startbutton.addEventListener('click', loadUrls);
MANIFEST JSON
{
"manifest_version": 2,
"name": "Like IG Links",
"version": "1.0",
"description": "Like IG Links",
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": ["content.js"]
}
],
"background": {
"scripts": ["popup.js"]
},
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": ["tabs", "storage", "activeTab"]
}
Remove the background script portion of the manifest. After updating the extension, the errors should disappear. In an extension I am working on, I had jquery.js and popup.js in the HTML and in the manifest. The background script tag for the manifest is for logic that tracks browser events and responds to them persistently, not for the js behind the extension HTML.

Access to Chrome extension elements from frontend

Can I interact with elements of the specific Chrome Extension (e.g. click on a button of the extension) in JS script of my frontend?
This extension shows a button when clicked on, you get to your profile (Activity tab).
To use this extension you have to be on this site (StackOverflow) but not when you are in Activity tab (otherwise you'll not see the effect).
Your steps (more here):
save all files
go to chrome://extensions
switch browser to Developer mode
click LOAD UNPACKED
manifest.json
{
"manifest_version": 2,
"name": "Click",
"description": "Simple extension",
"version": "1.0.0",
"permissions": ["tabs", "<all_urls>"],
"browser_action": {
"default_icon": "icon48.png",
"default_popup": "popup.html"
}
}
popup.html
<!DOCTYPE html>
<html>
<head><title>Title</title></head>
<body>
<button id="btn-click">Go to profile</button>
<script src="popup.js"></script>
</body>
</html>
popup.js
function injectTheScript() {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.executeScript(tabs[0].id, {file: "content_script.js"});
});
}
document.getElementById('btn-click').addEventListener('click', injectTheScript);
content_script.js
function clickProfileLink() {
var stackOverflowProfile = document.getElementsByClassName("my-profile")[0];
stackOverflowProfile.click();
}
clickProfileLink();
Helpful links
Examples from Google
Good tutorial for beginners

Chrome extension Javascript running only on icon click

I want my Chrome Extension to load Javascript once user visits a website. But currently, the Javascript is executed only when user click the extension icon and till the extension popup is open.
I saw the answer in this Chrome extension to load the script without clicking on icon question.
My manifest.json is:
{
"manifest_version": 2,
"name": "Javascript example",
"description": "Some description.",
"version": "1.1",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"activeTab",
"storage"
],
"content_scripts": [
{
"matches": ["*://*/*"],
"js": ["popup.js"]
}
]
}
The popup.js is:
document.addEventListener('DOMContentLoaded', () => {
alert("Working");
});
popup.html is:
<!doctype html>
<html>
<head>
<title>Getting Started Extension's Popup</title>
<script src="popup.js"></script>
</head>
<body>
</body>
</html>
The alert dialog is shown only when I click the extension icon (i.e. when popup.html is run), not when a page loads. I want the popup.js file to execute without user needing to click the extension icon. What am I missing?
Your manifest works, but run_at defaults to document_idle which means that DOMContentLoaded has already fired. This can be fixed by specifying run_at to document_start instead.
{
"manifest_version": 2,
"name": "Javascript example",
"description": "Some description.",
"version": "1.1",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"activeTab",
"storage"
],
"content_scripts": [
{
"matches": ["*://*/*"],
"run_at": "document_start",
"js": ["popup.js"]
}
]
}
Source: https://developer.chrome.com/extensions/content_scripts
You need the content script.
Content scripts are JavaScript files that run in the context of web
pages. By using the standard Document Object Model (DOM), they can
read details of the web pages the browser visits, or make changes to
them.
Here are some examples of what content scripts can do:
Find unlinked URLs in web pages and convert them into hyperlinks
Increase the font size to make text more legible
Find and process microformat data in the DOM
If your content script's code should always be injected, register it in the extension manifest using the content_scripts field, as in the following example.
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://www.google.com/*"],
"css": ["mystyles.css"],
"js": ["jquery.js", "myscript.js"]
}
],
...
}
Refer this link for more information & implementation.
You can use content script that runs in the context of the page and this way you'll know when the user visits a specific site: https://developer.chrome.com/extensions/content_scripts

How to save google search inputs into a CSV file using a chrome extension?

I am trying to create a chrome extension that will save your google search inputs in a CSV file that is downloadable. For example: I enter the search input in google search "programming python tutorials". When search input is typed, I should be able to click the action button chrome extension to save the search input in an organized CSV file that is downloadable. This is similar to web scraping, but not really. I don't want the website information saved, I just want the search inputs saved. I have searched the chrome extension web store and online tutorials, but really haven't found anything on this. Can you please suggest where I can get started? Thank you.
What you want is a content script that is run only on Google search.
eg
{
"name": "Log Google",
"version": "1.0",
"description": "Log Google search data",
"permissions": ["tabs", "*://*.google.com/*"],
"content_scripts": [
{
"matches": ["*://*.google.com/*"],
"js": ["logdata.js"]
}
]
}
Where logdata.js is the code that you want to run whenever you visit the search page. I would suggest parsing the url of the page and getting the query rather than sorting through html elements.
To get the url of the current tab:
chrome.tabs.query({'active': true, 'lastFocusedWindow': true}, function (tabs) {
var url = tabs[0].url;
});
As for writing to the disk, take a look at the chrome.fileSystem api.
Hope this helps.
document.addEventListener('DOMContentLoaded', function() {
var checkPageButton = document.getElementById('checkPage');
checkPageButton.addEventListener('click', function() {
chrome.tabs.query({'active': true, 'lastFocusedWindow': true}, function (tabs) {
var url = tabs[0].url;
}, false);
}, false);
//logdata.js
{
"manifest_version": 2,
"name": "Log Google",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"description": "Log Google search data",
"permissions": ["tabs", "*://*.google.com/*"],
"content_scripts": [
{
"matches": ["*://*.google.com/*"],
"js": ["logdata.js"]
}
]
}
//manifest.json
<!doctype html>
<html>
<head>
<title>Open Log</title>
<script src="logdata.js"></script>
</head>
<body>
<h1>Logger</h1>
<button id="checkPage">Results</button>
</body>
</html>
popup.html

Chrome application run javascript on click

What am I doing wrong? I want to run a function when clicking "Show me some foo".
manifest.json browser_action
"browser_action": {
"default_icon": "img/icon.png",
"default_popup": "popup.html"
},
popup.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="js/popup.js"></script>
</head>
<body>
<div class="changes">
<span class="reset">Show me some foo
</span>
</div>
</body>
</html>
popup.js
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null,
{file:"reset.js"});
});
reset.js
var el = document.getElementById('foo');
el.onclick = showFoo;
function showFoo() {
alert('I am foo!');
return false;
}
Full manifest.json file
{
"name": "App name",
"version": "1.0.2",
"manifest_version": 2,
"description": "Desc.",
"permissions": [
"tabs"
],
"browser_action": {
"default_icon": "img/icon.png"
},
"background": {
"page": "background.html"
},
"browser_action": {
"default_icon": "img/icon.png",
"default_popup": "popup.html"
},
"content_scripts": [
{
"matches": [
"http://*/*",
"https://*/*"
],
"js": ["js/myscript.js"],
"exclude_matches":[
"http://site.com/*"
]
}
],
"web_accessible_resources": [
"chrome_ex_oauth.html"
]
}
I'm not sure what you are trying to do, but I'll explain your code to you:
user clicks a browserAction
popup window is crated and scripts from popup.html are loaded
popup.js loads and registers a listener chrome.browserAction.onClicked.addListener
user closes a popup window (by clicking anywhere outside it or on the browserAction again)
pupup.html page is unloaded
chrome.browserAction.onClicked.addListener listener is unregistered
As you can see reset.js is never loaded as it's never injected. What's more, you can't have a popup.html and chrome.browserAction.onClicked.addListener in the same extension ("This event will not fire if the browser action has a popup." source).
You probably want to put chrome.browserAction.onClicked.addListener into the background page so that reset.js is injected to current page whenever browserAction is clicked. And, as I mentioned above, for chrome.browserAction.onClicked.addListener to fire, you need to get rid of "default_popup": "popup.html" from manifest.
If you wanted to inject a script to popup.html - it doesn't make much sense. You have full control over popup.html and you can simply put reset.js in the <head>.

Categories

Resources