I have a script where I´ve use on the first slide of Adobe Captivate, to automate the task ok creating, courses, the script create the UX, navigation elements, intro/end motions, a game, insert spritesheets with characters, etc...
I´ve used DOMNodeInserted until know to check the modifications on the slide, when the user go to the next slide, the elements are added to the DOM and the page content is changed I´ve used this timer until now to call the function:
function detectChange(){
var slideName = document.getElementById('div_Slide')
slideName.addEventListener("DOMNodeInserted", detectChange, false);
updateSlideElements();
setTimeout(updateSlideElements, 100);
}
So I´m trying to use mutation Observer now:
var observer = new MutationObserver(function(mutations, observer) {
updateSlideElements();
});
observer.observe(document.getElementById('div_Slide').firstChild, {
attributes: true,
childList:true
});
But this is what´s happening, before with setTimeout I could reach the following element:
var motionText2 = document.querySelectorAll('div[id*=motion][class=cp-accessibility]');
This element is the firstChild of:
And the element can be found:
But now with mutationObserver the console returns empty:
I´ve just use a setTimeout inside the observer and watch the parent container not the firstChild:
var observer = new MutationObserver(function(mutations, observer) {
setTimeout(updateSlideElements, 100);
});
observer.observe(document.getElementById('div_Slide'), {
attributes: true,
childList:true
//subtree:true
});
Related
I have an element that displays additional products. Looks like this:
<span class="load-products btn btn-default unveil-button">Další produkty</span>
I need to press this element when I reach the bottom window. Similar to infinity Scroll. I have a function that indicates window movement. I can't figure out a function that presses the span element.
https://446042.myshoptet.com/blahoprani/
document.getElementsByClassName('pagination-loader').click();
Solved
You can use the IntersectionObserver
Also, performance tip: avoid using classes for single elements like load-products
// options
const options = {
rootMargin: '0px',
threshold: 1.0
}
// define the observed object
const target = document.querySelector('.load-products');
// what to do when the object intersects the viewport
const callback = (entries) => {
// only listen to `intersection` events
if(entries[0].isIntersecting){
document.getElementsByClassName('load-products')[0].click()
}
}
const observer = new IntersectionObserver(callback, options);
observer.observe(target);
Is there a way to detect stylesheet changes ? MutationObserver only tracks inline css changes on the element.
html
<div class="exampleClass"></div>
js
let config = {
attributes: true,
// attributeFilter: ["style"],
};
let mutationCallback = function(mutationsList) {
mutationsList.forEach((mutation, i) => {
console.log(mutation);
});
};
let observer = new MutationObserver(mutationCallback);
observer.observe(document.querySelector('.exampleClass'), config);
If I modify the element throught js with
document.querySelector(‘exampleClass’).style.top = '10px'
or the webconsole inspector directly on the node, the mutation observer callback is called, but if the class (not the node itself) is modified in the webconsole inspector there is no callback
When I change an attribute value with the same value, looking at the inspector console, the DOM tree does not change, yet Mutation Observer triggers since I modified the attribute value, but for the actual same value.
Can someone explains how this works under the hood? I inserted a snippet to demonstrate my point.
/* OBSERVER */
var divToUpdate = document.querySelector('#update');
var config = {attributeFilter: ['data-update']};
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.target.dataset.update == 'true') {
console.log('Attribute value updated, but not really!', mutation);
}
});
});
observer.observe(divToUpdate, config);
/* BUTTON UPDATER */
document.querySelector('button').addEventListener('click', function() {
divToUpdate.setAttribute('data-update', true);
});
<div id="update" data-update="true">DIV WITH ATTRIBUTE</div>
<button type="button">UPDATE DIV ATTRIBUTE</button>
According to this history, MutationObserver was designed to work that way. Any call to setAttribute triggers a mutation, regardless of whether the value is being changed or set to the current value. https://github.com/whatwg/dom/issues/520#issuecomment-336574796
So I have these:
var containerId = 'anim1'
var animation = bodymovin.loadAnimation({
container: document.getElementById(containerId),
renderer: 'svg',
loop: false,
autoplay: false,
path: "https://assets10.lottiefiles.com/packages/lf20_rd4wrn81.json"
});
function playanim() {
animation.goToAndPlay(0);
}
$('div').on('click', function() {
containerId = $(this).attr('id');
$('#text').text(containerId + ' was just clicked');
playanim();
})
The global variable containerId is being updated on click events, however the updated value is not being passed to the same containerId within the variable animation. Not sure if it's a bodymovin specific issue- how can I get this to work?
In the line that begins var animation = ..., you are creating an object, setting its container property to document.getElementById(containerId) (using whatever value containerId has at that time, i.e. 'anim1') and then passing that object to bodymovin.loadAnimation (presumably as a configuration - I'm unfamiliar w/that library)
When the div is clicked, the value of containerId is being updated, but this is not changing the value of the container property in the config object you created earlier; that's still equal to anim1. And even if it did change, it might not make any difference unless bodymovin is monitoring that config object. It's quite possible that bodymovin.loadAnimation just checks the value of container when it's initialized, and then never checks it again.
It might achieve what you want if you rebuild the animation every time the div is clicked, e.g. something like this (you might want to stop the animation in the old div as well?)
var animation // just declare it for now, assign below
// The following function will load the animation to the specified container
function setAnimation (containerId) {
console.log ("Loading animation into " + containerId)
animation = bodymovin.loadAnimation({
container: document.getElementById(containerId),
renderer: 'svg',
loop: false,
autoplay: false,
path: "https://assets10.lottiefiles.com/packages/lf20_rd4wrn81.json"
});
}
// Load it in 'anim1' first
setAnimation ('anim1')
function playanim() {
animation.goToAndPlay(0);
}
$('div').on('click', function() {
var id = $(this).attr('id')
console.log(id + ' was just clicked');
$('#text').text(id + ' was just clicked');
setAnimation (id); // re-initialize the animation
animation.addEventListener('data_ready',playanim);
})
Without knowing more about bodymovin (sorry), I can't tell if this is a wildly inefficient way to do it. Maybe bodymovin has a more lightweight way of changing the container for an animation that's already loaded, in which case you could just do that in your click handler.
i have an empty list :
<ul id="select2-choices"></ul>
this list gets elements added to it using a ui ,so i get this :
<ul id="select2-choices">
<li>item1</li>
<li>item2</li>
</ul>
i want to fire an event , in order to call a function when that list get a new item :
$("#select2-choices").on("Thevent", function (e)){
self.SetDefaultTeam(e);
});
how to do that ?
You can use mutation observers as shown below. The code is commented. I created a button to mimic the addition of new items, but the mutation observer is the function that recognises that change in the DOM tree.
N.B. If you have access to the code that is adding the new li then it would be better to trigger your function from there.
Let me know if you were hoping for something else.
// Create a button to add options to mimic your functionality
$("#add-li").click(function() {
$("ul#select2-choices").append("<li>New</li>");
});
// Create mutation observer
var observer = new MutationObserver(function(mutations) {
// Something has changed in the #select2-choices
console.log("Change noticed in childList");
});
// Just look out for childList changes
var config = {
attributes: false,
childList: true,
characterData: false
};
// Select target
var target = document.querySelector('#select2-choices');
// Launch observer with above configuration
observer.observe(target, config);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="select2-choices">
</ul>
<button id="add-li">Add option</button>