-1

I have an array of years that I am using ECMAScript to filter through to find matches of animals that fall within a range between two years from another array of years.

The for loop I have inside my callback called buildList(animal) is not working in the fact that it is iterating over every year and ignoring the conditional I have placed inside the for loop.

I have worked with jQuery using two $.each, one to iterate across the years, and a nested $.each to compare the current year with the year of the animal.

** My comments in the code were stripped apparently. The expected result is to have each animal displayed but if their animaldate falls within the animalyears range then display the animaldate in and show it falls between the two years.

The example function I provided called buildList_example() demonstrates the expected outcome but is using hard coded iterators in the conditional for animalyears[0]

// array of years
let animalyears = ['1970', '1980', '1990', '2000', '2001']

// static data
let data = {
  "animals": [{
      "animaldate": "1972",
      "title": "Sparky"
    },
    {
      "animaldate": "1975",
      "title": "Max"
    },
    {
      "animaldate": "1980",
      "title": "Fido"
    },
    {
      "animaldate": "1981",
      "title": "Frank"
    },
    {
      "animaldate": "1994",
      "title": "Fiona"
    }
  ]
}


var allAnimals = data.animals;

var animalList
allAnimals.map((animal) => buildList(animal))

function buildList(animal) {
  for (var i = 0; i < animalyears.length; i++) {
    animalList += `<div class="animal">`
    if (animal.animaldate >= animalyears[i] && animal.animaldate < animalyears[i + 1]) {
      animalList += `<h1> ${animal.animaldate} </h1>`
      animalList += `<p> ${animal.title} </p>`
      animalList += `<p> Falls between ${animalyears[i]} and  ${animalyears[i + 1]}</p>`
    } else {
      animalList += `<p> ${animal.animaldate} </p>`
      animalList += `<p> ${animal.title} </p>`
    }
    animalList += `</div>`
  }

}


function buildList_example(animal) {
  animalList += `<div class="animal">`
  if (animal.animaldate >= animalyears[0] && animal.animaldate < animalyears[0 + 1]) {
    animalList += `<h1> ${animal.animaldate} </h1>`
    animalList += `<p> ${animal.title} </p>`
    animalList += `<p> Falls between ${animalyears[0]} and  ${animalyears[0 + 1]}</p>`
  } else {
    animalList += `<p> ${animal.animaldate} </p>`
    animalList += `<p> ${animal.title} </p>`
  }
  animalList += `</div>`
}

var output = document.getElementById("output")

output.innerHTML = animalList
.animal {
  border: 1px solid black;
  display: flex;
  flex-flow: column;
}
<div id="output">

</div>
ThS
  • 4,597
  • 2
  • 15
  • 27
VanCoon
  • 422
  • 4
  • 20
  • 3
    The error seems unrelated to the question. – Jonas Wilms Aug 14 '19 at 13:17
  • Is the loop supposed to add a `
    ` for each combination of year and animal? Because that's what it does right now. It's not ignoring the conditional at all, but your conditional only decides whether the loop adds a `div, p, p` or a `div, h1, p, p`. It does not skip over animals that don't fall in the year range.
    –  Aug 14 '19 at 13:23
  • No, I just caught that my comments got removed when I added them and put clarification at the top of the post. Calling buildList_example() instead shows the desired result but it's using hard coded iterators and when I add a for loop inside the function I get "undefined" returned, hence the issue. – VanCoon Aug 14 '19 at 13:27
  • 1
    Hmm. Seems weird. Anyway, something like this maybe? https://jsfiddle.net/khrismuc/90kjw6tz/ –  Aug 14 '19 at 13:32

1 Answers1

0

First of all, no need for jQuery for this task as it can be done using the forEach method (as the map returns an array that can't be used directly as HTML that is going to be assigned to innerHTML attribute).

Logic :

  • a function is created that loops through an array of objects (those with animaldate and title attributes).
  • that function constructs an HTML string based on the logic you have described and then returns it in order to be assigned to the innerHTML of an HTML element (the div#output in our case).
  • while looping through the animals (basically the data.animals), each one (animal) is compared to all the animalyears elements.

Without getting any longer, here's a demo that illustrates what being said :

const animalyears = ["1970", "1980", "1990", "2000", "2001"],
  data = {
    animals: [{
        animaldate: "1972",
        title: "Sparky"
      },
      {
        animaldate: "1975",
        title: "Max"
      },
      {
        animaldate: "1980",
        title: "Fido"
      },
      {
        animaldate: "1981",
        title: "Frank"
      },
      {
        animaldate: "1994",
        title: "Fiona"
      }
    ]
  },
  output = document.getElementById('output'),
  /** the filtering function
  * @param arr the animal array to be filtered.
  **/
  filterAnimals = arr => {
    /** the html that is going to be constructed **/
    let html = '';
    /** begining by looping through the "arr"
    * @param item the current element in the loop (from "arr").
    **/
    arr.forEach(item => {
      html += `<div class="animal"><h1>${item.animaldate}</h1>`;
      /** for every animal loop compare it to all the "animalyears" array's values 
      * @param y the current year from "animalyears".
      * @param i its index in the "animalyears" array.
      **/
      animalyears.forEach((y, i) => {
        html += `<p>${item.title}</p><p>`;
        /** while checking we ensure to check if we have an element at the index "i + 1" to prevent errors **/
        /** also the "+" sign used in front some variables is used to cast the strings into integers just to besure we compare real numbers not strings **/
        html += +item.animaldate >= +y && animalyears[i + 1] && +item.animaldate < +animalyears[i + 1] ? `Falls between ${y} and  ${animalyears[i + 1]}` : `${item.animaldate}`;
        html += `</p>`;
      });
      html += `</div>`;
    });
    /** return the constructed html **/
    return html;
  };

/** use the function **/
output.innerHTML = filterAnimals(data.animals);
.animal {
  border: 1px solid black;
  margin-top: 10px;
  padding: 0 8px;
}
<div id="output"></div>
ThS
  • 4,597
  • 2
  • 15
  • 27