Search code examples
javascriptrepeatrepeaterobservers

How to use an Observer() function instead of a loop


I am requesting help as no matter how many tutorials I watch, I cannot seem to figure out how use the Observer() function to get it to replace a link with another only if that link appears. Am I misunderstanding the Observer() function?

This is my current code:

    function loop(){
        
var images = document.querySelectorAll('img[src^="https://media.app.net/attachments"]');

images.forEach(function(image) {
  image.src = image.src.replace('https://media.app.net/attachments', 'https://cdn.app.com/attachments');
});

    setTimeout(loop, 1000);
}

I was told that I could make my code a lot less resource hungry by using an Observer() function and I would really like to achieve this, but obviously I can't. I want to learn.


Solution

  • You can use MutationObserver to listen for new elements being added. To improve performance, do not observe the entire document; instead, choose the closest static ancestor that will contain all the dynamically added <img> elements.

    Example:

    const observer = new MutationObserver(mutations => {
      for (const { addedNodes } of mutations)
        for (const node of addedNodes) {
          if (node?.matches?.('img[src^="https://media.app.net/attachments"]')) {
            console.log('original src', node.src);
            node.src = node.src.replace('https://media.app.net/attachments', 'https://cdn.app.com/attachments');
            console.log('updated src:', node.src);
          }
        }
    });
    observer.observe(document, { subtree: true, childList: true });
    
    document.querySelector('button').addEventListener('click', function(e) {
      const img = document.createElement('img');
      img.src = 'https://media.app.net/attachments/' + Math.random();
      document.body.append(img);
    });
    <button>Add img</button>