Dust_In_The_Wind
Dust_In_The_Wind

Reputation: 3692

Animate.css shake effect not working every time

I'm making a Twitch Streamer application, that pulls some data using Twitch API, for a predetermined set of streamers.

I have three buttons to select all/online/offline channels, and I am looking to add the animated shake effect to all these buttons.

On my first attempt, I had a simple if/else check in place to make the shake work correctly - detect if the animated shake class already exists, if so, remove it, and then add it again. Else, just add it.

That didn't work. I found an answer here on SO that said it won't work that way because the addClass and removeClass occur so fast that the DOM doesn't have time to catch up.

I then used a queue with an anonymous function to add the class back after inducing a slight delay after the removeClass -

if ($(this).hasClass("animated shake")) {
            $(this).removeClass("animated shake").delay(50).queue(
                function() {
                    $(this).addClass("animated shake");
                });
            //$(this).addClass("animated shake");
        } else {
            $(this).addClass("animated shake");
        }

Now, the shake effect works like 90% of the time, but if you keep switching back and forth between online/offline channels, there will be cases in between where the shake doesn't work.

Here's the app on Codepen.

I'd appreciate any help as to why it doesn't work every single time.

Note - The shake effect is on the online/offline buttons only, for now.

Upvotes: 0

Views: 1445

Answers (2)

shramee
shramee

Reputation: 5099

This works everytime :-D

function shakeButton($button) {
    console.log('Shaking button')
    $button.removeClass("animated shake");
    setTimeout(
      function() {
        $button.addClass("animated shake");
      },
      25
    );
  }

  $('button').click(function() {
    shakeButton($(this));
  });
<!-- Never mind, Just some Dummy html... -->

<link href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.1/animate.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h4>Never mind this, Just some Dummy Results</h4>
<h3>Check out the JS instead</h3>
<button>Button 1</button>
<button>Button 2</button>
<button>Button 3</button>

I just used setTimeout instead .delay() And it worked a treat :-)

Good Job, Your code is nice and well documented :-D A Few things though...

  1. In your code... you repeat the same code at three places, Instead you can create a function with that code and call that function everywhere instead ;-) This will make debugging easier.
  2. The if statement you use is not necessary... Just remove animate and shake classes every time ( it won't throw any error ;-) ) and add them after some time again, this will make code simpler.

This code is implemented in this snippet... http://codepen.io/shramee/pen/EyZJjN

Upvotes: 2

antoni
antoni

Reputation: 5546

can you try something like this?

$('.btn').on('click', function()
{
    // Siblings will target other buttons but not the current one
    $(this).addClass('animated shake').siblings().removeClass('animated shake');
});

[EDIT] more relevent to your structure:

According to your example structure you can add a class to your buttons wrapper like .btnWrapper for convenience and do:

$('.btn').on('click', function()
{
    var clicked = $(this);
    clicked.addClass('animated shake').parents('.btnWrapper').siblings().find('.shake').removeClass('animated shake');
})

Upvotes: 1

Related Questions