简体   繁体   中英

How do I consolidate eventlisteners?

I have an API app that lists of names that clicked on a modal pops up and shows the data.

There is another button that is connected to a second modal with more data.

The problem is that this second modal runs through all the data instead of only displaying the proper data for the name selected. I was told the reason is because I have two event listeners but I should only have 1.

Here is my codepen and here is where I was told the problem was.

https://codepen.io/drxl/pen/WNjJQXa

 function addListItem(pokemon) { let pokeUl = document.querySelector('.list-group'); let listItem = document.createElement('li'); let button = document.createElement('button'); let baseStatsButton = document.querySelector('#base-stats-button'); button.innerText = pokemon.name; button.classList.add('btn'); button.classList.add('btn-primary'); listItem.classList.add('group-list-item'); button.setAttribute("data-target", "#my-modal"); button.setAttribute("data-toggle", "modal"); listItem.appendChild(button); pokeUl.appendChild(listItem); button.addEventListener('click', function() { showDetails(pokemon); }); baseStatsButton.addEventListener('click', function() { showStatModal(pokemon); }); }

Right now when you add the pokemon, you add the same click event listener to the stats button every time. That ends up executing the event handler number-of-pokemon times when clicked. There is only one button so only one event listener is needed

Also you need to delegate instead of adding event handlers to each button

I added an extra class to the button

 button.classList.add('pokebutton');

to make it easier to check

then we can delegate from the UL so any click on the list will see if it was a pokebutton that was clicked

