· 4 years ago · May 01, 2021, 07:56 PM
1// Connect the variables to the UI elements
2const yearDropdown = document.getElementById("dropdown-year");
3const genreDropdown = document.getElementById("dropdown-genre");
4const searchBar = document.getElementById("search-title");
5const clearFiltersButton = document.getElementById("btn-clearFilters");
6const radioMoviesOrBooks = document.getElementsByName("moviesOrBooks");
7const mediaList = document.querySelector(".media-list");
8
9const yearsItems = [];
10const genresItems = [];
11const allMediaItems = [];
12const apiURL =
13 "https://raw.githubusercontent.com/tmoss0/media-filter/main/data.json";
14
15document.getElementById("button-show-years").addEventListener(
16 "click",
17 () => {
18 if (yearDropdown.style.display === "none") {
19 yearDropdown.style.display = "block";
20 } else {
21 yearDropdown.style.display = "none";
22 }
23 },
24 false
25);
26
27document.getElementById("button-show-genre").addEventListener(
28 "click",
29 () => {
30 if (genreDropdown.style.display === "none") {
31 genreDropdown.style.display = "block";
32 } else {
33 genreDropdown.style.display = "none";
34 }
35 },
36 false
37);
38
39window.onload = () => {
40 fetchMediaMetadata(apiURL);
41
42 radioMoviesOrBooks.forEach((selection) => {
43 selection.addEventListener("click", radioMoviesOrBooksClicked, false);
44 });
45};
46
47// Fetch data from API url link. Pass to startDisplayMediaData for parsing
48const fetchMediaMetadata = async (apiURL) => {
49 try {
50 const res = await fetch(apiURL);
51 const resMediaData = await res.json();
52 startDisplayMediaData(resMediaData);
53 } catch (error) {
54 console.log(error);
55 }
56};
57
58// Create the initial display UI of movies/books, sorted alphabetically by title
59const startDisplayMediaData = (resMediaData) => {
60 resMediaData.media.sort(sortData("title"));
61
62 for (let key in resMediaData) {
63 for (let i = 0; i < resMediaData[key].length; i++) {
64 const title = resMediaData[key][i].title;
65 const year = resMediaData[key][i].year;
66 const poster = resMediaData[key][i].poster;
67 const genres = resMediaData[key][i].genre;
68 const type = resMediaData[key][i].type;
69
70 allMediaItems[i] = [title, year, poster, genres, type];
71
72 genres = genres.map(
73 (letter) => letter.charAt(0).toUpperCase() + letter.substring(1)
74 );
75
76 if (!yearsItems.includes(year)) {
77 yearsItems.push(year);
78 }
79
80 for (let i = 0; i < genres.length; i++) {
81 if (!genresItems.includes(genres[i])) {
82 genresItems.push(genres[i]);
83 }
84 }
85
86 let mediaItemDiv = document.createElement("div");
87 mediaItemDiv.className = "media-item";
88 mediaItemDiv.innerHTML = `
89 <img class="img-poster" src="${poster}" alt="${title} Poster">
90 <h3 class="media-title">${title} (${year})</h3>
91 <h5 class="media-genres">Genres: ${genres.map(
92 (genre) => genre
93 )}</h5>
94 `;
95
96 mediaList.appendChild(mediaItemDiv);
97 }
98 }
99
100 buildDropdown(yearsItems, yearDropdown, "year");
101 buildDropdown(genresItems, genreDropdown, "genre");
102};
103
104// Updates the display after the first media items are displayed
105const updateMediaDisplay = (updatedItems) => {
106 mediaList.innerHTML = "";
107
108 for (let i = 0; i < updatedItems.length; i++) {
109 const genres = updatedItems[i][3];
110 genres = genres.map(
111 (letter) => letter.charAt(0).toUpperCase() + letter.substring(1)
112 );
113
114 let mediaItemDiv = document.createElement("div");
115 mediaItemDiv.className = "media-item";
116 mediaItemDiv.innerHTML = `
117 <img class="img-poster" src="${updatedItems[i][2]}" alt="${
118 updatedItems[i][0]
119 } Poster">
120 <h3 class="media-title">${updatedItems[i][0]} (${
121 updatedItems[i][1]
122 })</h3>
123 <h5 class="media-genres">Genres: ${genres.map(
124 (genre) => genre
125 )}</h5>
126 `;
127
128 mediaList.appendChild(mediaItemDiv);
129 }
130};
131
132// Dynamically builds the dropdowns for genre and year
133const buildDropdown = (dropdownItems, builtDropdown, mediaType) => {
134 dropdownItems.sort();
135 dropdownItems.map((mediaValue) => {
136 let dropdownBuilder = document.createElement("li");
137 dropdownBuilder.className = `select-${mediaType}`;
138 dropdownBuilder.innerHTML = `
139 <input type="checkbox" class="checkbox-${mediaType}" value="${mediaValue}">${mediaValue}
140 `;
141 builtDropdown.appendChild(dropdownBuilder);
142 });
143
144 filterCheckboxes("year");
145 filterCheckboxes("genre");
146
147 builtDropdown.style.display = "none";
148};
149
150// Assigns eventListener to each checkbox, compares checkboxes to the media
151// items, then passes the sorted values to be displayed to the user
152const filterCheckboxes = (mediaType) => {
153 let checkBoxes = document.querySelectorAll(`.checkbox-${mediaType}`);
154 let selectedValues = [];
155 let returnValues = [];
156
157 checkBoxes.forEach((checkBox) => {
158 checkBox.addEventListener("change", () => {
159 selectedValues = Array.from(checkBoxes)
160 .filter((i) => i.checked)
161 .map((i) => i.value);
162 selectedValues = selectedValues.map((index) => index.toLowerCase());
163 if (mediaType === "year") {
164 returnValues = allMediaItems.filter((element) =>
165 selectedValues.includes(element[1])
166 );
167 returnValues.sort(sortData("1"));
168 } else if (mediaType === "genre") {
169 returnValues = allMediaItems.filter((item) => {
170 return selectedValues.every((selectedValue) => {
171 return item[3].includes(selectedValue);
172 });
173 });
174 returnValues.sort(sortData("3"));
175 }
176 updateMediaDisplay(returnValues);
177 });
178 });
179};
180
181// Perform action based on radio button onClick
182const radioMoviesOrBooksClicked = () => {
183 let valueChecked;
184
185 for (let i = 0; i < radioMoviesOrBooks.length; i++) {
186 if (radioMoviesOrBooks[i].checked) {
187 valueChecked = radioMoviesOrBooks[i].value;
188 console.log(radioMoviesOrBooks[i]);
189 }
190 }
191
192 const mediaSelections = allMediaItems.filter((media) => {
193 if (media[4].includes(valueChecked)) {
194 return media[4];
195 }
196 });
197
198 updateMediaDisplay(mediaSelections);
199};
200
201// Search by title functionality (case insensitive)
202searchBar.addEventListener("keyup", (e) => {
203 const searchString = e.target.value;
204
205 const mediaSelections = allMediaItems.filter((media) => {
206 if (media[0].toLowerCase().includes(searchString.toLowerCase())) {
207 return media[0];
208 }
209 });
210
211 updateMediaDisplay(mediaSelections);
212});
213
214// Sort data based on property type
215const sortData = (property) => {
216 return (a, b) => {
217 if (a[property] > b[property]) {
218 return 1;
219 } else if (a[property] < b[property]) {
220 return -1;
221 }
222 return 0;
223 };
224};
225