2
votes

I want to add an event listener or something similar that changes the display of the character class in CSS from none to grid when a key is typed in the searchbar. I've tried several ways but am not having much luck and am not quite sure how to work it in. I would also like to make the elements clickable. Any help would really be appreciated. Code

HTML

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
    <link rel="stylesheet" href="app.css" />
  </head>
  <body>
    <div class="container">
      <h1>&#x2728;Harry Potter Characters &#x2728;</h1>
      <div id="searchWrapper">
        <input
          type="text"
          name="searchBar"
          id="searchBar"
          placeholder="search for a character"
        />
      </div>
      <ul id="charactersList"></ul>
    </div>
    <script src="app.js"></script>
  </body>
</html>

CSS

body {
  font-family: sans-serif;
  background-color: #111d4a;
}

* {
  box-sizing: border-box;
}
h1 {
  color: #eee;
  margin-bottom: 30px;
}
.container {
  padding: 40px;
  margin: 0 auto;
  max-width: 1000px;
  text-align: center;
}

#charactersList {
  padding-inline-start: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  grid-gap: 20px;
}

.character {
  list-style-type: none;
  background-color: #eaeaea;
  border-radius: 3px;
  padding: 10px 20px;
  display: none;
  grid-template-columns: 3fr 1fr;
  grid-template-areas:
    "name"
    "house";
  text-align: left;
}

.hide {
  display: none;
}

.character > h2 {
  grid-area: name;
  margin-bottom: 0px;
}

.character > p {
  grid-area: house;
  margin: 0;
}

#searchBar {
  width: 100%;
  height: 32px;
  border-radius: 3px;
  border: 1px solid #eaeaea;
  padding: 5px 10px;
  font-size: 12px;
}

#searchWrapper {
  position: relative;
}

#searchWrapper::after {
  content: "????";
  position: absolute;
  top: 7px;
  right: 15px;
}

JS

const charactersList = document.getElementById("charactersList");
const searchBar = document.getElementById("searchBar");
let hpCharacters = [];

searchBar.addEventListener("keyup", (e) => {
  const searchString = e.target.value.toLowerCase();

  const filteredCharacters = hpCharacters.filter((character) => {
    return character.name.toLowerCase().includes(searchString);
  });
  displayCharacters(filteredCharacters);
});

const loadCharacters = async () => {
  try {
    const res = await fetch("https://hp-api.herokuapp.com/api/characters");
    hpCharacters = await res.json();
    displayCharacters(hpCharacters);
  } catch (err) {
    console.error(err);
  }
};

const displayCharacters = (characters) => {
  const htmlString = characters
    .map((character) => {
      return `
            <li class="character">
                <h2>${character.name}</h2>
                <p>House: ${character.house}</p>
            </li>
        `;
    })
    .join("");
  charactersList.innerHTML = htmlString;
};

loadCharacters();

1
Basically, when you press a key you want to make a <li class="character"> to be active (visible). The best way to do that is to work at the high level of that concept, rather than twiddling with low-level attributes like the display value. So as @Wally answers, add (or toggle) a class so the element would become <li class="character active"> and have a CSS rule that says .character.active { display: grid; } Bonus advantage: if you were to redesign and used a flow layout, not grid, your code would not have to change, just your CSS (which has to change anyway in a redesign)Stephen P

1 Answers

0
votes

So

So I want to add an event listener or something similar that changes the display of the display of the "character" class in css from "none" to "grid" when a key is typed in the searchbar.

You could do this by applying an eventlistener i.e the keypress event listener - and on that functions callback just use the element.classlist.toggle or element.classlist.add to add another class to the element which has the display of grid.

another method would also to be use the event listener for the keypress of your choice, but in the call back, edit the style of the element in question - so

addEventListener('keypress', function (e) {
    if (e.key === 'Enter') {
      element.style.display="grid";

    // to make the element clickable - just add another event listener to it - 
    }
});

For any key being pressed the event listener is keydown -

https://developer.mozilla.org/en-US/docs/Web/API/Document/keydown_event

addEventListener('keydown', function (e) {
        
          element.style.display="grid"; 
    
    });

Hope that helps - W