Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chrome Extension: Waiting For Element to Load (async js)

Tags:

I have a Chrome extension, and I want to wait until an element is loaded before injecting content into the page.

I'm trying to inject a button:

myButton = document.createElement('button');
myButton.class = 'mybutton';
document.querySelector('.element_id').appendChild(myButton)

I have this at the top of my content script. It used to work just fine, but then it stopped working. The error that was displayed was:

Uncaught TypeError: Cannot read property 'appendChild' of null

In order to wait for the element with class id .element_id to load, I tried to use a MutationObserver

var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
        if (!mutation.addedNodes) return

        for (var i = 0; i < mutation.addedNodes.length; i++) {
            if (mutation.addedNodes[i].parentNode == document.querySelector('#outer-container')) {

                myButton = document.createElement('button');
                myButton.class = 'mybutton';
                document.querySelector('.element_id').appendChild(myButton)
        }
            var node = mutation.addedNodes[i]
        }
    })
})

observer.observe(document.body, {
    childList: true
    , subtree: true
    , attributes: false
    , characterData: false
})

When I used the mutation observer, the page would load an outer div element called outer-container, and there was no way for me to directly compare the class .element_id. The class .element_id is nested a number of layers into the outer div.

HOWEVER, the above did not work, and I still received the null property error.

Is there a better way to wait for some element to be loaded (which is loaded async), before injecting?

like image 457
confused Avatar asked Apr 21 '16 04:04

confused


1 Answers

Don't forget to add childList and subtree property when observing changes.

var observer = new MutationObserver(function (mutations) {
    mutations.forEach(function (mutation) {
        if (!mutation.addedNodes) {
            return;
        }
        for (var i = 0; i < mutation.addedNodes.length; i++) {
            if (mutation.addedNodes[i].classList.contains("element_id")) {
                // Your logic here
            }
        }
    });
});

observer.observe(document.body, {
    childList: true,
    subtree: true
});
like image 78
Haibara Ai Avatar answered Sep 28 '22 01:09

Haibara Ai