I have a div with some elements. When the users selects a button the div is cleared and is populated dynamically with new content. I run slideToggle before clearing the div and after populating it. The first toggle that hides the div works fine. The second slideToggle doesn't run (the new div just loads without an animation).
Ive spent a couple hours on this trying different things (callback functions, .on, promises, placing the 2nd slideToggle function in different parts of the code, etc..). I finally got it to work by using setTimeout with a time of 1 millisecond. Even though its working I am more confused than ever and questioning everything in my life. Help me understand whats going on please.
Working code:
changeCat:function(catName){
domObject.$positionsDiv.slideToggle(function(){
domObject.$positionsDiv.html('');
let yourCategories = getSubFolders(catName+"/");
if(catName==='s'){
tSCat.drawCats(yourCategories);
} else if(catName==='g'){
tGCat.drawCats(yourCategories);
}
setTimeout(function (){
domObject.$positionsDiv.slideToggle(function(){
resizeCanvas()
});
}, 1)
});
},
Whats really confusing me is if I console log the height of the target div.
Non-working Code (no timeout, with console logs)
changeCat:function(catName){
domObject.$positionsDiv.slideToggle(function(){
console.log('height 1: ' + domObject.$positionsDiv.height())
domObject.$positionsDiv.html('');
console.log('height 2: ' + domObject.$positionsDiv.height())
let yourCategories = getSubFolders(catName+"/");
if(catName==='s'){
tSCat.drawCats(yourCategories);
} else if(catName==='g'){
tGCat.drawCats(yourCategories);
}
console.log('height 3: ' + domObject.$positionsDiv.height())
domObject.$positionsDiv.slideToggle(function(){
console.log('height 4: ' + domObject.$positionsDiv.height())
resizeCanvas()
});
});
console.log('height 5: ' + domObject.$positionsDiv.height())
},
Console log returned in this order with the following values:
height 5: 359.333
height 1: 2214
height 2: 0
height 3: 3744
height 4: 324
The "traditional" way is to put the "show" code inside the "hide" callback:
$("#d").slideToggle(function() {
$(this).html("a<br/>b<br/>c<br/>");
$(this).slideToggle()
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='d'>
1<br/>2<br/>3<br/>
</div>
What's happening when you call "show" after a 1ms timeout is the same as if you call "show" immediately.
.slideToggle()
uses .animate()
and every .animate()
call on the same DOM node gets queued. So what happens:
$("#d").slideToggle(function() {
$(this).html("a<br/>b<br/>c<br/>");
});
$(this).slideToggle()
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='d'>
1<br/>2<br/>3<br/>
</div>