css animation does not get triggered a second time

Viewed 45

I have a problem, which is for sure simple to solve, except for me. Let me explain, the snippet below shows a dialogue-box. I added an interaction feedback. If the input field is empty and a user tries to access the cross, the field blinks red.

In case the input field is set, the cross can be clicked which displays options. If this are clicked too the input field blinks green. The problem: Unfortunately it works just once, even than I try to remove those CSS classes afterwards. Further if green appeared once and the input field is empty again, I can´t trigger the red blinking again.

My thoughts are, that JavaScript can´t remove and add CSS classes during the same time action. Or the animation will not start over again. I am not sure. I would be glad if somebody can enlighten me.

var dialogSettingToggle = document.getElementById("dialog-setting-toggle")
var dialogSettingInput = document.getElementById("dialog-setting-input")

dialogSettingToggle.addEventListener("click", function() {
  if (isEmpty(dialogSettingInput.value)) {
    dialogSettingInput.classList.toggle("dialog-input-alert")
  } else {
    dialogSettingToggle.classList.toggle("open")

    var dialogSettingContext = document.getElementById("dialog-setting-button-context")

    dialogSettingContext.addEventListener("click", function() {
      dialogSettingInput.classList.remove("dialog-input-alert")
      dialogSettingInput.classList.add("dialog-input-confirm")
      dialogSettingInput.value = ""
      dialogSettingToggle.classList.remove("open")
    })

    var dialogSettingLink = document.getElementById("dialog-setting-button-link")

    dialogSettingLink.addEventListener("click", function() {
      dialogSettingInput.classList.remove("dialog-input-alert")
      dialogSettingInput.classList.add("dialog-input-confirm")
      dialogSettingInput.value = ""
      dialogSettingToggle.classList.remove("open")
    })

    var dialogSettingObject = document.getElementById("dialog-setting-button-object")

    dialogSettingObject.addEventListener("click", function() {
      dialogSettingInput.classList.remove("dialog-input-alert")
      dialogSettingInput.classList.add("dialog-input-confirm")
      dialogSettingInput.value = ""
      dialogSettingToggle.classList.remove("open")
    })
  }
})

function isEmpty(str) {
  return !str.trim().length
}
body {
  height: 100%;
  background: #e6e7ee;
}

section {
  word-wrap: break-word;
  word-break: normal;
  width: 95%;
  max-width: 350px;
  margin: 40px auto;
  border-radius: 10px;
}

hr {
  color: white;
  height: 0px;
  cursor: default;
}

h5 {
  margin: 10px;
  font-size: 1.2em;
  font-weight: normal;
  color: #7b7e8c;
  cursor: default;
}

button {
  box-shadow: 6px 6px 10px rgba(0, 0, 0, 0.1), -6px -6px 10px white;
  background: #f2f3f7;
  cursor: pointer;
  border: 0;
  padding: 10px;
  margin: 7px;
  margin-top: 10px;
  width: 150px;
  font-size: 1rem;
  transition-property: background-color, box-shadow;
  transition-duration: .2s;
  color: #7b7e8c;
}

select {
  appearance: none;
  width: 270px;
  background: url(data:image/png;base64,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);
  background-repeat: no-repeat;
  background-position: right;
  background-size: 1.8em;
  border-radius: 10px;
  padding: 10px;
  margin: 7px;
  font-size: 1rem;
  color: #7b7e8c;
  border: 0;
  cursor: pointer;
  box-shadow: 0 0 transparent, 0 0 transparent, inset 3px 3px 5px rgba(0, 0, 0, 0.1), inset -3px -3px 5px white;
}

input {
  width: 270px;
  background: #f8f9fb;
  border-radius: 10px;
  padding: 10px;
  margin: 7px;
  font-size: 1rem;
  color: #7b7e8c;
  border: 0;
  cursor: text;
  box-shadow: 0 0 transparent, 0 0 transparent, inset 3px 3px 5px rgba(0, 0, 0, 0.1), inset -3px -3px 5px white;
}

button:hover,
select:hover,
input:hover {
  color: #3498db;
}

button:active {
  box-shadow: 0 0 transparent, 0 0 transparent, inset 3px 3px 5px rgba(0, 0, 0, 0.1), inset -3px -3px 5px white;
}

.border-round {
  border-radius: 10px;
}

.dialog {
  position: absolute;
  left: 0;
  right: 0;
  padding: 10px 20px 20px;
  margin-top: 20px;
  width: 340px;
  min-height: 100px;
  font-size: 1.2em;
  background: #f2f3f7;
}

.box-shadow {
  box-shadow: 6px 6px 10px rgba(0, 0, 0, 0.1), -6px -6px 10px white;
}

.dialog-setting-button-delete {
  position: relative;
  margin-top: 7px;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  background: #ecf0f3;
  cursor: pointer;
  box-shadow: 6px 6px 10px rgba(0, 0, 0, 0.1), -6px -6px 10px white;
}

.dialog-setting-close {
  position: absolute;
  width: 25px;
  height: 25px;
  padding: 0px;
  margin: 0px;
  left: 350px;
  top: 5px;
  border-radius: 10px;
  background: #ecf0f3;
  cursor: pointer;
  box-shadow: none;
}

