2

I need to add a click event to a css class so when clicked it switches to a different class. Specifically, I have a character class on li items that I would like to change to another class when the li item is clicked. Code: html

<!DOCTYPE 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>Client Search</h1>
            <div id="searchWrapper">
                <input
                    type="text"
                    name="searchBar"
                    id="searchBar"
                    placeholder="search for a character"
                    onkeyup="myFunction()"
                />
            </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: none;
    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: grid;
    grid-template-columns: 3fr 1fr;
    grid-template-areas:
        'name image'
        'house image';
    text-align: left;
}
.character:hover {
  background-color: blue;
  cursor: pointer;
}

.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;
}

javaScript

const charactersList = document.getElementById('charactersList');
const searchBar = document.getElementById('searchBar');
let clientNames = [];

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

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

const loadCharacters = async () => {
    try {
        const res = await fetch('https://hp-api.herokuapp.com/api/characters');
        clientNames = 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();


//change the display of characterListfrom none to grid
    function myFunction() {
      var charactersList = document.getElementById("charactersList");
      charactersList.style.display = "grid";

//also check if searchBar is empty and set display back to none
      var searchBar = document.getElementById("searchBar").value;
      if (searchBar === ""){
        charactersList.style.display = "none";
      }
    }
3
  • 1
    I do not believe this code shows any li object with the class of character Commented Jun 25, 2020 at 16:22
  • Sorry, the list is generated dynamically in the javaScript code in the ``` displayCharacters() ``` function Commented Jun 25, 2020 at 16:24
  • 1
    Ah yes that makes sense. Commented Jun 25, 2020 at 16:41

1 Answer 1

1

Great question!

I just made a CodePen to illustrate how to programmatically change CSS class names when a li item is clicked. Check out this example and let me know if this clarifies the problem : )

JS

let list = document.getElementById('myList');
let items = ['First', 'Second', 'Third', 'Fourth', 'Fifth'];

for(let item of items){
  let li = document.createElement("LI");
  li.appendChild(document.createTextNode(item));
  li.classList.add('blue');
  li.addEventListener("click", () => {
    li.classList.remove('blue');
    li.classList.add('red');
  });
  list.appendChild(li);
}

HTML

<ul id="myList"></ul>

CSS

.blue{
  color: blue;
}

.red{
  color: red;
}

https://codepen.io/CrowlsYung/pen/eYJRPjx

Suggested Change

<li class="character" onclick="handleItemClick(event)">
    <h2>${character.name}</h2>
    <p>House: ${character.house}</p>
</li>

function handleItemClick(e){
    e.currentTarget.classList.toggle('prevClass')
    e.currentTarget.classList.toggle('newClass');
}
Sign up to request clarification or add additional context in comments.

11 Comments

Thanks this is along the lines of what I'm looking for now I just need to figure out how to incorporate it into my code lol
The problem is I don't have an array in the js, it's called from an api.
I added a 'suggested change' section. It's not exactly what you need, but should be close.
Thanks, I tried it using ``` character ``` and ``` newCharacter ``` instead of prevClass and newClass. I just changed the background color on ``` newCharacter ``` to test but it doesn't seem to be working.
I think I have, I was missing the event argument in the handleItemClick(). Really appreciate the help!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.