Search code examples
javascriptjqueryhtmldommutation-observers

Cannot get an img element that is dynamically added to a page


Let's say I am trying to run code bellow on 9gag to get images that are dynamically added form infinite scroll. I am trying to figure out how to get img element.

    //want to do something useful in this function
    checkIfImg = function(toCheck){
        if (toCheck.is('img')) {
            console.log("finaly");
        }
        else {
            backImg = toCheck.css('background-image');
            if (backImg != 'none'){
            console.log("background fynaly");
            }
        }
    }
    //that works just fine, since it is not for dynamic content
    //$('*').each(function(){ 
    //    checkIfImg($(this));
    //})

    //this is sums up all my attempts
        var observer = new MutationObserver(function (mutations) {
            mutations.forEach(function (mutation) {
                switch (mutation.type) {
                case 'childList':
                    Array.prototype.forEach.call(mutation.target.children, function (child) {
                         if ( child.tagName === "IMG" ) {
                             console.log("img");
                         }
                        child.addEventListener( 'load', checkIfImg, false );
                        console.log("forEachChild");
                        console.log(child);
                        checkIfImg($(child));
                        $(child).each(function(){ 
                            console.log("inside each");
                            console.log($(this));
                            if ($(this).tagName == "IMG"){
                                console.log("img");
                            }
                            checkIfImg($(this));
                        })
                    });

                    break;
                default:
                }
            });
        });
    observer.observe(document, {childList: true, subtree: true});

Observer gets lots of different elements but I can't seem to find any img among them.


Solution

  • You need to check for img elements deeper down the tree, not only the direct children of mutation.children (each of them may contain additional children).

    You could do this with a $.find('img'), and use an array to eliminate duplicates:

    let imageList = [];
    
    //want to do something useful in this function
    function checkIfImg(toCheck) {
      // find all images in changed node
      let images = toCheck.find('img');
      for(let image of images) {
        let imageSource = $(image).attr('src');
        if(!imageList.includes(imageSource)) {
          imageList.push(imageSource);
          console.log("image:", imageSource);
        }
      }
    };
    
    // get existing images
    checkIfImg($(document));
    
    // observe changes
    var observer = new MutationObserver(function(mutations) {
      mutations.forEach(mutation => checkIfImg($(mutation.target)));
    });
    observer.observe(document, { childList: true, subtree: true });