Search code examples
javascripthtmldomgoogle-chrome-extensioncode-injection

How to create a Chrome Extension to Hide or Remove a Page Element using JavaScript?


I am trying to create a Chrome Extension to manipulate the HTML on a page. The extension should remove or hide some elements from a page when activated.

I created a simple manifest.json file:

{
  "manifest_version": 2,

  "name": "hide-msgs-ext",
  "version": "0.0.1",
  "description": "Hide msgs extension",

  "content_scripts": [{
    "js": ["content.js"],
    "matches": ["https://website.example.com/*"],
    "run_at":  "document_idle"
  }]

}

and a script content.js, which should remove/hide all my target elements:

var elements = document.querySelectorAll('div.card');
for (var i = 0, l = elements.length; i < l; i++) {
  subElement = elements[i].querySelector(':scope div.card-body');
  if (subElement.firstChild.tagName != 'A') {
    elements[i].style.display = "none";
  }
}

If I execute the above script in the chrome console I am able to hide all the elements I want and no errors are triggered. However I could not figure it out how to make it work in the extension.

Could someone point me in the right direction? Thanks you in advance!


Solution

  • It sounds like the content might be created by javascript after the page loads so you need to wait for it to appear. You can wrap your code in a function and execute it after a timeout:

    function hideCards() {
      var elements = document.querySelectorAll('div.card');
      for (var i = 0, l = elements.length; i < l; i++) {
        subElement = elements[i].querySelector(':scope div.card-body');
        if (subElement.firstChild.tagName != 'A') {
          elements[i].style.display = "none";
        }
      }
    }
    
    // execute after a second to give the page time to create the
    // elements you want to remove
    setTimeout(hideCards, 1000);
    

    If you want it to work throughout the life of the page and be very quick, you could try using MutationObserver. This lets you listen for DOM changes. Here's a sample of how to use that. The 'Add Item' button adds a new item, every other one has the 'remove-me' class. The MutationObserver executes a function that automatically removes any LI nodes added with that class so they don't appear:

    const observer = new MutationObserver(function(mutations) {
      let added = [];
      for (let i = 0; i < mutations.length; i++) {
        let m = mutations[i];
        for (let j = 0; j < m.addedNodes.length; j++) {
          let n = m.addedNodes[j];
          if (n.tagName === 'LI' && n.classList.contains('remove-me')) {
            added.push(n);
          }
        }
      }
      added.forEach(element => element.remove())
    });
    
    const config = { subtree: true, childList: true };
    observer.observe(document.body, config);
     
    let index = 0;
    document.getElementById('btnAddItem')
    .addEventListener('click', (event) => {
      let li = document.createElement('li');
      if (index & 1 == 1)  li.classList.add('remove-me');
      li.innerText = `Item ${index++}`;
      document.getElementById('myList').appendChild(li);
    });
    <ol id="myList">
      <li>First Item</li>
    </ol>
    
    <button id="btnAddItem">Add Item</button>