const showDetails = function(pokemonName) {
  console.log(pokemonName)
};
let currentPokemon;
document.querySelector('.list-group').addEventListener('click', function(e) {
  const tgt = e.target;
  if (tgt.classList.contains("pokebutton")) {
    const pokemon = tgt.innerText;
    currentPokemon = pokemon
    showDetails(pokemon) && showStatModal(pokemon);
  }
});
document.getElementById('base-stats-button').addEventListener('click', function() {
  if (currentPokemon) showStatModal(currentPokemon); 
});

 let pokemonRepository = (function() { let pokemonList = []; let apiUrl = 'https://pokeapi.co/api/v2/pokemon/?limit=150'; let searchInput = document.querySelector("#searchIn"); function add(pokemon) { pokemonList.push(pokemon); } function getAll() { return pokemonList; } function addListItem(pokemon) { let pokeUl = document.querySelector('.list-group'); let listItem = document.createElement('li'); let button = document.createElement('button'); button.innerText = pokemon.name; button.classList.add('pokebutton'); button.classList.add('btn'); button.classList.add('btn-primary'); listItem.classList.add('group-list-item'); button.setAttribute("data-target", "#my-modal"); button.setAttribute("data-toggle", "modal"); listItem.appendChild(button); pokeUl.appendChild(listItem); } function loadList() { return fetch(apiUrl).then(function(response) { return response.json(); }).then(function(json) { json.results.forEach(function(item) { let pokemon = { name: item.name, detailsUrl: item.url }; add(pokemon); }); }).catch(function(e) { console.error(e); }) } function loadDetails(item) { let url = item.detailsUrl; return fetch(url).then(function(response) { return response.json(); }).then(function(details) { //Add details to item item.imageUrl = details.sprites.front_default; item.imageUrlBack = details.sprites.back_default; item.height = details.height / 10; item.weight = details.weight / 10; // pokemon types item.types = []; for (var i = 0; i < details.types.length; i++) { item.types.push(details.types[i].type.name); } item.types = item.types.join(', '); //pokemon abilities item.abilities = []; // eslint-disable-next-line no-redeclare for (var i = 0; i < details.abilities.length; i++) { item.abilities.push(details.abilities[i].ability.name); } item.abilities = item.abilities.join(', '); }).catch(function(e) { console.error(e); }); } //loads the stats for 2nd modal function loadStats(item) { let url = item.detailsUrl; return fetch(url).then(function(response) { return response.json(); }).then(function(details) { //add details to stats item.stats = details.stats.map(({ base_stat, stat: { name } }) => `${name}: ${base_stat}`).join("<br/>") }).catch(function(e) { console.error(e); }); } function showDetails(item) { pokemonRepository.loadDetails(item).then(function() { // console.log("item:", item); showModal(item); }); } function showModal(item) { pokemonRepository.loadDetails(item).then(function() { // eslint-disable-next-line no-undef let modalBody = $(".modal-body"); // eslint-disable-next-line no-undef let modalTitle = $(".modal-title"); //clears previous content in modal modalTitle.empty(); modalBody.empty(); //create elenebtb for pokemon name // eslint-disable-next-line no-undef let nameElement = $("<h1>" + item.name + "</h1>"); //create img element // eslint-disable-next-line no-undef let imageElementFront = $('<img class="modal-img" style="width:50%">'); imageElementFront.attr("src", item.imageUrl); // eslint-disable-next-line no-undef let imageElementBack = $('<img class="modal-img" style="width:50%">'); imageElementBack.attr("src", item.imageUrlBack); //create element for pokemon height // eslint-disable-next-line no-undef let heightElement = $("<p>" + "Height: " + item.height + "m</p>"); //for pokemon weight let weightElement = $("<p>" + "Weight: " + item.weight + "kgs</p>"); //pokemon types // eslint-disable-next-line no-undef let typesElement = $("<p>" + "Types: " + item.types + "</p>"); //pokemon abilities // eslint-disable-next-line no-undef let typesAbilities = $("<p>" + "Abilities: " + item.abilities + "</p>"); //eventlistener to for search bar searchInput.addEventListener('input', function() { let listPokemon = document.querySelectorAll('.group-list-item'); let value = searchInput.value.toUpperCase(); listPokemon.forEach(function(pokemon) { if (pokemon.innerText.toUpperCase().indexOf(value) > -1) { pokemon.style.display = ''; } else { pokemon.style.display = 'none' } }) }); modalTitle.append(nameElement); modalBody.append(imageElementFront); modalBody.append(imageElementBack); modalBody.append(heightElement); modalBody.append(weightElement); modalBody.append(typesElement); modalBody.append(typesAbilities); // eslint-disable-next-line no-undef $('#my-modal').modal('toggle'); }); } function loadStatDetails(item) { pokemonRepository.loadStats(item).then(function() { showStatModal(item); }); } function showStatModal(item) { pokemonRepository.loadStats(item).then(function() { // eslint-disable-next-line no-undef let StatmodalBody = $(".Statmodal-body"); // eslint-disable-next-line no-undef let StatmodalTitle = $(".Statmodal-title"); //clears previous content in modal StatmodalTitle.empty(); StatmodalBody.empty(); //create elenebtb for pokemon name // eslint-disable-next-line no-undef let nameElement = $("<h1>" + item.name + "</h1>"); //add stats let statsElement = $("<p>" + item.stats + "<p>"); StatmodalTitle.append(nameElement); StatmodalBody.append(statsElement); $('#my-Statmodal').modal('show'); }); } return { add: add, getAll: getAll, addListItem: addListItem, loadList: loadList, loadDetails: loadDetails, showDetails: showDetails, loadStats: loadStats, loadStatDetails: loadStatDetails, }; })(); pokemonRepository.loadList().then(function() { pokemonRepository.getAll().forEach(function(pokemon) { pokemonRepository.addListItem(pokemon); }); }); let link = document.getElementById("back-to-top"); var amountScrolled = 250; //makes button show window.addEventListener('scroll', function(e) { if (this.window.pageYOffset > amountScrolled) { link.classList.add('show'); } else { link.className = 'back-to-top'; } }); //scrolls to top link.addEventListener('click', function(e) { e.preventDefault(); var distance = 0 - window.pageYOffset; var increments = distance / (500 / 16); function animateScroll() { window.scrollBy(0, increments); if (window.pageYOffset <= document.body.offsetTop) { clearInterval(runAnimation); } }; // Loop the animation function var runAnimation = setInterval(animateScroll, 16); }); const showDetails = function(pokemonName) { console.log(pokemonName) }; let currentPokemon; document.querySelector('.list-group').addEventListener('click', function(e) { const tgt = e.target; if (tgt.classList.contains("pokebutton")) { const pokemon = tgt.innerText; currentPokemon = pokemon showDetails(pokemon) && showStatModal(pokemon); } }); document.getElementById('base-stats-button').addEventListener('click', function() { if (currentPokemon) showStatModal(currentPokemon); });
 /* * Prefixed by https://autoprefixer.github.io * PostCSS: v7.0.29, * Autoprefixer: v9.7.6 * Browsers: last 4 version */ * { -webkit-box-sizing: border-box; box-sizing: border-box; } body { background-color: rgb(3, 136, 180); } .navbar { background-color: #ffcb05!important; } .navbar-brand { color: #3d7dca!important; } .navbar-logo { width: 42px; height: 42px; margin-left: 1rem; } .modal-header { border-bottom: 1px solid black; -webkit-box-pack: justify; -ms-flex-pack: justify; justify-content: space-between; } .modal-content { background-color: #ffcb05!important; border: #3d7dca solid 6px!important; text-align: center; } .modal-close { background-color: #ee1515; border: white solid 2px; color: white; padding: 8.5px 16.5px; border-radius: 50%; font-size: 1.25rem; } .modal-close:active { border-color: #ee1515; background-color: white; color: #ee1515; } .modal-title h1 { margin-bottom: 0; } .modal h1 { margin-top: 0; text-align: left; font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif; text-transform: uppercase; font-size: 3rem; color: #3d7dca; margin-left: 2rem; } .modal p { margin-bottom: 0; text-align: left; font-weight: 700; font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif; font-size: 1.5rem; color: #3d7dca; text-transform: capitalize; } .list-group { list-style-type: none; text-align: center; -webkit-padding-start: 0; padding-inline-start: 0; margin: 2rem; text-transform: capitalize; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-orient: horizontal; -webkit-box-direction: normal; -ms-flex-direction: row; flex-direction: row; -ms-flex-wrap: wrap; flex-wrap: wrap; -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; } .list-group li { width: auto; margin: 1rem; } .Statmodal-body p { margin-left: 3%; } .btn { /*👉 background-color: #cc1313;👈*/ background-color: #db0606; border: black solid 2px; color: white; text-transform: capitalize; padding: 24px 72px; width: 300px; } .btn:hover { background-color: white; border: black solid 2px; color: #ee1515; } .btn-outline-success:hover { background-color: white; color: #ee1515; border: black 2px solid; } .btn-primary { font-size: 1.5rem; } .btn-primary:hover { color: #ee1515; background-color: white; } #search-button { background-color: #db0606; border: black solid 2px; color: white; padding: 4px 25px; } .modal-footer { justify-content: center; border-top: none; } .modal-button { text-align: center; width: auto; } .back-to-top { background-color: #ee1515; color: #FFFFFF; opacity: 0; transition: opacity .6s ease-in-out; z-index: 999; position: fixed; right: 20px; bottom: 20px; width: 50px; height: 50px; box-sizing: border-box; border-radius: 0%; } a.back-to-top { font-weight: 1000; letter-spacing: 2px; font-size: 14px; text-transform: uppercase; text-align: center; line-height: 1.6; padding-left: 2px; padding-top: 14px; text-decoration: none; } .back-to-top:hover, .back-to-top:focus, .back-to-top:visited { color: #FFFFFF; } .back-to-top.show { opacity: 1; } @media screen and (max-width: 727px) { .btn { width: 250px; } } @media screen and (max-width:627px) { .btn { padding: 10px 10px; width: 200px; font-size: 1.15rem; } } @media screen and (max-width:575px) { .justify-content-between { -webkit-box-pack: center!important; -ms-flex-pack: center!important; justify-content: center!important; } .form-inline { -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; } #search-button { margin-top: .5rem; padding: 4px 42px; } .modal p { font-size: 1.5rem!important; } } @media screen and (max-width:500px) { .modal p { font-size: 1.5rem!important; } } @media screen and (max-width: 493px) { .justify-content-between { -webkit-box-pack: center!important; -ms-flex-pack: center!important; justify-content: center!important; } } @media screen and (max-width:450px) { .modal-header { -webkit-box-align: center!important; -ms-flex-align: center!important; align-items: center!important; } .modal-title h1 { font-size: 1.75rem; } button { font-size: .85rem; } .modal p { font-size: 1rem!important; } }
 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>PokemonAPI</title> <link href="img/Poke_Ball.png" rel="shortcut icon" type="image/x-icon" /> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.3/css/all.css" integrity="sha384-SZXxX4whJ79/gErwcOYf+zWLeJdY/qpuqC4cAa9rOGUstPomtqpuNWT9wdPEn2fk" crossorigin="anonymous"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <link href="css/styles.css" rel="stylesheet"> </head> <body> <!--Nav--> <nav class="navbar navbar-light bg-light justify-content-between"> <a class="navbar-brand">PokemonAPI<img class="navbar-logo" src="img/Poke_Ball.png"></a> <form class="form-inline"> <input id="searchIn" class="form-control mr-sm-2" type="search" placeholder="Search for a Pokemon" aria-label="Search for Pokemon"> <button id="search-button" type="submit">Search</button> </form> </nav> <!--list of pokemon--> <ul class="list-group"></ul> <div class="modal fade" id="my-modal" aria-hidden="true" tabindex="-1" role="dialog" aria-labelledby="pokemonModalLabel"> <div class="modal-dialog modal-dialog-centered" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" aria-labelledby="pokemonModalLabel">Modal 1 title</h5> <button type="button" class="modal-close" data-bs-dismiss="modal" aria-label="Close">X</button> </div> <div class="modal-body"> </div> <div class="modal-footer"> <button id="base-stats-button" class="btn modal-button" data-bs-target="#my-Statmodal" data-bs-toggle="modal" data-bs-dismiss="modal">Base Stats</button> </div> </div> </div> </div> <div class="modal fade" id="my-Statmodal" aria-hidden="true" aria-labelledby="pokemonStatModalLabel" tabindex="-1" role="dialog"> <div class="modal-dialog modal-dialog-centered" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="Statmodal-title" id="exampleModalToggleLabel2" aria-labelledby="pokemonStatModalLabel">Modal 2 title</h5> <button type="button" class="modal-close" data-bs-dismiss="modal" aria-label="Close">X</button> </div> <div class="Statmodal-body"> </div> <div class="modal-footer"> <button class="btn modal-button" data-bs-target="#my-modal" data-bs-toggle="modal" data-bs-dismiss="modal">Back to Pokemon</button> </div> </div> </div> </div> <!--Top of Page Button--> <a href="#" id="back-to-top" class="back-to-top" style="display: inline;"><i class="fas fa-arrow-up fa-2x"></i></a> <!-- jQuery first, then Popper.js, then Bootstrap JS --> <script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script> <!--PolyFills--> <script src="js/promise-polyfill.js"></script> <script src="js/fetch-polyfill.js"></script> <!--JS--> <script src="js/scripts.js"></script> </body> </html>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM