Build a Pokémon Search App Project - Build a Pokémon Search App

Tell us what’s happening:

Hey everyone,

My code seems to be working perfectly at my local environment using VScode. For some reason when I try to run it at the FreeCodeCamp console I can’t even click the searchButton and I cannot pass in the test. What am I doing wrong?

Thanks :slight_smile:

Your code so far

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Pokémon Search App</title>
    <link rel="stylesheet" href="styles.css">
    <script src="script.js" defer></script>
</head>
<body>
    <h1>Pokémon Search App</h1>
    <div class="container">
        <form role="search" id="search-form">
            <label for="search-input">Search for Pokémon name of ID</label>
            <input type="text" name="pokemon" id="search-input" required> 
            <button id="search-button">Search</button>
        </form>
        <div class="output">
            <div class="top-container">
                <div class="name-and-id">
                    <span class="to-be-rended" id="pokemon-name"></span>
                    <span class="to-be-rended" id="pokemon-id"></span>
                </div>
                <div class="size">
                    <span class="to-be-rended" id="weight"></span>
                    <span class="to-be-rended" id="height"></span>
                </div>
                <div class="sprite-container">
                    <img class="to-be-rended" id="sprite"> 
                </div>
                <div class="to-be-rended" id="types"></div>
            </div>
            <div class="bottom-container">
                <table>
                    <tbody>
                        <tr>
                            <th>Base</th>
                            <th>Stats</th>   
                        </tr>
                        <tr>
                            <td>HP:</td>
                            <td class="to-be-rended" id="hp"></td>
                        </tr>
                        <tr>
                            <td>Attack:</td>
                            <td class="to-be-rended" id="attack"></td>
                        </tr>
                        <tr>
                            <td>Defense:</td>
                            <td class="to-be-rended" id="defense"></td>
                        </tr>
                        <tr>
                            <td>Sp. Attack:</td>
                            <td class="to-be-rended" id="special-attack"></td>
                        </tr>
                        <tr>
                            <td>Sp. Defense:</td>
                            <td class="to-be-rended" id="special-defense"></td>
                        </tr>
                        <tr>
                            <td>Speed:</td>
                            <td class="to-be-rended" id="speed"></td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </div>
    </div>
</body>
</html>

const searchButton = document.getElementById('search-button');
const searchInputElement = document.getElementById('search-input');
const toBeRended = document.querySelectorAll('.to-be-rended');
const [nameSpan, pokemonIdSpan, weightSpan, heightSpan, spriteImg, typesDiv, hpTd, attackTd, defenseTd, specialAttackTd, specialDefenseTd, speedTd] = toBeRended;

async function fetchPokemon() {
    const userInput = checkInput();
    if (!userInput) return; 
    const url = `https://pokeapi-proxy.freecodecamp.rocks/api/pokemon/${userInput}`;
    const res = await fetch(url);

    if (!res.ok) {
        alert("Pokémon not found");
        return null;
    }

    const data = await res.json();
    return data;
};

function checkInput() {
    const searchInput = searchInputElement.value;

    if (searchInput) {
        const cleanedInput = String(searchInput.trim().toLowerCase().replace(/\s+/g, '-'));
        return cleanedInput;
    } else {
        alert('Please enter a Pokémon name or ID');
        return null;
    }
};

function renderPokemon(pokemon) {
    nameSpan.innerText = `${pokemon.name}`;
    pokemonIdSpan.innerText = `${pokemon.id}`;
    weightSpan.innerText = `Weight: ${pokemon.weight}`;
    heightSpan.innerText = `Height: ${pokemon.height}`;
    spriteImg.src = pokemon.sprites.front_default; 
    typesDiv.innerText = pokemon.types.map(type => type.type.name).join(' / '); 
    hpTd.innerText = `${pokemon.stats[0].base_stat}`;
    attackTd.innerText = `${pokemon.stats[1].base_stat}`;
    defenseTd.innerText = `${pokemon.stats[2].base_stat}`;
    specialAttackTd.innerText = `${pokemon.stats[3].base_stat}`;
    specialDefenseTd.innerText = `${pokemon.stats[4].base_stat}`;
    speedTd.innerText = `${pokemon.stats[5].base_stat}`;
};

searchButton.addEventListener('click', async (event) => {
    event.preventDefault();

    try {
        const pokemon = await fetchPokemon(); 
        if (pokemon) {
            renderPokemon(pokemon);  
        }
    } catch (error) {
        console.error("Error fetching Pokémon data:", error);
    }
    searchInputElement.value = '';
});

*,
*::before,
*::after {
  box-sizing: border-box;
}

* {
  margin: 0;
}

body {
  line-height: 1.5;
}

img {
  display: block;
}

body {
  height: 100vh;
  font-family: sans-serif;
  background-color: #1b1b32;
  color: #0a0a23;
  font-family: Verdana, Geneva, Tahoma, sans-serif;
}

