I'm creating a very simple gallery. It will live in Umbraco and I want to be able to read images from multiple folders and filter by folder. I have that part down, but I'm stuck on needing the images to appear one at a time with a slight delay between. The delay doesn't seem to work at all. Neither does setTimeout. They all just display at once. Any help would be appreciated.
$('body').on('click', '.filter-category', function(){
var filter = $(this).data('filter'),
dir = "../slides/" + filter;
$(this).toggleClass('filter-on');
if($(this).hasClass('filter-on')){
$.ajax({
url: dir,
timeout: 2000,
success: function(data) {
$(data).find("a:contains(" + fileextension + ")").each(function(i) {
var filename = this.href.replace(window.location.host, "").replace("http://", "");
var newImg = ("<div class='gallery-image' data-category='" + filter + "' ><img src='" + dir + filename + "'></div>");
$(newImg).delay(500).appendTo('.gallery').fadeIn(400);
});
updateSlides();
}
});
}else{
$('.gallery-image').each(function(){
var category = $(this).data('category');
if(category == filter){
$(this).remove();
}
});
updateSlides();
}
});
You can solve this problem in one line of code (as my example will show), but please read the whole answer to understand why your solution doesn't work.
This code:
$(data).find("a:contains(" + fileextension + ")").each(function(i) {
var filename = this.href.replace(window.location.host, "").replace("http://", "");
var newImg = ("<div class='gallery-image' data-category='" + filter + "' ><img src='" + dir + filename + "'></div>");
$(newImg).delay(500).appendTo('.gallery').fadeIn(400);
});
...just loops through the images and appends them all at once, and adds the same 500 ms delay to them. You will only get give or take a few milliseconds in between each since they are all being processed in a loop synchronously.
That will look like this (without the delay):
0ms // 1st image
3ms // 2nd image
5ms // 3rd image
...
Or this (with the delay):
500ms // 1st image
503ms // 2nd image
505ms // 3rd image
...
This is why they all appear to be happening at the same time, rather than staggering.
--
To achieve what you want (the staggering effect), you need to make sure each image completes its job before you start the delay for the next image. There are many ways to achieve this, but I will take a simple, pragmatic approach of just adding time.
New code:
var delay = 500;
$(data).find("a:contains(" + fileextension + ")").each(function(i) {
setTimeout(() => {
var filename = this.href.replace(window.location.host, "").replace("http://", "");
var newImg = ("<div class='gallery-image' data-category='" + filter + "' ><img src='" + dir + filename + "'></div>");
$(newImg).appendTo('.gallery').fadeIn(400);
}, delay);
delay += delay;
});
Every time an image is appended, you add the delay to itself. The next image will wait the extra delay amount, thus creating the illusion of a stagger.
So the new process will be as follows:
500ms // 1st image
1003ms // 2nd image
1505ms // 3rd image
...