2

  const ANIMATE_TIMEOUT = 3000 + 200;

    const button = document.getElementById("button");

    button.addEventListener("click", event => {
      if (!button.classList.contains("animate")) {
        button.classList.add("animate");
        setTimeout(() => {
          button.classList.remove("animate");
        }, ANIMATE_TIMEOUT);
      }
    });

I have tried querySelectorAll

const elementsList = document.querySelectorAll("#button, #button2");
 const elementsArray = [...elementsList];
  button.addEventListener("click", event => {
      if (!button.classList.contains("animate")) {
        button.classList.add("animate");
        setTimeout(() => {
          button.classList.remove("animate");
        }, ANIMATE_TIMEOUT);
      }

solution suggested here : Similar issue

and the other ones provided in the same page but ,in all of them the animation does not run at all but querySelectorAll one does not break the animation itself but only applies to the first item .Thanks in advance for your time ***Update after Zer00ne support,added: Original Document with HTML/CSS/JS

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="description" content="">
  <meta name="author" content="test sheet">
  <meta name="generator" content="test content">
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet"
    integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/js/bootstrap.bundle.min.js"
    integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" crossorigin="anonymous">
    </script>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  <link href="https://fonts.googleapis.com/css2?family=Amaranth:ital,wght@0,400;0,700;1,700&display=swap"
    rel="stylesheet">
  <title>test 2 buttons</title>
  <link rel="icon" type="image/x-icon" href="/images/favicon.ico">
  <link rel="canonical" href="https://www.google.com">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
</head>

<body data-bs-spy="scroll" data-bs-target=".navbar" data-bs-offset="50">
  <style>
    body {
      font-family: 'Amaranth', sans-serif;
      background: url(https://images.pexels.com/photos/531602/pexels-photo-531602.jpeg) no-repeat center center fixed;
      -webkit-background-size: cover;
      background-size: cover;
      overflow: auto;
      opacity: 99%;
      overflow-x: hidden;
      background-repeat: no-repeat;
      background-position: center;
      position: relative;

    }

    .z {
      margin-top: 60px;
      padding-top: 60px;
    }
    h1 {
      position: relative;
      text-align: center;
      color: #353535;
      font-size: 50px;
      font-family: "Cormorant Garamond", serif;
    }    
    .frame {
      width: 90%;
      margin: 40px auto;
      text-align: center;
    }    
    .copy-button {
      height: 25px;
      display: flex;
      justify-content: center;
      align-items: center;
      position: relative
    } 

    :root {
      /* Scale setup */
      --button-height: 27;
      /* in px */
      --height-to-scale: 33;
      /* in px */
      --scale-ratio: calc(var(--height-to-scale) / var(--button-height));

      /* Slide setup */
      --button-height-px: 27px;
      --button-vertical-padding-px: 6px;
      --button-content-spacing-px: calc(var(--button-height-px) + var(--button-vertical-padding-px) * 2);
      --slide-step-1: calc(var(--button-height-px) * -1);
      --slide-step-2: calc(var(--button-height-px) * -2);
    }

    .wrapper {
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      padding: 33px;
    }

    /* Button styles */

    .button {
      display: flex;
      justify-content: center;
      align-items: start;
      flex-wrap: nowrap;
      height: var(--button-height-px);
      padding: var(--button-vertical-padding-px) 9px;
      border-style: none;
      border-radius: 6px;
      background-color: #f3f6f9;
      color: #708ebc;
      font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
      font-size: 12.605px;
      line-height: 15px;
      cursor: pointer;
      transition: all 200ms;
    }

    .button:hover {
      background-color: #e4ebf2;
      color: #708ebc;
    }

    .button:focus {
      background-color: #e4ebf2;
      box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.7);
      outline: none;
    }

    .button:active {
      background-color: #10428f;
      color: #f3f6f9;
    }

    .copy {
      display: flex;
      align-items: center;
      justify-content: start;
    }

    .icon {
      margin-right: 6px;
    }

    /* Align content to animate */

    .button {
      overflow: hidden;
    }

    .copied {
      visibility: hidden;
      margin-top: var(--button-content-spacing-px);
    }

    /* Animations */

    .button.animate {
      background-color: #10428f;

      color: #b6c8eb;
      box-shadow: none;
      animation: scale 3s cubic-bezier(1, -0.5, 0, 1.5) forwards;
    }

    .animate .content {
      animation: slide 3s cubic-bezier(1, -0.5, 0, 1.5) forwards;
    }

    .animate .copied {
      visibility: visible;
    }

    @keyframes scale {
      0% {
        transform: none;
      }

      12.5% {
        transform: none;
      }

      25% {
        transform: scale(var(--scale-ratio));
      }

      37.5% {
        transform: scale(var(--scale-ratio));
      }

      50% {
        transform: none;
      }

      100% {
        transform: none;
      }
    }

    @keyframes slide {
      0% {
        transform: none;
      }

      12.5% {
        transform: translateY(var(--slide-step-1));
      }

      25% {
        transform: translateY(var(--slide-step-1));
      }

      37.5% {
        transform: translateY(var(--slide-step-2));
      }

      87.5% {
        transform: translateY(var(--slide-step-2));
      }

      100% {
        transform: none;
      }
    }
    body {
      position: relative;
    }

    @media (max-width: 767px) {}

    ::-webkit-scrollbar {
      display: none;
    }

    .dropdown-menu {
      max-height: 280px;
      overflow-y: auto;
    }
    @media (prefers-reduced-motion: no-preference) {
  :root {
    scroll-behavior: smooth;
  }

  </style>
  
  <div class="wrapper">
    <button onclick="copy('Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod')"
      class="button copy-button  " type="button" id="button" title="Copy link">
      <div class="content ">
        <div class="copy">           
          <div>
          Copy Link
          </div>
        </div>
        <div class="copied">Copied!</div>
      </div>
    </button>
  </div>
  
  <script>
    const ANIMATE_TIMEOUT = 3000 + 200;

    const button = document.getElementById("button");

    button.addEventListener("click", event => {
      if (!button.classList.contains("animate")) {
        button.classList.add("animate");
        setTimeout(() => {
          button.classList.remove("animate");
        }, ANIMATE_TIMEOUT);
      }
    });</script>



  <script>


    document.querySelectorAll('[data-bs-toggle="tooltip"]')
      .forEach(tooltip => {
        new bootstrap.Tooltip(tooltip)
      })
  </script>




  <script>
    function copy(text, target) {
      setTimeout(function () {
        $('#copied_tip').remove();
      }, 800);
      $(target).append("<div class='tip' id='copied_tip'>Copied!</div>");
      var input = document.createElement('input');
      input.setAttribute('value', text);
      document.body.appendChild(input);
      input.select();
      var result = document.execCommand('copy');
      document.body.removeChild(input)
      return result;

    }
  </script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"
    integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ=="
    crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  <script src="https://cdn.jsdelivr.net/npm/clipboard@2.0.10/dist/clipboard.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/svg.js/3.1.2/svg.min.js" integrity="sha512-I+rKw3hArzZIHzrkdELbKqrXfkSvw/h0lW/GgB8FThaBVz2e5ZUlSW8kY8v3q6wq37eybIwyufkEZxe4qSlGcg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>


</body>

</html>
Poly80
  • 23
  • 7
  • Please show what you did attempt with `querySelectorAll()` – mykaf Jul 19 '22 at 17:11
  • Sure ! From> const button = document.getElementById("button"); to> const elementsList = document.querySelectorAll("#button, #button2"); const elementsArray = [...elementsList]; – Poly80 Jul 19 '22 at 17:13
  • This worked on #button but not on #button2 – Poly80 Jul 19 '22 at 17:14
  • Please update your post to include this, as well as the relevant html. – mykaf Jul 19 '22 at 17:16
  • Ok I will try to add a short snippet , cannot share 1580 lines – Poly80 Jul 19 '22 at 17:19
  • I have added the relevant html snippet and added the attempt,thanks @user1599011 – Poly80 Jul 19 '22 at 17:26
  • What is `button` in your `querySelectorAll()` attempt? – mykaf Jul 19 '22 at 17:28
  • button is the ID of the first button.There is a class too called button – Poly80 Jul 19 '22 at 17:29
  • Right, but you're referencing a variable called `button`. What's that? And you're not using `elementsArray` either. – mykaf Jul 19 '22 at 17:30
  • Button is both a class name and an ID name in this HTML – Poly80 Jul 19 '22 at 17:34
  • Yes, as well as a variable you are referencing. In your `getElementById()` example, you set `const button = document.getElementById("button");`, but you don't set that variable in your `querySelectorAll()` example. Run your snippet. Notice the errors. – mykaf Jul 19 '22 at 17:36
  • Ok I will try – Poly80 Jul 19 '22 at 17:37
  • Do you have any suggestion on how to apply the const variable in the queryselector all? Anybody? – Poly80 Jul 19 '22 at 18:21
  • Why not iterate over `elementsArray` and add your event listener to each of those elements? – mykaf Jul 19 '22 at 18:29
  • I am a super noob on this, but will this possibly affect all elements of that type? In that case it could not be used in my case because there are are many other "buttons" in the HTML that have different properties and do not need any animation, they should not be affected by the script ,sorry for the bad explanation – Poly80 Jul 19 '22 at 18:36
  • How would it affect all buttons? It's only selecting `"#button, #button2"` – mykaf Jul 19 '22 at 18:38

1 Answers1

0

At the time I started writing this answer, the question had no HTML. I'd update this answer with the OP's added HTML, but the JavaScript barely matches the HTML, so it isn't critical. The HTML and JavaScript in this answer is generic so it shouldn't be very difficult to adapt to typical HTML layouts.

Details are commented in example

// Collect all <button>s into an array
const btns = [...document.querySelectorAll('button')];
// Bind click event to each <button>
btns.forEach(btn => btn.addEventListener("click", animate));
/*
Event handler passes Event Object as default
On click, toggle .increase/.decrease classes on the clicked <button>
*/
function animate(event) {
  this.classList.toggle('increase');
  this.classList.toggle('decrease');
}

// Added to stop animation from running when page is loaded 
document.addEventListener('DOMContentLoaded', function() {
  setTimeout(() => btns.forEach(btn => btn.classList.remove('x')), 1000);
});
  
    
  
@keyframes inc {
  0% {
    transform: scale(1);
  }
  100% {
    transform: scale(1.5);
  }
}

@keyframes dec {
  0% {
    transform: scale(1.5);
  }
  100% {
    transform: scale(1);
  }
}

button {
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 13px;
  padding: 3px 5px;
  cursor: pointer;
}

.decrease {
  animation: 0.5s linear forwards dec;
}

.increase {
  animation: 0.5s linear forwards inc;
}

.decrease::before {
  content: '➕';
}

.increase::before {
  content: '➖';
}

.x.x {
  animation: 9999999s forwards paused;
}
<menu>
  <button class='decrease x'></button>
  <button class='decrease x'></button>
  <button class='decrease x'></button>
  <button class='decrease x'></button>
  <button class='decrease x'></button>
  <button class='decrease x'></button>
</menu>
zer00ne
  • 41,936
  • 6
  • 41
  • 68
  • 1
    Thanks a lot in advance I am trying to figure out how to apply this but it seems exactly fixing the issue ,really thanks a lot Zer00ne – Poly80 Jul 19 '22 at 18:42
  • Stop using `event.target` unless you really know what you're doing. Use always `event.currentTarget` by finger-memory. `.target` is used in most cases when in need to do stuff using `.closest()` - or when in need to know exactly the Element that started the Event propagation - which might not be the expected ` – Roko C. Buljan Jul 19 '22 at 20:43
  • Also, no need to destructure using `[...document.querySelectorAll('button')];` querySelectorAll returns a NodeList, and a NodeList has a `.forEach()` method prototype by default. – Roko C. Buljan Jul 19 '22 at 20:47
  • Also, there's no need to toggle two expansion classes. Just use one default styles class and one expansion class. Toggle just the expansion one. – Roko C. Buljan Jul 19 '22 at 20:49
  • @Zer00ne I have added the full button HTML/CSS/JS there are now all dependencies ,thanks again, I am still trying but in my attempts animation fails but at least it run for short time then stop kinda at the half – Poly80 Jul 19 '22 at 20:50
  • It's good to use `type="button"` because by default a ` – Roko C. Buljan Jul 19 '22 at 20:50
  • Thanks @ Roko C. Buljan It is all new for me , I will get better with time , I do not have great skills at the moment ,sorry – Poly80 Jul 19 '22 at 21:31
  • @RokoC.Buljan Updated `e.target` to `this`. I know that the destructuring the NodeList isn't needed, I like how it looks like an iterable . Two classes are used because there's two different `animation`, and `@keyframes` – zer00ne Jul 20 '22 at 02:30
  • 2
    @RokoC.Buljan and zer00ne thanks a lot for the updates I am trying to apply the changes now,again thanks a lot ! – Poly80 Jul 20 '22 at 08:40