Reputation: 435
The website I'm targeting is pretty much a Javascript application. So I need to add HTML after everything has completed loading. I tried using MutationObserver, but it still tries to execute javascript too early and I get the following error code `Uncaught TypeError: Cannot read property 'appendChild' of undefined
My code
manifest.json
{
"manifest_version": 2,
"name": "Test",
"version": "1.0",
"description": "Test Description",
"content_scripts": [{
"js": ["content.js"],
"run_at" : "document_idle",
"matches": ["https://pastvu.com/p/*"]
}]
}
content.js
new MutationObserver(function(mutations, observer) {
addHtml();
observer.disconnect();
}).observe(document.querySelector('body'), {childList: true});
function addHtml(){
var newDiv = document.createElement("div");
newDiv.setAttribute("class","tltp-wrap");
var newLink = document.createElement('a');
newLink.setAttribute('href','http://www.google.com');
var linkButton = document.createElement('span');
linkButton.setAttribute('class','glyphicon glyphicon-map-marker');
newLink.appendChild(linkButton);
newDiv.appendChild(newLink);
document.getElementsByClassName("toolsBtm")[0].appendChild(newDiv);
}
Here is the page I'm targeting. As you can see the <body>
looks like this
<body>
<script type="text/javascript" src="/js/module/appMain.js?__=wfDkO"></script>
</body>
My goal is to wait until the body html loads or at least unitil .toolsBtm
div is present.
I changed content.js
to this and still no luck
new MutationObserver(function(mutations, observer) {
var bodyLoaded = document.getElementsByClassName('toolsBtm');
if (bodyLoaded.length > 0) {
alert('a');
addHtml();
}
}).observe(document.querySelector('body'), {childList: true});
function addHtml(){
var newDiv = document.createElement("div");
newDiv.setAttribute("class","tltp-wrap");
var newLink = document.createElement('a');
newLink.setAttribute('href','http://www.google.com');
var linkButton = document.createElement('span');
linkButton.setAttribute('class','glyphicon glyphicon-map-marker');
newLink.appendChild(linkButton);
newDiv.appendChild(newLink);
document.getElementsByClassName("toolsBtm")[0].appendChild(newDiv);
}
Upvotes: 0
Views: 416
Reputation: 307
In our plugin we have something like
export function invokeAfterDomIsReady(context = document, selector, time = 400, func) {
const domEl = context.querySelector(selector);
if (domEl != null) {
func(domEl);
} else {
setTimeout(function () {
invokeAfterDomIsReady(context, selector, time, func);
}, time);
}
}
It is something what usually used during ui testing with Selenium.
Upvotes: 1