Search code examples
javascriptmutation-observers

Javascript MutationObserver: How to Highlight edited DOM element?


I am trying to detect when a value of an <li> changes and then add a class to the the li by adding a background color.

I have this switch:

mutationList.forEach((mutation) => {
  switch(mutation.type) {
    case 'childList':
    $(this).css('background-color','red');
      console.log('childlist edited');
      break;
    case 'attributes':
      console.log('attr edited')
      break;
  }
});

but the color is not adding to the background. I am however getting loads of console logs like so:

(66) childlist edited

(2) childlist edited

(14) childlist edited

(81) childlist edited

This is what I want to happen:

1) when the value of the li changes, run a function

2) That function will clear all css from all li's and then add background-red to the li that was just edited.

function onTimerElapsed() {
	var next = Math.floor(Math.random() * jQuery('#stuff ul li').length - 1);

	if (next === -1) {
		next = 0;

	}

	var nextLi = document.querySelectorAll('#stuff ul li')[next];

	var id = nextLi.attributes["id"].value;

	$('#' + id).text(Math.floor(Math.random() * 1150));
	
	var targetNode = document.querySelector("#stuff ul");
	var observerOptions = {
	  childList: true,
	  attributes: true,
	  subtree: true //Omit or set to false to observe only changes to the parent node.
	}

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

	function callback(mutationList, observer) {
  mutationList.forEach((mutation) => {
    switch(mutation.type) {
      case 'childList':
        console.log('childlist edited')
        break;
      case 'attributes':
        console.log('attr edited')
        break;
    }
  });
}

$(document).ready(function() {
setInterval(onTimerElapsed, 4000);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Detect Dom change</h1>
<div id="stuff">
	<ul>
		<li class="total" id="t1">1453</li>
		<li class="total" id="t2">523</li>
		<li class="total" id="t3">54643</li>
		<li class="total" id="t4">2324</li>
		<li class="total" id="t5">56476</li>
		<li class="total" id="t6">3434</li>
	</ul>
</div>


Solution

  • The MutationObserver callback takes a MutationRecord, which has a target property that refers to the element in question. Use target instead of this to refer to the element whose attributes or subtree changed:

    mutationList.forEach((mutation) => {
      switch(mutation.type) {
        case 'childList':
          mutation.target.style.backgroundColor = 'red';
          console.log('childlist edited');
          break;
        case 'attributes':
          console.log('attr edited')
          break;
      }
    });