Reputation: 3103
Hi,
I need to execute a javascript function once as soon as an element with a given class appears on the code (the element will be generated by another script).
This is my function:
play(sound);
the element would appear inside this:
<div id="canvas">
The element would look like this:
<span class="sound">sound name</span>
where "sound name" will determine the argument for play();
how can this be done with javascript?
Thank you.
Upvotes: 1
Views: 854
Reputation: 135812
You can use a You could use a MutationObserver as shown below.
The second argument to .observe()
, MutationObserverInit
, is important:
In the options, use childList: true
if the span
will only be added as a direct child. subTree: true
if it can be at any level down below #canvas
.
From the docs:
childList
: Set to true
if additions and removals of the target node's child elements (including text nodes) are to be observed.subtree
: Set to true
if mutations to target and target's descendants are to be observed.$("#go").click(function () {
$("#canvas").append($('<span class="sound">sound name</span>'));
});
function play(n) { alert('playing '+ n); }
var obs = new MutationObserver(function(mutations, observer) {
$.each(mutations, function (i, mutation) {
var addedNodes = $(mutation.addedNodes);
var selector = "span.sound"
var spanSounds = addedNodes.find(selector).addBack(selector); // finds either added alone or as tree
spanSounds.each(function () { // handles any number of added spans
play($(this).text());
});
});
});
obs.observe($("#canvas")[0], {childList: true, subtree: true});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="canvas"></div>
<button id="go">Add span to canvas</button>
The code is a little less compact, but it is definitely doable:
document.getElementById("go").addEventListener('click', function () {
var s = document.createElement('span');
s.innerText = 'sound name';
s.classList.add('sound')
document.getElementById('canvas').appendChild(s);
});
function play(n) { alert('playing '+ n); }
var obs = new MutationObserver(function(mutations, observer) {
for(var i=0; i<mutations.length; ++i) {
for(var j=0; j<mutations[i].addedNodes.length; ++j) {
var addedNode = mutations[i].addedNodes[j];
//NOTE: if the element was added as child of another element, you would have to traverse
// the addedNode to find it. I recommend the jQuery solution above if that's the case
if(addedNode.tagName == "SPAN" && addedNode.classList.contains("sound")) {
play(addedNode.innerText);
}
}
}
});
obs.observe(document.getElementById('canvas'), {childList: true, subtree: true});
<div id="canvas"></div>
<button id="go">Add span to canvas</button>
Upvotes: 2
Reputation: 2113
You need a listener to detect the DOM change, MutationObserver
// Select the node that will be observed for mutations
var targetNode = document.getElementById('some-id');
// Options for the observer (which mutations to observe)
var config = { attributes: true, childList: true };
// Callback function to execute when mutations are observed
var callback = function(mutationsList) {
for(var mutation of mutationsList) {
if (mutation.type == 'childList') {
console.log('A child node has been added or removed.');
}
else if (mutation.type == 'attributes') {
console.log('The ' + mutation.attributeName + ' attribute was modified.');
}
}
};
// Create an observer instance linked to the callback function
var observer = new MutationObserver(callback);
// Start observing the target node for configured mutations
observer.observe(targetNode, config);
// Later, you can stop observing
observer.disconnect();
Upvotes: 0