so i'm currently trying to build search icon on the header clickable where you're able to search for, in this case, pokemon names, however i keep getting a console error
searchQuery.value undefined
Not sure why because the code looks valid.
Also, when you click on the search icon the icon goes above it and once you hit submit on the input it duplicates. I'm sure it's all connected the bug.
No sure why this is happening and would greatly appreciate any advice to fix this.
let pokemonRepository = (function() {
let pokemonList = [];
// API
let apiUrl = "https://pokeapi.co/api/v2/pokemon/?limit=150";
let searchIcon = $(".btn-outline-secondary");
let modalContainer = $(".modal");
let modalDialog = $(".modal-dialog");
let modalContent = $(".modal-content");
let modalBody = $(".modal-body");
let modalTitle = $(".modal-title");
let modalHeader = $(".modal-header");
let modalClose = $(".btn-close");
let listItemArray = $("li");
function add(pokemon) {
if (
typeof pokemon === "object" &&
"name" in pokemon &&
"detailsUrl" in pokemon
) {
pokemonList.push(pokemon);
} else {
console.error("pokemon is not correct");
}
}
function getAll() {
return pokemonList;
}
// filters through pokemon names
function search(pokemonName) {
return pokemonList.filter((pokemon) => pokemon.name === pokemonName);
}
// Function adds a list of pokemon
function addListItem(pokemon) {
let pokemonDisplay = $(".list-group-horizontal");
// Creates li element
let listItem = $("<li>");
listItem.addClass(
"list-group-item text-center col-sm-6 col-md-4 border border-secondary bg-image img-fluid"
);
// Creates h1 for Pokemon Name
let listTitle = $("<h1>");
listTitle.html(`${pokemon.name}`);
listTitle.addClass("display-6");
// Creates div which holds sprites
let listImg = $("<div>");
loadDetails(pokemon).then(function() {
listImg.append(
`<img src=${pokemon.imageUrlFront} alt="${pokemon.name} sprite"/>`
);
});
let listButton = $("<button>");
listButton.text("show More");
// Added Bootstrap Utility Class
listButton.addClass("mp-2 btn btn-secondary");
listButton.attr("type", "button");
listButton.attr("data-bs-toggle", "modal");
listButton.attr("data-bs-toggle", "#pokemonModal");
listItem.append(listTitle);
listItem.append(listImg);
listItem.append(listButton);
pokemonDisplay.append(listItem);
buttonEvent(listButton, pokemon);
}
function buttonEvent(listButton, pokemon) {
listButton.on("click", () => {
showDetails(pokemon);
});
}
function showDetails(pokemon) {
loadDetails(pokemon).then(() => {
// Clears existing content
modalContainer.empty();
modalTitle.addClass("modal-title h5 col-sml-3");
let pokemonType = {
fire: "text-danger",
grass: "text-success",
water: "text-primary",
electric: "text-warning",
flying: "text-info",
poison: "text-secondary",
};
pokemon.types.forEach((type) =>
modalTitle.addClass(pokemonType[type.type.name])
);
modalTitle.html(`${pokemon.name}`);
modalBody.html(`
Entry: ${pokemon.id}<br>
Height: ${pokemon.height}<br>
Weight: ${pokemon.weight}<br>
Types: ${pokemon.types[0].type.name}`);
if (pokemon.types.length === 2) {
modalBody.innerHTML = `, ${pokemon.types[1].type.name}`;
}
modalBody.innerHTML = `<br>Abilities: ${pokemon.abilities[0]}.ability.name}`;
if (pokemon.abilities.length === 2) {
modalBody.innerHTML = `, ${pokemon.abilities[1]}.ability.name}`;
}
modalBody.append(`<br>
<img src=${pokemon.imageUrlFront} alt="${pokemon.name} front sprite">
<img src=${pokemon.imageUrlBack} alt="${pokemon.name} back sprite">
<br>
`);
modalDialog.append(modalContent);
modalContent.append(modalHeader);
modalHeader.append(modalTitle);
modalHeader.append(modalClose);
modalContent.append(modalBody);
modalContainer.append(modalDialog);
});
modalContainer.modal("show");
}
modalContainer.on("shown.bs.modal", () => {
// Jquery eventlistener
modalClose.on("click", () => {
modalContainer.removeClass("fade");
modalContainer.modal("hide");
listItemArray[0].children().click();
});
});
searchIcon.on("click", () => {
// fetching .d-flex class in form
let bodyHeader = $(".d-flex");
// returns the number of child elements
if (bodyHeader.length === 1) {
//creates input element
let searchQuery = $("<input>");
searchQuery.attr("placeholder", "Pokemon Name");
searchQuery.attr("type", "search");
searchQuery.attr("aria-label", "search Pokemon Name");
searchQuery.addClass("form-control my-3 ps-2 col-sm");
searchIcon.blur();
searchQuery.focus();
bodyHeader.append(searchQuery);
searchQuery.on("keydown", (e) => {
if (e.key === "Enter") {
e.preventDefault();
searchQuery.value =
searchQuery.value.charAt(0).toUpperCase()
searchQuery.value.slice(1);
for (let i = 0; i < listItemArray.length; i ) {
if (
902 >
listItemArray[i].children().last().getBoundingClientRect()[
"top"
] &&
listItemArray[i].children().last().getBoundingClientRect()[
"top"
] > 42
) {
listItemArray[i].children().last().click();
}
}
for (let i = 0; i < listItemArray.length; i ) {
if (listItemArray[i].text().split("\n")[0] === searchQuery.value) {
setTimeout(function() {
listItemArray[i].children().last().click();
}, 5);
}
}
}
});
}
});
// Fetches data from API
function loadList() {
return fetch(apiUrl)
.then(function(response) {
return response.json();
})
.then(function(json) {
json.results.forEach((item) => {
let pokemon = {
name: item.name.charAt(0).toUpperCase() item.name.slice(1),
detailsUrl: item.url,
};
add(pokemon);
});
})
.catch(function(error) {
console.error(error);
});
}
function loadDetails(item) {
let url = item.detailsUrl;
return fetch(url)
.then(function(response) {
return response.json();
})
.then(function(details) {
item.imageUrlFront = details.sprites.front_default;
item.imageUrlBack = details.sprites.back_default;
item.id = details.id;
item.height = details.height;
item.weight = details.weight;
item.types = details.types;
item.abilities = details.abilities;
})
.catch(function(error) {
console.error(error);
});
}
return {
add: add,
getAll: getAll,
addListItem: addListItem,
search: search,
showDetails: showDetails,
loadList: loadList,
loadDetails: loadDetails,
buttonEvent: buttonEvent,
};
})();
pokemonRepository.loadList().then(function() {
pokemonRepository.getAll().forEach(function(pokemon) {
pokemonRepository.addListItem(pokemon);
});
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="The Pokédex is a simple encyclopedia of Pokémon and their characteristics." />
<link rel="shortcut icon" href="img/favicon.png" type="image/x-icon" />
<title>Pokédex App</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css" />
<link rel="stylesheet" href="/dist/style.production.css" />
</head>
<body>
<nav >
<div >
<a href="#home" >
<img src="img/ball.png" width="30" height="24" alt="" /><span >Pokèdex</span>
</a>
<button type="button" data-bs-toggle="collapse" data-bs-target="#navbarTogglerDemo01" aria-controls="navbarTogglerDemo01" aria-expanded="false" aria-label="Toggle navigation">
<span ></span>
</button>
<div id="navbarSupportedContent">
<ul >
<li >
<a aria-current="page" href="#home">Home</a
>
</li>
<li >
<a href="#about">About</a>
</li>
</ul>
</li>
</ul>
<form role="search">
<!-- <input
placeholder="Pokemon Name"
aria-label="Search"
/> -->
<button type="submit">
<i ></i>
</button>
</form>
</div>
</div>
</nav>
<p ></p>
<!-- Pokemon Display -->
<div >
<ul ></ul>
</div>
<!-- Display Ends Here -->
<div id="pokemonModal" tabindex="-1" role="dialog" aria-labelledby="pokemonModalLabel" aria-hidden="true">
<div role="document">
<div >
<div >
<h5 id="pokemonModalLabel"></h5>
<button type="button" data-dismiss="modal" aria-label="Close" aria-hidden="true"></button>
</div>
<!-- Content is dynamically created using jquery -->
<div ></div>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js" integrity="sha384-Xe 8cL9oJa6tN/veChSP7q mnSPaj5Bcu9mPX5F5xIGE0DVittaqT5lorf0EI7Vk" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-ODmDIVzN pFdexxHEHFBQH3/9/vQ9uori45z4JjnFsRydbmQbmL5t1tQ0culUzyK" crossorigin="anonymous"></script>
<script src="/src/js/scripts.js"></script>
<script src="/src/js/promise-polyfill.js"></script>
<script src="/src/js/fetch-pollyfill.js"></script>
</body>
</html>
CodePudding user response:
Since searchQuery
is a jQuery object, you need to use its .val()
method to set and get the value. So change.
searchQuery.value =
searchQuery.value.charAt(0).toUpperCase()
searchQuery.value.slice(1);
to
searchQuery.val((i, value) => value[0].toUpperCase() value.slice(1));