I want to fire a function when the innerHTML of a div
element changes.
Been testing with element.addEventListener('DOMCharacterDataModified', myFunction());
but it does not seem to work properly. It fires once when the page is loaded but never again after? See example code below.
Anyone have a solution to my task? Any help is greatly appreciated!
The task:
div
.myFunction()
.My current example code:
var element = document.getElementById('div');
element.addEventListener('DOMCharacterDataModified', myFunction());
function myFunction() {
console.log(element.innerHTML);
}
setTimeout(function(){
element.innerHTML = 'Hello World!';
}, 1000);
setTimeout(function(){
element.innerHTML = 'Hello Space!';
}, 2000);
The setTimeout
s visualize the data feeding from an external source.
If possible it needs to be JS only, but jQuery could be used if really needed.
Thanks in advance!
// wirrew
The Element property innerHTML gets or sets the HTML or XML markup contained within the element. Note: If a <div> , <span>, or <noembed> node has a child text node that includes the characters (&), (<), or (>), innerHTML returns these characters as the HTML entities "&", "<" and ">" respectively.
Thrown if an attempt was made to insert the HTML into a node whose parent is a Document . The innerHTML property can be used to examine the current HTML source of the page, including any changes that have been made since the page was initially loaded.
The "innerHTML is not a function" error occurs when we try to call the innerHTML property as a function. To solve the error, assign a value to the innerHTML property of the specific DOM element, e.g. element.innerHTML = 'example'.
Setting the value of innerHTML removes all of the element's descendants and replaces them with nodes constructed by parsing the HTML given in the string htmlString. An attempt was made to set the value of innerHTML using a string which is not properly-formed HTML. An attempt was made to insert the HTML into a node whose parent is a Document.
Use DOMSubtreeModified
event:
var element = document.getElementById('div');
element.addEventListener('DOMSubtreeModified', myFunction);
function myFunction(e) {
console.log(element.innerHTML);
}
setTimeout(function(){
element.innerHTML = 'Hello World!';
}, 1000);
setTimeout(function(){
element.innerHTML = 'Hello Space!';
}, 2000);
<div id="div"></div>
BTW, DOM mutation events were deprecated. Use MutationObserver:
window.addEventListener('load', function () {
var element = document.getElementById('div');
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
var observer = new MutationObserver(myFunction);
observer.observe(element, {
childList: true
});
function myFunction() {
console.log(element);
console.log(element.innerHTML);
}
setTimeout(function(){
element.innerHTML = 'Hello World!';
}, 1000);
setTimeout(function(){
element.innerHTML = 'Hello Space!';
}, 2000);
});
<div id="div">
Raw snippet on GitHub
NOTE: May not be the best of explanations, please add your knowledge to make it more clear.
If you are willing to use element attributes then there is a way to create custom elements and add Observers
as you please to the attributes. attributeChangedCallback
is where you can add your custom code for listener.
Custom Elements
is of the Web Components
with support on Chrome
, Opera
and Safari
. Here is the link which explains everything about them. https://developer.mozilla.org/en-US/docs/Web/Web_Components/Custom_Elements
There is a chance you can modify observers for your div
elements but I am not aware of such, you probably need to dig a little deeper should you choose to do it this way.
Since you are trying to listen to a single element's innerHTML, it might be better to just create a custom element like the one in the code snippet.
class ObservableDiv extends HTMLElement {
// Monitor the 'name' attribute for changes.
static get observedAttributes() {return ['name']; }
// Respond to attribute changes.
attributeChangedCallback(attr, oldValue, newValue) {
if (attr == 'name') {
this.textContent = `HELLO, ${newValue}`;
}
}
}
// Define the new element
customElements.define('observable-div', ObservableDiv);
setTimeout(() => { document.getElementById("change").setAttribute("name", "I CHANGED A LOTTTTTTTTTTT") }, 1000)
<observable-div id="change" name="BEFORE CHANGING"></observable-div>
PS :
This may not be a proper answer at all but I am posting this because this strategy served me better, than relying on the sub tree listeners which used to work sporadically but never consistently. The only down fall to this is that this does not have good browser support. There might be some good polyfills
available already.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With