最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Chrome Extension: Waiting For Element to Load (async js) - Stack Overflow

programmeradmin2浏览0评论

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 pare 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?

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 pare 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?

Share Improve this question edited Apr 21, 2016 at 5:57 confused asked Apr 21, 2016 at 4:31 confusedconfused 811 silver badge4 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 4

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
});

An insertion into DOM may have the element in question deeper in the added node.

For example, this can be inserted into the DOM:

<div class="container">
  <div class="element_id">...</div>
  ...
</div>

In that case, the added node list will only contain the .container node.

The mutation will not list everything added, it's your responsibility to recursively dig into the added fragment looking through added nodes.

Using mutation-summary library may help you avoid such headaches.

var observer = new MutationSummary({
  rootNode: document.body,
  callback: function(summaries) {
    summaries.forEach(function(summary) {
      summary.added.forEach(function(idElement) {
        /* ... */
        idElement.appendChild(myButton);
      });
    });
  },
  queries: [{element: ".element_id"}]
});

If you don't want to use a library, you can try calling querySelector or querySelectorAll on addedNodes[i].

发布评论

评论列表(0)

  1. 暂无评论