0

let count = 0;
let counter = document.querySelector("#number-el");
let btns = document.querySelectorAll(".btn");
let decreaseEl = document.querySelector(".decrease-el");
let increaseEl = document.querySelector(".increase-el");

btns.forEach(function(btn) {
  btn.addEventListener("click", function() {
    if (decreaseEl) {
      count--;
      console.log(count);
    } else if (increaseEl) {
      count++;
    } else {
      count = 0;
    }
    if (count < 0) {
      counter.style.color = "green";
    }
    if (count > 0) {
      counter.style.color = "red";
    }
    if (count === 0) {
      counter.style.color = "yellow";
    }
    counter.textContent = count;
  });
});
<div class="container">
  <div>
    <p id="counter-el">COUNTER
      <div id="number-el">0</div>
    </p>
    <button class="btn increase-el">INCREASE</button>
    <button class="btn reset-el">RESET</button>
    <button class="btn decrease-el">DECREASE</button>
  </div>
</div>

It's a program to perform a counter which increases, decreases, and reset the count from 0, but the output that I am getting is only increasing with a negative sign

i access classes inside if statement directly. is it possible to directly access classes without using event objects.

DarkBee
  • 16,592
  • 6
  • 46
  • 58
  • 1
    Please [edit] your post to include the actual output and the expected output. It's not clear – mousetail Dec 02 '22 at 06:39
  • 2
    `if (decreaseEl)` will always be true – Layhout Dec 02 '22 at 06:45
  • how can I access classes inside the if statement? – Rahul Peethambaran Dec 02 '22 at 06:46
  • @RahulPeethambaran Why do you need to access _classes_ in the `if` statement? Don’t you want to check _which element has been clicked_? This can be done with the [event argument](//developer.mozilla.org/en/docs/Web/API/EventTarget/addEventListener#The_event_listener_callback). See [this Q&A](/a/34896387/4642212) on how to implement event delegation. You need `if(event.target.closest(".decrease-el"))` and `if(event.target.closest(".increase-el"))`. – Sebastian Simon Dec 02 '22 at 06:48
  • so classes can not possibly identify which element has been clicked @SebastianSimon – Rahul Peethambaran Dec 02 '22 at 07:02
  • @RahulPeethambaran Classes _can_ be used to match specific elements, including those that have been clicked. Classes and event targets are two orthogonal concepts. You want to find the closest parent matching a specific class. It doesn’t sound like “access classes” fits this approach, but maybe you meant something different, which is why I asked what the purpose of “accessing classes” was. – Sebastian Simon Dec 02 '22 at 07:23
  • @SebastianSimon actually what is happening when we do if (event. target.closest(".decrease-el"). I don't understand – Rahul Peethambaran Dec 02 '22 at 09:44
  • @Rahul [`.closest`](//developer.mozilla.org/en/docs/Web/API/Element/closest) checks if `event.target` (the clicked element) matches the selector `".decrease-el"` (an element with the `decrease-el` class). If it does, it returns it; otherwise it looks for the closest ascendant (parents and parents’ parents, until it reaches the document root) that matches the selector and returns that; if no element is found, it returns `null`. So `if(`…`)` receives either an Element ([truthy](//developer.mozilla.org/en/docs/Glossary/Truthy)) or `null` ([falsy](//developer.mozilla.org/en/docs/Glossary/Falsy)). – Sebastian Simon Dec 02 '22 at 09:55
  • `.closest` is better than [`.matches`](//developer.mozilla.org/en/docs/Web/API/Element/matches) because it also works if you happen to click on an inner element, e.g. the icon in ``. `addEventListener("click", ({ target }) => { const myButton = target.closest(".myButton"); if(myButton){ console.log(myButton, "was clicked") } });`. – Sebastian Simon Dec 02 '22 at 09:59

2 Answers2

0

Change

btn.addEventListener("click", function () {
    if (decreaseEl) { ... }

into

btn.addEventListener("click", function (ev) {
    if (ev.target.closest(".btn") == decreaseEl) { ... }

as otherwise the if will always be fulfilled (true). ev.target.closest(".btn") == decreaseEl will check, whether you have clicked on the decreaseEl DOM element or on any of its children.

Carsten Massmann
  • 26,510
  • 2
  • 22
  • 43
  • 1
    It should either be `if(ev.target.closest(".decrease-el"))` or `if(decreaseEl.contains(ev.target))` in case clicking an _inner_ element inside `decreaseEl` should be accepted as well. – Sebastian Simon Dec 02 '22 at 06:50
  • yep - changed it accordingly! – Carsten Massmann Dec 02 '22 at 06:51
  • The intention of `if(ev.target.closest(".decrease-el"))` is to check whether the clicked element is anywhere inside an element that matches the `".decrease-el"` selector, or is such an element itself. `closest` returns `null` if such an element cannot be found, which causes the `if` statement to be skipped. The output of `closest` shouldn’t be compared to anything; only the existence of the element should be checked. – Sebastian Simon Dec 02 '22 at 06:58
  • @SebastianSimon, I agree that my statement can be shortened in the way you described. However, my condition `ev.target.closest(".btn")==decreaseEl` will also return true if the clicked element happens to be a child element of the button that is referenced by the variable `decreaseEl`. – Carsten Massmann Dec 02 '22 at 07:27
0

Added values in button and used switch/case

let count = 0;
let counter = document.querySelector("#number-el");
let btns = document.querySelectorAll(".btn");
let decreaseEl = document.querySelector(".decrease-el");
let increaseEl = document.querySelector(".increase-el");

btns.forEach(function(btn) {
  btn.addEventListener("click", function(e) {
    switch (e.target.value) {
      case "INCREASE":
        count++;
        break;
      case "DECREASE":
        count--;
        break;
      case "RESET":
        count = 0;
        break;
      default:
        break;
    }
    if (count < 0) {
      counter.style.color = "green";
    }
    if (count > 0) {
      counter.style.color = "red";
    }
    if (count === 0) {
      counter.style.color = "yellow";
    }
    counter.textContent = count;
  });
});
<div class="container">
  <div>
    <p id="counter-el">COUNTER
      <div id="number-el">0</div>
    </p>
    <button class="btn increase-el" value="INCREASE">INCREASE</button>
    <button class="btn reset-el" value="RESET">RESET</button>
    <button class="btn decrease-el" value="DECREASE">DECREASE</button>
  </div>
</div>
Jay
  • 2,826
  • 2
  • 13
  • 28