Search code examples
javascriptjquerydommutation-observers

Dynamically Insert Content After Mutation Observed


I have a dynamic product list. On page load, the list of products and data are populated by an API. When someone sorts or filters the products, the data is refreshed and repainted to the page. Some product containers may have updated data, while others do not (depending on how the user sorted)

I need to dynamically calculate the discount (money saved) whenever the filter/sort is applied.

I'm trying to do this via a mutationObserver, which observes any changes to the price of a product.

My observer works just fine, I am just struggling on how to insert the discount into the DOM tree when the observer detects a change. Again, some of the products will have updated data, while others don't.

My biggest struggle is how do I connect the mutation record to the DOM element so that I can make changes? For example, if products one and four data changed, how do I target only those DOM elements to insert/change my content?

<div class="mainContainer">
    <div class="product one">
        <div class="prodImg"></div>
        <div class="prodDesc"></div>
        <div class="origPrice"></div>
        <div class="prodPrice"></div>
        <div class="prodAddtoCart"></div>
    </div>
    <div class="product two">
        <div class="prodImg"></div>
        <div class="prodDesc"></div>
        <div class="origPrice"></div>
        <div class="prodPrice"></div>
        <div class="prodAddtoCart"></div>
    </div>
    <div class="product three">
        <div class="prodImg"></div>
        <div class="prodDesc"></div>
        <div class="origPrice"></div>
        <div class="prodPrice"></div>
        <div class="prodAddtoCart"></div>
    </div>
    <div class="product four">
        <div class="prodImg"></div>
        <div class="prodDesc"></div>
        <div class="origPrice"></div>
        <div class="prodPrice"></div>
        <div class="prodAddtoCart"></div>
    </div>
</div>


var targetNode = document.querySelector(".mainContainer");
var config = { attributes: true, childList: true, subtree: true, characterData:true };

var callback = (mutationList, observer) => {

for (const mutation of mutationList) {
  if (mutation.type === 'characterData') {
    if (mutation.target.parentElement.className === 'prodPrice') {
        //my psuedo code would look something like this
        $(this).closest('.product').find('.prodAddtoCart').after('<div class="discount">$xx.xx</div>')

     }
    }
}

};

var observer = new MutationObserver(callback);
observer.observe(targetNode, config);

Solution

  • $(this).closest('.product').find('.prodAddtoCart').after('<div class="discount">$xx.xx</div>')
    

    The function doesn't know what this is at that point, but you already have a reference to the object, mutation.target.parentElement:

    $(mutation.target.parentElement).closest('.product').find('.prodAddtoCart').after('<div class="discount">$xx.xx</div>')