Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

EKATERINA L
seal-mask
.a{fill-rule:evenodd;}techdegree
EKATERINA L
Front End Web Development Techdegree Student 12,563 Points

Shake effect with JavaScript only

I am trying to make input field shake upon form submission with the empty input. So far it only shakes only first time. Why is it like this and how can I make it shake each time I submit the form with empty input?

Here is my JS code for this step:

function emptyField(e){
   element.style.WebkitAnimation = "shake .5s";
   element.style.animation = "shake .5s";
}

form.addEventListener('submit', (e) => {
    e.preventDefault();
    const text = input.value;
    const li = createLI(text);
    if (input.value == ''){
    emptyField(e);
    console.log('pressed');
    } else {
        input.value = '';
        ul.appendChild(li);
        }
});

And html:

<form id="registrar">
        <input type="text" name="name" placeholder="Invite Someone">
        <button type="submit" name="submit" value="submit">Submit</button>
      </form>

3 Answers

Dane Parchment
MOD
Dane Parchment
Treehouse Moderator 11,075 Points

Ok the reason this is not working is actually relatively simple, but is something that even experienced users can miss.

You still have the css shake animation active on whatever element you want to shake. So you need to remove the animation once it finishes playing, and then add it back whenever necessary. I will walk you through a little example:

Assume that this is the HTML:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="./main.css">
    <title>3d Vector Kata</title>
</head>
<body>
    <form id="test-form">
        <input type="text" id="test-input">
        <button type="submit" id="submit-button">Submit</button>
    </form>
    <script src="./index.js"></script>
</body>
</html>

And this is our CSS:

/* Standard syntax */
@keyframes shake {
  10%, 90% {
    transform: translate3d(-1px, 0, 0);
  }

  20%, 80% {
    transform: translate3d(2px, 0, 0);
  }

  30%, 50%, 70% {
    transform: translate3d(-4px, 0, 0);
  }

  40%, 60% {
    transform: translate3d(4px, 0, 0);
  }
}

.apply-shake {
    animation: shake 0.82s cubic-bezier(.36,.07,.19,.97) both;
}

Now as you can see we have a form and a shaking css animation so in our javascript file let's gain access to the dom elements that will handle the animations, namely the shaking input and the button that makes it shake:

const input = document.querySelector("input#test-input");
const submit = document.querySelector("button#submit-button");

Now that we have those, let's work on actually creating the animation whenever the users submits an empty form:

const input = document.querySelector("input#test-input");
const submit = document.querySelector("button#submit-button");

submit.addEventListener("click", (e) => {
    e.preventDefault();
    if(input.value === "") {
        input.classList.add("apply-shake");
    }
});

This is rather simple, all we do is prevent the page from refreshing by default, and then we check if the input has an empy value. If it does then we access our input field, and add the .apply shake class to it in order to play the shake animation.

If you refresh the browser you will see your form shake when you click the button! However, as you noted before it will not shake when you add click the button again. This is because the animation class has already been applied to the element, so it cannot animate again, based on CSS animation rules!

So to fix this we simply have to remove the animation class once it finishes animating...but how? Well with the animationend event! So by implementing the following we will remove the animation class once the animation stops playing!

const input = document.querySelector("input#test-input");
const submit = document.querySelector("button#submit-button");

submit.addEventListener("click", (e) => {
    e.preventDefault();
    if(input.value === "") {
        input.classList.add("apply-shake");
    }
});

input.addEventListener("animationend", (e) => {
    input.classList.remove("apply-shake");
});

Now, whenever you click your button and the field is empty it will shake!

EKATERINA L
seal-mask
.a{fill-rule:evenodd;}techdegree
EKATERINA L
Front End Web Development Techdegree Student 12,563 Points

Dane, thanks a lot!!! It's working finally! I felt like I should remove this animation and apply it back but I could not find out how! And I loved animation you offered, it looks fantastic on my interface!

Dane Parchment
Dane Parchment
Treehouse Moderator 11,075 Points

No problem! I am just glad that I was able to help you out!

However, I did not come up with that shake animation and I think it would be disingenuous of me not to provide the actual author of it with their credit:

CSS Tricks Shaking Animation

CSS Tricks also has a collection of snippets for css/javascript and other web languages that you can check out as well!

EKATERINA L
seal-mask
.a{fill-rule:evenodd;}techdegree
EKATERINA L
Front End Web Development Techdegree Student 12,563 Points

Yeah I tried this one, so it gives the same if i set 1 (only first time button click it works) or unstopable shaking if i set infinite)

Dane Parchment
Dane Parchment
Treehouse Moderator 11,075 Points

This is not the reason for the their error, they just need to remove and then re-add the animation class back to their element! I detailed how to solve it in my answer.

Dane Parchment
Dane Parchment
Treehouse Moderator 11,075 Points

This is not the reason for their error, I detailed what the problem was in my answer below yours!