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 listener on the document with "DOMContentLoaded" as the event but the javascript seems to execute after the page is displayed to the user and then deletes it so it's not as smooth as I want (not showing the unwanted content at all)
document.addEventListener("DOMContentLoaded", function() {
var elements = document.getElementsByClassName("header-nav-item");
while(elements.length > 0){
elements[0].parentNode.removeChild(elements[0]);
}
var element = document.getElementById("topchapter");
element.parentNode.removeChild(element);
element = document.getElementById("wrapper_header");
element.parentNode.removeChild(element);
});
This is the content script that my extension uses which deletes after the page is loaded. What do I need to use to modify the DOM before the pages is seen by the user?
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 listener on the document with "DOMContentLoaded" as the event but the javascript seems to execute after the page is displayed to the user and then deletes it so it's not as smooth as I want (not showing the unwanted content at all)
document.addEventListener("DOMContentLoaded", function() {
var elements = document.getElementsByClassName("header-nav-item");
while(elements.length > 0){
elements[0].parentNode.removeChild(elements[0]);
}
var element = document.getElementById("topchapter");
element.parentNode.removeChild(element);
element = document.getElementById("wrapper_header");
element.parentNode.removeChild(element);
});
This is the content script that my extension uses which deletes after the page is loaded. What do I need to use to modify the DOM before the pages is seen by the user?
Share Improve this question asked Sep 11, 2015 at 23:36 irregularirregular 1,5873 gold badges22 silver badges43 bronze badges 3- consider injecting styles to hide those elements before they do get rendered. Not much you can do otherwise as you'll need the dom loaded to be able to find them for removal – charlietfl Commented Sep 11, 2015 at 23:43
- @charlietfl I'll give it a try. I was thinking I might have to use something from here developer.chrome.com/extensions/webRequest then try somehow intercepting and changing the html – irregular Commented Sep 11, 2015 at 23:52
- @charlietfl the css would have to be hardcoded into the css file though right? (can't be set in options since that requires javascript to pull out anyway) – irregular Commented Sep 11, 2015 at 23:56
1 Answer
Reset to default 19Use 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": ["*://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) {
let stopped;
for (const {addedNodes} of mutations) {
for (const n of addedNodes) {
if (n.tagName) {
if (n.matches(DEL_SELECTOR)) {
stopped = true;
mo.disconnect();
n.remove();
} else if (n.firstElementChild && n.querySelector(DEL_SELECTOR)) {
stopped = true;
mo.disconnect();
for (const el of n.querySelectorAll(DEL_SELECTOR)) el.remove();
}
}
}
}
if (stopped) 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 suretagName
is present - it means the node is an element.- Each mutation's
addedNodes
array usually has container elements likeDIV
, for example, which in turn may have an element we want to delete inside. So we have to examine it withquerySelector
orquerySelectorAll
. - childNode.remove() works since Chrome 23