I'm just starting out with javascript. My chrome extension is currently functioning but I'd like to add more functionality to it. When clicked, it runs this in background.html:
chrome.browserAction.onClicked.addListener(function (tab) {
chrome.tabs.executeScript(null, { file: "hello.js" });
});
If I wanted to have the button toggle between hello.js script and goodbye.js; how would I accomplish this?
if (localStorage["toggle"] && localStorage["toggle"]=="hello"){
alert("Good Bye");
localStorage["toggle"]="goodbye";
} else {
alert("Hello");
localStorage["toggle"]="hello";
}
Thats how Id do it in the popup of a Browser Actions html/js.
If your doing it from the background then just change the localStorage to a variable.
var toggle;
chrome.browserAction.onClicked.addListener(function (tab) {
if (toggle=="hello"){
chrome.tabs.executeScript(null, { file: "goodbye.js" });;
toggle="goodbye";
} else {
chrome.tabs.executeScript(null, { file: "hello.js" });
toggle="hello";
}
});
Related
Ok, So I was working on deleting tabs with a Chrome Extension, but it's not working. Here's my code for each file.
backround.js
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(tab.id, {file: "bookmarklet.js"})
});
bookmarklet.js
if (window.location.href.indexOf("unblocked", "games", "1v1", "smash carts", "slope unblocked", "retrobowl",) > -1) {
alert("You are not supposed to be on the website. You will be reported to an adminstrator immediatly.");
console.log(window.location.href)
chrome.tabs.getCurrent(function(tab) {
chrome.tabs.remove(tab.id, function() { });
});
}else {
console.log("This Website is Safe")
}enter code here
My question is, how am I supposed to get the chrome. tab. remove function to work? Also my mainfest.json includes the tab permissions.
I'm currently building an extension for chrome (I'm a beginner) and looking for some help to some one issue. The flow of the extension is the following:
User activate the extension
User click an icon in the extension panel to start the capture
When the mouse cursor is over a DOM element it highlight it
When the user click it gets the "selector" (unique identifier/path to the element)
After step 2 I attach a new Debugger instance to the tab. it seems like you can do this action either in background.js or content-script.js. Both work so my question is which one makes more sense. I'd say content-script because it doesn't interact directly with the browser but only with my extension. Am I right?
Second question is when using the DebuggerAPI I need to send command using the DevTools Protocol Viewer. I guess the command I must send to interact with my DOM element sit under this category (https://chromedevtools.github.io/devtools-protocol/tot/DOM). Most of the command requires a NodeId parameter. My question is how would I get this NodeId when the mouse cursor is over it. I have the following event in my content-script
chrome.runtime.onMessage.addListener(function(msg, sender){
if(msg == "togglePanel"){
togglePanel();
} else if (msg == "startCaptureElement") {
console.log("- Content-Script.js: Add Mouse Listener");
document.addEventListener('mouseover', captureEvent);
} else if (msg == "stopCaptureElement") {
console.log("- Content-Script.js: Remove Mouse Listener");
document.removeEventListener('mouseover', captureEvent);
}
});
function captureEvent(el) {
//console.log("- Content-Script.js: It's moving");
console.log(el);
chrome.runtime.sendMessage("highlightElement");
}
In my background.js script
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(sender);
if (request == "startCaptureElement") {
console.log("- Background.js: Attach the debugger");
chrome.debugger.attach({tabId: sender.tab.id}, "1.0");
chrome.tabs.sendMessage(sender.tab.id, "startCaptureElement");
} else if (request == "stopCaptureElement") {
console.log("- Background.js: Detach the debugger");
chrome.debugger.detach({tabId: sender.tab.id});
chrome.tabs.sendMessage(sender.tab.id, "stopCaptureElement");
} else if (request == "highlightElement") {
console.log("- Background.js: Highlight Element");
chrome.debugger.sendCommand({tabId: sender.tab.id}, "DOM.enable", {});
chrome.debugger.sendCommand({tabId: sender.tab.id}, "Overlay.inspectNodeRequested", {}, function(result) {
console.log(result);
});
}
}
);
I found the similar question here How to highlight elements in a Chrome Extension similar to how DevTools does it? but the code provided confused me a little bit.
Thanks for your help
"Overlay.inspectNodeRequested" is an event that should be listened to.
you can call "Overlay.setInspectMode" to select a node.
background.js:
var version = "1.0";
//show popup page while click icon
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.debugger.attach({tabId:tab.id}, version,
onAttach.bind(null, tab.id));
});
function onAttach(tabId) {
if (chrome.runtime.lastError) {
alert(chrome.runtime.lastError.message);
return;
}
chrome.windows.create(
{url: "headers.html?" + tabId, type: "popup", width: 800, height: 600});
}
headers.html:
<html>
<head>
<meta charset="utf-8">
<script src="headers.js"></script>
</head>
<body>
<div id="container">
<button id="btn_inspect">select node</button>
</div>
</body>
</html>
headers.js:
var tabId = parseInt(window.location.search.substring(1));
var hightCfg = {
'showInfo': true, 'showStyles':true, 'contentColor':{r: 155, g: 11, b: 239, a: 0.7}
}
//listen events when page is loaded
window.addEventListener("load", function() {
chrome.debugger.sendCommand({tabId:tabId}, "DOM.enable");
chrome.debugger.sendCommand({tabId:tabId}, "Overlay.enable");
chrome.debugger.onEvent.addListener(onEvent);
document.getElementById('btn_inspect').addEventListener('click', function(){
chrome.debugger.sendCommand({tabId:tabId}, "Overlay.setInspectMode",
{'mode':'searchForNode', 'highlightConfig':hightCfg});
});
});
window.addEventListener("unload", function() {
chrome.debugger.detach({tabId:tabId});
});
var requests = {};
function onEvent(debuggeeId, message, params) {
console.log('onEvent ...'+message);
if (tabId != debuggeeId.tabId)
return;
if (message == "Network.inspectNodeRequested") {
//do something..
}
}
I am developing a chrome extension in which one can select a color scheme from list given in popup and apply it to the open (highlighted) tab. From one of code snippet I comes to know that using code : "document.body.style.backgroundColor='red'" in chrome.tabs.executeScript change the background color. but there is only one line in code.
What my steps are
select the color scheme from popup
get the class name of the selected li
apply that class to the DOM document
Please see the code below
popup.js
document.addEventListener('DOMContentLoaded', function () {
var li = document.querySelectorAll('li');
for (var i = 0; i < li.length; i++) {
li[i].addEventListener('click', click);
}
});
function click(e) {
// console.log(e.target.className); // gives correct value
chrome.tabs.executeScript(null, {
code : "var scriptOptions = { param1: e.target.className} ;"}, function(e){
console.log('clicked class');
console.info(param1); // gives nothing
document.body.setAttribute('class', e.target.className);
});
window.close();
}
How to get e.target.className inside function(e) ?
again If I use jquery. it changed the that popup background color only, see the code
$(function(){
console.log('jQuery added');
$(document).on ('click', 'li', function(){
var cl = this.className;
$('body').removeClass().addClass(cl);
});
});
Please tell me
What is the proper way to accomplish this in both javascript and jQuery
How to get e.target.className inside function(e) ?
Let's look at the following sample code:
var a = 1;
function f(a) {
alert(a);
}
f(2);
This is a simplified version of your problem. There is a variable a in the global scope, but by naming your function parameter a you're essentially making a local variable of the same name.
In your code:
function click(e) {
// e is now from click(e)
chrome.tabs.executeScript(null, {
code : "var scriptOptions = { param1: e.target.className} ;"}, function(e){
// e is now from function(e)
});
}
The solution is simple: you're not using the parameter of the callback of executeScript, so just use function() { /* ... */ } as a callback.
If I use jQuery, it changes the popup background color only
Your code operates in the context of your popup; $('body') refers to popup's body. Same with document.body - the callback of executeScript executes in the popup.
To change the active tab, this needs to be done from the content script in that tab.
What is the proper way to accomplish this
While you could just inject code, it's better to make a content script that waits for a command.
// content.js
if(!injected) { // Make sure it's only executed once
injected = true;
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
if(message.action == "bodyClass") {
document.body.setAttribute('class', message.class);
}
});
}
Then from the popup, you inject this script then message it:
chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
// requires only activeTab permission
chrome.tabs.executeScript(tabs[0].id, {file: "content.js"}, function() {
// This code executes in the popup after the content script code executes
// so it is ready for the message
chrome.tabs.sendMessage(tabs[0].id, {action: "bodyClass", class: "example"});
});
});
If you need jQuery, you need to inject it first:
chrome.tabs.executeScript(tabs[0].id, {file: "jquery.js"}, function() {
chrome.tabs.executeScript(tabs[0].id, {file: "content.js"}, function() {
/* content script ready */
}
}
Alternatively, you can define the script in the manifest and not inject it every time, but this potentially drains memory as it is injected in tabs where it is not needed.
There is bug in chromium and in chrome I need to use JSON.stringify(e.target.className) the before sending via code
code : "var scriptOptions = { selectedClass: " + JSON.stringify(cl) + " }"
from chorme.sendMessage documentation
Sending a request from the extension to a content script looks very
similar, except that you need to specify which tab to send it to.
function click(e) {
var cl = e.target.className; // both gives the same result that is OK.
chrome.tabs.query({ active: true, highlighted: true, currentWindow: true }, function(htab) {
// console.log(JSON.stringify(htab, ['active', 'id', 'index', 'windowId', 'title', 'url'], 4));
chrome.tabs.executeScript(htab[0].id, {
code : "var scriptOptions = { selectedClass:" + JSON.stringify(cl) + " }" }, function() {
chrome.tabs.executeScript(htab[0].id, { file: "js/script.js" }, function(){
console.log('Inside script file');
chrome.tabs.sendMessage(htab[0].id, { action: "bodyColor" }, function(resp) {
console.log('response aaya');
});
});
});
});
}
I am working on a chrome extension ,this extension have 2 icons in the browser action (On & Off) ;
basically when it is On the background execute the script.js (Inject the file:script.js)
using the chrome.tabs.executeScript(tab.id,{file:"script.js",function(){});
I had problems to turn it off !
I have tried to use messages communication between the background.js and the script.js but this does not work neither .
If I understand correctly, your extension should have two states, On and Off. Clicking the extension icon toggles it on/off.
In this case you should use storage so the extension knows what state it is in. So on a click event, use something like:
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.storage.sync.get('state', function(data) {
if (data.state === 'on') {
chrome.storage.sync.set({state: 'off'});
//do something, removing the script or whatever
} else {
chrome.storage.sync.set({state: 'on'});
//inject your script
}
});
});
Note though that this is happening at the extension/browser level and will apply to all tabs, so you may need something more complex that records both the tab ID and the state.
You then have the choice to either always run a content script and check the on/off state before performing some action, or inject and remove the script. I'm not sure if you remove a script though. Depending on what the script does, you may just want to refresh the page (i.e. if your script messes with the DOM and you want to undo that when turning the extension off).
background.js
var enable=false;
chrome.browserAction.onClicked.addListener(function (tab) {
enable = enable ? false : true;
if(enable){
//turn on...
chrome.browserAction.setIcon({ path: 'icon.png' });
chrome.browserAction.setBadgeText({ text: 'ON' });
chrome.tabs.executeScript(null, { file: 'content.js' });
}else{
//turn off...
chrome.browserAction.setIcon({ path: 'disable.png'});
chrome.browserAction.setBadgeText({ text: '' });
}
});
To add onto what #david-gilbertson stated for making it active and inactive for certain tabs, I have created that functionality here. I also took added some functions for removing and adding tabs to the array. Enjoy!
function addTab(array, new_tab_id)
{
array.push(new_tab_id);
//then call the set to update with modified value
chrome.storage.sync.set({
active_tabs:array
}, function() {
console.log("added tab");
});
}
function removeTab(array, rem_tab_id)
{
const index = array.indexOf(rem_tab_id);
if (index > -1) {
array.splice(index, 1);
}
//then call the set to update with modified value
chrome.storage.sync.set({
active_tabs:array
}, function() {
console.log("removed tab");
});
}
chrome.browserAction.onClicked.addListener(function (tab) {`enter code here`
chrome.storage.sync.get({active_tabs : []}, function(data) {
if (data.active_tabs.includes(request.tab_id)) {
removeTab(data.active_tabs, request.tab_id)
console.log("Turned Off ".concat(request.tab_id))
document.removeEventListener("mousemove", highlightCurrentHover, false);
} else {
addTab(data.active_tabs, request.tab_id)
console.log("Turned On ".concat(request.tab_id))
document.addEventListener('mousemove', highlightCurrentHover, false);
}
});
);
I am writing a Chrome extension that needs to be able to add code into the web page it is viewing. Right now in my background page I have:
chrome.tabs.onUpdated.addListener(function(tabId, info) {
if (info.status=="complete") {
chrome.tabs.executeScript(null, {file: "injectme.js"})
}
})
and the injected script injectme.js which contains a function that looks like this:
function() {
if (!document.getElementById('searchforme')) {
x=document.createElement('script')
x.setAttribute('src','https://sites.google.com/site/searchformechrome/files/theinjectedcode.js')
x.setAttribute('id','searchforme')
document.appendChild(x)
alert('it is finished')
} else {
alert('so close')
}
}
My question is how do I call this function the moment it loads so it can insert the script into a web page?
If I understood you :)
All you need to do is to warp you current function inside something like:
(function () {
// your code
if (!document.getElementById('searchforme')) {
x=document.createElement('script')
x.setAttribute('src','https://sites.google.com/site/searchformechrome/files/theinjectedcode.js')
x.setAttribute('id','searchforme')
document.appendChild(x)
alert('it is finished')
} else {
alert('so close')
}
}());
so it will be an 'immediate invocation' function.