Chrome Extension to trigger click event on icon press - javascript

I'm trying to make an extension for Chrome, so that when the icon is clicked, it triggers a click event on a div in the relevant webpages. I can't figure it out. Can anyone see or tell me what I'm doing wrong? Is this even possible?
Manifest.json
{
"name": "Name",
"version": "1.0",
"manifest_version": 2,
"icons": {
"128": "icon128.png",
"48": "icon.png"
},
"browser_action": {
"name": "Name"
},
"background":{
"scripts":["background.js"]
},
"permissions":["https://inbox.google.com/*"] //Put All your URL here
}
background
chrome.browserAction.onClicked.addListener(function (tab) {
if (tab.url.indexOf("https://inbox.google.com/*") != -1) {
chrome.tabs.executeScript(tab.id, {
"file": "clicky.js"
}, function () {
console.log("Script Executed .. ");
});
}
});
js
$('.b2')[0].click()

You're not including jquery in your manifest.json and you don't have access to the page's jQuery instance (read this), so you can't use jQuery on your content scripts.
Assuming there's an element with the 'b2' class present, change the code in clicky.js to this and it should work:
var btn = document.querySelector('.b2');
if(btn){
btn.click();
}
EDIT
Also, in your background.js, remove the wildcard when you call indexOf:
if (tab.url.indexOf("https://inbox.google.com/") != -1) {

Related

How can I run a extension with Google Chrome for Youtube?

Hello there,
I want to remove thumbnail images that appear on YouTube. I am using the following code for this.
while (true) {
$("ytd-thumbnail").remove()
}
When I paste this code into console, all thumbnail images are removed. I want it to work on the backplane by adding an extension. The code for the plug-in I'm preparing is below.
manifest.json;
{
"manifest_version": 2,
"name": "test",
"description": "test extension",
"version": "1.0",
"browser_action": {
"default_popup": "popup.html"
},
"permissions": [
"activeTab"
]
}
popup.html
<!doctype html>
<html>
<head>
<title>TEST</title>
<script src="popup.js"></script>
</head>
<body>
<h1>TEST</h1>
<button id="checkPage">Check !</button>
</body>
</html>
popup.js
document.addEventListener('DOMContentLoaded', function() {
var checkPageButton = document.getElementById('checkPage');
checkPageButton.addEventListener('click', function() {
chrome.tabs.getSelected(null, function(tab) {
d = document;
while (true) {
$("ytd-thumbnail").remove()
}
});
}, false);
}, false);
When I press the checkPage button nothing happens. But this code works when I add a console. What is the problem? Thanks in advance.
There are several issues with the extension :
You are trying to use $ i.e. jquery which is not available in your
popup.js
You are trying to access "ytd-thumbnail" dom elements which belong
to youtube page and not your popup.html. So, even if you replace $
with document.querySelector , you won't find those elements.
I created a working version that looks something like this. I have not included popup.html which is same as yours.
manifest.json
{
"manifest_version": 2,
"name": "Hello Extensions",
"description" : "Base Level Extension",
"version": "1.0",
"browser_action": {
"default_icon": "hello_extensions.png",
"default_popup": "popup.html"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["background.js"],
"all_frames" : true
}
],
"permissions": [
"activeTab",
"tabs"
]
}
2.popup.js
document.addEventListener('DOMContentLoaded', function()
{
var checkPageButton = document.getElementById('checkPage');
checkPageButton.addEventListener('click', function()
{
chrome.tabs.query({"active":true}, function (tabs){
chrome.tabs.sendMessage(tabs[0].id, "removeThumbnails", function (response) {
});
});
});
});
When the button is clicked, retrieve the active tab and send it a "removeThumbnails" message.
3.background.js
chrome.runtime.onMessage.addListener(function(message, callback) {
if (message == "removeThumbnails")
{
var elements = document.querySelectorAll("ytd-thumbnail");
elements.forEach(a => a.parentNode.removeChild(a));
}
});
background.js is content script and runs in youtube page. It can now access all the dom elements in youtube page. When we receive a "removeThumbnails" message , get all ytd-thumbnail elements and remove them from page.

Getting element in DOM after ajax call

