Leave the dynamic code in an array filter

1

I'm wanting to leave my code more 'dynamic' so I do not need to add a new block for every new item / category I add, it's a study-only project. What I thought was to use the functions with parameters but I could not implement them well

let animals = [{
    name: 'catOne',
    species: 'cat'
  },
  {
    name: 'catTwo',
    species: 'cat'
  },
  {
    name: 'dogOne',
    species: 'dog'
  },
  {
    name: 'dogTwo',
    species: 'dog'
  },
]

let catsEl = document.getElementById('cats');
let dogsEl = document.getElementById('dogs');
let result = document.getElementById('list');

let clickCount = 0;

catsEl.addEventListener('click', function() {

  clickCount++;

  function isAnimal(animal, species) {
    return animal.species === species;
  }

  let cat = animals.filter(function(animal) {
    return isAnimal(animal, 'cat');
  });

  let lis = document.createElement('li');


  for (let i = 0; i <= clickCount; i++) {
    for (let j = 0; j < i; j++) {
      result.appendChild(lis).textContent = cat[j].name;

      if (clickCount > cat.length) {
        result.appendChild(lis).textContent = "No more cats";
      }
    }


  }

});
html {
  font-family: Verdana;
}

.wrapper {
  display: flex;
}

.button {
  padding: 10px;
  width: 100%;
  border: 1px solid;
  width: 100px;
  text-align: center;
  margin: 0 20px;
}

.button:hover {
  background: #111;
  color: #fff;
}

ul#list li {
  padding: 10px;
  border: 1px solid #111;
  list-style-type: none;
  width: 10vw;
}
<div class="wrapper">
  <div class="button" id="cats">Cats</div>
  <div class="button" id="dogs">Dogs</div>
</div>

<div>
  <ul id="list"></ul>
</div>
    
asked by anonymous 23.12.2017 / 23:55

1 answer

0

Even considering only cats, the logic they have is complex and with an error when passing the amount of existing cats:

for (let i = 0; i <= clickCount; i++) {
    for (let j = 0; j < i; j++) {
      result.appendChild(lis).textContent = cat[j].name; //<--aqui

Because the first for goes up to the number of clicks that may already be out how many cats you have. In addition, you do not need a for to fetch a specific element from the array.

For just cats you can do it this way:

let animals = [{
    name: 'catOne',
    species: 'cat'
  },
  {
    name: 'catTwo',
    species: 'cat'
  },
  {
    name: 'dogOne',
    species: 'dog'
  },
  {
    name: 'dogTwo',
    species: 'dog'
  },
];

let catsEl = document.getElementById('cats');
let dogsEl = document.getElementById('dogs');
let result = document.getElementById('list');

let clickCount = 0;

catsEl.addEventListener('click', function() {
  //filter só numa linha com Arrow Functions
  let cats = animals.filter(animal => animal.species === 'cat');

  if (clickCount < cats.length){ //se ainda tem elementos para por
    let lis = document.createElement('li');
    //vai buscar o gato pela posição dada pela variavel clickCount
    result.appendChild(lis).textContent = cats[clickCount].name;
  }
  else if (clickCount == cats.length){ //se está no ultimo
    let lis = document.createElement('li');
    result.appendChild(lis).textContent = "No more cats";
  }

  clickCount++;
});
html {
  font-family: Verdana;
}

.wrapper {
  display: flex;
}

.button {
  padding: 10px;
  width: 100%;
  border: 1px solid;
  width: 100px;
  text-align: center;
  margin: 0 20px;
}

.button:hover {
  background: #111;
  color: #fff;
}

ul#list li {
  padding: 10px;
  border: 1px solid #111;
  list-style-type: none;
  width: 10vw;
}
<div class="wrapper">
  <div class="button" id="cats">Cats</div>
  <div class="button" id="dogs">Dogs</div>
</div>

<div>
  <ul id="list"></ul>
</div>

In this example clickCount serves as the position where you are going to get elements to add, referring only to cats. Notice that I've used Arrow Functions in filter that simplify a lot.

Now to generalize this logic for dogs and cats it is best to create a function with logic that is common to both and just call it in each click function. This function will have to receive the species to be added, and information regarding clickcount as there will have to be a different count for each species:

let animals = [{
    name: 'catOne',
    species: 'cat'
  },
  {
    name: 'catTwo',
    species: 'cat'
  },
  {
    name: 'dogOne',
    species: 'dog'
  },
  {
    name: 'dogTwo',
    species: 'dog'
  },
];

let catsEl = document.getElementById('cats');
let dogsEl = document.getElementById('dogs');
let result = document.getElementById('list');

let clickCounts = [0, 0]; //agora um array de contagem de clicks por especie

function addAnimal(species, speciesIndex){//adicionar um animal leva especie e clicks
  let filteredAnimals = animals.filter(animal => animal.species === species);
  let clickCount = clickCounts[speciesIndex]; //obter os clicks para esta especie

  if (clickCount < filteredAnimals.length){
    let lis = document.createElement('li');
    result.appendChild(lis).textContent = filteredAnimals[clickCount].name;
  }
  else if (clickCount == filteredAnimals.length){ 
    let lis = document.createElement('li');
    result.appendChild(lis).textContent = "No more " + species + "s";
  }

  clickCounts[speciesIndex]++; //o incremento tem de ser no array
}

catsEl.addEventListener('click', function(){ 
  addAnimal('cat',0); //click para gatos passando posição dos clicks 0
});

dogsEl.addEventListener('click', function(){ 
  addAnimal('dog',1); //click para cães passando posição dos clicks 1
});
html {
  font-family: Verdana;
}

.wrapper {
  display: flex;
}

.button {
  padding: 10px;
  width: 100%;
  border: 1px solid;
  width: 100px;
  text-align: center;
  margin: 0 20px;
}

.button:hover {
  background: #111;
  color: #fff;
}

ul#list li {
  padding: 10px;
  border: 1px solid #111;
  list-style-type: none;
  width: 10vw;
}
<div class="wrapper">
  <div class="button" id="cats">Cats</div>
  <div class="button" id="dogs">Dogs</div>
</div>

<div>
  <ul id="list"></ul>
</div>

If you want you can also modify the site where each species is added in html. In this case you would also have to modify the animal addition function to get the html element where to put the result.

    
24.12.2017 / 01:29