const events = [
{
event: "ComicCon",
city: "New York",
state: "New York",
attendance: 240000,
date: "06/01/2017",
},
{
event: "ComicCon",
city: "New York",
state: "New York",
attendance: 250000,
date: "06/01/2018",
},
{
event: "ComicCon",
city: "New York",
state: "New York",
attendance: 257000,
date: "06/01/2019",
},
{
event: "ComicCon",
city: "San Diego",
state: "California",
attendance: 130000,
date: "06/01/2017",
},
{
event: "ComicCon",
city: "San Diego",
state: "California",
attendance: 140000,
date: "06/01/2018",
},
{
event: "ComicCon",
city: "San Diego",
state: "California",
attendance: 150000,
date: "06/01/2019",
},
{
event: "HeroesCon",
city: "Charlotte",
state: "North Carolina",
attendance: 40000,
date: "06/01/2017",
},
{
event: "HeroesCon",
city: "Charlotte",
state: "North Carolina",
attendance: 45000,
date: "06/01/2018",
},
{
event: "HeroesCon",
city: "Charlotte",
state: "North Carolina",
attendance: 50000,
date: "06/01/2019",
},
];
// build dropdown for specific cities
const buildDropDown = () => {
let dropDownMenu = document.getElementById("eventDropDown");
dropDownMenu.innerHTML = "";
let currentEvents = getEventData(); // TO - DO: get these from storage
const cityNames = currentEvents.map((event) => event.city);
const citiesSet = new Set(cityNames);
let distinctCities = [...citiesSet];
const dropDownTemplate = document.getElementById("dropDownItemTemplate");
// copy the template
let dropDownItemNode = document.importNode(dropDownTemplate.content, true);
// make our changes
let dropDownItemLink = dropDownItemNode.querySelector("a");
dropDownItemLink.innerHTML = "All Cities";
dropDownItemLink.setAttribute("data-string", "All");
// add our copy to the page
dropDownMenu.appendChild(dropDownItemNode);
for (let i = 0; i < distinctCities.length; i++) {
// get city name
let cityName = distinctCities[i];
// generate dropdown menu
let itemNode = document.importNode(dropDownTemplate.content, true);
let anchorTag = itemNode.querySelector("a");
anchorTag.innerHTML = cityName;
anchorTag.setAttribute("data-string", cityName);
// append it to the dropdown menu
dropDownMenu.appendChild(itemNode);
}
displayEventData(currentEvents);
displayStats(currentEvents);
document.getElementById('location').innerText = 'All Events';
};
const displayEventData = (currentEvents) => {
const eventTable = document.getElementById("eventTable");
const template = document.getElementById("tableRowTemplate");
eventTable.innerHTML = "";
for (let i = 0; i < currentEvents.length; i++) {
let event = currentEvents[i];
let tableRow = document.importNode(template.content, true);
tableRow.querySelector('[data-id="event"]').textContent = event.event;
tableRow.querySelector('[data-id="city"]').textContent = event.city;
tableRow.querySelector('[data-id="state"]').textContent = event.state;
tableRow.querySelector('[data-id="attendance"]').textContent =
event.attendance.toLocaleString();
tableRow.querySelector('[data-id="date"]').textContent = new Date(event.date).toLocaleDateString();
eventTable.appendChild(tableRow);
}
};
const calculateStats = (currentEvents) => {
let total = 0;
let most = currentEvents[0].attendance;
let least = currentEvents[0].attendance;
let average = 0;
currentEvents.forEach((thisEvent) => {
let currentAttendance = thisEvent.attendance;
total += currentAttendance;
if (most < currentAttendance) most = currentAttendance;
if (least > currentAttendance) least = currentAttendance;
});
average = total / currentEvents.length;
return {
total: total,
average: average,
most: most,
least: least,
};
};
const displayStats = (currentEvents) => {
let statistics = calculateStats(currentEvents);
document.getElementById("total").textContent =
statistics.total.toLocaleString();
document.getElementById("average").textContent = Math.round(
statistics.average
).toLocaleString();
document.getElementById("most").textContent =
statistics.most.toLocaleString();
document.getElementById("least").textContent =
statistics.least.toLocaleString();
};
const getEventData = () => {
let data = localStorage.getItem("stadiumStatsEventData");
if (data == null) {
localStorage.setItem("stadiumStatsEventData", JSON.stringify(events));
}
let currentEvents = data == null ? events : JSON.parse(data);
return currentEvents;
};
const viewFilteredEvents = (dropDownItem) => {
let cityName = dropDownItem.getAttribute("data-string");
// get all events
let allEvents = getEventData();
if (cityName == 'All') {
displayStats(allEvents);
displayEventData(allEvents);
document.getElementById("location").innerText = cityName;
return;
}
// filter to just selected city
let filteredEvents = allEvents.filter(
(event) => event.city.toLowerCase() == cityName.toLowerCase()
);
// display stats for those events
displayStats(filteredEvents);
// change the stats header
document.getElementById('location').innerText = cityName;
// display only those events in the table
displayEventData(filteredEvents);
};
const saveNewEvent = () => {
// get the form input values
let name = document.getElementById('eventName').value;
let city = document.getElementById('cityName').value;
let attendance = parseInt(document.getElementById('attendance').value, 10);
// let state = document.getElementById("newEventState");
let dateValue = document.getElementById('eventDate').value;
dateValue = new Date(dateValue);
let date = dateValue.toLocaleDateString();
let stateSelect = document.getElementById('newEventState');
let stateIndex = stateSelect.selectedIndex;
let state = stateSelect.options[stateIndex].text;
// create a new event object
const newEvent = {
event: name,
city: city,
state: state,
attendance: attendance,
date: date
}
// add it to the array of current events
let events = getEventData();
events.push(newEvent);
// then, save the array with the new event (local storage)
localStorage.setItem("stadiumStatsEventData", JSON.stringify(events));
buildDropDown();
}
Each task in this application being executed needs specific
instructions, so keeping these concerns carefully organized in
different functions is of primary importance for readability.
Some of the functions are for display purposes, and others are for
fetching data. Others still, are designed to sort through data to
only present content that the user wants.
Overall, I think the most interesting aspect of this application is
how it saves data that the user enters, using only JavaScript, which
is not a back end language. Much like how websites can store cookies
on your device, this app keeps note on your own machine of any
changes you've made to the content.
Going through the code now in broad terms, we start simply with an
array of objects to populate the event table by default. Next we
build a dropdown menu by mapping the city properties from each
object into an array, importing an appropriate HTML template, and
appending the content to the dropdown.
Inside of that function, we make sure to call the relevant display
functions automatically, showing the user the event data table and
updating the statistics. The displayEventData function simply
takes the passed in events, clears out the table, and loops through
each piece of information re-populating the table, cell by cell, and
row by row.
In the bottom of this function, we start calling other display
functions, so that everything needed to load onto the page is being
run automatically. displayStats doesn't get its information
from a parameter, but rather from calculateStats which checks
for minimum values, averages, and whatever other statistics we want
to feature.
In order to filter through the data to view events in a particular
city, the viewFilteredEvents function sorts through an array
of all events and simply runs displayStats as before, passing
along only relevant filtered data to be displayed i.e. events in San
Diego.
Finally, getEventData and saveNewEvent contain my
favorite functionalities. By referencing your machine's local
storage, each of them are able to manipulate .JSON files, turning
them into strings or objects as needed, to execute or store your
inputs respectively, even when you refresh or close the page.