1

I'm working on a simple Chrome extension to hide elements on certain pages. I've been hacking up a few examples I found online and I have it to the point where it's working as a browser action that requires the user to click on the icon for it to activate. I'm looking for a way to make it just run and hide the content automatically.

I haven't done much programming in a few years so please pardon the mess. I'm thinking about getting back into programming and thought that putting together a few extensions would be fun.

So what am I missing here? I've attached the code for the one I'm working on now that hides chat from Pinterest.com.

manifest

{
  "name": "NoPChat",
  "version": "1.0.0",
  "manifest_version": 2,
  "description": "Hide Pinterest Chat",
  "background": {
    "scripts": ["background.js"],
    "persistent": false
  },
  "page_action" :
  {
    "default_icon" : "images/icon-19.png",
    "default_title" : "Toggle Pinterest chat"
  },
  "permissions" : [
    "declarativeContent",
    "activeTab"
  ],
  "content_scripts":
  [
    {
      "matches": ["*://*.pinterest.com/*"],
      "js": ["content.js"],
      "run_at": "document_end"
    }
  ],
  "icons" : {
    "48" : "images/icon-48.png",
    "128" : "images/icon-128.png"
  }
}

content.js

hidePinterestChat();

function hidePinterestChat() {
   var el = document.getElementsByClassName("Conversation Module"),
       n = el.length;

   for (var i = 0; i < n; i++) {
     var e = el[i];
     e.style.display = 'none';
    }

    var el2 = document.getElementsByClassName("Module Dropdown PositionModule aboveModal activeConversationDropdown active ui-droppable positionModuleFixed positionFixed defaultCaret positionModuleElement positionRight"),
       n = el2.length;

   for (var i = 0; i < n; i++) {
     var e = el2[i];
     e.style.display = 'none';
    }
}

background.js

// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// When the extension is installed or upgraded ...
chrome.runtime.onInstalled.addListener(function() {
  // Replace all rules ...
  chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
    // With a new rule ...
    chrome.declarativeContent.onPageChanged.addRules([
      {
        // That fires when a page's URL contains a 'g' ...
        conditions: [
          new chrome.declarativeContent.PageStateMatcher({
            pageUrl: { urlContains: 'pinterest.com' },
          })
        ],
        // And shows the extension's page action.
        actions: [ new chrome.declarativeContent.ShowPageAction() ]
      }
    ]);
  });
});


chrome.pageAction.onClicked.addListener(function(tab) {
  chrome.tabs.executeScript(null, {file: "content.js"});
});

Edit: I got it to work better by adding a timeout in content.js

function partA() {
  window.setTimeout(hidePinterestChat,5000);
}
partA();
hidePinterestChat();
...

It's to the point where the conversation bubbles pop up for a few seconds and then disappear. I'm sure there must be a better way to it.

Xan
  • 74,770
  • 16
  • 179
  • 206
Skeleton
  • 11
  • 4
  • I have deleted my answer, since I misunderstood your code; you made a very important typo by not formatting `hidePinterestChat();` as code. – Xan Jan 13 '16 at 17:24
  • Sorry - I'm not sure where the formatting mistake is. – Skeleton Jan 13 '16 at 17:48
  • I fixed it already - you did not leave a blank line before multi-line code. See the edit history. – Xan Jan 13 '16 at 17:49

1 Answers1

2

First off, you probably already found out that only Content Scripts can interact with pages. So far so good, you have a content script.

Next task is to make that content script run. There are 2 ways to do that:

  1. By declaring where it should run in the manifest. Chrome will then run it automatically when you visit a matching page.

  2. By explicitly injecting it with executeScript (so-called programmatic injection).

Bizarrely, you do both. You just need one - and since you don't want interaction, you don't want anything but the content script and its matching manifest section. No need for a page action, and (currently) no need for a background script.

Finally, let's look at your content script and why your edit works.

Your first version tries to loop through some DOM nodes as soon as the script executes. Your second version does absolutely the same, but with a 5-second delay. Your page action version does so with a variable delay depending on when it's clicked.

So, what does it tell us? That the nodes probably don't exist yet when your script executes. Considering that a content script, by default, runs after the initial DOM tree is fully constructed, this means that the comments are added dynamically, by page's JavaScript code, after it finishes loading.

There's a canonical question regarding detecting DOM changes, I'll just link to it here. It's not a very easy topic, but not too complicated either. My personal recommendation would be to use the mutation-summary library, see its tutorials.

Community
  • 1
  • 1
Xan
  • 74,770
  • 16
  • 179
  • 206