I think you misunderstand the idea of โโa port. The port is used for multiple messages in a session. But the port is destroyed when the session ends (for example, when the tab is closed). Regardless, you should not recreate the port every time you click.
In one of your comments, a page refresh was mentioned, which makes me think that you want this color to remain when the pages reload. This makes sense in terms of the user interface, but you really should have mentioned it at the beginning.
As I said, ports are destroyed when the tab is closed (or reloaded). If you want the value to be saved, you will need a storage mechanism, for example chrome.storage (you can also use local storage, but the previous link gives several reasons why not).
manifest.json just requires "permissions": [ "activeTab", "storage" ], You probably also want page actions, not a browser action (or none of them will get this).
ContentScript.js:
var myBgColor = false; chrome.storage.sync.get("myBgColor",function(items) { if ( items.myBgColor ) { myBgColor = items.myBgColor; document.querySelector(".navbar").style.backgroundColor = myBgColor; } }); chrome.runtime.onMessage.addListener(function(request,sender,sendResponse) { if ( request.setColor ) { document.querySelector(".navbar").style.backgroundColor = request.setColor; chrome.storage.sync.set({"myBgColor":request.setColor}); } else if ( request.getColor ) { sendResponse({"myBgColor":myBgColor}); } });
I changed the argument to querySelector since I could not find the items you were looking for on the index page.
Popup.html:
<!DOCTYPE html> <html> <body> <p>Choose a color:</p> <input type="color" id="color" value=""> <button type="button" id="button">Change Color!</button> <script src="Script.js"></script> </body> </html>
I'm not sure why you had your inputs at the top of the page.
Script.js (but please rename the file to something more descriptive than Script.js):
document.getElementById('button').addEventListener("click",function() { chrome.tabs.query({currentWindow: true, active: true},function(tabArray) { chrome.tabs.sendMessage(tabArray[0].id,{"setColor":document.getElementById("color").value}); }); }); chrome.tabs.query({currentWindow: true, active: true}, function(tabArray) { chrome.tabs.sendMessage(tabArray[0].id,{"getColor":1},setCurColor); }); function setCurColor(response) { if ( response.myBgColor ) { document.getElementById("color").value = response.myBgColor; } }
Wed like to have ContentScript.js message when loading Script.js if the background color is previously set. Unfortunately, Script.js only exists when weve clicked on the action icon. So we have Script.js ask ContentScript.js for the current color (if it was set).
As Ruvenka Madhushan noted, your original script failed (in part) because you assumed that the asynchronous chrome.tabs.query would complete before moving on to the next line of code. Asynchronous javascript is very powerful, but it is not responsible for the fact that the code is not complete. You need to use nested function calls, either anonymously (for example, using Script.js s onclick) or naming a utility function (as with setCurColor ). (There are also javascript libraries that will help with asynchronous functions, but I don't know them.)
Everything works, but there is a small problem: Popup.html closes when it loses focus - in this case, when you click on the color picker tab. (Very bad) to open a pop-up window and right-click and select Inspect Element. This calls up the console for the popup and prevents the popup from closing when you select a color. Another option might be to enable color picker in the iframe inside the popup (I don't know if this is possible).
But since it was about expansion options, a better alternative would be to use a page. It will also give much more room for your html. For example, you might want to consider a button to remove localStorage.myBgColor so that you can return the default value. Or other site customization options, since Im hoping you wonโt go for all these problems, just change the color. And it will hide the action icon, since presumably you are going to set your parameters, and then want to forget about the existing extension.