diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..2ba986f --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "chrome", + "request": "launch", + "name": "Launch Chrome against localhost", + "url": "http://localhost:8080", + "webRoot": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/helpers.js b/helpers.js new file mode 100644 index 0000000..98dfd3a --- /dev/null +++ b/helpers.js @@ -0,0 +1,54 @@ +export function handleSearch() { + const searchTerm = this.value.trim().toLowerCase(); + const episodes = document.getElementsByClassName("episode-container"); + + let matchedCount = 0; + + for (const episode of episodes) { + const episodeName = episode.querySelector("h2").textContent.toLowerCase(); + const episodeSummary = episode.querySelector("p").textContent.toLowerCase(); + + if (episodeName.includes(searchTerm) || episodeSummary.includes(searchTerm)) { + episode.style.display = "block"; + matchedCount++; + } else { + episode.style.display = "none"; + } + } + + updateMatchedCount(matchedCount); + } + + export function updateMatchedCount(count) { + const countElem = document.querySelector(".matched-count"); + + // Create the matched count element if it doesn't exist + if (!countElem) { + const parentElem = document.querySelector("main"); + const newCountElem = document.createElement("p"); + newCountElem.classList.add("matched-count"); + parentElem.insertBefore(newCountElem, parentElem.firstChild); + countElem = newCountElem; + } + + countElem.textContent = `Displaying ${count} episode(s)`; + } + + export function getEpisodeCode(season, episode) { + const seasonCode = String(season).padStart(2, "0"); + const episodeCode = String(episode).padStart(2, "0"); + return `S${seasonCode}E${episodeCode}`; + } + + + export function handleEpisodeSelection(event) { + const selectedIndex = event.target.value; + + document.querySelectorAll(".episode-container").forEach((container, index) => { + if (index === Number(selectedIndex)) { + container.style.display = "block"; + } else { + container.style.display = "none"; + } + }) + } diff --git a/index.html b/index.html index 9a400d1..46baf37 100644 --- a/index.html +++ b/index.html @@ -16,6 +16,6 @@ - + diff --git a/script.js b/script.js index 87a7de8..99e4f9a 100644 --- a/script.js +++ b/script.js @@ -1,12 +1,122 @@ -//You can edit ALL of the code here +import {handleSearch, getEpisodeCode, handleEpisodeSelection} from './helpers.js' + + function setup() { - const allEpisodes = getAllEpisodes(); - makePageForEpisodes(allEpisodes); + const allEpisodes = getAllEpisodes(); + makePageForEpisodes(allEpisodes); } function makePageForEpisodes(episodeList) { - const rootElem = document.getElementById("root"); - rootElem.textContent = `Got ${episodeList.length} episode(s)`; + const rootElem = document.getElementById("root"); + createHeader(rootElem) + + + const mainElem = document.createElement("main"); + rootElem.appendChild(mainElem); + + createNav(rootElem, episodeList) + allEpisodesDiv(rootElem, episodeList) + createFooter(rootElem) +} + +function allEpisodesDiv(parentElem, episodeList) { + const episodesContainer = document.createElement("div"); + episodesContainer.classList.add("episode-Container-MainDiv"); + + episodeList.forEach((episode) => { + const episodeContainer = document.createElement("div"); + episodeContainer.classList.add("episode-container"); + + const episodeCode = getEpisodeCode(episode.season, episode.number); + + const episodeCodeElem = document.createElement("p"); + episodeCodeElem.textContent = episodeCode; + episodeContainer.appendChild(episodeCodeElem); + + const episodeNameElem = document.createElement("h2"); + episodeNameElem.textContent = episode.name; + episodeContainer.appendChild(episodeNameElem); + + const episodeImageElem = document.createElement("img"); + episodeImageElem.src = episode.image.medium; + episodeImageElem.alt = episode.name; + episodeContainer.appendChild(episodeImageElem); + + const episodeSummaryElem = document.createElement("p"); + episodeSummaryElem.innerHTML = episode.summary; + episodeContainer.appendChild(episodeSummaryElem); + + const episodeLinkElem = document.createElement("a"); + episodeLinkElem.href = episode.url; + episodeLinkElem.textContent = "More info on TVMaze.com"; + episodeContainer.appendChild(episodeLinkElem); + + episodesContainer.appendChild(episodeContainer); + }); + + parentElem.appendChild(episodesContainer); +} + +function createHeader(parentElem) { + const headerElem = document.createElement("header"); + headerElem.classList.add("banner") + headerElem.textContent = "My Episode List"; + parentElem.appendChild(headerElem); +} + +function createNav(parentElem, episodeList) { + const navElem = document.createElement("nav"); + navElem.classList.add("nav-Banner"); + + // Create the selector section + const selectorDiv = document.createElement("div"); + selectorDiv.classList.add("selector"); + + // search bar + const searchInput = document.createElement("input"); + searchInput.type = "text"; + searchInput.placeholder = "Search episodes"; + searchInput.addEventListener("input", handleSearch); + selectorDiv.appendChild(searchInput); + + + const selectInput = document.createElement("select"); + selectInput.addEventListener("change", handleEpisodeSelection); + selectorDiv.appendChild(selectInput); + + const defaultOption = document.createElement("option"); + defaultOption.textContent = "Jump to an episode"; + selectInput.appendChild(defaultOption); + + episodeList.forEach((episode, index) => { + const option = document.createElement("option"); + const episodeCode = getEpisodeCode(episode.season, episode.number); + option.textContent = `${episodeCode} - ${ + episode.name + }`; + option.value = index; + selectInput.appendChild(option); + }); + + // Show "Show all episodes" button + const showAllButton = document.createElement("button"); + showAllButton.textContent = "Show all episodes"; + showAllButton.addEventListener("click", () => { + document.querySelectorAll(".episode-container").forEach((container) => { + container.style.display = "block"; + }); + }); + selectorDiv.appendChild(showAllButton); + + navElem.appendChild(selectorDiv); + parentElem.appendChild(navElem); +} + + +function createFooter(parentElem) { + const footerElem = document.createElement("footer"); + footerElem.textContent = " 2023 My Website"; + parentElem.appendChild(footerElem); } window.onload = setup; diff --git a/style.css b/style.css index 77cb8d4..e7d0125 100644 --- a/style.css +++ b/style.css @@ -1,3 +1,74 @@ +/* CSS */ + +/* Overall layout */ +body { + margin: 0; + padding: 0; + font-family: Arial, sans-serif; +} + #root { - color: red; + display: flex; + flex-direction: column; + align-items: center; +} + +/* Header */ +header { + background-color: #39223e; + color: #fff; + padding: 31px; + text-align: center; + width: 105%; + height: 34px; + +} + +/* Main content */ +main { + margin: 20px 0; +} + +.episode-container { + flex-basis: 25%; + padding: 10px; + box-sizing: border-box; + text-align: center; + width: 40rem; +} + +.episode-container h1 { + font-size: 18px; + margin-bottom: 10px; +} + +.episode-container img { + width: 78%; + height: auto; + margin-bottom: 10px; +} + +.episode-container p { + font-size: 14px; +} + +.episode-Container-MainDiv{ + display: flex; + flex-direction: row; + flex-wrap: wrap; + background-color: #f3f3f3; + margin: 12px 0px; +} + +.matched-count { + font-weight: bold; + margin-top: 10px; +} + +/* Footer */ +footer { + background-color: #333; + color: #fff; + padding: 20px; + text-align: center; }