main {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.freecodecamp-logo {
  height: 30px;
  margin: 25px 0;
}

h1 {
  color: #f5f6f7;
  font-size: 1.7em;
  text-align: center;
  margin-bottom: 1rem;
}

.container {
  margin: auto;
  width: 100%;
  background-color: #f5f6f7;
  border: 1px solid #f5f6f7;
  border-radius: 15px;
  box-shadow: 10px 10px 0px 0px rgba(223, 220, 220, 0.75);
}

.output,
#search-form {
  display: flex;
  justify-content: center;
}

#search-form {
  flex-wrap: wrap;
  margin: 10px 0;
  padding: 5px;
  border-radius: 8px 8px 0 0;
  gap: 10px;
}

label {
  align-self: center;
}

#search-input:focus-visible,
#search-button:focus-visible {
  outline: 3px solid #198eee;
}

#search-input {
  height: 40px;
  padding-left: 10px;
  width: 200px;
}

#search-button {
  padding: 14px 0;
  width: 80px;
  border-radius: 20px;
  text-align: center;
  background-color: #7f21ab;
  color: #f5f6f7;
  border: none;
}

.output {
  margin: 10px 0;
  padding: 5px;
  flex-direction: column;
  align-items: center;
}

.top-container,
.bottom-container {
  display: flex;
  flex-direction: column;
  width: 100%;
  min-height: 325px;
}

.top-container {
  margin-bottom: 10px;
  padding: 10px;
  background-color: #f0f1f7;
}

.name-and-id {
  height: 28px;
  font-size: 1.1em;
  text-transform: capitalize;
  margin-bottom: 5px;
}

.size {
  height: 22px;
  font-size: 0.85rem;
}

.sprite-container {
  flex-grow: 2;
  display: flex;
  align-items: center;
  justify-content: center;
}

#sprite {
  width: 180px;
}

#types {
  min-height: 30px;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: 5px;
}

.type {
  width: 66px;
  padding: 5px;
  font-size: 0.7rem;
  text-align: center;
  border-radius: 5px;
  background-color: red;
  text-transform: uppercase;
}

table {
  border-collapse: collapse;
  border-spacing: 0;
  width: 100%;
  font-size: 1 rem;
  color: #f5f6f7;
  background-color: #7f21ab;
}

th:nth-child(even),
td:nth-child(even) {
  border-left: 5px solid #f5f6f7;
}

tr {
  border-bottom: 5px solid #f5f6f7;
}

td,
th {
  text-align: center;
  padding: 8px;
}

/* Special styling for Pokémon types */

.normal {
  background-color: #b7b7aa;
}

.fire {
  background-color: #ff6f52;
}

.water {
  background-color: #42a1ff;
}

.electric {
  background-color: #fecc33;
}

.grass {
  background-color: #78cc55;
}

.ice {
  background-color: #66ccfe;
}

.fighting {
  background-color: #d3887e;
}

.poison {
  background-color: #c68bb7;
}

.ground {
  background-color: #dfba52;
}

.flying {
  background-color: #8899ff;
}

.psychic {
  background-color: #ff66a3;
}

.bug {
  background-color: #aabb23;
}

.rock {
  background-color: #baaa66;
}

.ghost {
  background-color: #9995d0;
}

.dragon {
  background-color: #9e93f1;
}

.dark {
  background-color: #b59682;
}

.steel {
  background-color: #abaabb;
}

.fairy {
  background-color: #ed99ed;
}

@media screen and (min-width: 550px) {
  h1 {
    font-size: 2em;
  }

  .container {
    width: 450px;
  }

  #search-form,
  .top-container,
  .bottom-container {
    width: 95%;
  }

  .type {
    width: 75px;
  }
}

Your browser information:

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36

Challenge Information:

Build a Pokémon Search App Project - Build a Pokémon Search App

looks like the console has something to say that is worth reading.
Take a look.

1 Like
  1. You can’t use defer in the fCC editor. Move the script to the bottom of the HTML before the closing </body> tag.

  2. The #types test is expecting nested elements for the values. You can update the map to return elements with the values and update innerText to innerHTML.

the #types element should contain a single inner element with the value ELECTRIC
the #types element should contain two inner elements with the text values GHOST and POISON

1 Like

Thanks a lot! I was very confused why the .js file wasn’t running at all. I placed the script on the bottom of the HTML file and after that everything made sense and it was an easy fix and I finally got the certification!!! :slight_smile: By the way, do you know why defer doesn’t work on FCC console? Is using defer maybe not a good practice?

defer doesn’t work because the content of the script “file” is added to a script element and its position is relative to the “files” position.

So if you add it to the head, a script element is created in the head and the code execution is not deferred as it would have been using an actual script file with the defer attribute.

It is a good practice, it just doesn’t work with the fCC editor because of how it works as explained above.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.