user6333114
user6333114

Reputation: 51

How to have chrome extension button communicate with injected js?

I have a chrome extension that injects a js file into a webpage. And also open a popup when clicked in the browser. In the popup there is a button that should change a variable in the js file. But the injected file usually cant communicate with the rest of the extension. How do i change this?

I'm still a bit new to chrome extensions, thank you for your help.

EDIT: Here is what i have so far

Manifest file:

     {
    "manifest_version": 2,
    "name": "Minds Color Extension",
    "version": "1",
"content_scripts": [
    {
      "matches": ["https://www.minds.com/*"], 
      "js": ["injectedjs.js"],
      "css" : ["injectedcss.css"]
    }
],
        "browser_action": {

          "default_icon": { 
            "19": "icon.png",
            "38": "icon.png"
          },
          "default_title": "Minds Notification page",
          "default_popup": "popup.html"

        }

      }

Popup.html

<!--
<!doctype html>
 This page is shown when the extension button is clicked, because the
 "browser_action" field in manifest.json contains the "default_popup" key with
 value "popup.html".
 -->
<html>
  <head>
    <title>Minds Theme Extension</title>
    <style>
html, body {
margin:0;
padding:10;
width: 250px;
}
   #blue {
    background-color: #337dff;
}
   #orange {
    background-color: #ff5733;
}
   #dark {
    background-color: #4a505b;
}
    button {
    border: none;
    color: white;
    padding: 10px 27px;
    text-align: center;
    text-decoration: none;
    display: inline-block;
    font-size: 16px;
    margin: 4px 2px;
    cursor: pointer;
}
#footer {
position: fixed;
bottom: 0;
}
    </style>

    <!--
      - JavaScript and HTML must be in separate files: see our Content Security
      - Policy documentation[1] for details and explanation.
      -
      - [1]: https://developer.chrome.com/extensions/contentSecurityPolicy
     -->
    <script src="injectedjs.js"></script>
  </head>
  <body>
    <div id="status">
<h2> Pick a theme: </h2>
<a href="blue.html"><button type="button" id="blue" onclick="activeBlue(); run();">Blue</button></a>
<a href="orange.html"><button type="button" id="orange" onclick="activeOrange(); run();">Orange</button></a> 
<a href="dark.html"><button type="button" id="dark" onclick="activeDark(); run();">Dark</button></a>
<br />
<div id="footer">
<font size="1"> <a href="mailto:?Subject=Minds%20Support" target="_top">Contact us</a></font>
</div>
</div>
</body>
</html>

Injectedjs.js

// Var block
var blue = 0;
var orange = 0;
var dark = 0;

// Activation block
function activeBlue() {
blue = 1;
}
function activeOrange() {
orange = 1;
}
function activeDark() {
dark = 1;
}

// Resets var block
function reset() {
blue = 0;
orange = 0;
dark = 0;
}

//Changes Minds css (Runs theme)
function run() {
if (blue == 1) {
    // Runs code that will change minds to blue. 
document.getElementById("mdl-color--white").className = "mdl-color--blue";
} 
if (orange == 1) {
    // Runs code that will change minds to orange
document.getElementById("mdl-color--white").className = "mdl-color--orange";
} 
if (dark == 1) {
    // Runs code that will change minds to dark
document.getElementById("mdl-color--white").className = "mdl-color--grey";

} 
}

Injectedcss.css has nothing in it. If you need the other files like dark.html i can give them to you but i dont see why you'd need them.

Upvotes: 1

Views: 3331

Answers (1)

Teepeemm
Teepeemm

Reputation: 4508

The big thing to understand is that an injected script interacts with a webpage, but is separate from what happens in your popup (or your background). So while you have injected.js listed as a content script and loaded by popup.html, they actually end up as two separate files.

So the first step will be to create a popup.js. It needs to attach the click listener (“onclick” counts as not separating javascript and html) and use message passing to tell the content script what to do. (I’ve also consolidated your logic a bit.)

["blue","orange","grey"].forEach(addListenerFor);

function addListenerFor(color) {
  document.getElementById(color)
    .addEventListener(click,turnPage.bind(undefined,color);
}

function turnPage(color) {
  chrome.tabs.query({"active": true, "currentWindow": true}, function(tabs) {
    chrome.tabs.sendMessage(tabs[0].id, {"newClass": "mdl-color--"+color});
  });
}

Within the content script, we need to listen for the message and take the appropriate action:

chrome.runtime.onMessage.addListener(changeClass);

function changeClass(message) {
  reset();
  if ( message.newClass ) {
    document.getElementById("mdl-color--white").className = message.newClass;
  }
}

Some final thoughts:

  • Since your extension targets a specific page, you’re supposed to use a page action instead of a browser action. The difference used to be more important (your extension wouldn't appear at all). These days it would make it so that you can’t open the popup unless you’re on the right page.
  • If your injected.css is truly empty, then you can simply remove the css key from the manifest.conent_scripts entry.
  • In order for getElementById to work in popup.js, you need to run the script after the element is present. You could put everything into an onload call, but it's probably easier to move your script tag to just before body closes.

Upvotes: 2

Related Questions