I've got a 3rd-party script that loads a photo gallery on my page with the images coming from off-site.
My page starts as empty:
<div class="container-fluid" id="cincopa"> </div> The 3rd-party script then adds other stuff (like the frame of the photo gallery):
<div class="container-fluid" id="cincopa"> <div id="cp_widget_38cc1320-f4a4-407a-a80e-1747bd339b64"> </div> </div> Then finally the images load:
<div class="container-fluid" id="cincopa"> <div id="cp_widget_38cc1320-f4a4-407a-a80e-1747bd339b64"> <div class="galleria_images"> <div class="galleria_image">SomeImage</div> <div class="galleria_image">SomeImage</div> <div class="galleria_image">SomeImage</div> </div> </div> </div> I want to:
display a loading animation
set a
MutationObserveron$('#cincopa')when it detects that
$('.galleria_image')has been created, it means images have been loaded, so I canremove the loading animation
Code:
var target = document.querySelector('#cincopa'); // create an observer instance var observer = new MutationObserver(function(mutations) { console.log(mutations); mutations.forEach(function(mutation) { console.log(mutation.type); }); }); // configuration of the observer: var config = { attributes: true, childList: true, characterData: true }; // start the observer, pass in the target node, as well as the observer options observer.observe(target, config); The problem is that the MutationObserver only console logs one mutation and the MutationRecord only has one mutation in its array. I would expect numerous mutations as the 3rd-party script creates DOM elements.
Am I misunderstanding how MutationObserver works?
Here's the solution
// This is MeteorJS creating the loading spinning thing var loadingView = Blaze.render(Template.loading, $('#cincopa')[0]); // select the target node var target = document.querySelector('#cincopa'); // create an observer instance var observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if(mutation.target.className === "galleria_image"){ // a image has been loaded, so remove the loading spinner and // kill the observer Blaze.remove(loadingView); observer.disconnect(); } }); }); // configuration of the observer: var config = { attributes: true, childList: true, characterData: true, subtree: true }; // start the observer, pass in the target node, as well as the observer options observer.observe(target, config); Updated Solution
.forEach is dumb and doesn't have a good way to break out of the loop, which meant that I was getting multiple commands to Blaze.remove() and observer.disconnect(), even after .galleria_image had been found.
So I used underscore instead:
// create an observer instance var observer = new MutationObserver(function(mutations) { var loaded = _.find(mutations, function(mutation){ console.log("observer running"); return mutation.target.className === "galleria-image"; }); if(loaded){ Blaze.remove(loadingView); observer.disconnect(); console.log("observer stopped"); }; });