Search code examples
javascriptgoogle-chromegoogle-chrome-extensioncontent-scriptmessage-passing

Turn Google chrome extension "off" and "on"?


I'm developing a Chrome extension for the first time and I have a content script that I would like fired every time the extension icon is clicked, and then turned "off" when the icon is clicked again, and so on. I'm wondering if anyone can help me with this? Below is the code I have so far.

manifest.json

  {
 "manifest_version": 2,

 "name": "ROTATE",
 "description": "This extension will do unspeakable deeds of great importance.",
 "version": "1.0",
 "browser_action": { },

 "icons": { "16": "icon16.png",
            "48": "icon48.png",
           "128": "icon128.png" 
 },

 "background": {
   "scripts": ["background.js"]
 },

  "content_scripts": [
    {
    "matches": ["<all_urls>"],
    "js": ["content.js"]
    }
  ],

 "permissions": 
     ["activeTab"]
  }

content.js

['', '-ms-', '-webkit-', '-o-', '-moz-'].map(function(prefix){
Array.prototype.slice.call(document.querySelectorAll('div,p,span,img,a,body')).map(function(el){
    el.style[prefix + 'transform'] = 'rotate(' + (Math.floor(Math.random() * 10) - 1) + 'deg)';
    });
});

background.js

(I know there's a better way to do it that uses message passing but I can't figure it out. Plus, this actually doesn't restore the page back to normal.)

 r toggle = false;
  chrome.browserAction.onClicked.addListener(function(tab) {
    toggle = !toggle;

 if(toggle){
   chrome.tabs.executeScript(tab.id, {file:"content.js"});
 }
 else{
   chrome.tabs.return;
 }
 });

I would greatly appreciate any kind of help. Thank you!

Edit: Still open to any feedback! Thanks!


Solution

  • The least amount of change would be to have a second content script that would undo everything done by the first content script:

    el.style[prefix+'transform'] = 'rotate(0deg)';
    

    But then if you click the button several times, you’ve injected the same code several times, and my brain is getting confused about what priority everything takes.

    The message passing approach would probably be better. The main change I’ll make is to move toggle into the content script, so that you can have this running in two separate tabs (this also takes the state out of the background page, so you can turn it into an event page). Your content script would end up being:

    var toggle = false;
    chrome.runtime.onMessage.addListener(function() {
      toggle = ! toggle;
      Array.prototype.forEach.call(document.querySelectorAll('div,p,span,img,a,body'),function(el) {
        el.style.transform = 'rotate(' + (toggle?(Math.floor(Math.random() * 10) - 1):0) + 'deg)';
      });
    });
    

    And your background script would simply be:

    chrome.browserAction.onClicked.addListener(function(tab) {
      chrome.tabs.sendMessage(tab.id,{});
    });
    

    Final notes: You know it’s Chrome, so you only need one transform prefix (I think the blank one). The function argument to Array.prototype.map should return something; since you’re not returning anything, I’ve used Array.prototype.forEach. And it turns out you don’t need slice if you’re calling map or forEach anyway.

    The end result: rotated picture