Deleting DOM elements before the Page is displayed to the screen (in a Chrome extension)

后端 未结 1 1842
谎友^
谎友^ 2020-12-29 14:50

I am trying to create an extension that will get rid of certain Page elements (by id or class) before the page is displayed to the screen. I\'ve tried using an event listene

相关标签:
1条回答
  • 2020-12-29 15:36

    Use MutationObserver in the content script injected at document_start to actually delete the HTML elements from DOM during page load before they are rendered so that there's no flickering.

    • manifest.json:
    {
      "name": "Delete elements",
      "version": "1.0",
      "content_scripts": [
        {
          "matches": ["http://somesite.com/*"],
          "run_at": "document_start",
          "all_frames": true,
          "js": ["content.js"]
        }
      ],
      "manifest_version": 2
    }
    
    • content.js:
    const DEL_SELECTOR = '.header-nav-item, #topchapter, #wrapper_header';
    
    const mo = new MutationObserver(onMutation);
    // in case the content script was injected after the page is partially loaded
    onMutation([{addedNodes: [document.documentElement]}]);
    observe();
    
    function onMutation(mutations) {
      const toRemove = [];
      for (const {addedNodes} of mutations) {
        for (const n of addedNodes) {
          if (n.tagName) {
            if (n.matches(DEL_SELECTOR)) {
              toRemove.push(n);
            } else if (n.firstElementChild && n.querySelector(DEL_SELECTOR)) {
              toRemove.push(...n.querySelectorAll(DEL_SELECTOR));
            }
          }
        }
      }
      if (toRemove.length) {
        mo.disconnect();
        for (const el of toRemove) el.remove();
        observe();
      }
    }
    
    function observe() {
      mo.observe(document, {
        subtree: true,
        childList: true,
      });
    }
    

    Notes:

    • The observer callback must be simple and fast in order not to introduce lags during page loading so use simple selectors and direct DOM access instead of jQuery.
    • When the job is done it's best to disconnect the observer immediately so that the rest of the page isn't needlessly observed.
    • Don't add multiple observers, incorporate all checks in just one
    • mutations array also contains text subnodes along with the added elements themselves. That's why we make sure tagName is present - it means the node is an element.
    • Each mutation's addedNodes array usually has container elements like DIV, for example, which in turn may have an element we want to delete inside. So we have to examine it with querySelector or querySelectorAll.
    • childNode.remove() works since Chrome 23
    0 讨论(0)
提交回复
热议问题