Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using mutationObserver doesn't seem to keep track of a changing table in the DOM

I am trying to write a simple chrome extension that changes the values of a table in the DOM.The important thing here is that the webpage is using ajax commands to build and change the contents of this table.(First, there is nothing in the page.Then you click on a link, and with an ajax request(no page reloads) a table will be created and after that by clicking other links, this table will be modified).

Here's the code I am using to listen to the table's changes :

var target = document.querySelector('#my-table');

var observer = new MutationObserver(function (mutations) {
    mutations.forEach(function (mutation) {
        alert('The table has appeared');
    });
});

var config = {
    attributes: true,
    childList: true,
    characterData: true,
    subtree: true
};

observer.observe(target, config);

observer.disconnect();

The problem is that nothing will happens when I press a link in the page that makes the table change.And when I was inspecting chrome's console to debug my work, I saw that it gave me this error as soon as the page loads :

Uncaught NotFoundError: Failed to execute 'observe' on 'MutationObserver': The provided node was null

I am really lost and don't know what to do.Does anyone have any suggestions? ps:Here's my extension's manifest file:

"manifest_version": 2,

  "name": "MyExtension",
  "description": "Testing the Content Script api",
  "version": "1.0",

  "content_scripts": [
    {
      "matches": ["www.myWebsite.com"],
      "js": ["script.js"]
    }
  ],

  "browser_action": {
    "default_icon": "icon.png"
  }
}
like image 877
roostaamir Avatar asked Feb 11 '23 11:02

roostaamir


1 Answers

You need to re-evaluate the selection after the mutation, inspecting each added element in turn.

  var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
      mutation.addedNodes.forEach(function(node) {
        if (node.id == 'my-table') { // or node.getElementsByClassName(..).length or whatever
          console.log('table has appeared.');
        });
      });
    });
  });
  observer.observe(document, {
    childList: true,
    subtree: true,
    attributes: false,
    characterData: false,
  });

Less efficiently, but shorter code, you can re-select the entire document after each mutation:

  var observer = new MutationObserver(function() {
    if (document.getElementById('my-table')) {
      console.log('table has appeared.');
    }
  });
  observer.observe(document, {
    childList: true,
    subtree: true,
    attributes: false,
    characterData: false,
  });

If you are using a simple ID selector, it might be efficient since selecting by id is highly optimized.

like image 148
Julian Avatar answered Feb 14 '23 00:02

Julian