.dialog-input-alert {
  animation: input-alert 1.5s;
}

@keyframes input-alert {
  from {
    background: red;
    color: white
  }
  to {
    background: #f8f9fb;
    color: #7b7e8c;
  }
}

.dialog-input-confirm {
  animation: input-confirm 1.5s;
}

@keyframes input-confirm {
  from {
    background: greenyellow;
    color: white
  }
  to {
    background: #f8f9fb;
    color: #7b7e8c;
  }
}


/****************************************
******** dialog-setting-toggle ***********
****************************************/

.dialog-setting-toggle {
  position: relative;
  margin-top: 7px;
  margin-right: 7px;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  background: #ecf0f3;
  cursor: pointer;
  box-shadow: 6px 6px 10px rgba(0, 0, 0, 0.1), -6px -6px 10px white;
}

.dialog-setting-toggle::before,
.dialog-setting-toggle::after {
  content: "";
  background: #7b7e8c;
  border-radius: 5px;
  width: 20px;
  height: 5px;
  position: absolute;
  left: 10px;
  top: 18px;
  transition: 0.2s ease;
  z-index: 1;
}

.dialog-setting-toggle::before {
  transform: rotate(0deg);
}

.dialog-setting-toggle::after {
  transform: rotate(-90deg);
}

.dialog-setting-toggle:hover::before {
  transform: rotate(0deg);
  background-color: #3498db;
}

.dialog-setting-toggle:hover::after {
  transform: rotate(-90deg);
  background-color: #3498db;
}

.dialog-setting-toggle.open::before {
  transform: rotate(45deg);
  background-color: #3498db;
}

.dialog-setting-toggle.open::after {
  transform: rotate(-45deg);
  background-color: #3498db;
}

.dialog-setting-toggle.open .dialog-setting-button {
  opacity: 1;
  pointer-events: auto;
}

.dialog-setting-toggle.open .dialog-setting-button:first-of-type {
  right: -50px;
  justify-content: center;
  align-items: center;
}

.dialog-setting-toggle.open .dialog-setting-button:nth-of-type(2) {
  right: -100px;
  justify-content: center;
  align-items: center;
  transition-delay: 0.05s;
}

.dialog-setting-toggle.open .dialog-setting-button:last-of-type {
  right: -150px;
  justify-content: center;
  align-items: center;
  transition-delay: 0.1s;
}

.dialog-setting-button {
  width: 40px;
  height: 40px;
  border-radius: 10px;
  cursor: pointer;
  background: #ecf0f3;
  position: absolute;
  color: #7b7e8c;
  display: flex;
  opacity: 0;
  pointer-events: none;
  box-shadow: inherit;
}

.dialog-setting-button:hover {
  transform: scale(1.2);
  color: #3498db;
}
<script src="https://kit.fontawesome.com/39094309d6.js" crossorigin="anonymous"></script>
<section id="dialog-setting" class="dialog box-shadow">
  <div>
    <h5 style="text-align:center">Options</h5>
    <button style="float: right" id="dialog-setting-close" class="dialog-setting-close border-round"><i class="fas fa-times"></i></button>
  </div>

  <hr class="border-round">

  <input style="float: left" id="dialog-setting-input" type="search" placeholder="context / link / object" class="item dialog-setting-input"></input>
  <div style="float: right" id="dialog-setting-toggle" class="dialog-setting-toggle">
    <div title="Kontext" id="dialog-setting-button-context" class="dialog-setting-button"><i class="fab fa-uncharted"></i></div>
    <div title="Link" id="dialog-setting-button-link" class="dialog-setting-button"><i class="fas fa-link"></i></div>
    <div title="Objekt" id="dialog-setting-button-object" class="dialog-setting-button"><i class="fas fa-server"></i></div>
  </div>
</section>

1 Answers

It isn´t the best solution but it is one solution. I added a timeout with the same duration as the animation goes. Works fine for my needs.

dialogSettingToggle.addEventListener("click", function () {
        if (isEmpty(dialogSettingInput.value)) {
            dialogSettingInput.classList.add("dialog-input-alert")
            setTimeout(function() {
                dialogSettingInput.classList.remove("dialog-input-alert")
            }, 1000)
        } else {
            dialogSettingToggle.classList.toggle("open")

            var dialogSettingContext = document.getElementById("dialog-setting-button-context")

            dialogSettingContext.addEventListener("click", function() {
                resetInput()
            })

            var dialogSettingLink = document.getElementById("dialog-setting-button-link")

            dialogSettingLink.addEventListener("click", function() {
                resetInput()
            })

            var dialogSettingObject = document.getElementById("dialog-setting-button-object")

            dialogSettingObject.addEventListener("click", function() {
                resetInput()
            })
        }
    })

    function resetInput() {
        dialogSettingInput.classList.add("dialog-input-confirm")
        setTimeout(function() {
            dialogSettingInput.classList.remove("dialog-input-confirm")
        }, 1000)
        dialogSettingInput.value=""
        dialogSettingToggle.classList.remove("open")
    }
Related