Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

addEventListener multiple use

I am making an application according to the youtube tutorial. I already know what the correct solution looks like, but I don’t know why such a code does not work. It is only executed once. I check ‘Inspector’ in the browser and there it shows that the second div got active class, but the second click doesn’t work.

document.querySelector('.emoji').addEventListener('click', function() {
  document.querySelector('.open').classList.toggle('active');
  document.querySelector('.closed').classList.toggle('active');
});
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.emoji {
  text-align: center;
  font-size: 20rem;
  cursor: pointer;
  display: none;
}

body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 100vh;
}

.active {
  display: block;
}
<!-- emoji no evil 🙈
        emoji monkey 🐵 -->

<div class="emoji open active">🙉</div>
<div class="emoji closed">🙈</div>

And now why this solution doesn’t work?

I think that i have 2 elements with ’emoji’ class so this should work. Today I tried create calculator app and has same problem . Only first button works when i clicked on it. I know that correct solution is :

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

    document.querySelector('.open').addEventListener('click', function () {
      document.querySelector('.open').classList.toggle('active');
      document.querySelector('.closed').classList.toggle('active');
    });
    
    document.querySelector('.closed').addEventListener('click', function () {
      document.querySelector('.closed').classList.toggle('active');
      document.querySelector('.open').classList.toggle('active');
    });

But i dont understand why first solution is wrong. Please could you explain.

>Solution :

document.querySelector returns only one element, which is the first element matching the selector.

One way you could target that problem is to wrap both elements, into one container and listen for the click on that element:

document.querySelector('.emoji-toggle').addEventListener('click', function() {
  document.querySelector('.open').classList.toggle('active');
  document.querySelector('.closed').classList.toggle('active');
});
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.emoji {
  text-align: center;
  font-size: 20rem;
  cursor: pointer;
  display: none;
}

body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 100vh;
}

.active {
  display: block;
}
<div class="emoji-toggle">
<div class="emoji open active">🙉</div>
<div class="emoji closed">🙈</div>
</div>

Or to use event delegation:

document.addEventListener('click', function(e) {
  if (e.target.matches('.emoji')) {
    document.querySelector('.open').classList.toggle('active');
    document.querySelector('.closed').classList.toggle('active');
  }
});
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.emoji {
  text-align: center;
  font-size: 20rem;
  cursor: pointer;
  display: none;
}

body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 100vh;
}

.active {
  display: block;
}
<div class="emoji open active">🙉</div>
<div class="emoji closed">🙈</div>

If it is something like a checkbox you probably want to use the first approach.

Depending on what you want to do you don’t even need JavaScript for that:

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.emoji {
  text-align: center;
  font-size: 20rem;
  cursor: pointer;
  display: none;
}

#mycheckbox:checked + label .open {
   display: block;
}

#mycheckbox:not(:checked) + label .closed {
   display: block;
}

#mycheckbox {
   display: none;
}


body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 100vh;
}
<input type="checkbox" id="mycheckbox">
<label for="mycheckbox">
  <div class="emoji open">🙉</div>
  <div class="emoji closed">🙈</div>
</label>
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading