Home > Software engineering >  Detect a change in span content with javascript
Detect a change in span content with javascript

Time:04-26

I've been trying to detect if a spans content has changed and if it has changed to get the value, I've made a code snippet below that will change the span content for testing yet for some reason I can't detect whether the content has changed. I think it's possibly a limitation of the "changed" jquery where you possibly have to declare the change it can expect for it to do anything.

Does anyone have any recommendations of a better way to execute this? Once I have the changed value in js I'll need to do js math on it to finish the solution.

$(document).ready(function() {

  // change contents of a span - testing purposes

  var delay = (function() {
    var timer = 0;
    return function(callback, ms) {
      clearTimeout(timer);
      timer = setTimeout(callback, ms);
    };
  })();

  delay(function() {
    document.getElementById('price').innerHTML = '$100.00';
  }, 5000);

  // detect a change to contents a span

  $(".price").change(function() {
    alert(this.value);
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

<span >$90.00</span>

CodePudding user response:

Many issues

  1. Spans do not have values
  2. you have a class, not an ID so the selector is .price in a jQuery statement or document.querySelector(".price") or document.querySelectorAll(".price") in DOM
  3. Only form elements like <input>, <textarea> and <select> elements have a change event
  4. What changes the span? Why can't you just add code to where you change the span?
  5. If not, then you need a mutation observer:

$(function() {

  // change contents of a span - testing purposes

  const delay = (() => { let timer = 0; return (callback, ms) => { clearTimeout(timer); timer = setTimeout(callback, ms); }; })();
  delay(() => { $('.price').html('$100.00'); }, 2000);

  // detect a change to contents a span

  const elementToObserve = $('.price')[0]; // get the DOM element
  
  const process = () => { // callback
    const text = elementToObserve.textContent ; // gets $100.00
    const amount =  text.trim().slice(1); // converts to 100
    console.log("changed to", amount)
  }
  

  // create a new instance of 'MutationObserver' named 'observer', 
  // passing it a callback function
  const observer = new MutationObserver(process);

  // call 'observe' on that MutationObserver instance, 
  // passing it the element to observe, and the options object
  observer.observe(elementToObserve, { childList: true });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

<span >$90.00</span>

Older version 'DOMSubtreeModified' - note it triggers twice!

$(function() {

  // change contents of a span - testing purposes

  const delay = (() => { let timer = 0; return (callback, ms) => { clearTimeout(timer); timer = setTimeout(callback, ms); }; })();
  delay(() => { $('.price').html('$100.00'); }, 2000);

  // detect a change to contents a span - deprecated but short

  $(".price").on("DOMSubtreeModified", function(e) {
    const amount =  $(this).text().trim().slice(1); // converts to 100
    console.log(new Date(),amount)
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

<span >$90.00</span>

CodePudding user response:

Use MutationObserver

$(document).ready(function() {
    var delay = (function() {
    var timer = 0;
    return function(callback, ms) {
        clearTimeout(timer);
        timer = setTimeout(callback, ms);
      };
    })();

    delay(function() {
      document.getElementById('price').innerHTML = '$100.00';
    }, 5000);

    // Select the target node.
    var target = document.querySelector('#price')

    // Create an observer instance.
    var observer = new MutationObserver(function(mutations) {
        console.log(target.innerText);   
    });

    // Pass in the target node, as well as the observer options.
    observer.observe(target, {
        attributes:    true,
        childList:     true,
        characterData: true
    });

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

<span id="price">$90.00</span>

CodePudding user response:

If you really need to run some code when the span content is changed you can try Mutation observer https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver#example

  • Related