Así que estoy trabajando en una aplicación de prueba, probando mi conocimiento de js y encontré un pequeño problema.

Aquí está mi código:

// pokedex
var pokemonRepository = (function() {
  var repository = [];
  var apiUrl = "https://pokeapi.co/api/v2/pokemon/";

  // Loading data from external API
  function loadList() {
    return fetch(apiUrl)
      .then(function(response) {
        return response.json();
      })
      .then(function(json) {
        json.results.forEach(function(item) {
          var pokemon = {
            name: item.name,
            detailsUrl: item.url
          };
          add(pokemon);
          console.log(item);
        });
      })
      .catch(function(e) {
        console.log(e);
      });
  }

  // Get the pokemon details using the Url from the pokemon object in the parameter
  function loadDetails(item) {
    var url = item.detailsUrl;

    return fetch(url)
      .then(function(response) {
        return response.json();
      })
      .then(function(details) {
        // Now we add the details to the item
        item.imageUrl = details.sprites.front_default;
        item.height = details.height;
        item.weight = details.weight;
        item.types = Object.keys(details.types);
      })
      .catch(function(e) {
        console.error(e);
      });
  }

  function addListItem(pokemon) {
    var $list = document.querySelector('.pokemon-list'); // target the 'pokemon-list'
    var details = document.createElement('details'); // create details list items
    var summary = document.createElement('summary'); // create summary

    summary.innerText = pokemon.name; // set summary text to display the pokemon name

    summary.classList.add(
      "hover:bg-indigo-400",
      "justify-between",
      "bg-indigo-300",
      "pokemon-list",
      "text-white",
      "flex-wrap",
      "flex-row",
      "title",
      "flex",
      "mb-4",
      "p-4",
    ); // summary class names

    summary.classList.add('btn'); // add a class name to all 'summarys' via the 'summary' variable
    details.appendChild(summary); // append the 'summary' into the 'li' list items
    $list.appendChild(details) // append the 'li' list items along with all child elements into the 'ul' list

    // add event click using targetting the 'show details' function above to console.log the pokemon name when clicked
    summary.addEventListener('click', function() {
      showDetails(pokemon);
    });
  };


  // Creating modal content
  function showModal(item) {
    var pokemonItem = document.querySelector('details');
    var modal = document.createElement('div');

    modal.classList.add(
      "border-orange-500",
      "border-l-4",
      "shadow-lg",
      "bg-white",
      "rounded",
      "content",
      "border",
      "fixed",
      "top-0",
      "p-4"
    ); // modal class names

    // Creating element for name in modal content
    var nameElement = document.createElement('h1');
    nameElement.classList.add('text-xl');
    nameElement.innerText = item.name;

    //creating img in modal content
    var imageElement = document.createElement('img');
    imageElement.classList.add('modal-img');
    imageElement.setAttribute('src', item.imageUrl);

    // Creating element for height
    var heightElement = document.createElement('p');
    heightElement.innerText = 'height : ' + item.height;

    // // Creating element for weight in modal content
    var typesElement = document.createElement('p');
    typesElement.innerText = 'weight : ' + item.weight;

    // Appending modal content to webpage
    modal.appendChild(nameElement);
    modal.appendChild(imageElement);
    modal.appendChild(heightElement);
    modal.appendChild(typesElement);
    pokemonItem.appendChild(modal);
  }

  // hides modal when you click on close button
  function hideModal() {
    var $modalContainer = document.querySelector('#modal-container');
    $modalContainer.classList.remove('is-visible');
  }

  // Hides modal when clicked on ESC on keyboard
  window.addEventListener('keydown', (e) => {
    var $modalContainer = document.querySelector('#modal-container');

    if ( e.key === 'Escape' && $modalContainer.classList.contains('is-visible')) {
      hideModal();
    }
  });

  // Hides modal if clicked outside of it
  var $modalContainer = document.querySelector('.pokemon-list');
  $modalContainer.addEventListener('click', (e) => {
    var target = e.target;
    if (target === $modalContainer) {
      hideModal();
    }
  });

  function showDetails(item) {
    pokemonRepository.loadDetails(item).then(function () {
      showModal(item);
      console.log(item)
    });
  };

  function add(item) {
    repository.push(item);
  }

  function getAll() {
    return repository;
  }

  return {
    add: add,
    getAll: getAll,
    addListItem: addListItem,
    loadList: loadList,
    loadDetails: loadDetails
  };
})();

// Get all pokemon and loop through each one
pokemonRepository.loadList().then(function() {
  pokemonRepository.getAll().forEach(function(pokemon) {
    pokemonRepository.addListItem(pokemon);
  });
});
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=#, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet">

  <style>
    details .title { cursor: pointer; }

    details[open] > .title::before {
      background: rgba(27, 31, 35, 0.9);
      cursor: default;
      position: fixed;
      display: block;
      content: " ";
      z-index: 99;
      bottom: 0;
      right: 0;
      left: 0;
      top: 0;
    }

    details > .content {
      animation-timing-function: ease-in-out;
      transform: translateX(-50%);
      animation-duration: 300ms;
      animation-name: fadein;
      margin: 10vh auto;
      max-height: 80vh;
      max-width: 90vw;
      width: 448px;
      z-index: 999;
      left: 50%;
    }

    @keyframes fadein {
      from { opacity: 0; }
      to { opacity: 1; }
    }

    details > summary:first-of-type {
      list-style-type: none;
    }
  </style>
</head>
<body>

  <nav class="text-center bg-gray-400 shadow-lg p-4">
    <a href="/">Pokédex</a>
  </nav>

  <div class="px-4 py-10 max-w-md mx-auto pokemon-list">
    <div id="modal-container"></div>
  </div>

  <script src="./js/promise-polyfill.js"></script>
  <script src="./js/fetch.umd.js"></script>
  <script src="./js/scripts.js"></script>
</body>
</html>

El problema aquí es que puedo hacer clic en el primer elemento sin problemas, sin embargo, todo el contenido modal solo va al details donde necesitaba un contenido div para cada {{X2 }} ya que estoy extrayendo un objeto JSON diferente de la API.

Esto es lo que obtengo.

enter image description here

Estoy muy cerca de terminar la aplicación, solo un pequeño problema antes de terminarla.

Gracias.

0
user8331511 23 sep. 2019 a las 00:43

1 respuesta

La mejor respuesta

El problema es que está haciendo un document.querySelector('details') en todo el documento en showModal(). Así que devolverá el primero que encuentre.

Agregué el evento del clic en <summary> al hilo del código.

summary.addEventListener('click', function(e) {
  showDetails(pokemon, e);
});

Continuando

function showDetails(item, e) {
  pokemonRepository.loadDetails(item).then(function () {
    showModal(item, e);
    console.log(item)
  });
};

Y en showModal()

function showModal(item, e) {
  var pokemonItem = e.srcElement.parentNode;
  var modal = document.createElement('div');
  ...

Cambiado para usar el objetivo de evento de clic (en nuestro caso <summary>) nodo principal (en este caso <details>)

https://jsfiddle.net/5rqvejpm/

0
Pedro Estrada 22 sep. 2019 a las 22:01