I have the following DOM Mutation Observer code:
<script type="text/javascript">
var targetNodes = $("#history");
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
var myObserver = new MutationObserver (mutationHandler);
var obsConfig = { childList: true, characterData: true, attributes: true, subtree: true };
//--- Add a target node to the observer. Can only add one node at a time.
targetNodes.each ( function () {
myObserver.observe (this, obsConfig);
} );
function mutationHandler (mutationRecords) {
console.info ("mutationHandler:");
mutationRecords.forEach ( function (mutation) {
$("span.badge").show();
} );
}
</script>
It is working fine when events changes are detected in #history id.
<p id="history"></p>
The problem is that i have some p.class inside #history as follows:
<p id="history">
<p class="mine"></p>
<p class="theirs"></p>
</p>
i need to detect the observer changes only in p class="theirs".
How is that possible only with child class, rather than observing DOM changes in #history id as a whole...
Introduction:
when you use the format:
$("#history").each ( function () {
myObserver.observe (this, obsConfig);
});
this is useless. $("#history") returns one element or nothing. To test if a value is returned you may use
$("#history").length
This value in your case is 1. Remember that cannot exist more than one element with the same id (refer to: # selector).
In the each loop you use the this keyword. The value of this keyword is "Node target" element required from observe function.
So, because you have only one history element it's completely useless to cycle con only one element (refer: each function). Use the value by itself.
This value can be searched also with:
var target = document.getElementsByClassName('theirs')[0];
or
target = document.querySelectorAll('.theirs')[0];
or
target = $('.theirs').get(0);
Of course, if you do not have such new element on which to observe you cannot use the observe function.
For details see MutationObserver
The best way is to test the return value of the selected element, for instance:
if ($('.theirs').length == 0) {
// raise error and stop
} else {
target = $('.theirs').get(0);
}
Instead, if you have more than one element you may continue to use the each loop:
$(".theirs").each ( function () {
myObserver.observe (this, obsConfig);
});
My proposal:
According to HTML Paragraph tag you cannot have nested paragraphs.
If you need to observe only what happens for your 'theirs' paragraph you need simply to change a bit your code:
$(function () {
var targetNodes = $(".theirs");
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
var myObserver = new MutationObserver(mutationHandler);
var obsConfig = {childList: true, characterData: true, attributes: true, subtree: true};
// get the target node on which to observe DOM mutations
var target = document.getElementsByClassName('theirs')[0];
// another way to get the target is
target = document.querySelectorAll('.theirs')[0];
// another way to get the target is
if ($('.theirs').length == 0) {
// raise error and stop
} else {
target = $('.theirs').get(0);
}
myObserver.observe(target, obsConfig);
function mutationHandler(mutationRecords) {
alert("mutationHandler:");
mutationRecords.forEach(function (mutation) {
$("span.badge").show();
});
}
$('#btn').on('click', function (e) {
$('.theirs').text('Date Now is: ' + Date.now());
});
});
<script src="https://code.jquery.com/jquery-1.12.1.min.js"></script>
<div id="history">
<p class="mine"></p>
<p class="theirs"></p>
</div>
<button id="btn">Add text to theirs</button>
If you are interested in changes happening only for paragraphs added or changed inside the div with class theirs, according to the MutationRecord in the following I report only a demo on how to filter the events for new such added nodes (remember to start and stop the observer):
var myObserver = null;
function mutationHandler(mutationRecords, mutationInstance) {
// new node added
if (mutationRecords.length == 1 && mutationRecords[0].addedNodes.length == 1) {
// if element added is a paragraph with class theirs....
var eleAdded = $(mutationRecords[0].addedNodes[0]);
if (eleAdded.is('p.theirs')) {
alert("mutationHandler: added new paragraph with class theirs: " + eleAdded.text());
}
}
// if you need to listen for other events like attribute changed or element removed... please read the documentation regarding mutationRecords object
}
$(function () {
$('#startObserver').on('click', function(e) {
var targetNodes = $('#history');
var target = null;
if (targetNodes.length != 1) {
alert('Cannot start Observer on no element!')
return;
} else {
target = targetNodes.get(0);
}
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
myObserver = new MutationObserver(mutationHandler);
var obsConfig = {childList: true, characterData: true, attributes: true, subtree: true};
myObserver.observe(target, obsConfig);
});
$('#stopObserver').on('click', function(e) {
if (myObserver === null) {
alert('Cannot stop an Observer never started!')
} else {
myObserver.disconnect();
myObserver = null;
}
});
$('#btnMine').on('click', function (e) {
var txt = $('#mineInput').val();
$('#history').prepend('<p class="mine">Added mine paragraph with text: ' + (txt.trim() ? txt : 'empty text!') + '</p>');
});
$('#btnTheirs').on('click', function (e) {
var txt = $('#theirsInput').val();
$('#history').append($('<p class="theirs">Added theirs paragraph with text: ' + (txt.trim() ? txt : 'empty text!') + '</p>'));
});
});
<script src="https://code.jquery.com/jquery-1.12.1.min.js"></script>
<div id="history">
</div>
Mine paragraphs text: <input id="mineInput" type="text"><br>
Theirs paragraphs text: <input id="theirsInput" type="text"><br>
<button id="btnMine">Add new Mine paragrapgh</button>
<button id="btnTheirs">Add new Theirs paragrapgh</button><br><br>
<button id="startObserver">Start Observer</button>
<button id="stopObserver">Stop Observer</button>
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