There is a lot question and answers about that question, but I'm not being able to make it work for my case.
My extension gets the positions (1,2,...,100) on the scores pages of a game. When I first load the page I get the first 100 positions, but there are more pages, the problem is that the other pages are called with ajax and I cannot get them after the ajax call.
I came to conclusion that I could use Mutation Observers to detect changes in DOM, but I tried a lot of different codes and they all seem to not work.
My manifest.json file:
{
"manifest_version": 2,
"name": "Ogame Fleet Counter",
"short_name": "OFC",
"version": "1.0",
"icons": { "16": "16.png",
"48": "48.png",
"128": "128.png"
},
"browser_action": {
"default_icon": "48.png"
},
"background": {
"scripts": ["js/background.js"]
},
"content_scripts": [
{
"matches":[
"https://*.ogame.gameforge.com/game/index.php?page=shipyard*",
"https://*.ogame.gameforge.com/game/index.php?page=highscore"
],
"js": ["js/jquery.js", "js/content.js"]
}
]
}
My background.js file:
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, { file: "js/jquery.js" }, function() {
chrome.tabs.executeScript(null, { file: "js/content.js" });
});
});
var insertedNodes = [];
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
for (var i = 0; i < mutation.addedNodes.length; i++)
insertedNodes.push(mutation.addedNodes[i]);
})
});
observer.observe(document, { childList: true });
console.log(insertedNodes);
My extension consists in only background.js, the content.js (content script) and jquery.js.
I tried much more codes and tried changed my own, no luck. Could I use another method than Mutation Observers ? Adding onclick function in all buttons to trigger my content script maybe? Appreciate some help.
Edit: So I saw on the DOM that I need to catch: <span class=" activePager">1</span> changing, the number 1 there represents page one when I click on page two it changes to 2.
You need use your Mutation Observer on content script, because changes are happens there.
After this, you can send these changes to the Background page and process it from there.

tabs.getCurrent() result is undefined?

Not sure why I cannot retrieve info about current tab using getCurrent() when I navigate to, say, amazon.com or google.com and hit the browser icon for a browser action. Any hints on what I am missing?
MANIFEST:
{
"name": "testGetCurrentTab",
"version": "1.0",
"description": "",
"manifest_version": 2,
"icons": {
"48": "icons/icon-48.png"
},
"permissions": [
"tabs",
"<all_urls>"
],
"browser_action": {
"default_icon": "icon/icon-32.png"
},
"background": {
"scripts": ["background.js"]
}
}
BACKGROUND:
function displayInfo() {
function onGot(tabInfo) {
console.log('Inside onGot() ...');
console.log(tabInfo);
}
function onError(error) {
console.log(`Error: ${error}`);
}
var gettingCurrent = browser.tabs.getCurrent();
gettingCurrent.then(onGot, onError);
}
browser.browserAction.onClicked.addListener(displayInfo);
Here is the output:
Inside onGot() ... background.js:4:7
undefined background.js:5:7
Firefox Dev Edition 54 (64bit)
https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/tabs/getCurrent
You can get the currently active tab in the background.js file as well when doing
browser.tabs.query({active: true, windowId: browser.windows.WINDOW_ID_CURRENT})
.then(tabs => browser.tabs.get(tabs[0].id))
.then(tab => {
console.info(tab);
});
From MDN tabs.getCurrent():
Get a tabs.Tab containing information about the tab that this script is running in.
You can call this function in contexts where there is a browser tab, such as an options page. If you call it from a background script or a popup, it will return undefined.
The browserAction.onClicked event returns the active tab, you do not need another API call.
browser.browserAction.onClicked.addListener(function(tab) {
console.log(tab)
})
See the tab parameter for browserAction.onClicked listener.

Chrome extension: Execute only on current domain name once browser action is clicked

