Sorting data with JavaScript can seem like a scary and daunting task. However, it’s actually a very easy thing to do! That’s exactly what I am going to show you in this tutorial!
To begin, let’s create a couple of files: index.html, sort.js and style.css.
A working example can be found here.
Let’s open index.html and paste some basic HTML in there, which can be found in the GitHub repo for this project.
Next, open style.css and paste some premade styles there, which can be found in the GitHub repo
Neither the HTML, or the CSS are important in this tutorial, so I won’t go over them. Feel free to explore them and customize as you see fit.
Now, let’s open sort.js and start having some fun. We will start by setting up a few variables that we will need in a few minutes.
const input = document.querySelector('.input-sort'); const sortedDiv = document.querySelector('.sorted-output'); let characters = []; let apiURL = `https://hp-api.herokuapp.com/api/characters`;The first two lines just get references to the HTML elements we will need to use and modify with this project.
let characters = []; initializes an empty array where will store the character data so that we aren’t hitting the API endpoint every time we type or modify the page.
And let apiURL = `https://hp-api.herokuapp.com/api`; is just setting the API endpoint for easy use.
Next, we need to set up our page to grab the character data from the API when the page loads, and only when the page loads. This will prevent us from needing to hit the endpoint every time we type in the search box.
window.addEventListener('DOMContentLoaded', (event) => { fetch(`${apiURL}`) .then(response => response.json()) .then(data => { data.map(character => character); data.forEach(character => { characters.push({ name: character.name, house: character.house, image: character.image }); }); displayCharacters(characters); }); });This may seem a little scary but we will go through it all and you will see it isn’t all that bad.
The first line is just setting up an event listener on DOMContentLoaded (more info on MDN)
Next, we are doing a pretty simple fetch request using the API endpoint we set up earlier.
In the next line, .then(response => response.json()) is simply setting the “response” variable to the json-formatted version of the response data. This makes it easier to read and manipulate later.
In the next “then” statement, we are doing a few things, but not really that much.
data.map(character => character); seems weird, but in reality, needed to be done because of the way the data was returned from the API call. It simply loops through all the data that was returned and gives it back to us in a proper array format.
The next code is simply looping through our array of characters and only returning the info we want. This isn’t strictly necessary, but for me, it made things a little simpler when using the data.
data.forEach(character => { characters.push({ name: character.name, house: character.house, image: character.image }); });Finally, displayCharacters(characters); passes our array of characters into the function for displaying the info, that we will define in just a few minutes.
Next, we need to set up an event listener for when the user types something in our textbox. This event listener is where the real magic happens for this tutorial so pay close attention.
input.addEventListener('keyup', e => { while (sortedDiv.firstChild) { sortedDiv.removeChild(sortedDiv.firstChild); } let results = characters.filter(char => char.name.includes(e.target.value)); displayCharacters(results); });There isn’t a whole lot going on in this event but it is very important. The while loop here, is doing a bit of cleanup, just removing any child DIVs that might be living on the page from the last search, so that we can cleanly display the character info on the page.
This next bit is very much the most important piece of code in this tutorial:
let results = characters.filter(char => char.name.includes(e.target.value));
This code is responsible for sorting the data. This is where you can customize how the search works. You can make the search case-sensitive, or insensitive, limit search result numbers, etc in this bit.
So what is it doing? Well, using the filter method, we are returning only the character’s who’s names includes the text that you have typed in the searchbox.
This next bit of code looks like a lot, but despite that, isn’t actually doing all that much.
const displayCharacters = chars => { chars.forEach(char => { let charDiv = document.createElement('div'); charDiv.setAttribute('id', char.name.replace(' ', '_')); charDiv.classList.add('character-div'); let mysteryPic = 'mysteryperson.webp'; let picDiv = document.createElement('div'); picDiv.innerHTML = ``; picDiv.classList.add('pic-div'); charDiv.append(picDiv); let charNameDiv = document.createElement('div'); charNameDiv.innerText = `Name: ${char.name}`; charDiv.append(charNameDiv); let charHouseDiv = document.createElement('div'); charHouseDiv.innerText = `House: ${char.house}`; charDiv.append(charHouseDiv); sortedDiv.append(charDiv); }); }This code is just a function that loops through the characters array passed to it, and will set up a few divs with styling and populate them with the data for each character in the array that matches for this data. I won’t go into much more detail than that, as it isn’t very important for this tutorial. If you are reading this tutorial, and need more explanation on this function, please comment down below and I will do my best to explain.
That’s it! Basically one very important line of code let results = characters.filter(char => char.name.includes(e.target.value)); does the heavy lifting, and sorting of the data!
The keen-eyed among you, might have noticed that this search is case-sensitive as it is. As such, typing harry potter will not return Harry in the search results… you will need to type Harry Potter. I am leaving this for you, the reader, to explore and try for yourself! Also, if you think of any other customizations or changes you think would improve this, do them and let me know down in the comments below!