Reputation: 426
I like to toggle the browserAction in chrome extension which should be tab independent
Here is the code
Manifest.json
{
"name": "Toggle",
"version": "1.0",
"description": "Build an Extension!",
"manifest_version": 2,
"permissions": ["activeTab"],
"icons": {
"16": "images/hand16.png",
"32": "images/hand32.png",
"48": "images/hand48.png"
},
"background": {
"scripts": ["background.js"],
"persistent": false
},
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": ["jquery.min.js","content.js"]
}
],
"browser_action": {
"default_icon": "images/hand16.png",
"default_title": "toggle"
}
}
content.js
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if(request.message === "current-tab"){
console.log('activated');
chrome.runtime.sendMessage({"message": "set_active_icon"});
}
if(request.message === "deactivate"){
console.log('deactivated');
chrome.runtime.sendMessage({"message": "set_default_icon"});
}
});
background.js
click=0;
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
if(click == 0){
chrome.tabs.sendMessage(tabs[0].id, {"message": "current-tab"});
click=1;
}
else{
chrome.tabs.sendMessage(tabs[0].id, {"message": "deactivate"});
click=0;
}
});
});
// Icon change
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if( request.message === "set_active_icon" ) {
console.log('suces');
chrome.browserAction.setIcon({
path: "images/grab.png",
tabId: sender.tab.id
});
}
else if (request.message === "set_default_icon") {
chrome.browserAction.setIcon({
path: "images/hand16.png",
tabId: sender.tab.id
});
}
});
you can notice that when the icon is clicked, "activated" is printed in the console and on clicking it again you can see "deactivated" message but when you repeat the same action in other tab, the script will work where you left off in the previous tab, but i need it to be independent of the tab and i know that its because of the global variable which i declared as "click" and not sure how to approach it in a different way or am i missing some property? Do i need to use local storage, if so how?
Thanks in advance
Upvotes: 0
Views: 2627
Reputation: 2635
Right now, it looks like you're keeping track of the click
state globally. You need to keep track of it for each tab independently.
You can accomplish this by putting that logic in the content script. Let the background page listen for browserAction
clicks, then send a "toggle-tab"
message to the relevant tab. Then, the tab can just respond to the message with its current active state, and the background page can set the icon accordingly.
Another note: you don't have to respond to a message by sending a new message. That's what the sendResponse
parameter of the addListener
callback is for. The chrome.tabs.sendMessage
function takes a third parameter, which is a callback function that receives the arguments passed to sendResponse
. For example:
content.js
// Let each content script manage its own active state.
let isActive = false;
// When the background page sends a message telling this tab to toggle its
// active state, do so, and then respond with the new active state.
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if(request.message === "toggle-tab") {
isActive = !isActive; // toggle the active state
sendResponse(isActive); // respond with the new active state
}
});
background.js
// When the browserAction click occurs, tell the content script to
// toggle its own active state. When the content script responds with
// its new active state, set the right icon.
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.sendMessage(tab.id, {message: "toggle-tab"}, function(isActive) {
setIcon(tab.id, isActive);
});
});
// Set the right icon in the given tab id, depending on that tab's active state.
function setIcon(tabId, isActive) {
const path = isActive ? "images/grab.png" : "images/hand16.png";
chrome.browserAction.setIcon({
path, tabId
});
}
Upvotes: 4