Here is my scenario: By clicking the browser icon, I create a sidebar (html and css) next to the whole page, thus creating two columns (one is my sidebar, the other one is the actual page).
What I to achieve is having the sidebar stay when I reload the page or navigate to another page WITHIN the same domain. What I have right now is just the creation of the sidebar, but I have to click the browser action every time I navigate or reload the web page.
Manifest:
{
"name": "apdrop",
"version": "0.1",
"manifest_version": 2,
"description": "first prototype for apdrop extension",
"icons": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
},"background": {
"scripts": ["background.js"],
"persistent": false
},
"browser_action": {
"default_icon": "icons/icon19.png",
"default_title": "apdrop"
},
"permissions": [
"background",
"tabs",
"http://*/*/",
"https://*/*/"
]
}
Background.js
function injectedScript(tab, method){
chrome.tabs.insertCSS(tab.id, {file:"style.css"});
//chrome.tabs.insertCSS(tab.id, {file:"bootstrap.css"});
chrome.tabs.executeScript(tab.id, { file: 'jquery-2.1.1.min.js'});
//chrome.tabs.executeScript(tab.id, { file: 'bootstrap.min.js'});
chrome.tabs.executeScript(tab.id, { file: 'inject.js'});
}
function click(tab){
console.log("browser action clicked");
injectedScript(tab, 'click');
//alert("action button was clicked");
}
chrome.browserAction.onClicked.addListener(click);
Inject.js
var ev = $("body > *");
if (!document.getElementById('contentxf343487d32'))
{
ev.wrapAll("<div id='insidecontent65675f526567'>");
$("#insidecontent65675f526567").wrapAll("<div id='contentxf343487d32'>");
$("<div id='sidebar343gf87897fh'><div id='insidesidebar87678bbbb'><p>this is my name</p></div></div>").insertBefore("#contentxf343487d32");
}
else
{
$("#sidebar343gf87897fh").remove();
$("#insidecontent65675f526567").unwrap();
$("#insidecontent65675f526567 > div").unwrap();
}
Hope this helps clarify a bit more.
The simplest strategy would be to save state in domain's sessionStorage and have a "detector" script that re-injects your UI.
Add setting the state in your content script:
// inject.js
if (!document.getElementById('contentxf343487d32'))
{
// ...
sessionStorage["contentxf343487d32"] = true;
}
else
{
// ...
sessionStorage["contentxf343487d32"] = false;
}
Add a "detector" script:
// detect.js
if(sessionStorage["contentxf343487d32"])
{
chrome.runtime.sendMessage({injectSidebar: true});
}
Always inject the script on page load, via the manifest (and change to a better permission):
"content_scripts" : [
{
"matches": ["<all_urls>"],
"js": ["detect.js"]
}
],
"permissions": [
"background",
"tabs",
"<all_urls>"
]
In the background, inject the script upon message:
// background.js
chrome.runtime.onMessage.addListener( function (message, sender, sendResponse){
if(message.injectSidebar)
{
click(sender.tab);
}
});
If you need more persistence than sessionStorage provides, use localStorage. If you need a different logic, you can still use this skeleton of a detector signalling the background.

Run Content Script From Toolbar

I want to have a Chrome Extension that will replace text on a page. I've got all the code working on the Javascript side of things, and it runs perfectly when a page loads, the problem is I only want it to replace the text on the page when you click a button on the toolbar.
I setup a button on the toolbar but the replacement Javascript still just runs when the page loads, rather than when you click the button. Additionally at the moment when you click the toolbar button, despite it not doing anything, it still shows a flash of a popup window. All I want it to do is run the text replacement code when you click the toolbar button, without showing a popup.html box.
The code currently is as follows,
Manifest.json
{
"name": "Browser Action",
"version": "0.0.1",
"manifest_version": 2,
"description": "Show how options page works",
// Needed to retrieve options from content script
"background": "background.html",
// This is how you load Browser Action. Nearly equal to Page one.
"browser_action": {
"default_icon": "icon.png",
"popup": "popup.html"
},
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js" : ["popup.js"]
}
]
}
popup.js
function htmlreplace(a, b, element) {
if (!element) element = document.body;
var nodes = element.childNodes;
for (var n=0; n<nodes.length; n++) {
if (nodes[n].nodeType == Node.TEXT_NODE) {
var r = new RegExp(a, 'gi');
nodes[n].textContent = nodes[n].textContent.replace(r, b);
} else {
htmlreplace(a, b, nodes[n]);
}
}
}
htmlreplace('a', 'IT WORKS!!!');
popup.html - Blank
background.html
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, {file: "popup.js"});
});
There are a few changes you must make (most of them mentioned by rsanchez - but not all) and a couple more changes that could/should be made.
So, instead of listing things that could/should/must be changed, I will demonstrate a sample extension that does what you want.
First things first - More info on a few key concepts, related to your question/problem:
Manifest File Format
Permissions
Background pages, Event pages
Content scripts
Browser actions
Extension directory structure:
extension-root-directory/
|_____manifest.json
|_____background.js
|_____content.js
manifest.json:
{
"manifest_version": 2,
"name": "Test Extension",
"version": "0.0",
"offline_enabled": true,
"background": {
"persistent": false,
"scripts": ["./bg/background.js"]
},
"browser_action": {
"default_title": "Test Extension"
//"default_icon": {
// "19": "img/icon19.png",
// "38": "img/icon38.png"
//},
},
"permissions": [
"activeTab"
]
}
background.js:
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(tab.id, { file: "content.js" });
});
content.js:
function htmlReplace(a, b, element) {
if (!element) {
element = document.body;
}
var r = new RegExp(a, "gi");
var nodes = element.childNodes;
for (var n = 0; n < nodes.length; n++) {
if (nodes[n].nodeType == Node.TEXT_NODE) {
nodes[n].textContent = nodes[n].textContent.replace(r, b);
} else {
htmlReplace(a, b, nodes[n]);
}
}
}
htmlReplace("a", "IT WORKS !!!");
You just need to do the following changes to your manifest:
Remove the content_scripts section.
Remove the browser_action.popup entry.
Add a section: "permissions": ["activeTab"]
Change your background section to read: "background": { "scripts": ["background.js"] } and rename your file background.html to background.js

Categories