4

I have several elements with class name "hidden" that basically sets display to none. I'm trying to create a function using jquery that when I click on a button every element with that class name should become visible one at a time and preferably with some animation.

I tried the following

$('btn1').click(function() {
    $('.hide').each(function(index) {
        $(this).toggle();
    });
});

This works but everything shows at the same time. Since I would like it one at a time I tried doing the following

$('btn1').click(function() {
    $('.hide').each(function(index) {
        setTimeOut(function() {
            $(this).toggle();
        },1500);
    });
});

This gives me an error an TypeError 'cannot read property Display.....' I'm guessing it is because I'm inside another function and the $(this) does not reference the element that I want. How can I pass the element to the SetTimeOut function?

Any help would be greatly appreciated

Thanks

CES

Carlos Sosa
  • 445
  • 1
  • 5
  • 19

2 Answers2

2

Use a temporary variable.

Here's a sample; I fixed a few other typos in the sample code.

$('.btn1').click(function() {
    $('.hide').each(function(index) {
        var e = $(this);
        e.css('--animation-order',"\""+index+"\"");
        e.addClass('show');
    });
});
.hide{
  opacity: 0;
}
.hide.show{
  animation-name: animateIn;
  animation-duration: 350ms;
  animation-delay: calc(var(--animation-order) * 200ms + 200ms);
  animation-fill-mode:both;
}
@keyframes animateIn {
  0% {
    opacity: 0;
  }
  
  100% {
    opacity: 1;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="btn1">start</button>

<div class="hide">a</div>
<div class="hide">b</div>
<div class="hide">c</div>
Charlie
  • 8,530
  • 2
  • 55
  • 53
  • Great thanks. It worked. Is it possible to add animation?? Or with display none/block is not possible to animate? – Carlos Sosa Feb 14 '20 at 01:01
  • @Charlie wouldn't `setTimeout` be troublesome if there are a lot of elements? Reference: https://stackoverflow.com/a/14863064/1169686 – Mihail Minkov Feb 14 '20 at 01:01
  • using setTimeout is risky because you lose track of the timer and if something else happens that hides the now-visible elements, that old timeout will suddenly pop into existence and show it again. I might suggest a custom css property: https://css-tricks.com/different-approaches-for-creating-a-staggered-animation/ – Charlie Feb 14 '20 at 01:36
  • I updated to use a fancy css animation with custom css property. It won't work in IE. – Charlie Feb 14 '20 at 01:49
1

This is basically how jQuery.animate() work. Since you affect all the elements in a row they execute the function at the same time.

What you need is basically animation completion callbacks. The only thing I'd be worried is that if there are a lot of elements this could take a while to execute.

You can check this thread on jQuery animation usage and also check animate()'s documentation.

What would ideally solve your problem would be to have an array with all the elements you want to affect and create a recursive function which executes animations for each of these elements until all elements have been animated.

Mihail Minkov
  • 2,463
  • 2
  • 24
  • 41