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

Why does this work but not this?

I don't understand why the chunk of code on top works fine but the code on the bottom doesn't? The code on bottom works for the first "book" only when I click img but it won't work when I click again to reverse the effect. The second book doesn't work at all. If you need all the code to run it let me know.

const card = document.querySelector('#books-wrap');
const recImgs = document.querySelector('.recBookPic');
var flip;
var recFlip;
//working
card.addEventListener('click', () => {
  if (flip === false) {
    document.querySelector('.bookTitle').style.display = '';
    document.querySelector('.images').style.display = '';
    document.querySelector('.author').style.display = '';
    document.querySelector('.bookDesc').style.opacity = 0;
    flip = true;
  } else {
    document.querySelector('.bookTitle').style.display = 'none';
    document.querySelector('.images').style.display = 'none';
    document.querySelector('.author').style.display = 'none';
    document.querySelector('.bookDesc').style.opacity = 1;
    flip = false;
  }
});
//not working?
  recImgs.addEventListener('click', () => {
  if (recFlip === false) {
    console.log("start");
    document.querySelector('.recBookTitle').style.display = '';
    document.querySelector('.recBookPic').style.display = '';
    document.querySelector('.recAuthor').style.display = '';
    document.querySelector('.recBookDesc').style.opacity = 0;
    recFlip = true;
  } else {
    document.querySelector('.recBookTitle').style.display = 'none';
    document.querySelector('.recBookPic').style.display = 'none';
    document.querySelector('.recAuthor').style.display = 'none';
    document.querySelector('.recBookDesc').style.opacity = 1;
    recFlip = false;
  }
});

1 Answer

Steven Parker
Steven Parker
243,658 Points

Without seeing the HTML, this is mostly a guess. But the most obvious difference between these chunks is that they appear to be handlers that are attached to different elements.

Both bits of code rely on "querySelector", which by design only returns the first item that matches the selector. So I would expect either one of these to only work on the first item.

A more detailed analysis would require seeing the rest of the code, particularly the HTML. A good way to share large or multi-module code is to make a snapshot of your workspace and post the link to it here.

I got it to where it works fine on the first book, but the second book when I click on it it works but it works for the first book. EX: When I click first book it shows description. When I click second book it shows description but for the first book. I gave you the edited javascript and html. I don't think the html is the problem though. Sorry i couldn't do snapshot. It's in atom and everything is linked to multiple files and it would be a nightmare to get the full thing on here.

const card = document.querySelector('#books-wrap');
const recCard = document.querySelector('#recBooks-wrap');
const checkBox = document.createElement('input');
var flip;
//working
card.addEventListener('click', () => {
  if (flip === false) {
    document.querySelector('.bookTitle').style.display = '';
    document.querySelector('.bookPic').style.display = '';
    document.querySelector('.author').style.display = '';
    document.querySelector('.bookDesc').style.opacity = 0;
    flip = true;
  } else {
    document.querySelector('.bookTitle').style.display = 'none';
    document.querySelector('.bookPic').style.display = 'none';
    document.querySelector('.author').style.display = 'none';
    document.querySelector('.bookDesc').style.opacity = 1;
    flip = false;
  }
});
window.addEventListener('dblclick', () => {
checkBox.type = 'checkbox';
card.appendChild(checkBox);
checkBox.classList.add('checkBox');
});
//not working?
  var recFlip = true;
    recCard.addEventListener('click', () => {
      while (true) {
        if (recFlip === false) {
        console.log("start");
        document.getElementById('recBookTitle').style.display = '';
        document.getElementById('recBookPic').style.display = '';
        document.getElementById('recAuthor').style.display = '';
        document.getElementById('recBookDesc').style.opacity = 0;
        recFlip = true;
        break;
      } else {
        document.getElementById('recBookTitle').style.display = 'none';
        document.getElementById('recBookPic').style.display = 'none';
        document.getElementById('recAuthor').style.display = 'none';
        document.getElementById('recBookDesc').style.opacity = 1;
        recFlip = false;
        break;
      }
    }
  });
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>library</title>
  <link rel="stylesheet" type="text/css" title="Cool stylesheet" href="library.css">

  <h2 class="searchTitle" id="searchTitle">Book Search</h2>
  <input class="bookSearch" type="text" id="bookSearch"></input>
</head>

<body>
  <div id="root">
    <div class="topBack">
    </div>
    <div class="bottomBack">
    </div>
    <div class="navBack">
    </div>
    <div class="searchBack">
    </div>
    <div id="dialogoverlay"></div>
<div id="dialogbox">
  <div>
    <div id="dialogboxhead"></div>
    <div id="dialogboxbody"></div>
    <div id="dialogboxfoot"></div>
  </div>
</div>
    <div class="navBar">
      <a href="site.html"><button class="home"><img class="homeIcon" src="http://icons.iconarchive.com/icons/alecive/flatwoken/512/Apps-Home-icon.png"></button></a>
      <a href="clock/clock.html"><button class="time"><img class="homeIcon" src="http://icons.iconarchive.com/icons/graphicloads/100-flat/256/clock-icon.png"></button></a>
      <a href="game.html"><button class="drum"><img class="drumIcon" src="http://icons.iconarchive.com/icons/iconsmind/outline/512/Drum-icon.png"></button></a>
    </div>
    <hr class="line" width="2" size="900">
    <hr class="navLine" width="2" size="900">
    <hr class="searchLine" width="2" size="900">
    <h1 class "rec">New Arrivals</h1>
    <button class="searchButton" id="searchButton">Search</button>
    <div id="books-wrap"></div>
    <div id="recBooks-wrap"></div>
  </div>
  <script src="library.js"></script>
  <script src="libraryBooks.js"></script>
  <script src="libraryInteract.js"></script>
</body>

</html>
Steven Parker
Steven Parker
243,658 Points

I don't see any elements with the ID's that the "getElementById" calls look for. But ID's are required to be unique, so this code will only work on one specific element.

And now that I see the HTML, it looks like these event handlers are being attached to empty div elements. Assuming that they will be filled by some code not shown here, the events will be generated by propagation from any of the added child elements. But there's no filtering in the handler, and also no code to distinguish one child from another. This seems to be much of the issue, if I'm understanding it correctly.

My guess is that to obtain the behavior you want, you'll probably need to use DOM traversal with the event target to access the things you want to change in the delegated handler.

I see...I’m not super familiar with event.target. I’ve used it before but I’m still new to it so I didn’t even think of using that. I will implement that tomorrow and it should work. I’ll probably have to refresh my memory with a video on event target before hand but otherwise I should be good. Thanks for your help Steven as always!