From dd9b9dceeb7ac372124124d58e68d58930752761 Mon Sep 17 00:00:00 2001 From: Enice-Codes Date: Sat, 8 Aug 2026 14:38:37 +0200 Subject: [PATCH 01/20] used js to replicate tv show --- index.html | 2 +- script.js | 42 ++++++++++++++++++++++++++++++++++++------ style.css | 33 ++++++++++++++++++++++++++++++++- 3 files changed, 69 insertions(+), 8 deletions(-) diff --git a/index.html b/index.html index 9a400d1..27ba131 100644 --- a/index.html +++ b/index.html @@ -3,7 +3,7 @@ - TV Show Project | My Name (My GitHub username) + TV Show Project | Enice Mutanda(Enice-Codes) diff --git a/script.js b/script.js index 87a7de8..296d27a 100644 --- a/script.js +++ b/script.js @@ -1,12 +1,42 @@ //You can edit ALL of the code here -function setup() { - const allEpisodes = getAllEpisodes(); - makePageForEpisodes(allEpisodes); -} +// no getAllEpisodes() here at all — episodes.js already gives you one function makePageForEpisodes(episodeList) { const rootElem = document.getElementById("root"); - rootElem.textContent = `Got ${episodeList.length} episode(s)`; + rootElem.textContent = ""; + + console.log ("epispodelist:", episodeList.length); + + const counter = document.createElement("p"); + counter.textContent = `Got ${episodeList.length} episode(s)`; + rootElem.appendChild(counter); + + episodeList.forEach((episode) => { + const seasonCode = String(episode.season).padStart(2, "0"); + const episodeCode = String(episode.number).padStart(2, "0"); + const code = `S${seasonCode}E${episodeCode}`; + + const card = document.createElement("div"); + card.className = "episode-card"; + + let heading = document.createElement ("h2"); + heading.textContent = `${code} - ${episode.name}`; + card.appendChild(heading); +console.log(episode.image); + +let image = document.createElement ("img"); + image.setAttribute('src', episode.image.medium); + card.appendChild(image); + +let summary= document.createElement("p"); +summary.textContent = episode.summary; + card.appendChild(summary); + + rootElem.appendChild(card); + }); } -window.onload = setup; +window.onload = function () { + const allEpisodes = getAllEpisodes(); // this calls the one from episodes.js + makePageForEpisodes(allEpisodes); +}; \ No newline at end of file diff --git a/style.css b/style.css index 77cb8d4..de44e6e 100644 --- a/style.css +++ b/style.css @@ -1,3 +1,34 @@ #root { - color: red; + color: rgb(39, 38, 38); + display: flex; + flex-wrap: wrap; + gap: 20px; + padding: 20px; + justify-content: center; } + + +.episode-card { +border: 1px solid whitesmoke; + border-radius: 8px; + padding: 15px; + width: 300px; + +} + +.episode-card h2 { + text-align: center; + font-size: 16px; + margin-top: 0; +} + +.episode-card img { + width: 100%; + border-radius: 4px; + display: block; +} + +.episode-card p { + font-size: 14px; + color: #333; +} \ No newline at end of file From 1d6dccf0b3fbe6f7f99e928d1c9e91809c003b6e Mon Sep 17 00:00:00 2001 From: shafiekwalker7861 Date: Sat, 8 Aug 2026 17:12:29 +0200 Subject: [PATCH 02/20] Complete level 0 setup --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 9a400d1..c35a117 100644 --- a/index.html +++ b/index.html @@ -3,7 +3,7 @@ - TV Show Project | My Name (My GitHub username) + TV Show Project | Shafiek Walker (shafiekwalker7861) From e9e658956e161d0fe1877cc143d0f559cda1a512 Mon Sep 17 00:00:00 2001 From: shafiekwalker7861 Date: Sat, 8 Aug 2026 17:34:11 +0200 Subject: [PATCH 03/20] Test netlify deployment --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index c35a117..86604c9 100644 --- a/index.html +++ b/index.html @@ -11,7 +11,7 @@
- +

Netlify deployment test

From 2008b6f36b8c3b342b5e216177a739096a3200b5 Mon Sep 17 00:00:00 2001 From: shafiekwalker7861 Date: Sat, 8 Aug 2026 17:36:11 +0200 Subject: [PATCH 04/20] Remove Netlify deployment test --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 86604c9..c35a117 100644 --- a/index.html +++ b/index.html @@ -11,7 +11,7 @@
-

Netlify deployment test

+ From 1150f8e0de30a358046bb9a471b7f9b5a4530968 Mon Sep 17 00:00:00 2001 From: shafiekwalker7861 Date: Sun, 9 Aug 2026 11:54:20 +0200 Subject: [PATCH 05/20] Complete TV Show Project level 100 --- index.html | 12 ++++++++-- script.js | 36 +++++++++++++++++++++++++--- style.css | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 112 insertions(+), 6 deletions(-) diff --git a/index.html b/index.html index c35a117..bd174b2 100644 --- a/index.html +++ b/index.html @@ -9,8 +9,16 @@ -
-
+

+ +
+ +
+

+ Episode data originally provided by + TVMaze.com +

+
diff --git a/script.js b/script.js index 87a7de8..76d662e 100644 --- a/script.js +++ b/script.js @@ -1,4 +1,5 @@ -//You can edit ALL of the code here +// You can edit ALL of the code here + function setup() { const allEpisodes = getAllEpisodes(); makePageForEpisodes(allEpisodes); @@ -6,7 +7,36 @@ function setup() { function makePageForEpisodes(episodeList) { const rootElem = document.getElementById("root"); - rootElem.textContent = `Got ${episodeList.length} episode(s)`; + const episodeCount = document.getElementById("episode-count"); + + episodeCount.textContent = `Got ${episodeList.length} episode(s)`; + + for (const episode of episodeList) { + const episodeName = episode.name; + + const seasonNumber = String(episode.season).padStart(2, "0"); + const episodeNumber = String(episode.number).padStart(2, "0"); + const episodeCode = `S${seasonNumber}E${episodeNumber}`; + + const episodeCard = document.createElement("div"); + episodeCard.classList.add("episode-card"); + + const heading = document.createElement("h2"); + heading.textContent = `${episodeName} - ${episodeCode}`; + + const episodeImage = document.createElement("img"); + episodeImage.src = episode.image.medium; + episodeImage.alt = `Image for ${episodeName}`; + + const episodeSummary = document.createElement("div"); + episodeSummary.innerHTML = episode.summary; + + episodeCard.appendChild(heading); + episodeCard.appendChild(episodeImage); + episodeCard.appendChild(episodeSummary); + + rootElem.appendChild(episodeCard); + } } -window.onload = setup; +window.onload = setup; \ No newline at end of file diff --git a/style.css b/style.css index 77cb8d4..7df0e89 100644 --- a/style.css +++ b/style.css @@ -1,3 +1,71 @@ +body { + margin: 0; + font-family: Arial, sans-serif; + background: #f4f4f4; + color: #222; +} + +#episode-count { + max-width: 1200px; + margin: 20px auto; + padding: 0 20px; + font-weight: bold; +} + #root { - color: red; + max-width: 1200px; + margin: 0 auto; + padding: 20px; + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 24px; +} + +.episode-card { + background: white; + border-radius: 10px; + padding: 16px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); +} + +.episode-card h2 { + font-size: 18px; + text-align: center; + margin-top: 0; + margin-bottom: 16px; +} + +.episode-card img { + width: 100%; + height: auto; + display: block; + border-radius: 6px; +} + +.episode-card p { + line-height: 1.5; + font-size: 14px; +} + +footer { + max-width: 1200px; + margin: 30px auto; + padding: 20px; + text-align: center; +} + +footer a { + color: inherit; +} + +@media (max-width: 900px) { + #root { + grid-template-columns: repeat(2, 1fr); + } } + +@media (max-width: 600px) { + #root { + grid-template-columns: 1fr; + } +} \ No newline at end of file From 86a9d5ca1f4bd1a930702d2d6faa1617e7153a89 Mon Sep 17 00:00:00 2001 From: shafiekwalker7861 Date: Tue, 11 Aug 2026 14:12:33 +0200 Subject: [PATCH 06/20] Refactor episode card rendering --- script.js | 51 ++++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/script.js b/script.js index 296d27a..051ae26 100644 --- a/script.js +++ b/script.js @@ -1,42 +1,43 @@ -//You can edit ALL of the code here -// no getAllEpisodes() here at all — episodes.js already gives you one +function createEpisodeCard(episode) { + const seasonNumber = String(episode.season).padStart(2, "0"); + const episodeNumber = String(episode.number).padStart(2, "0"); + const episodeCode = `S${seasonNumber}E${episodeNumber}`; + + const card = document.createElement("div"); + card.className = "episode-card"; + + const heading = document.createElement("h2"); + heading.textContent = `${episodeCode} - ${episode.name}`; + card.appendChild(heading); + + const image = document.createElement("img"); + image.src = episode.image.medium; + image.alt = `Image for ${episode.name}`; + card.appendChild(image); + + const summary = document.createElement("div"); + summary.innerHTML = episode.summary; + card.appendChild(summary); + + return card; +} function makePageForEpisodes(episodeList) { const rootElem = document.getElementById("root"); - rootElem.textContent = ""; - console.log ("epispodelist:", episodeList.length); + rootElem.textContent = ""; const counter = document.createElement("p"); counter.textContent = `Got ${episodeList.length} episode(s)`; rootElem.appendChild(counter); episodeList.forEach((episode) => { - const seasonCode = String(episode.season).padStart(2, "0"); - const episodeCode = String(episode.number).padStart(2, "0"); - const code = `S${seasonCode}E${episodeCode}`; - - const card = document.createElement("div"); - card.className = "episode-card"; - - let heading = document.createElement ("h2"); - heading.textContent = `${code} - ${episode.name}`; - card.appendChild(heading); -console.log(episode.image); - -let image = document.createElement ("img"); - image.setAttribute('src', episode.image.medium); - card.appendChild(image); - -let summary= document.createElement("p"); -summary.textContent = episode.summary; - card.appendChild(summary); - + const card = createEpisodeCard(episode); rootElem.appendChild(card); }); } window.onload = function () { - const allEpisodes = getAllEpisodes(); // this calls the one from episodes.js + const allEpisodes = getAllEpisodes(); makePageForEpisodes(allEpisodes); }; \ No newline at end of file From 04956cffc89af6b38739a9a44974da339350ae9e Mon Sep 17 00:00:00 2001 From: shafiekwalker7861 Date: Mon, 17 Aug 2026 00:03:56 +0200 Subject: [PATCH 07/20] Add live episode search --- script.js | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/script.js b/script.js index 051ae26..db73398 100644 --- a/script.js +++ b/script.js @@ -1,3 +1,5 @@ +let allEpisodes = []; + function createEpisodeCard(episode) { const seasonNumber = String(episode.season).padStart(2, "0"); const episodeNumber = String(episode.number).padStart(2, "0"); @@ -28,7 +30,8 @@ function makePageForEpisodes(episodeList) { rootElem.textContent = ""; const counter = document.createElement("p"); - counter.textContent = `Got ${episodeList.length} episode(s)`; + counter.textContent = + `Displaying ${episodeList.length} / ${allEpisodes.length} episodes`; rootElem.appendChild(counter); episodeList.forEach((episode) => { @@ -37,7 +40,45 @@ function makePageForEpisodes(episodeList) { }); } +function setupSearch() { + const rootElem = document.getElementById("root"); + + const searchContainer = document.createElement("div"); + + const label = document.createElement("label"); + label.setAttribute("for", "search-input"); + label.textContent = "Search episodes: "; + + const searchInput = document.createElement("input"); + searchInput.id = "search-input"; + searchInput.type = "search"; + searchInput.placeholder = "Search by name or summary"; + + searchContainer.appendChild(label); + searchContainer.appendChild(searchInput); + + rootElem.parentNode.insertBefore(searchContainer, rootElem); + + searchInput.addEventListener("input", function () { + const searchTerm = searchInput.value.toLowerCase().trim(); + + const filteredEpisodes = allEpisodes.filter((episode) => { + const episodeName = episode.name.toLowerCase(); + const episodeSummary = (episode.summary || "").toLowerCase(); + + return ( + episodeName.includes(searchTerm) || + episodeSummary.includes(searchTerm) + ); + }); + + makePageForEpisodes(filteredEpisodes); + }); +} + window.onload = function () { - const allEpisodes = getAllEpisodes(); + allEpisodes = getAllEpisodes(); + + setupSearch(); makePageForEpisodes(allEpisodes); }; \ No newline at end of file From e8501ad23ee27c5afab6bed32fc09aff6af74405 Mon Sep 17 00:00:00 2001 From: shafiekwalker7861 Date: Mon, 17 Aug 2026 08:38:39 +0200 Subject: [PATCH 08/20] Add episode selector --- script.js | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/script.js b/script.js index db73398..53139bf 100644 --- a/script.js +++ b/script.js @@ -1,12 +1,18 @@ let allEpisodes = []; -function createEpisodeCard(episode) { +function getEpisodeCode(episode) { const seasonNumber = String(episode.season).padStart(2, "0"); const episodeNumber = String(episode.number).padStart(2, "0"); - const episodeCode = `S${seasonNumber}E${episodeNumber}`; + + return `S${seasonNumber}E${episodeNumber}`; +} + +function createEpisodeCard(episode) { + const episodeCode = getEpisodeCode(episode); const card = document.createElement("div"); card.className = "episode-card"; + card.id = `episode-${episode.id}`; const heading = document.createElement("h2"); heading.textContent = `${episodeCode} - ${episode.name}`; @@ -32,6 +38,7 @@ function makePageForEpisodes(episodeList) { const counter = document.createElement("p"); counter.textContent = `Displaying ${episodeList.length} / ${allEpisodes.length} episodes`; + rootElem.appendChild(counter); episodeList.forEach((episode) => { @@ -76,9 +83,62 @@ function setupSearch() { }); } +function setupEpisodeSelector() { + const rootElem = document.getElementById("root"); + + const selectorContainer = document.createElement("div"); + + const label = document.createElement("label"); + label.setAttribute("for", "episode-selector"); + label.textContent = "Select episode: "; + + const episodeSelector = document.createElement("select"); + episodeSelector.id = "episode-selector"; + + const defaultOption = document.createElement("option"); + defaultOption.value = ""; + defaultOption.textContent = "Choose an episode"; + episodeSelector.appendChild(defaultOption); + + allEpisodes.forEach((episode) => { + const option = document.createElement("option"); + + option.value = episode.id; + option.textContent = `${getEpisodeCode(episode)} - ${episode.name}`; + + episodeSelector.appendChild(option); + }); + + selectorContainer.appendChild(label); + selectorContainer.appendChild(episodeSelector); + + rootElem.parentNode.insertBefore(selectorContainer, rootElem); + + episodeSelector.addEventListener("change", function () { + if (episodeSelector.value === "") { + return; + } + + const searchInput = document.getElementById("search-input"); + searchInput.value = ""; + + makePageForEpisodes(allEpisodes); + + const selectedEpisode = document.getElementById( + `episode-${episodeSelector.value}` + ); + + selectedEpisode.scrollIntoView({ + behavior: "smooth", + block: "start", + }); + }); +} + window.onload = function () { allEpisodes = getAllEpisodes(); setupSearch(); + setupEpisodeSelector(); makePageForEpisodes(allEpisodes); }; \ No newline at end of file From 704b1af4d97496a51a18ef92363b66a7c9784d79 Mon Sep 17 00:00:00 2001 From: shafiekwalker7861 Date: Mon, 17 Aug 2026 08:50:53 +0200 Subject: [PATCH 09/20] Refactor episode card rendering --- script.js | 59 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/script.js b/script.js index 76d662e..8c09dba 100644 --- a/script.js +++ b/script.js @@ -1,42 +1,49 @@ // You can edit ALL of the code here -function setup() { - const allEpisodes = getAllEpisodes(); - makePageForEpisodes(allEpisodes); -} +function getEpisodeCode(episode) { + const seasonNumber = String(episode.season).padStart(2, "0"); + const episodeNumber = String(episode.number).padStart(2, "0"); -function makePageForEpisodes(episodeList) { - const rootElem = document.getElementById("root"); - const episodeCount = document.getElementById("episode-count"); + return `S${seasonNumber}E${episodeNumber}`; +} - episodeCount.textContent = `Got ${episodeList.length} episode(s)`; +function createEpisodeCard(episode) { + const episodeCard = document.createElement("div"); + episodeCard.classList.add("episode-card"); - for (const episode of episodeList) { - const episodeName = episode.name; + const heading = document.createElement("h2"); + heading.textContent = `${episode.name} - ${getEpisodeCode(episode)}`; - const seasonNumber = String(episode.season).padStart(2, "0"); - const episodeNumber = String(episode.number).padStart(2, "0"); - const episodeCode = `S${seasonNumber}E${episodeNumber}`; + const episodeImage = document.createElement("img"); + episodeImage.src = episode.image.medium; + episodeImage.alt = `Image for ${episode.name}`; - const episodeCard = document.createElement("div"); - episodeCard.classList.add("episode-card"); + const episodeSummary = document.createElement("div"); + episodeSummary.innerHTML = episode.summary; - const heading = document.createElement("h2"); - heading.textContent = `${episodeName} - ${episodeCode}`; + episodeCard.appendChild(heading); + episodeCard.appendChild(episodeImage); + episodeCard.appendChild(episodeSummary); - const episodeImage = document.createElement("img"); - episodeImage.src = episode.image.medium; - episodeImage.alt = `Image for ${episodeName}`; + return episodeCard; +} - const episodeSummary = document.createElement("div"); - episodeSummary.innerHTML = episode.summary; +function makePageForEpisodes(episodeList) { + const rootElem = document.getElementById("root"); + const episodeCount = document.getElementById("episode-count"); - episodeCard.appendChild(heading); - episodeCard.appendChild(episodeImage); - episodeCard.appendChild(episodeSummary); + rootElem.textContent = ""; + episodeCount.textContent = `Got ${episodeList.length} episode(s)`; + episodeList.forEach((episode) => { + const episodeCard = createEpisodeCard(episode); rootElem.appendChild(episodeCard); - } + }); +} + +function setup() { + const allEpisodes = getAllEpisodes(); + makePageForEpisodes(allEpisodes); } window.onload = setup; \ No newline at end of file From c625529aac9e1e73022ebbd2c6f42d43379e93cf Mon Sep 17 00:00:00 2001 From: shafiekwalker7861 Date: Mon, 17 Aug 2026 13:53:18 +0200 Subject: [PATCH 10/20] Add partner live episode search --- script.js | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/script.js b/script.js index 8c09dba..2163469 100644 --- a/script.js +++ b/script.js @@ -1,5 +1,7 @@ // You can edit ALL of the code here +let allEpisodes = []; + function getEpisodeCode(episode) { const seasonNumber = String(episode.season).padStart(2, "0"); const episodeNumber = String(episode.number).padStart(2, "0"); @@ -33,7 +35,8 @@ function makePageForEpisodes(episodeList) { const episodeCount = document.getElementById("episode-count"); rootElem.textContent = ""; - episodeCount.textContent = `Got ${episodeList.length} episode(s)`; + episodeCount.textContent = + `Displaying ${episodeList.length} / ${allEpisodes.length} episodes`; episodeList.forEach((episode) => { const episodeCard = createEpisodeCard(episode); @@ -41,8 +44,42 @@ function makePageForEpisodes(episodeList) { }); } +function setupSearch() { + const searchInput = document.createElement("input"); + searchInput.type = "search"; + searchInput.id = "search-input"; + searchInput.placeholder = "Search by name or summary"; + + const label = document.createElement("label"); + label.setAttribute("for", "search-input"); + label.textContent = "Search episodes: "; + + const rootElem = document.getElementById("root"); + + rootElem.parentNode.insertBefore(searchInput, rootElem); + rootElem.parentNode.insertBefore(label, searchInput); + + searchInput.addEventListener("input", function () { + const searchTerm = searchInput.value.toLowerCase().trim(); + + const filteredEpisodes = allEpisodes.filter((episode) => { + const episodeName = episode.name.toLowerCase(); + const episodeSummary = (episode.summary || "").toLowerCase(); + + return ( + episodeName.includes(searchTerm) || + episodeSummary.includes(searchTerm) + ); + }); + + makePageForEpisodes(filteredEpisodes); + }); +} + function setup() { - const allEpisodes = getAllEpisodes(); + allEpisodes = getAllEpisodes(); + + setupSearch(); makePageForEpisodes(allEpisodes); } From 7fb08edfc706eef4e121d3df2d0b1da0f2c6b1c8 Mon Sep 17 00:00:00 2001 From: shafiekwalker7861 Date: Mon, 17 Aug 2026 14:01:25 +0200 Subject: [PATCH 11/20] Add partner episode selector --- script.js | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/script.js b/script.js index 2163469..152e7df 100644 --- a/script.js +++ b/script.js @@ -12,6 +12,7 @@ function getEpisodeCode(episode) { function createEpisodeCard(episode) { const episodeCard = document.createElement("div"); episodeCard.classList.add("episode-card"); + episodeCard.id = `episode-${episode.id}`; const heading = document.createElement("h2"); heading.textContent = `${episode.name} - ${getEpisodeCode(episode)}`; @@ -35,6 +36,7 @@ function makePageForEpisodes(episodeList) { const episodeCount = document.getElementById("episode-count"); rootElem.textContent = ""; + episodeCount.textContent = `Displaying ${episodeList.length} / ${allEpisodes.length} episodes`; @@ -76,10 +78,66 @@ function setupSearch() { }); } +function setupEpisodeSelector() { + const rootElem = document.getElementById("root"); + + const selectorContainer = document.createElement("div"); + + const label = document.createElement("label"); + label.setAttribute("for", "episode-selector"); + label.textContent = "Select episode: "; + + const episodeSelector = document.createElement("select"); + episodeSelector.id = "episode-selector"; + + const defaultOption = document.createElement("option"); + defaultOption.value = ""; + defaultOption.textContent = "Choose an episode"; + + episodeSelector.appendChild(defaultOption); + + allEpisodes.forEach((episode) => { + const option = document.createElement("option"); + + option.value = episode.id; + option.textContent = + `${getEpisodeCode(episode)} - ${episode.name}`; + + episodeSelector.appendChild(option); + }); + + selectorContainer.appendChild(label); + selectorContainer.appendChild(episodeSelector); + + rootElem.parentNode.insertBefore(selectorContainer, rootElem); + + episodeSelector.addEventListener("change", function () { + if (episodeSelector.value === "") { + return; + } + + const searchInput = document.getElementById("search-input"); + + searchInput.value = ""; + + makePageForEpisodes(allEpisodes); + + const selectedEpisode = document.getElementById( + `episode-${episodeSelector.value}` + ); + + selectedEpisode.scrollIntoView({ + behavior: "smooth", + block: "start", + }); + }); +} + function setup() { allEpisodes = getAllEpisodes(); setupSearch(); + setupEpisodeSelector(); makePageForEpisodes(allEpisodes); } From d7780b4ed5c1b47c63d4e458ae564836ea70a9ac Mon Sep 17 00:00:00 2001 From: shafiekwalker7861 Date: Mon, 17 Aug 2026 18:09:07 +0200 Subject: [PATCH 12/20] Load episodes from TVMaze API --- episodes.js | 1855 --------------------------------------------------- index.html | 3 +- script.js | 38 +- 3 files changed, 31 insertions(+), 1865 deletions(-) delete mode 100644 episodes.js diff --git a/episodes.js b/episodes.js deleted file mode 100644 index 5ef6e9e..0000000 --- a/episodes.js +++ /dev/null @@ -1,1855 +0,0 @@ -//DO NOT EDIT THIS FILE - -//This content is from https://www.tvmaze.com/ -//specifically: https://api.tvmaze.com/shows/82/episodes - -function getOneEpisode() { - return { - id: 4952, - url: - "http://www.tvmaze.com/episodes/4952/game-of-thrones-1x01-winter-is-coming", - name: "Winter is Coming", - season: 1, - number: 1, - airdate: "2011-04-17", - airtime: "21:00", - airstamp: "2011-04-18T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2668.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2668.jpg", - }, - summary: - "

Lord Eddard Stark, ruler of the North, is summoned to court by his old friend, King Robert Baratheon, to serve as the King's Hand. Eddard reluctantly agrees after learning of a possible threat to the King's life. Eddard's bastard son Jon Snow must make a painful decision about his own future, while in the distant east Viserys Targaryen plots to reclaim his father's throne, usurped by Robert, by selling his sister in marriage.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4952", - }, - }, - }; -} - -function getAllEpisodes() { - return [ - { - id: 4952, - url: - "http://www.tvmaze.com/episodes/4952/game-of-thrones-1x01-winter-is-coming", - name: "Winter is Coming", - season: 1, - number: 1, - airdate: "2011-04-17", - airtime: "21:00", - airstamp: "2011-04-18T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2668.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2668.jpg", - }, - summary: - "

Lord Eddard Stark, ruler of the North, is summoned to court by his old friend, King Robert Baratheon, to serve as the King's Hand. Eddard reluctantly agrees after learning of a possible threat to the King's life. Eddard's bastard son Jon Snow must make a painful decision about his own future, while in the distant east Viserys Targaryen plots to reclaim his father's throne, usurped by Robert, by selling his sister in marriage.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4952", - }, - }, - }, - { - id: 4953, - url: - "http://www.tvmaze.com/episodes/4953/game-of-thrones-1x02-the-kingsroad", - name: "The Kingsroad", - season: 1, - number: 2, - airdate: "2011-04-24", - airtime: "21:00", - airstamp: "2011-04-25T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2669.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2669.jpg", - }, - summary: - "

An incident on the Kingsroad threatens Eddard and Robert's friendship. Jon and Tyrion travel to the Wall, where they discover that the reality of the Night's Watch may not match the heroic image of it.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4953", - }, - }, - }, - { - id: 4954, - url: "http://www.tvmaze.com/episodes/4954/game-of-thrones-1x03-lord-snow", - name: "Lord Snow", - season: 1, - number: 3, - airdate: "2011-05-01", - airtime: "21:00", - airstamp: "2011-05-02T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2671.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2671.jpg", - }, - summary: - "

Jon Snow attempts to find his place amongst the Night's Watch. Eddard and his daughters arrive at King's Landing.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4954", - }, - }, - }, - { - id: 4955, - url: - "http://www.tvmaze.com/episodes/4955/game-of-thrones-1x04-cripples-bastards-and-broken-things", - name: "Cripples, Bastards, and Broken Things", - season: 1, - number: 4, - airdate: "2011-05-08", - airtime: "21:00", - airstamp: "2011-05-09T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2673.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2673.jpg", - }, - summary: - "

Tyrion stops at Winterfell on his way home and gets a frosty reception from Robb Stark. Eddard's investigation into the death of his predecessor gets underway.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4955", - }, - }, - }, - { - id: 4956, - url: - "http://www.tvmaze.com/episodes/4956/game-of-thrones-1x05-the-wolf-and-the-lion", - name: "The Wolf and the Lion", - season: 1, - number: 5, - airdate: "2011-05-15", - airtime: "21:00", - airstamp: "2011-05-16T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2674.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2674.jpg", - }, - summary: - "

Catelyn's actions on the road have repercussions for Eddard. Tyrion enjoys the dubious hospitality of the Eyrie.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4956", - }, - }, - }, - { - id: 4957, - url: - "http://www.tvmaze.com/episodes/4957/game-of-thrones-1x06-a-golden-crown", - name: "A Golden Crown", - season: 1, - number: 6, - airdate: "2011-05-22", - airtime: "21:00", - airstamp: "2011-05-23T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2676.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2676.jpg", - }, - summary: - "

Viserys is increasingly frustrated by the lack of progress towards gaining his crown.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4957", - }, - }, - }, - { - id: 4958, - url: - "http://www.tvmaze.com/episodes/4958/game-of-thrones-1x07-you-win-or-you-die", - name: "You Win or You Die", - season: 1, - number: 7, - airdate: "2011-05-29", - airtime: "21:00", - airstamp: "2011-05-30T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2677.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2677.jpg", - }, - summary: - "

Eddard's investigations in King's Landing reach a climax and a dark secret is revealed.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4958", - }, - }, - }, - { - id: 4959, - url: - "http://www.tvmaze.com/episodes/4959/game-of-thrones-1x08-the-pointy-end", - name: "The Pointy End", - season: 1, - number: 8, - airdate: "2011-06-05", - airtime: "21:00", - airstamp: "2011-06-06T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2678.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2678.jpg", - }, - summary: - "

Tyrion joins his father's army with unexpected allies. Events in King's Landing take a turn for the worse as Arya's lessons are put to the test.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4959", - }, - }, - }, - { - id: 4960, - url: "http://www.tvmaze.com/episodes/4960/game-of-thrones-1x09-baelor", - name: "Baelor", - season: 1, - number: 9, - airdate: "2011-06-12", - airtime: "21:00", - airstamp: "2011-06-13T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2679.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2679.jpg", - }, - summary: - "

Catelyn must negotiate with the irascible Lord Walder Frey.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4960", - }, - }, - }, - { - id: 4961, - url: - "http://www.tvmaze.com/episodes/4961/game-of-thrones-1x10-fire-and-blood", - name: "Fire and Blood", - season: 1, - number: 10, - airdate: "2011-06-19", - airtime: "21:00", - airstamp: "2011-06-20T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2681.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2681.jpg", - }, - summary: - "

Daenerys must realize her destiny. Jaime finds himself in an unfamiliar predicament.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4961", - }, - }, - }, - { - id: 4962, - url: - "http://www.tvmaze.com/episodes/4962/game-of-thrones-2x01-the-north-remembers", - name: "The North Remembers", - season: 2, - number: 1, - airdate: "2012-04-01", - airtime: "21:00", - airstamp: "2012-04-02T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/3174.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/3174.jpg", - }, - summary: - "

War grips the continent of Westeros. As Tyrion Lannister tries to take his strong-willed nephew in hand in King's Landing, Stannis Baratheon launches his own campaign to take the Iron Throne with the help of a mysterious priestess. In the east, Daenerys must lead her retinue through a desolate wasteland whilst beyond the Wall the Night's Watch seeks the aid of a wildling.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4962", - }, - }, - }, - { - id: 4963, - url: - "http://www.tvmaze.com/episodes/4963/game-of-thrones-2x02-the-night-lands", - name: "The Night Lands", - season: 2, - number: 2, - airdate: "2012-04-08", - airtime: "21:00", - airstamp: "2012-04-09T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/3175.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/3175.jpg", - }, - summary: - "

Stannis uses Ser Davos to seek out new allies for his war with the Lannisters. On the road north, Arya confides in Gendry. Robb Stark sends Theon Greyjoy to win an alliance with his father and the fierce warriors of the Iron Islands. Cersei and Tyrion clash on how to rule in King's Landing.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4963", - }, - }, - }, - { - id: 4964, - url: - "http://www.tvmaze.com/episodes/4964/game-of-thrones-2x03-what-is-dead-may-never-die", - name: "What is Dead May Never Die", - season: 2, - number: 3, - airdate: "2012-04-15", - airtime: "21:00", - airstamp: "2012-04-16T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/3176.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/3176.jpg", - }, - summary: - "

Catelyn Stark treats with King Renly in the hope of winning an alliance. Tyrion undertakes a complex plan in King's Landing to expose an enemy. At Winterfell, Bran's dreams continue to trouble him.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4964", - }, - }, - }, - { - id: 4965, - url: - "http://www.tvmaze.com/episodes/4965/game-of-thrones-2x04-garden-of-bones", - name: "Garden of Bones", - season: 2, - number: 4, - airdate: "2012-04-22", - airtime: "21:00", - airstamp: "2012-04-23T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/3177.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/3177.jpg", - }, - summary: - "

Tyrion attempts to restrain Joffrey's cruelty. Catelyn attempts to broker a peace between Stannis and Renly. Daenerys and her followers arrive at the great city of Qarth and hope to find refuge there. Arya and Gendry arrive at Harrenhal, a great castle now under Lannister occupation.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4965", - }, - }, - }, - { - id: 4966, - url: - "http://www.tvmaze.com/episodes/4966/game-of-thrones-2x05-the-ghost-of-harrenhal", - name: "The Ghost of Harrenhal", - season: 2, - number: 5, - airdate: "2012-04-29", - airtime: "21:00", - airstamp: "2012-04-30T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/3178.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/3178.jpg", - }, - summary: - "

Confusion rages in the Stormlands in the wake of a devastating reversal. Catelyn must flee with a new ally, whilst Littlefinger sees an opportunity in the chaos. Theon seeks to prove himself to his father in battle. Arya receives a promise from the enigmatic Jaqen H'ghar. The Night's Watch arrives at the Fist of the First Men. Daenerys Targaryen receives a marriage proposal.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4966", - }, - }, - }, - { - id: 4967, - url: - "http://www.tvmaze.com/episodes/4967/game-of-thrones-2x06-the-old-gods-and-the-new", - name: "The Old Gods and the New", - season: 2, - number: 6, - airdate: "2012-05-06", - airtime: "21:00", - airstamp: "2012-05-07T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/3180.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/3180.jpg", - }, - summary: - "

Arya has a surprise visitor; Dany vows to take what is hers; Joffrey meets his subjects; Qhorin gives Jon a chance to prove himself.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4967", - }, - }, - }, - { - id: 4968, - url: - "http://www.tvmaze.com/episodes/4968/game-of-thrones-2x07-a-man-without-honor", - name: "A Man Without Honor", - season: 2, - number: 7, - airdate: "2012-05-13", - airtime: "21:00", - airstamp: "2012-05-14T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/3192.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/3192.jpg", - }, - summary: - "

Jaime meets a relative; Theon hunts; Dany receives an invitation.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4968", - }, - }, - }, - { - id: 4969, - url: - "http://www.tvmaze.com/episodes/4969/game-of-thrones-2x08-the-prince-of-winterfell", - name: "The Prince of Winterfell", - season: 2, - number: 8, - airdate: "2012-05-20", - airtime: "21:00", - airstamp: "2012-05-21T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/3194.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/3194.jpg", - }, - summary: - "

Theon holds the fort; Arya calls in her debt with Jaqen; Robb is betrayed; Stannis and Davos approach their destination.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4969", - }, - }, - }, - { - id: 4970, - url: - "http://www.tvmaze.com/episodes/4970/game-of-thrones-2x09-blackwater", - name: "Blackwater", - season: 2, - number: 9, - airdate: "2012-05-27", - airtime: "21:00", - airstamp: "2012-05-28T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/3196.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/3196.jpg", - }, - summary: - "

A massive battle rages for control of King's Landing and the Iron Throne.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4970", - }, - }, - }, - { - id: 4971, - url: - "http://www.tvmaze.com/episodes/4971/game-of-thrones-2x10-valar-morghulis", - name: "Valar Morghulis", - season: 2, - number: 10, - airdate: "2012-06-03", - airtime: "21:00", - airstamp: "2012-06-04T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/3197.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/3197.jpg", - }, - summary: - "

Tyrion awakens to a changed situation. King Joffrey doles out rewards to his subjects. As Theon stirs his men to action, Luwin offers some final advice. Brienne silences Jaime; Arya receives a gift from Jaqen; Dany goes to a strange place; Jon proves himself to Qhorin.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4971", - }, - }, - }, - { - id: 4972, - url: - "http://www.tvmaze.com/episodes/4972/game-of-thrones-3x01-valar-dohaeris", - name: "Valar Dohaeris", - season: 3, - number: 1, - airdate: "2013-03-31", - airtime: "21:00", - airstamp: "2013-04-01T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2628.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2628.jpg", - }, - summary: - "

Jon is brought before Mance Rayder, the King Beyond the Wall, while the Night's Watch survivors retreat south. In King's Landing, Tyrion asks for his reward. Littlefinger offers Sansa a way out. Cersei hosts a dinner for the royal family. Daenerys sails into Slaver's Bay.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4972", - }, - }, - }, - { - id: 4973, - url: - "http://www.tvmaze.com/episodes/4973/game-of-thrones-3x02-dark-wings-dark-words", - name: "Dark Wings, Dark Words", - season: 3, - number: 2, - airdate: "2013-04-07", - airtime: "21:00", - airstamp: "2013-04-08T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2618.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2618.jpg", - }, - summary: - "

Sansa says too much. Shae asks Tyrion for a favor. Jaime finds a way to pass the time. Arya runs into the Brotherhood Without Banners.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4973", - }, - }, - }, - { - id: 4974, - url: - "http://www.tvmaze.com/episodes/4974/game-of-thrones-3x03-walk-of-punishment", - name: "Walk of Punishment", - season: 3, - number: 3, - airdate: "2013-04-14", - airtime: "21:00", - airstamp: "2013-04-15T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2616.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2616.jpg", - }, - summary: - "

Tyrion shoulders new responsibilities. Jon is taken to the Fist of the First Men. Daenerys meets with the slavers. Jaime strikes a deal with his captors.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4974", - }, - }, - }, - { - id: 4975, - url: - "http://www.tvmaze.com/episodes/4975/game-of-thrones-3x04-and-now-his-watch-is-ended", - name: "And Now His Watch is Ended", - season: 3, - number: 4, - airdate: "2013-04-21", - airtime: "21:00", - airstamp: "2013-04-22T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2615.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2615.jpg", - }, - summary: - "

The Night's Watch takes stock. Varys meets his better. Arya is taken to the commander of the Brotherhood. Daenerys exchanges a chain for a Whip.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4975", - }, - }, - }, - { - id: 4976, - url: - "http://www.tvmaze.com/episodes/4976/game-of-thrones-3x05-kissed-by-fire", - name: "Kissed by Fire", - season: 3, - number: 5, - airdate: "2013-04-28", - airtime: "21:00", - airstamp: "2013-04-29T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2614.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2614.jpg", - }, - summary: - "

The Hound is judged by the gods; Jaime is judged by men. Jon proves himself; Robb is betrayed. Tyrion learns the cost of weddings.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4976", - }, - }, - }, - { - id: 4977, - url: "http://www.tvmaze.com/episodes/4977/game-of-thrones-3x06-the-climb", - name: "The Climb", - season: 3, - number: 6, - airdate: "2013-05-05", - airtime: "21:00", - airstamp: "2013-05-06T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2612.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2612.jpg", - }, - summary: - "

Tywin plans strategic unions for the Lannisters. Melisandre visits the Riverlands. Robb weighs a compromise to repair his alliance with House Frey. Roose Bolton decides what to do with Jaime Lannister. Jon, Ygritte and the Wildlings face a daunting climb.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4977", - }, - }, - }, - { - id: 4978, - url: - "http://www.tvmaze.com/episodes/4978/game-of-thrones-3x07-the-bear-and-the-maiden-fair", - name: "The Bear and the Maiden Fair", - season: 3, - number: 7, - airdate: "2013-05-12", - airtime: "21:00", - airstamp: "2013-05-13T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2611.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2611.jpg", - }, - summary: - "

Daenerys exchanges gifts with a slave lord outside Yunkai. As Sansa frets about her prospects, Shae chafes at Tyrion's new situation. Tywin counsels the king, and Melisandre reveals a secret to Gendry. Brienne faces a formidable foe in Harrenhal.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4978", - }, - }, - }, - { - id: 4979, - url: - "http://www.tvmaze.com/episodes/4979/game-of-thrones-3x08-second-sons", - name: "Second Sons", - season: 3, - number: 8, - airdate: "2013-05-19", - airtime: "21:00", - airstamp: "2013-05-20T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2599.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2599.jpg", - }, - summary: - "

King's Landing hosts a wedding, and Tyrion and Sansa spend the night together. Daenerys meets the Titan's Bastard. Davos demands proof from Melisandre. Sam and Gilly meet an older Gentleman.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4979", - }, - }, - }, - { - id: 4980, - url: - "http://www.tvmaze.com/episodes/4980/game-of-thrones-3x09-the-rains-of-castamere", - name: "The Rains of Castamere", - season: 3, - number: 9, - airdate: "2013-06-02", - airtime: "21:00", - airstamp: "2013-06-03T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2598.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2598.jpg", - }, - summary: - "

Robb presents himself to Walder Frey, and Edmure meets his bride. Jon faces his harshest test yet. Bran discovers a new gift. Daario and Jorah debate how to take Yunkai. House Frey joins with House Tully.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4980", - }, - }, - }, - { - id: 4981, - url: "http://www.tvmaze.com/episodes/4981/game-of-thrones-3x10-mhysa", - name: "Mhysa", - season: 3, - number: 10, - airdate: "2013-06-09", - airtime: "21:00", - airstamp: "2013-06-10T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2597.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2597.jpg", - }, - summary: - "

Joffrey challenges Tywin. Bran tells a ghost story. In Dragonstone, mercy comes from strange quarters. Daenerys waits to see if she is a conqueror or a liberator.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4981", - }, - }, - }, - { - id: 4982, - url: - "http://www.tvmaze.com/episodes/4982/game-of-thrones-4x01-two-swords", - name: "Two Swords", - season: 4, - number: 1, - airdate: "2014-04-06", - airtime: "21:00", - airstamp: "2014-04-07T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2583.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2583.jpg", - }, - summary: - "

Tyrion welcomes a guest to King's Landing. At Castle Black, Jon Snow finds himself unwelcome. Dany is pointed to Meereen, the mother of all slave cities. Arya runs into an old friend.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4982", - }, - }, - }, - { - id: 4983, - url: - "http://www.tvmaze.com/episodes/4983/game-of-thrones-4x02-the-lion-and-the-rose", - name: "The Lion and the Rose", - season: 4, - number: 2, - airdate: "2014-04-13", - airtime: "21:00", - airstamp: "2014-04-14T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2584.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2584.jpg", - }, - summary: - "

Tyrion lends Jaime a hand. Joffrey and Margaery host a breakfast. At Dragonstone, Stannis loses patience with Davos. Ramsay finds a purpose for his pet. North of the Wall, Bran sees where they must go.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4983", - }, - }, - }, - { - id: 4984, - url: - "http://www.tvmaze.com/episodes/4984/game-of-thrones-4x03-breaker-of-chains", - name: "Breaker of Chains", - season: 4, - number: 3, - airdate: "2014-04-20", - airtime: "21:00", - airstamp: "2014-04-21T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2585.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2585.jpg", - }, - summary: - "

Tyrion ponders his options. Tywin extends an olive branch. Sam realizes Castle Black isn't safe, and Jon proposes a bold plan. The Hound teaches Arya the way things are. Dany chooses her Champion.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4984", - }, - }, - }, - { - id: 4985, - url: - "http://www.tvmaze.com/episodes/4985/game-of-thrones-4x04-oathkeeper", - name: "Oathkeeper", - season: 4, - number: 4, - airdate: "2014-04-27", - airtime: "21:00", - airstamp: "2014-04-28T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2586.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2586.jpg", - }, - summary: - "

Dany balances justice and mercy. Jaime tasks Brienne with his honor. Jon secures volunteers while Bran, Jojen, Meera and Hodor stumble on shelter.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4985", - }, - }, - }, - { - id: 4986, - url: - "http://www.tvmaze.com/episodes/4986/game-of-thrones-4x05-first-of-his-name", - name: "First of His Name", - season: 4, - number: 5, - airdate: "2014-05-04", - airtime: "21:00", - airstamp: "2014-05-05T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2587.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2587.jpg", - }, - summary: - "

Cersei and Tywin plot the Crown's next move. Dany discusses future plans. Jon embarks on a new mission.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4986", - }, - }, - }, - { - id: 4987, - url: - "http://www.tvmaze.com/episodes/4987/game-of-thrones-4x06-the-laws-of-gods-and-men", - name: "The Laws of Gods and Men", - season: 4, - number: 6, - airdate: "2014-05-11", - airtime: "21:00", - airstamp: "2014-05-12T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2588.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2588.jpg", - }, - summary: - "

Stannis and Davos set sail with a new strategy. Dany meets with supplicants. Tyrion faces down his father in the throne room.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4987", - }, - }, - }, - { - id: 4988, - url: - "http://www.tvmaze.com/episodes/4988/game-of-thrones-4x07-mockingbird", - name: "Mockingbird", - season: 4, - number: 7, - airdate: "2014-05-18", - airtime: "21:00", - airstamp: "2014-05-19T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2589.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2589.jpg", - }, - summary: - "

Tyrion enlists an unlikely ally. Daario entreats Dany to allow him to do what he does best. Jon's warnings about the Wall's vulnerability fall on deaf ears. Brienne follows a new lead on the road with Pod.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4988", - }, - }, - }, - { - id: 4989, - url: - "http://www.tvmaze.com/episodes/4989/game-of-thrones-4x08-the-mountain-and-the-viper", - name: "The Mountain and the Viper", - season: 4, - number: 8, - airdate: "2014-06-01", - airtime: "21:00", - airstamp: "2014-06-02T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2591.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2591.jpg", - }, - summary: - "

Mole's Town receives unexpected visitors. Littlefinger's motives are questioned. Ramsay attempts to prove himself to his father. Tyrion's fate is decided.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4989", - }, - }, - }, - { - id: 4990, - url: - "http://www.tvmaze.com/episodes/4990/game-of-thrones-4x09-the-watchers-on-the-wall", - name: "The Watchers on the Wall", - season: 4, - number: 9, - airdate: "2014-06-08", - airtime: "21:00", - airstamp: "2014-06-09T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2593.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2593.jpg", - }, - summary: - "

Jon Snow and the rest of the Night's Watch face the biggest challenge to the Wall yet.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4990", - }, - }, - }, - { - id: 4991, - url: - "http://www.tvmaze.com/episodes/4991/game-of-thrones-4x10-the-children", - name: "The Children", - season: 4, - number: 10, - airdate: "2014-06-15", - airtime: "21:00", - airstamp: "2014-06-16T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2594.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2594.jpg", - }, - summary: - "

An unexpected arrival north of the Wall changes circumstances. Dany is forced to face harsh realities. Bran learns more of his destiny. Tyrion sees the truth of his situation.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4991", - }, - }, - }, - { - id: 116522, - url: - "http://www.tvmaze.com/episodes/116522/game-of-thrones-5x01-the-wars-to-come", - name: "The Wars to Come", - season: 5, - number: 1, - airdate: "2015-04-12", - airtime: "21:00", - airstamp: "2015-04-13T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/10/25988.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/10/25988.jpg", - }, - summary: - "

Varys discusses a conspiracy with Tyrion; Daenerys' rule faces a new threat; Jon finds himself between two kings; and Cersei and Jaime try to move on from Tywin's demise.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/116522", - }, - }, - }, - { - id: 144328, - url: - "http://www.tvmaze.com/episodes/144328/game-of-thrones-5x02-the-house-of-black-and-white", - name: "The House of Black and White", - season: 5, - number: 2, - airdate: "2015-04-19", - airtime: "21:00", - airstamp: "2015-04-20T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/10/25989.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/10/25989.jpg", - }, - summary: - "

Arya arrives in Braavos; Brienne and Podrick find danger while traveling; Cersei worries about Myrcella in Dorne when Ellaria Sand seeks revenge for Oberyn's death; Jon is tempted by Stannis.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/144328", - }, - }, - }, - { - id: 144329, - url: - "http://www.tvmaze.com/episodes/144329/game-of-thrones-5x03-high-sparrow", - name: "High Sparrow", - season: 5, - number: 3, - airdate: "2015-04-26", - airtime: "21:00", - airstamp: "2015-04-27T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/10/25990.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/10/25990.jpg", - }, - summary: - "

Cersei meets the High Sparrow after learning of a clergyman's embarrassing tale. Meanwhile, Davos talks to Jon about the future of Winterfell, where Ramsay Snow has just learned the identity of his future bride; Arya grows impatient doing menial tasks in the House of Black and White; and Tyrion searches for more comfortable surroundings on a long trip with Varys.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/144329", - }, - }, - }, - { - id: 144330, - url: - "http://www.tvmaze.com/episodes/144330/game-of-thrones-5x04-sons-of-the-harpy", - name: "Sons of the Harpy", - season: 5, - number: 4, - airdate: "2015-05-03", - airtime: "21:00", - airstamp: "2015-05-04T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/10/26444.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/10/26444.jpg", - }, - summary: - "

Margaery seeks prudent counsel. Jaime Struggles in foreign lands. Dany answers the Harpy's call.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/144330", - }, - }, - }, - { - id: 151777, - url: - "http://www.tvmaze.com/episodes/151777/game-of-thrones-5x05-kill-the-boy", - name: "Kill the Boy", - season: 5, - number: 5, - airdate: "2015-05-10", - airtime: "21:00", - airstamp: "2015-05-11T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/10/26819.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/10/26819.jpg", - }, - summary: - "

Dany makes a difficult decision in Meereen. Jon recruits the help of an unexpected ally. Brienne searches for Sansa. Theon remains under Ramsay's control.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/151777", - }, - }, - }, - { - id: 152766, - url: - "http://www.tvmaze.com/episodes/152766/game-of-thrones-5x06-unbowed-unbent-unbroken", - name: "Unbowed, Unbent, Unbroken", - season: 5, - number: 6, - airdate: "2015-05-17", - airtime: "21:00", - airstamp: "2015-05-18T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/10/27259.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/10/27259.jpg", - }, - summary: - "

Arya trains. Jorah and Tyrion run into slavers. Trystane and Myrcella make plans. Jaime and Bronn reach their destination. The Sand Snakes attack.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/152766", - }, - }, - }, - { - id: 153327, - url: - "http://www.tvmaze.com/episodes/153327/game-of-thrones-5x07-the-gift", - name: "The Gift", - season: 5, - number: 7, - airdate: "2015-05-24", - airtime: "21:00", - airstamp: "2015-05-25T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/11/27535.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/11/27535.jpg", - }, - summary: - "

Jon prepares for conflict. Sansa tries to talk to Theon. Brienne waits for a sign. Stannis remains stubborn. Jaime attempts to reconnect with family.



", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/153327", - }, - }, - }, - { - id: 155299, - url: - "http://www.tvmaze.com/episodes/155299/game-of-thrones-5x08-hardhome", - name: "Hardhome", - season: 5, - number: 8, - airdate: "2015-05-31", - airtime: "21:00", - airstamp: "2015-06-01T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/11/28151.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/11/28151.jpg", - }, - summary: - "

Arya makes progress in her training. Sansa confronts an old friend. Cersei struggles. Jon travels.



", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/155299", - }, - }, - }, - { - id: 160040, - url: - "http://www.tvmaze.com/episodes/160040/game-of-thrones-5x09-the-dance-of-dragons", - name: "The Dance of Dragons", - season: 5, - number: 9, - airdate: "2015-06-07", - airtime: "21:00", - airstamp: "2015-06-08T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/11/29160.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/11/29160.jpg", - }, - summary: - "

Stannis confronts a troubling decision. Jon returns to The Wall. Mace visits the Iron Bank. Arya encounters someone from her past. Dany reluctantly oversees a traditional celebration of athleticism.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/160040", - }, - }, - }, - { - id: 162186, - url: - "http://www.tvmaze.com/episodes/162186/game-of-thrones-5x10-mothers-mercy", - name: "Mother's Mercy", - season: 5, - number: 10, - airdate: "2015-06-14", - airtime: "21:00", - airstamp: "2015-06-15T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/12/30012.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/12/30012.jpg", - }, - summary: - "

Cersei seeks forgiveness; Jon faces a new challenge; Arya plots to cross a name off her list; Tyrion sees a familiar face; and Daenerys finds herself surrounded by strangers.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/162186", - }, - }, - }, - { - id: 560813, - url: - "http://www.tvmaze.com/episodes/560813/game-of-thrones-6x01-the-red-woman", - name: "The Red Woman", - season: 6, - number: 1, - airdate: "2016-04-24", - airtime: "21:00", - airstamp: "2016-04-25T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/56/142371.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/56/142371.jpg", - }, - summary: - "

Jon Snow is dead. Daenerys meets a strong man. Cersei sees her daughter again.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/560813", - }, - }, - }, - { - id: 664672, - url: "http://www.tvmaze.com/episodes/664672/game-of-thrones-6x02-home", - name: "Home", - season: 6, - number: 2, - airdate: "2016-05-01", - airtime: "21:00", - airstamp: "2016-05-02T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/56/142372.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/56/142372.jpg", - }, - summary: - "

Bran trains with the Three-Eyed Raven. In King's Landing, Jaime advises Tommen. Tyrion demands good news, but has to make his own. At Castle Black, the Night's Watch stands behind Thorne. Ramsay Bolton proposes a plan, and Balon Greyjoy entertains other proposals.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/664672", - }, - }, - }, - { - id: 664673, - url: - "http://www.tvmaze.com/episodes/664673/game-of-thrones-6x03-oathbreaker", - name: "Oathbreaker", - season: 6, - number: 3, - airdate: "2016-05-08", - airtime: "21:00", - airstamp: "2016-05-09T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/56/142370.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/56/142370.jpg", - }, - summary: - "

Daenerys meets her future. Bran meets the past. Tommen confronts the High Sparrow. Arya trains to be No One. Varys finds an answer. Ramsay gets a gift.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/664673", - }, - }, - }, - { - id: 664674, - url: - "http://www.tvmaze.com/episodes/664674/game-of-thrones-6x04-book-of-the-stranger", - name: "Book of the Stranger", - season: 6, - number: 4, - airdate: "2016-05-15", - airtime: "21:00", - airstamp: "2016-05-16T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/56/142273.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/56/142273.jpg", - }, - summary: - "

Tyrion strikes a deal. Jorah and Daario undertake a difficult task. Jaime and Cersei try to improve their situation.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/664674", - }, - }, - }, - { - id: 664675, - url: - "http://www.tvmaze.com/episodes/664675/game-of-thrones-6x05-the-door", - name: "The Door", - season: 6, - number: 5, - airdate: "2016-05-22", - airtime: "21:00", - airstamp: "2016-05-23T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/60/150273.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/60/150273.jpg", - }, - summary: - "

Tyrion seeks a strange ally. Bran learns a great deal. Brienne goes on a mission. Arya is given a chance to prove herself.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/664675", - }, - }, - }, - { - id: 664676, - url: - "http://www.tvmaze.com/episodes/664676/game-of-thrones-6x06-blood-of-my-blood", - name: "Blood of My Blood", - season: 6, - number: 6, - airdate: "2016-05-29", - airtime: "21:00", - airstamp: "2016-05-30T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/60/150274.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/60/150274.jpg", - }, - summary: - "

An old foe comes back into the picture. Gilly meets Sam's family. Arya faces a difficult choice. Jaime faces off against the High Sparrow.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/664676", - }, - }, - }, - { - id: 717449, - url: - "http://www.tvmaze.com/episodes/717449/game-of-thrones-6x07-the-broken-man", - name: "The Broken Man", - season: 6, - number: 7, - airdate: "2016-06-05", - airtime: "21:00", - airstamp: "2016-06-06T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/60/150275.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/60/150275.jpg", - }, - summary: - "

The High Sparrow eyes another target. Jaime confronts a hero. Arya makes a plan. The North is reminded.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/717449", - }, - }, - }, - { - id: 729573, - url: "http://www.tvmaze.com/episodes/729573/game-of-thrones-6x08-no-one", - name: "No One", - season: 6, - number: 8, - airdate: "2016-06-12", - airtime: "21:00", - airstamp: "2016-06-13T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/61/153044.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/61/153044.jpg", - }, - summary: - "

Jaime encounters a hero; the High Sparrow fixates on another prey; Arya hatches a new plan; Yara and Theon plot their next move; Olenna and Cersei discuss their families' futures.

While Jaime weighs his options, Cersei answers a request. Tyrion's plans bear fruit. Arya faces a new test.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/729573", - }, - }, - }, - { - id: 729574, - url: - "http://www.tvmaze.com/episodes/729574/game-of-thrones-6x09-battle-of-the-bastards", - name: "Battle of the Bastards", - season: 6, - number: 9, - airdate: "2016-06-19", - airtime: "21:00", - airstamp: "2016-06-20T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/62/155042.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/62/155042.jpg", - }, - summary: - "

Ramsay surprises his audience. Jon retaliates. Dany is true to her word.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/729574", - }, - }, - }, - { - id: 729575, - url: - "http://www.tvmaze.com/episodes/729575/game-of-thrones-6x10-the-winds-of-winter", - name: "The Winds of Winter", - season: 6, - number: 10, - airdate: "2016-06-26", - airtime: "21:00", - airstamp: "2016-06-27T01:00:00+00:00", - runtime: 69, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/63/157920.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/63/157920.jpg", - }, - summary: - "

Alliances are made, the High Sparrow is holding trials at King's Landing, Daenerys is sailing for the Seven Kingdoms and a new King of the North is crowned.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/729575", - }, - }, - }, - { - id: 937256, - url: - "http://www.tvmaze.com/episodes/937256/game-of-thrones-7x01-dragonstone", - name: "Dragonstone", - season: 7, - number: 1, - airdate: "2017-07-16", - airtime: "21:00", - airstamp: "2017-07-17T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/120/302038.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/120/302038.jpg", - }, - summary: - "

Jon organizes the defense of the North. Cersei tries to even the odds. Daenerys comes home.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/937256", - }, - }, - }, - { - id: 1221410, - url: - "http://www.tvmaze.com/episodes/1221410/game-of-thrones-7x02-stormborn", - name: "Stormborn", - season: 7, - number: 2, - airdate: "2017-07-23", - airtime: "21:00", - airstamp: "2017-07-24T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/120/302047.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/120/302047.jpg", - }, - summary: - "

Daenerys receives an unexpected visitor. Jon faces a revolt. Tyrion plans the conquest of Westeros.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/1221410", - }, - }, - }, - { - id: 1221411, - url: - "http://www.tvmaze.com/episodes/1221411/game-of-thrones-7x03-the-queens-justice", - name: "The Queen's Justice", - season: 7, - number: 3, - airdate: "2017-07-30", - airtime: "21:00", - airstamp: "2017-07-31T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/122/306938.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/122/306938.jpg", - }, - summary: - "

Daenerys holds court. Cersei returns a gift. Jaime learns from his mistakes.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/1221411", - }, - }, - }, - { - id: 1221412, - url: - "http://www.tvmaze.com/episodes/1221412/game-of-thrones-7x04-the-spoils-of-war", - name: "The Spoils of War", - season: 7, - number: 4, - airdate: "2017-08-06", - airtime: "21:00", - airstamp: "2017-08-07T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/123/307677.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/123/307677.jpg", - }, - summary: - "

Arya gets to the final destination. Daenerys takes it upon herself to strike back.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/1221412", - }, - }, - }, - { - id: 1221413, - url: - "http://www.tvmaze.com/episodes/1221413/game-of-thrones-7x05-eastwatch", - name: "Eastwatch", - season: 7, - number: 5, - airdate: "2017-08-13", - airtime: "21:00", - airstamp: "2017-08-14T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/124/310839.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/124/310839.jpg", - }, - summary: - "

Daenerys demands loyalty from the surviving Lannister soldiers; Jon heeds Bran's warning about White Walkers on the move; Cersei vows to vanquish anyone or anything that stands in her way.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/1221413", - }, - }, - }, - { - id: 1221414, - url: - "http://www.tvmaze.com/episodes/1221414/game-of-thrones-7x06-beyond-the-wall", - name: "Beyond the Wall", - season: 7, - number: 6, - airdate: "2017-08-20", - airtime: "21:00", - airstamp: "2017-08-21T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/125/312651.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/125/312651.jpg", - }, - summary: - "

Jon's mission continues north of the wall, but the odds against his ragged band of misfits may be greater than he imagined.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/1221414", - }, - }, - }, - { - id: 1221415, - url: - "http://www.tvmaze.com/episodes/1221415/game-of-thrones-7x07-the-dragon-and-the-wolf", - name: "The Dragon and the Wolf", - season: 7, - number: 7, - airdate: "2017-08-27", - airtime: "21:00", - airstamp: "2017-08-28T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/125/314502.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/125/314502.jpg", - }, - summary: - "

Cersei sits on the Iron Throne; Daenerys sails across the Narrow Sea; Jon Snow is King in the North, and winter is finally here.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/1221415", - }, - }, - }, - { - id: 1590943, - url: - "http://www.tvmaze.com/episodes/1590943/game-of-thrones-8x01-winterfell", - name: "Winterfell", - season: 8, - number: 1, - airdate: "2019-04-14", - airtime: "21:00", - airstamp: "2019-04-15T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/191/479477.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/191/479477.jpg", - }, - summary: - "

Arriving at Winterfell, Jon and Daenerys struggle to unite a divided North. Jon gets some big news.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/1590943", - }, - }, - }, - { - id: 1623964, - url: - "http://www.tvmaze.com/episodes/1623964/game-of-thrones-8x02-a-knight-of-the-seven-kingdoms", - name: "A Knight of the Seven Kingdoms", - season: 8, - number: 2, - airdate: "2019-04-21", - airtime: "21:00", - airstamp: "2019-04-22T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/192/482451.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/192/482451.jpg", - }, - summary: - "

Jaime faces judgement and Winterfell prepares for the battle to come.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/1623964", - }, - }, - }, - { - id: 1623965, - url: - "http://www.tvmaze.com/episodes/1623965/game-of-thrones-8x03-the-long-night", - name: "The Long Night", - season: 8, - number: 3, - airdate: "2019-04-28", - airtime: "21:00", - airstamp: "2019-04-29T01:00:00+00:00", - runtime: 90, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/192/482465.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/192/482465.jpg", - }, - summary: "

Winterfell fights the Army of the Dead.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/1623965", - }, - }, - }, - { - id: 1623966, - url: - "http://www.tvmaze.com/episodes/1623966/game-of-thrones-8x04-the-last-of-the-starks", - name: "The Last of the Starks", - season: 8, - number: 4, - airdate: "2019-05-05", - airtime: "21:00", - airstamp: "2019-05-06T01:00:00+00:00", - runtime: 78, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/195/487839.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/195/487839.jpg", - }, - summary: - "

The survivors plan their next steps; Cersei makes a power move.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/1623966", - }, - }, - }, - { - id: 1623967, - url: - "http://www.tvmaze.com/episodes/1623967/game-of-thrones-8x05-the-bells", - name: "The Bells", - season: 8, - number: 5, - airdate: "2019-05-12", - airtime: "21:00", - airstamp: "2019-05-13T01:00:00+00:00", - runtime: 79, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/196/491994.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/196/491994.jpg", - }, - summary: - "

Varys betrays his queen, and Daenerys brings her forces to King's Landing.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/1623967", - }, - }, - }, - { - id: 1623968, - url: - "http://www.tvmaze.com/episodes/1623968/game-of-thrones-8x06-the-iron-throne", - name: "The Iron Throne", - season: 8, - number: 6, - airdate: "2019-05-19", - airtime: "21:00", - airstamp: "2019-05-20T01:00:00+00:00", - runtime: 80, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/198/495648.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/198/495648.jpg", - }, - summary: - "

In the aftermath of the devastating attack on King's Landing, Daenerys must face the survivors.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/1623968", - }, - }, - }, - ]; -} diff --git a/index.html b/index.html index bd174b2..7663129 100644 --- a/index.html +++ b/index.html @@ -20,8 +20,7 @@

- - + diff --git a/script.js b/script.js index 152e7df..895d50a 100644 --- a/script.js +++ b/script.js @@ -100,8 +100,7 @@ function setupEpisodeSelector() { const option = document.createElement("option"); option.value = episode.id; - option.textContent = - `${getEpisodeCode(episode)} - ${episode.name}`; + option.textContent = `${getEpisodeCode(episode)} - ${episode.name}`; episodeSelector.appendChild(option); }); @@ -117,7 +116,6 @@ function setupEpisodeSelector() { } const searchInput = document.getElementById("search-input"); - searchInput.value = ""; makePageForEpisodes(allEpisodes); @@ -133,12 +131,36 @@ function setupEpisodeSelector() { }); } -function setup() { - allEpisodes = getAllEpisodes(); +async function setup() { + const episodeCount = document.getElementById("episode-count"); + const rootElem = document.getElementById("root"); + + episodeCount.textContent = "Loading episodes..."; + rootElem.textContent = "Please wait while episodes are loading..."; + + + + try { + const response = await fetch( + "https://api.tvmaze.com/shows/82/episodes" + ); + + if (!response.ok) { + throw new Error("Could not load episode data"); + } - setupSearch(); - setupEpisodeSelector(); - makePageForEpisodes(allEpisodes); + allEpisodes = await response.json(); + + rootElem.textContent = ""; + + setupSearch(); + setupEpisodeSelector(); + makePageForEpisodes(allEpisodes); + } catch (error) { + episodeCount.textContent = "Unable to load episodes."; + rootElem.textContent = + "Sorry, we could not load the episodes. Please try again later."; + } } window.onload = setup; \ No newline at end of file From d8232ea2de6248f2868289a72ad5f2606e195e6e Mon Sep 17 00:00:00 2001 From: shafiekwalker7861 Date: Mon, 17 Aug 2026 19:57:03 +0200 Subject: [PATCH 13/20] Load episodes from TVMaze API --- episodes.js | 1855 --------------------------------------------------- index.html | 3 +- script.js | 33 +- 3 files changed, 28 insertions(+), 1863 deletions(-) delete mode 100644 episodes.js diff --git a/episodes.js b/episodes.js deleted file mode 100644 index 5ef6e9e..0000000 --- a/episodes.js +++ /dev/null @@ -1,1855 +0,0 @@ -//DO NOT EDIT THIS FILE - -//This content is from https://www.tvmaze.com/ -//specifically: https://api.tvmaze.com/shows/82/episodes - -function getOneEpisode() { - return { - id: 4952, - url: - "http://www.tvmaze.com/episodes/4952/game-of-thrones-1x01-winter-is-coming", - name: "Winter is Coming", - season: 1, - number: 1, - airdate: "2011-04-17", - airtime: "21:00", - airstamp: "2011-04-18T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2668.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2668.jpg", - }, - summary: - "

Lord Eddard Stark, ruler of the North, is summoned to court by his old friend, King Robert Baratheon, to serve as the King's Hand. Eddard reluctantly agrees after learning of a possible threat to the King's life. Eddard's bastard son Jon Snow must make a painful decision about his own future, while in the distant east Viserys Targaryen plots to reclaim his father's throne, usurped by Robert, by selling his sister in marriage.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4952", - }, - }, - }; -} - -function getAllEpisodes() { - return [ - { - id: 4952, - url: - "http://www.tvmaze.com/episodes/4952/game-of-thrones-1x01-winter-is-coming", - name: "Winter is Coming", - season: 1, - number: 1, - airdate: "2011-04-17", - airtime: "21:00", - airstamp: "2011-04-18T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2668.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2668.jpg", - }, - summary: - "

Lord Eddard Stark, ruler of the North, is summoned to court by his old friend, King Robert Baratheon, to serve as the King's Hand. Eddard reluctantly agrees after learning of a possible threat to the King's life. Eddard's bastard son Jon Snow must make a painful decision about his own future, while in the distant east Viserys Targaryen plots to reclaim his father's throne, usurped by Robert, by selling his sister in marriage.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4952", - }, - }, - }, - { - id: 4953, - url: - "http://www.tvmaze.com/episodes/4953/game-of-thrones-1x02-the-kingsroad", - name: "The Kingsroad", - season: 1, - number: 2, - airdate: "2011-04-24", - airtime: "21:00", - airstamp: "2011-04-25T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2669.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2669.jpg", - }, - summary: - "

An incident on the Kingsroad threatens Eddard and Robert's friendship. Jon and Tyrion travel to the Wall, where they discover that the reality of the Night's Watch may not match the heroic image of it.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4953", - }, - }, - }, - { - id: 4954, - url: "http://www.tvmaze.com/episodes/4954/game-of-thrones-1x03-lord-snow", - name: "Lord Snow", - season: 1, - number: 3, - airdate: "2011-05-01", - airtime: "21:00", - airstamp: "2011-05-02T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2671.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2671.jpg", - }, - summary: - "

Jon Snow attempts to find his place amongst the Night's Watch. Eddard and his daughters arrive at King's Landing.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4954", - }, - }, - }, - { - id: 4955, - url: - "http://www.tvmaze.com/episodes/4955/game-of-thrones-1x04-cripples-bastards-and-broken-things", - name: "Cripples, Bastards, and Broken Things", - season: 1, - number: 4, - airdate: "2011-05-08", - airtime: "21:00", - airstamp: "2011-05-09T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2673.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2673.jpg", - }, - summary: - "

Tyrion stops at Winterfell on his way home and gets a frosty reception from Robb Stark. Eddard's investigation into the death of his predecessor gets underway.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4955", - }, - }, - }, - { - id: 4956, - url: - "http://www.tvmaze.com/episodes/4956/game-of-thrones-1x05-the-wolf-and-the-lion", - name: "The Wolf and the Lion", - season: 1, - number: 5, - airdate: "2011-05-15", - airtime: "21:00", - airstamp: "2011-05-16T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2674.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2674.jpg", - }, - summary: - "

Catelyn's actions on the road have repercussions for Eddard. Tyrion enjoys the dubious hospitality of the Eyrie.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4956", - }, - }, - }, - { - id: 4957, - url: - "http://www.tvmaze.com/episodes/4957/game-of-thrones-1x06-a-golden-crown", - name: "A Golden Crown", - season: 1, - number: 6, - airdate: "2011-05-22", - airtime: "21:00", - airstamp: "2011-05-23T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2676.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2676.jpg", - }, - summary: - "

Viserys is increasingly frustrated by the lack of progress towards gaining his crown.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4957", - }, - }, - }, - { - id: 4958, - url: - "http://www.tvmaze.com/episodes/4958/game-of-thrones-1x07-you-win-or-you-die", - name: "You Win or You Die", - season: 1, - number: 7, - airdate: "2011-05-29", - airtime: "21:00", - airstamp: "2011-05-30T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2677.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2677.jpg", - }, - summary: - "

Eddard's investigations in King's Landing reach a climax and a dark secret is revealed.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4958", - }, - }, - }, - { - id: 4959, - url: - "http://www.tvmaze.com/episodes/4959/game-of-thrones-1x08-the-pointy-end", - name: "The Pointy End", - season: 1, - number: 8, - airdate: "2011-06-05", - airtime: "21:00", - airstamp: "2011-06-06T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2678.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2678.jpg", - }, - summary: - "

Tyrion joins his father's army with unexpected allies. Events in King's Landing take a turn for the worse as Arya's lessons are put to the test.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4959", - }, - }, - }, - { - id: 4960, - url: "http://www.tvmaze.com/episodes/4960/game-of-thrones-1x09-baelor", - name: "Baelor", - season: 1, - number: 9, - airdate: "2011-06-12", - airtime: "21:00", - airstamp: "2011-06-13T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2679.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2679.jpg", - }, - summary: - "

Catelyn must negotiate with the irascible Lord Walder Frey.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4960", - }, - }, - }, - { - id: 4961, - url: - "http://www.tvmaze.com/episodes/4961/game-of-thrones-1x10-fire-and-blood", - name: "Fire and Blood", - season: 1, - number: 10, - airdate: "2011-06-19", - airtime: "21:00", - airstamp: "2011-06-20T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2681.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2681.jpg", - }, - summary: - "

Daenerys must realize her destiny. Jaime finds himself in an unfamiliar predicament.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4961", - }, - }, - }, - { - id: 4962, - url: - "http://www.tvmaze.com/episodes/4962/game-of-thrones-2x01-the-north-remembers", - name: "The North Remembers", - season: 2, - number: 1, - airdate: "2012-04-01", - airtime: "21:00", - airstamp: "2012-04-02T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/3174.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/3174.jpg", - }, - summary: - "

War grips the continent of Westeros. As Tyrion Lannister tries to take his strong-willed nephew in hand in King's Landing, Stannis Baratheon launches his own campaign to take the Iron Throne with the help of a mysterious priestess. In the east, Daenerys must lead her retinue through a desolate wasteland whilst beyond the Wall the Night's Watch seeks the aid of a wildling.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4962", - }, - }, - }, - { - id: 4963, - url: - "http://www.tvmaze.com/episodes/4963/game-of-thrones-2x02-the-night-lands", - name: "The Night Lands", - season: 2, - number: 2, - airdate: "2012-04-08", - airtime: "21:00", - airstamp: "2012-04-09T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/3175.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/3175.jpg", - }, - summary: - "

Stannis uses Ser Davos to seek out new allies for his war with the Lannisters. On the road north, Arya confides in Gendry. Robb Stark sends Theon Greyjoy to win an alliance with his father and the fierce warriors of the Iron Islands. Cersei and Tyrion clash on how to rule in King's Landing.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4963", - }, - }, - }, - { - id: 4964, - url: - "http://www.tvmaze.com/episodes/4964/game-of-thrones-2x03-what-is-dead-may-never-die", - name: "What is Dead May Never Die", - season: 2, - number: 3, - airdate: "2012-04-15", - airtime: "21:00", - airstamp: "2012-04-16T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/3176.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/3176.jpg", - }, - summary: - "

Catelyn Stark treats with King Renly in the hope of winning an alliance. Tyrion undertakes a complex plan in King's Landing to expose an enemy. At Winterfell, Bran's dreams continue to trouble him.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4964", - }, - }, - }, - { - id: 4965, - url: - "http://www.tvmaze.com/episodes/4965/game-of-thrones-2x04-garden-of-bones", - name: "Garden of Bones", - season: 2, - number: 4, - airdate: "2012-04-22", - airtime: "21:00", - airstamp: "2012-04-23T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/3177.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/3177.jpg", - }, - summary: - "

Tyrion attempts to restrain Joffrey's cruelty. Catelyn attempts to broker a peace between Stannis and Renly. Daenerys and her followers arrive at the great city of Qarth and hope to find refuge there. Arya and Gendry arrive at Harrenhal, a great castle now under Lannister occupation.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4965", - }, - }, - }, - { - id: 4966, - url: - "http://www.tvmaze.com/episodes/4966/game-of-thrones-2x05-the-ghost-of-harrenhal", - name: "The Ghost of Harrenhal", - season: 2, - number: 5, - airdate: "2012-04-29", - airtime: "21:00", - airstamp: "2012-04-30T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/3178.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/3178.jpg", - }, - summary: - "

Confusion rages in the Stormlands in the wake of a devastating reversal. Catelyn must flee with a new ally, whilst Littlefinger sees an opportunity in the chaos. Theon seeks to prove himself to his father in battle. Arya receives a promise from the enigmatic Jaqen H'ghar. The Night's Watch arrives at the Fist of the First Men. Daenerys Targaryen receives a marriage proposal.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4966", - }, - }, - }, - { - id: 4967, - url: - "http://www.tvmaze.com/episodes/4967/game-of-thrones-2x06-the-old-gods-and-the-new", - name: "The Old Gods and the New", - season: 2, - number: 6, - airdate: "2012-05-06", - airtime: "21:00", - airstamp: "2012-05-07T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/3180.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/3180.jpg", - }, - summary: - "

Arya has a surprise visitor; Dany vows to take what is hers; Joffrey meets his subjects; Qhorin gives Jon a chance to prove himself.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4967", - }, - }, - }, - { - id: 4968, - url: - "http://www.tvmaze.com/episodes/4968/game-of-thrones-2x07-a-man-without-honor", - name: "A Man Without Honor", - season: 2, - number: 7, - airdate: "2012-05-13", - airtime: "21:00", - airstamp: "2012-05-14T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/3192.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/3192.jpg", - }, - summary: - "

Jaime meets a relative; Theon hunts; Dany receives an invitation.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4968", - }, - }, - }, - { - id: 4969, - url: - "http://www.tvmaze.com/episodes/4969/game-of-thrones-2x08-the-prince-of-winterfell", - name: "The Prince of Winterfell", - season: 2, - number: 8, - airdate: "2012-05-20", - airtime: "21:00", - airstamp: "2012-05-21T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/3194.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/3194.jpg", - }, - summary: - "

Theon holds the fort; Arya calls in her debt with Jaqen; Robb is betrayed; Stannis and Davos approach their destination.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4969", - }, - }, - }, - { - id: 4970, - url: - "http://www.tvmaze.com/episodes/4970/game-of-thrones-2x09-blackwater", - name: "Blackwater", - season: 2, - number: 9, - airdate: "2012-05-27", - airtime: "21:00", - airstamp: "2012-05-28T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/3196.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/3196.jpg", - }, - summary: - "

A massive battle rages for control of King's Landing and the Iron Throne.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4970", - }, - }, - }, - { - id: 4971, - url: - "http://www.tvmaze.com/episodes/4971/game-of-thrones-2x10-valar-morghulis", - name: "Valar Morghulis", - season: 2, - number: 10, - airdate: "2012-06-03", - airtime: "21:00", - airstamp: "2012-06-04T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/3197.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/3197.jpg", - }, - summary: - "

Tyrion awakens to a changed situation. King Joffrey doles out rewards to his subjects. As Theon stirs his men to action, Luwin offers some final advice. Brienne silences Jaime; Arya receives a gift from Jaqen; Dany goes to a strange place; Jon proves himself to Qhorin.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4971", - }, - }, - }, - { - id: 4972, - url: - "http://www.tvmaze.com/episodes/4972/game-of-thrones-3x01-valar-dohaeris", - name: "Valar Dohaeris", - season: 3, - number: 1, - airdate: "2013-03-31", - airtime: "21:00", - airstamp: "2013-04-01T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2628.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2628.jpg", - }, - summary: - "

Jon is brought before Mance Rayder, the King Beyond the Wall, while the Night's Watch survivors retreat south. In King's Landing, Tyrion asks for his reward. Littlefinger offers Sansa a way out. Cersei hosts a dinner for the royal family. Daenerys sails into Slaver's Bay.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4972", - }, - }, - }, - { - id: 4973, - url: - "http://www.tvmaze.com/episodes/4973/game-of-thrones-3x02-dark-wings-dark-words", - name: "Dark Wings, Dark Words", - season: 3, - number: 2, - airdate: "2013-04-07", - airtime: "21:00", - airstamp: "2013-04-08T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2618.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2618.jpg", - }, - summary: - "

Sansa says too much. Shae asks Tyrion for a favor. Jaime finds a way to pass the time. Arya runs into the Brotherhood Without Banners.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4973", - }, - }, - }, - { - id: 4974, - url: - "http://www.tvmaze.com/episodes/4974/game-of-thrones-3x03-walk-of-punishment", - name: "Walk of Punishment", - season: 3, - number: 3, - airdate: "2013-04-14", - airtime: "21:00", - airstamp: "2013-04-15T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2616.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2616.jpg", - }, - summary: - "

Tyrion shoulders new responsibilities. Jon is taken to the Fist of the First Men. Daenerys meets with the slavers. Jaime strikes a deal with his captors.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4974", - }, - }, - }, - { - id: 4975, - url: - "http://www.tvmaze.com/episodes/4975/game-of-thrones-3x04-and-now-his-watch-is-ended", - name: "And Now His Watch is Ended", - season: 3, - number: 4, - airdate: "2013-04-21", - airtime: "21:00", - airstamp: "2013-04-22T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2615.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2615.jpg", - }, - summary: - "

The Night's Watch takes stock. Varys meets his better. Arya is taken to the commander of the Brotherhood. Daenerys exchanges a chain for a Whip.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4975", - }, - }, - }, - { - id: 4976, - url: - "http://www.tvmaze.com/episodes/4976/game-of-thrones-3x05-kissed-by-fire", - name: "Kissed by Fire", - season: 3, - number: 5, - airdate: "2013-04-28", - airtime: "21:00", - airstamp: "2013-04-29T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2614.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2614.jpg", - }, - summary: - "

The Hound is judged by the gods; Jaime is judged by men. Jon proves himself; Robb is betrayed. Tyrion learns the cost of weddings.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4976", - }, - }, - }, - { - id: 4977, - url: "http://www.tvmaze.com/episodes/4977/game-of-thrones-3x06-the-climb", - name: "The Climb", - season: 3, - number: 6, - airdate: "2013-05-05", - airtime: "21:00", - airstamp: "2013-05-06T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2612.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2612.jpg", - }, - summary: - "

Tywin plans strategic unions for the Lannisters. Melisandre visits the Riverlands. Robb weighs a compromise to repair his alliance with House Frey. Roose Bolton decides what to do with Jaime Lannister. Jon, Ygritte and the Wildlings face a daunting climb.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4977", - }, - }, - }, - { - id: 4978, - url: - "http://www.tvmaze.com/episodes/4978/game-of-thrones-3x07-the-bear-and-the-maiden-fair", - name: "The Bear and the Maiden Fair", - season: 3, - number: 7, - airdate: "2013-05-12", - airtime: "21:00", - airstamp: "2013-05-13T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2611.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2611.jpg", - }, - summary: - "

Daenerys exchanges gifts with a slave lord outside Yunkai. As Sansa frets about her prospects, Shae chafes at Tyrion's new situation. Tywin counsels the king, and Melisandre reveals a secret to Gendry. Brienne faces a formidable foe in Harrenhal.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4978", - }, - }, - }, - { - id: 4979, - url: - "http://www.tvmaze.com/episodes/4979/game-of-thrones-3x08-second-sons", - name: "Second Sons", - season: 3, - number: 8, - airdate: "2013-05-19", - airtime: "21:00", - airstamp: "2013-05-20T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2599.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2599.jpg", - }, - summary: - "

King's Landing hosts a wedding, and Tyrion and Sansa spend the night together. Daenerys meets the Titan's Bastard. Davos demands proof from Melisandre. Sam and Gilly meet an older Gentleman.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4979", - }, - }, - }, - { - id: 4980, - url: - "http://www.tvmaze.com/episodes/4980/game-of-thrones-3x09-the-rains-of-castamere", - name: "The Rains of Castamere", - season: 3, - number: 9, - airdate: "2013-06-02", - airtime: "21:00", - airstamp: "2013-06-03T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2598.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2598.jpg", - }, - summary: - "

Robb presents himself to Walder Frey, and Edmure meets his bride. Jon faces his harshest test yet. Bran discovers a new gift. Daario and Jorah debate how to take Yunkai. House Frey joins with House Tully.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4980", - }, - }, - }, - { - id: 4981, - url: "http://www.tvmaze.com/episodes/4981/game-of-thrones-3x10-mhysa", - name: "Mhysa", - season: 3, - number: 10, - airdate: "2013-06-09", - airtime: "21:00", - airstamp: "2013-06-10T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2597.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2597.jpg", - }, - summary: - "

Joffrey challenges Tywin. Bran tells a ghost story. In Dragonstone, mercy comes from strange quarters. Daenerys waits to see if she is a conqueror or a liberator.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4981", - }, - }, - }, - { - id: 4982, - url: - "http://www.tvmaze.com/episodes/4982/game-of-thrones-4x01-two-swords", - name: "Two Swords", - season: 4, - number: 1, - airdate: "2014-04-06", - airtime: "21:00", - airstamp: "2014-04-07T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2583.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2583.jpg", - }, - summary: - "

Tyrion welcomes a guest to King's Landing. At Castle Black, Jon Snow finds himself unwelcome. Dany is pointed to Meereen, the mother of all slave cities. Arya runs into an old friend.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4982", - }, - }, - }, - { - id: 4983, - url: - "http://www.tvmaze.com/episodes/4983/game-of-thrones-4x02-the-lion-and-the-rose", - name: "The Lion and the Rose", - season: 4, - number: 2, - airdate: "2014-04-13", - airtime: "21:00", - airstamp: "2014-04-14T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2584.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2584.jpg", - }, - summary: - "

Tyrion lends Jaime a hand. Joffrey and Margaery host a breakfast. At Dragonstone, Stannis loses patience with Davos. Ramsay finds a purpose for his pet. North of the Wall, Bran sees where they must go.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4983", - }, - }, - }, - { - id: 4984, - url: - "http://www.tvmaze.com/episodes/4984/game-of-thrones-4x03-breaker-of-chains", - name: "Breaker of Chains", - season: 4, - number: 3, - airdate: "2014-04-20", - airtime: "21:00", - airstamp: "2014-04-21T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2585.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2585.jpg", - }, - summary: - "

Tyrion ponders his options. Tywin extends an olive branch. Sam realizes Castle Black isn't safe, and Jon proposes a bold plan. The Hound teaches Arya the way things are. Dany chooses her Champion.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4984", - }, - }, - }, - { - id: 4985, - url: - "http://www.tvmaze.com/episodes/4985/game-of-thrones-4x04-oathkeeper", - name: "Oathkeeper", - season: 4, - number: 4, - airdate: "2014-04-27", - airtime: "21:00", - airstamp: "2014-04-28T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2586.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2586.jpg", - }, - summary: - "

Dany balances justice and mercy. Jaime tasks Brienne with his honor. Jon secures volunteers while Bran, Jojen, Meera and Hodor stumble on shelter.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4985", - }, - }, - }, - { - id: 4986, - url: - "http://www.tvmaze.com/episodes/4986/game-of-thrones-4x05-first-of-his-name", - name: "First of His Name", - season: 4, - number: 5, - airdate: "2014-05-04", - airtime: "21:00", - airstamp: "2014-05-05T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2587.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2587.jpg", - }, - summary: - "

Cersei and Tywin plot the Crown's next move. Dany discusses future plans. Jon embarks on a new mission.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4986", - }, - }, - }, - { - id: 4987, - url: - "http://www.tvmaze.com/episodes/4987/game-of-thrones-4x06-the-laws-of-gods-and-men", - name: "The Laws of Gods and Men", - season: 4, - number: 6, - airdate: "2014-05-11", - airtime: "21:00", - airstamp: "2014-05-12T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2588.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2588.jpg", - }, - summary: - "

Stannis and Davos set sail with a new strategy. Dany meets with supplicants. Tyrion faces down his father in the throne room.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4987", - }, - }, - }, - { - id: 4988, - url: - "http://www.tvmaze.com/episodes/4988/game-of-thrones-4x07-mockingbird", - name: "Mockingbird", - season: 4, - number: 7, - airdate: "2014-05-18", - airtime: "21:00", - airstamp: "2014-05-19T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2589.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2589.jpg", - }, - summary: - "

Tyrion enlists an unlikely ally. Daario entreats Dany to allow him to do what he does best. Jon's warnings about the Wall's vulnerability fall on deaf ears. Brienne follows a new lead on the road with Pod.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4988", - }, - }, - }, - { - id: 4989, - url: - "http://www.tvmaze.com/episodes/4989/game-of-thrones-4x08-the-mountain-and-the-viper", - name: "The Mountain and the Viper", - season: 4, - number: 8, - airdate: "2014-06-01", - airtime: "21:00", - airstamp: "2014-06-02T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2591.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2591.jpg", - }, - summary: - "

Mole's Town receives unexpected visitors. Littlefinger's motives are questioned. Ramsay attempts to prove himself to his father. Tyrion's fate is decided.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4989", - }, - }, - }, - { - id: 4990, - url: - "http://www.tvmaze.com/episodes/4990/game-of-thrones-4x09-the-watchers-on-the-wall", - name: "The Watchers on the Wall", - season: 4, - number: 9, - airdate: "2014-06-08", - airtime: "21:00", - airstamp: "2014-06-09T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2593.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2593.jpg", - }, - summary: - "

Jon Snow and the rest of the Night's Watch face the biggest challenge to the Wall yet.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4990", - }, - }, - }, - { - id: 4991, - url: - "http://www.tvmaze.com/episodes/4991/game-of-thrones-4x10-the-children", - name: "The Children", - season: 4, - number: 10, - airdate: "2014-06-15", - airtime: "21:00", - airstamp: "2014-06-16T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/1/2594.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/1/2594.jpg", - }, - summary: - "

An unexpected arrival north of the Wall changes circumstances. Dany is forced to face harsh realities. Bran learns more of his destiny. Tyrion sees the truth of his situation.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/4991", - }, - }, - }, - { - id: 116522, - url: - "http://www.tvmaze.com/episodes/116522/game-of-thrones-5x01-the-wars-to-come", - name: "The Wars to Come", - season: 5, - number: 1, - airdate: "2015-04-12", - airtime: "21:00", - airstamp: "2015-04-13T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/10/25988.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/10/25988.jpg", - }, - summary: - "

Varys discusses a conspiracy with Tyrion; Daenerys' rule faces a new threat; Jon finds himself between two kings; and Cersei and Jaime try to move on from Tywin's demise.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/116522", - }, - }, - }, - { - id: 144328, - url: - "http://www.tvmaze.com/episodes/144328/game-of-thrones-5x02-the-house-of-black-and-white", - name: "The House of Black and White", - season: 5, - number: 2, - airdate: "2015-04-19", - airtime: "21:00", - airstamp: "2015-04-20T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/10/25989.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/10/25989.jpg", - }, - summary: - "

Arya arrives in Braavos; Brienne and Podrick find danger while traveling; Cersei worries about Myrcella in Dorne when Ellaria Sand seeks revenge for Oberyn's death; Jon is tempted by Stannis.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/144328", - }, - }, - }, - { - id: 144329, - url: - "http://www.tvmaze.com/episodes/144329/game-of-thrones-5x03-high-sparrow", - name: "High Sparrow", - season: 5, - number: 3, - airdate: "2015-04-26", - airtime: "21:00", - airstamp: "2015-04-27T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/10/25990.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/10/25990.jpg", - }, - summary: - "

Cersei meets the High Sparrow after learning of a clergyman's embarrassing tale. Meanwhile, Davos talks to Jon about the future of Winterfell, where Ramsay Snow has just learned the identity of his future bride; Arya grows impatient doing menial tasks in the House of Black and White; and Tyrion searches for more comfortable surroundings on a long trip with Varys.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/144329", - }, - }, - }, - { - id: 144330, - url: - "http://www.tvmaze.com/episodes/144330/game-of-thrones-5x04-sons-of-the-harpy", - name: "Sons of the Harpy", - season: 5, - number: 4, - airdate: "2015-05-03", - airtime: "21:00", - airstamp: "2015-05-04T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/10/26444.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/10/26444.jpg", - }, - summary: - "

Margaery seeks prudent counsel. Jaime Struggles in foreign lands. Dany answers the Harpy's call.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/144330", - }, - }, - }, - { - id: 151777, - url: - "http://www.tvmaze.com/episodes/151777/game-of-thrones-5x05-kill-the-boy", - name: "Kill the Boy", - season: 5, - number: 5, - airdate: "2015-05-10", - airtime: "21:00", - airstamp: "2015-05-11T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/10/26819.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/10/26819.jpg", - }, - summary: - "

Dany makes a difficult decision in Meereen. Jon recruits the help of an unexpected ally. Brienne searches for Sansa. Theon remains under Ramsay's control.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/151777", - }, - }, - }, - { - id: 152766, - url: - "http://www.tvmaze.com/episodes/152766/game-of-thrones-5x06-unbowed-unbent-unbroken", - name: "Unbowed, Unbent, Unbroken", - season: 5, - number: 6, - airdate: "2015-05-17", - airtime: "21:00", - airstamp: "2015-05-18T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/10/27259.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/10/27259.jpg", - }, - summary: - "

Arya trains. Jorah and Tyrion run into slavers. Trystane and Myrcella make plans. Jaime and Bronn reach their destination. The Sand Snakes attack.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/152766", - }, - }, - }, - { - id: 153327, - url: - "http://www.tvmaze.com/episodes/153327/game-of-thrones-5x07-the-gift", - name: "The Gift", - season: 5, - number: 7, - airdate: "2015-05-24", - airtime: "21:00", - airstamp: "2015-05-25T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/11/27535.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/11/27535.jpg", - }, - summary: - "

Jon prepares for conflict. Sansa tries to talk to Theon. Brienne waits for a sign. Stannis remains stubborn. Jaime attempts to reconnect with family.



", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/153327", - }, - }, - }, - { - id: 155299, - url: - "http://www.tvmaze.com/episodes/155299/game-of-thrones-5x08-hardhome", - name: "Hardhome", - season: 5, - number: 8, - airdate: "2015-05-31", - airtime: "21:00", - airstamp: "2015-06-01T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/11/28151.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/11/28151.jpg", - }, - summary: - "

Arya makes progress in her training. Sansa confronts an old friend. Cersei struggles. Jon travels.



", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/155299", - }, - }, - }, - { - id: 160040, - url: - "http://www.tvmaze.com/episodes/160040/game-of-thrones-5x09-the-dance-of-dragons", - name: "The Dance of Dragons", - season: 5, - number: 9, - airdate: "2015-06-07", - airtime: "21:00", - airstamp: "2015-06-08T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/11/29160.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/11/29160.jpg", - }, - summary: - "

Stannis confronts a troubling decision. Jon returns to The Wall. Mace visits the Iron Bank. Arya encounters someone from her past. Dany reluctantly oversees a traditional celebration of athleticism.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/160040", - }, - }, - }, - { - id: 162186, - url: - "http://www.tvmaze.com/episodes/162186/game-of-thrones-5x10-mothers-mercy", - name: "Mother's Mercy", - season: 5, - number: 10, - airdate: "2015-06-14", - airtime: "21:00", - airstamp: "2015-06-15T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/12/30012.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/12/30012.jpg", - }, - summary: - "

Cersei seeks forgiveness; Jon faces a new challenge; Arya plots to cross a name off her list; Tyrion sees a familiar face; and Daenerys finds herself surrounded by strangers.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/162186", - }, - }, - }, - { - id: 560813, - url: - "http://www.tvmaze.com/episodes/560813/game-of-thrones-6x01-the-red-woman", - name: "The Red Woman", - season: 6, - number: 1, - airdate: "2016-04-24", - airtime: "21:00", - airstamp: "2016-04-25T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/56/142371.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/56/142371.jpg", - }, - summary: - "

Jon Snow is dead. Daenerys meets a strong man. Cersei sees her daughter again.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/560813", - }, - }, - }, - { - id: 664672, - url: "http://www.tvmaze.com/episodes/664672/game-of-thrones-6x02-home", - name: "Home", - season: 6, - number: 2, - airdate: "2016-05-01", - airtime: "21:00", - airstamp: "2016-05-02T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/56/142372.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/56/142372.jpg", - }, - summary: - "

Bran trains with the Three-Eyed Raven. In King's Landing, Jaime advises Tommen. Tyrion demands good news, but has to make his own. At Castle Black, the Night's Watch stands behind Thorne. Ramsay Bolton proposes a plan, and Balon Greyjoy entertains other proposals.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/664672", - }, - }, - }, - { - id: 664673, - url: - "http://www.tvmaze.com/episodes/664673/game-of-thrones-6x03-oathbreaker", - name: "Oathbreaker", - season: 6, - number: 3, - airdate: "2016-05-08", - airtime: "21:00", - airstamp: "2016-05-09T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/56/142370.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/56/142370.jpg", - }, - summary: - "

Daenerys meets her future. Bran meets the past. Tommen confronts the High Sparrow. Arya trains to be No One. Varys finds an answer. Ramsay gets a gift.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/664673", - }, - }, - }, - { - id: 664674, - url: - "http://www.tvmaze.com/episodes/664674/game-of-thrones-6x04-book-of-the-stranger", - name: "Book of the Stranger", - season: 6, - number: 4, - airdate: "2016-05-15", - airtime: "21:00", - airstamp: "2016-05-16T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/56/142273.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/56/142273.jpg", - }, - summary: - "

Tyrion strikes a deal. Jorah and Daario undertake a difficult task. Jaime and Cersei try to improve their situation.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/664674", - }, - }, - }, - { - id: 664675, - url: - "http://www.tvmaze.com/episodes/664675/game-of-thrones-6x05-the-door", - name: "The Door", - season: 6, - number: 5, - airdate: "2016-05-22", - airtime: "21:00", - airstamp: "2016-05-23T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/60/150273.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/60/150273.jpg", - }, - summary: - "

Tyrion seeks a strange ally. Bran learns a great deal. Brienne goes on a mission. Arya is given a chance to prove herself.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/664675", - }, - }, - }, - { - id: 664676, - url: - "http://www.tvmaze.com/episodes/664676/game-of-thrones-6x06-blood-of-my-blood", - name: "Blood of My Blood", - season: 6, - number: 6, - airdate: "2016-05-29", - airtime: "21:00", - airstamp: "2016-05-30T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/60/150274.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/60/150274.jpg", - }, - summary: - "

An old foe comes back into the picture. Gilly meets Sam's family. Arya faces a difficult choice. Jaime faces off against the High Sparrow.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/664676", - }, - }, - }, - { - id: 717449, - url: - "http://www.tvmaze.com/episodes/717449/game-of-thrones-6x07-the-broken-man", - name: "The Broken Man", - season: 6, - number: 7, - airdate: "2016-06-05", - airtime: "21:00", - airstamp: "2016-06-06T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/60/150275.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/60/150275.jpg", - }, - summary: - "

The High Sparrow eyes another target. Jaime confronts a hero. Arya makes a plan. The North is reminded.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/717449", - }, - }, - }, - { - id: 729573, - url: "http://www.tvmaze.com/episodes/729573/game-of-thrones-6x08-no-one", - name: "No One", - season: 6, - number: 8, - airdate: "2016-06-12", - airtime: "21:00", - airstamp: "2016-06-13T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/61/153044.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/61/153044.jpg", - }, - summary: - "

Jaime encounters a hero; the High Sparrow fixates on another prey; Arya hatches a new plan; Yara and Theon plot their next move; Olenna and Cersei discuss their families' futures.

While Jaime weighs his options, Cersei answers a request. Tyrion's plans bear fruit. Arya faces a new test.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/729573", - }, - }, - }, - { - id: 729574, - url: - "http://www.tvmaze.com/episodes/729574/game-of-thrones-6x09-battle-of-the-bastards", - name: "Battle of the Bastards", - season: 6, - number: 9, - airdate: "2016-06-19", - airtime: "21:00", - airstamp: "2016-06-20T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/62/155042.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/62/155042.jpg", - }, - summary: - "

Ramsay surprises his audience. Jon retaliates. Dany is true to her word.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/729574", - }, - }, - }, - { - id: 729575, - url: - "http://www.tvmaze.com/episodes/729575/game-of-thrones-6x10-the-winds-of-winter", - name: "The Winds of Winter", - season: 6, - number: 10, - airdate: "2016-06-26", - airtime: "21:00", - airstamp: "2016-06-27T01:00:00+00:00", - runtime: 69, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/63/157920.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/63/157920.jpg", - }, - summary: - "

Alliances are made, the High Sparrow is holding trials at King's Landing, Daenerys is sailing for the Seven Kingdoms and a new King of the North is crowned.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/729575", - }, - }, - }, - { - id: 937256, - url: - "http://www.tvmaze.com/episodes/937256/game-of-thrones-7x01-dragonstone", - name: "Dragonstone", - season: 7, - number: 1, - airdate: "2017-07-16", - airtime: "21:00", - airstamp: "2017-07-17T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/120/302038.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/120/302038.jpg", - }, - summary: - "

Jon organizes the defense of the North. Cersei tries to even the odds. Daenerys comes home.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/937256", - }, - }, - }, - { - id: 1221410, - url: - "http://www.tvmaze.com/episodes/1221410/game-of-thrones-7x02-stormborn", - name: "Stormborn", - season: 7, - number: 2, - airdate: "2017-07-23", - airtime: "21:00", - airstamp: "2017-07-24T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/120/302047.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/120/302047.jpg", - }, - summary: - "

Daenerys receives an unexpected visitor. Jon faces a revolt. Tyrion plans the conquest of Westeros.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/1221410", - }, - }, - }, - { - id: 1221411, - url: - "http://www.tvmaze.com/episodes/1221411/game-of-thrones-7x03-the-queens-justice", - name: "The Queen's Justice", - season: 7, - number: 3, - airdate: "2017-07-30", - airtime: "21:00", - airstamp: "2017-07-31T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/122/306938.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/122/306938.jpg", - }, - summary: - "

Daenerys holds court. Cersei returns a gift. Jaime learns from his mistakes.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/1221411", - }, - }, - }, - { - id: 1221412, - url: - "http://www.tvmaze.com/episodes/1221412/game-of-thrones-7x04-the-spoils-of-war", - name: "The Spoils of War", - season: 7, - number: 4, - airdate: "2017-08-06", - airtime: "21:00", - airstamp: "2017-08-07T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/123/307677.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/123/307677.jpg", - }, - summary: - "

Arya gets to the final destination. Daenerys takes it upon herself to strike back.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/1221412", - }, - }, - }, - { - id: 1221413, - url: - "http://www.tvmaze.com/episodes/1221413/game-of-thrones-7x05-eastwatch", - name: "Eastwatch", - season: 7, - number: 5, - airdate: "2017-08-13", - airtime: "21:00", - airstamp: "2017-08-14T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/124/310839.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/124/310839.jpg", - }, - summary: - "

Daenerys demands loyalty from the surviving Lannister soldiers; Jon heeds Bran's warning about White Walkers on the move; Cersei vows to vanquish anyone or anything that stands in her way.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/1221413", - }, - }, - }, - { - id: 1221414, - url: - "http://www.tvmaze.com/episodes/1221414/game-of-thrones-7x06-beyond-the-wall", - name: "Beyond the Wall", - season: 7, - number: 6, - airdate: "2017-08-20", - airtime: "21:00", - airstamp: "2017-08-21T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/125/312651.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/125/312651.jpg", - }, - summary: - "

Jon's mission continues north of the wall, but the odds against his ragged band of misfits may be greater than he imagined.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/1221414", - }, - }, - }, - { - id: 1221415, - url: - "http://www.tvmaze.com/episodes/1221415/game-of-thrones-7x07-the-dragon-and-the-wolf", - name: "The Dragon and the Wolf", - season: 7, - number: 7, - airdate: "2017-08-27", - airtime: "21:00", - airstamp: "2017-08-28T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/125/314502.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/125/314502.jpg", - }, - summary: - "

Cersei sits on the Iron Throne; Daenerys sails across the Narrow Sea; Jon Snow is King in the North, and winter is finally here.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/1221415", - }, - }, - }, - { - id: 1590943, - url: - "http://www.tvmaze.com/episodes/1590943/game-of-thrones-8x01-winterfell", - name: "Winterfell", - season: 8, - number: 1, - airdate: "2019-04-14", - airtime: "21:00", - airstamp: "2019-04-15T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/191/479477.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/191/479477.jpg", - }, - summary: - "

Arriving at Winterfell, Jon and Daenerys struggle to unite a divided North. Jon gets some big news.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/1590943", - }, - }, - }, - { - id: 1623964, - url: - "http://www.tvmaze.com/episodes/1623964/game-of-thrones-8x02-a-knight-of-the-seven-kingdoms", - name: "A Knight of the Seven Kingdoms", - season: 8, - number: 2, - airdate: "2019-04-21", - airtime: "21:00", - airstamp: "2019-04-22T01:00:00+00:00", - runtime: 60, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/192/482451.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/192/482451.jpg", - }, - summary: - "

Jaime faces judgement and Winterfell prepares for the battle to come.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/1623964", - }, - }, - }, - { - id: 1623965, - url: - "http://www.tvmaze.com/episodes/1623965/game-of-thrones-8x03-the-long-night", - name: "The Long Night", - season: 8, - number: 3, - airdate: "2019-04-28", - airtime: "21:00", - airstamp: "2019-04-29T01:00:00+00:00", - runtime: 90, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/192/482465.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/192/482465.jpg", - }, - summary: "

Winterfell fights the Army of the Dead.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/1623965", - }, - }, - }, - { - id: 1623966, - url: - "http://www.tvmaze.com/episodes/1623966/game-of-thrones-8x04-the-last-of-the-starks", - name: "The Last of the Starks", - season: 8, - number: 4, - airdate: "2019-05-05", - airtime: "21:00", - airstamp: "2019-05-06T01:00:00+00:00", - runtime: 78, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/195/487839.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/195/487839.jpg", - }, - summary: - "

The survivors plan their next steps; Cersei makes a power move.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/1623966", - }, - }, - }, - { - id: 1623967, - url: - "http://www.tvmaze.com/episodes/1623967/game-of-thrones-8x05-the-bells", - name: "The Bells", - season: 8, - number: 5, - airdate: "2019-05-12", - airtime: "21:00", - airstamp: "2019-05-13T01:00:00+00:00", - runtime: 79, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/196/491994.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/196/491994.jpg", - }, - summary: - "

Varys betrays his queen, and Daenerys brings her forces to King's Landing.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/1623967", - }, - }, - }, - { - id: 1623968, - url: - "http://www.tvmaze.com/episodes/1623968/game-of-thrones-8x06-the-iron-throne", - name: "The Iron Throne", - season: 8, - number: 6, - airdate: "2019-05-19", - airtime: "21:00", - airstamp: "2019-05-20T01:00:00+00:00", - runtime: 80, - image: { - medium: - "http://static.tvmaze.com/uploads/images/medium_landscape/198/495648.jpg", - original: - "http://static.tvmaze.com/uploads/images/original_untouched/198/495648.jpg", - }, - summary: - "

In the aftermath of the devastating attack on King's Landing, Daenerys must face the survivors.

", - _links: { - self: { - href: "http://api.tvmaze.com/episodes/1623968", - }, - }, - }, - ]; -} diff --git a/index.html b/index.html index 27ba131..13c884b 100644 --- a/index.html +++ b/index.html @@ -12,8 +12,7 @@
- - + diff --git a/script.js b/script.js index 53139bf..2a1e273 100644 --- a/script.js +++ b/script.js @@ -135,10 +135,31 @@ function setupEpisodeSelector() { }); } -window.onload = function () { - allEpisodes = getAllEpisodes(); +async function setup() { + const rootElem = document.getElementById("root"); + + rootElem.textContent = "Loading episodes..."; + + try { + const response = await fetch( + "https://api.tvmaze.com/shows/82/episodes" + ); + + if (!response.ok) { + throw new Error("Could not load episode data"); + } + + allEpisodes = await response.json(); + + rootElem.textContent = ""; + + setupSearch(); + setupEpisodeSelector(); + makePageForEpisodes(allEpisodes); + } catch (error) { + rootElem.textContent = + "Sorry, we could not load the episodes. Please try again later."; + } +} - setupSearch(); - setupEpisodeSelector(); - makePageForEpisodes(allEpisodes); -}; \ No newline at end of file +window.onload = setup; \ No newline at end of file From a60a0821973be92721950657154664282ad07a48 Mon Sep 17 00:00:00 2001 From: shafiekwalker7861 Date: Mon, 17 Aug 2026 20:13:36 +0200 Subject: [PATCH 14/20] Add TV show selector --- script.js | 227 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 167 insertions(+), 60 deletions(-) diff --git a/script.js b/script.js index 2a1e273..89a8ba0 100644 --- a/script.js +++ b/script.js @@ -1,4 +1,25 @@ let allEpisodes = []; +let allShows = []; + +// Stores API results so the same URL is never fetched twice +const apiCache = new Map(); + +async function fetchJsonOnce(url) { + if (apiCache.has(url)) { + return apiCache.get(url); + } + + const response = await fetch(url); + + if (!response.ok) { + throw new Error(`Could not load data from ${url}`); + } + + const data = await response.json(); + apiCache.set(url, data); + + return data; +} function getEpisodeCode(episode) { const seasonNumber = String(episode.season).padStart(2, "0"); @@ -16,15 +37,24 @@ function createEpisodeCard(episode) { const heading = document.createElement("h2"); heading.textContent = `${episodeCode} - ${episode.name}`; - card.appendChild(heading); const image = document.createElement("img"); - image.src = episode.image.medium; + + if (episode.image) { + image.src = episode.image.medium; + } + image.alt = `Image for ${episode.name}`; - card.appendChild(image); const summary = document.createElement("div"); - summary.innerHTML = episode.summary; + summary.innerHTML = episode.summary || "No summary available."; + + card.appendChild(heading); + + if (episode.image) { + card.appendChild(image); + } + card.appendChild(summary); return card; @@ -47,24 +77,29 @@ function makePageForEpisodes(episodeList) { }); } -function setupSearch() { - const rootElem = document.getElementById("root"); +function updateEpisodeSelector() { + const episodeSelector = document.getElementById("episode-selector"); - const searchContainer = document.createElement("div"); + episodeSelector.textContent = ""; - const label = document.createElement("label"); - label.setAttribute("for", "search-input"); - label.textContent = "Search episodes: "; + const defaultOption = document.createElement("option"); + defaultOption.value = ""; + defaultOption.textContent = "Choose an episode"; - const searchInput = document.createElement("input"); - searchInput.id = "search-input"; - searchInput.type = "search"; - searchInput.placeholder = "Search by name or summary"; + episodeSelector.appendChild(defaultOption); - searchContainer.appendChild(label); - searchContainer.appendChild(searchInput); + allEpisodes.forEach((episode) => { + const option = document.createElement("option"); - rootElem.parentNode.insertBefore(searchContainer, rootElem); + option.value = episode.id; + option.textContent = `${getEpisodeCode(episode)} - ${episode.name}`; + + episodeSelector.appendChild(option); + }); +} + +function setupSearch() { + const searchInput = document.getElementById("search-input"); searchInput.addEventListener("input", function () { const searchTerm = searchInput.value.toLowerCase().trim(); @@ -84,35 +119,7 @@ function setupSearch() { } function setupEpisodeSelector() { - const rootElem = document.getElementById("root"); - - const selectorContainer = document.createElement("div"); - - const label = document.createElement("label"); - label.setAttribute("for", "episode-selector"); - label.textContent = "Select episode: "; - - const episodeSelector = document.createElement("select"); - episodeSelector.id = "episode-selector"; - - const defaultOption = document.createElement("option"); - defaultOption.value = ""; - defaultOption.textContent = "Choose an episode"; - episodeSelector.appendChild(defaultOption); - - allEpisodes.forEach((episode) => { - const option = document.createElement("option"); - - option.value = episode.id; - option.textContent = `${getEpisodeCode(episode)} - ${episode.name}`; - - episodeSelector.appendChild(option); - }); - - selectorContainer.appendChild(label); - selectorContainer.appendChild(episodeSelector); - - rootElem.parentNode.insertBefore(selectorContainer, rootElem); + const episodeSelector = document.getElementById("episode-selector"); episodeSelector.addEventListener("change", function () { if (episodeSelector.value === "") { @@ -120,6 +127,7 @@ function setupEpisodeSelector() { } const searchInput = document.getElementById("search-input"); + searchInput.value = ""; makePageForEpisodes(allEpisodes); @@ -128,37 +136,136 @@ function setupEpisodeSelector() { `episode-${episodeSelector.value}` ); - selectedEpisode.scrollIntoView({ - behavior: "smooth", - block: "start", - }); + if (selectedEpisode) { + selectedEpisode.scrollIntoView({ + behavior: "smooth", + block: "start", + }); + } }); } -async function setup() { +async function loadEpisodesForShow(showId) { const rootElem = document.getElementById("root"); + const searchInput = document.getElementById("search-input"); rootElem.textContent = "Loading episodes..."; + searchInput.value = ""; try { - const response = await fetch( - "https://api.tvmaze.com/shows/82/episodes" - ); + const episodeUrl = + `https://api.tvmaze.com/shows/${showId}/episodes`; + + allEpisodes = await fetchJsonOnce(episodeUrl); + + updateEpisodeSelector(); + makePageForEpisodes(allEpisodes); + } catch (error) { + rootElem.textContent = + "Sorry, we could not load the episodes. Please try again later."; + } +} + +function setupShowSelector() { + const showSelector = document.getElementById("show-selector"); - if (!response.ok) { - throw new Error("Could not load episode data"); + showSelector.addEventListener("change", function () { + if (showSelector.value === "") { + return; } - allEpisodes = await response.json(); + loadEpisodesForShow(showSelector.value); + }); +} + +function createControls() { + const rootElem = document.getElementById("root"); + + const controls = document.createElement("div"); + + const showLabel = document.createElement("label"); + showLabel.setAttribute("for", "show-selector"); + showLabel.textContent = "Select show: "; + + const showSelector = document.createElement("select"); + showSelector.id = "show-selector"; + + const showDefault = document.createElement("option"); + showDefault.value = ""; + showDefault.textContent = "Choose a show"; + + showSelector.appendChild(showDefault); + + const searchLabel = document.createElement("label"); + searchLabel.setAttribute("for", "search-input"); + searchLabel.textContent = " Search episodes: "; + + const searchInput = document.createElement("input"); + searchInput.id = "search-input"; + searchInput.type = "search"; + searchInput.placeholder = "Search by name or summary"; + + const episodeLabel = document.createElement("label"); + episodeLabel.setAttribute("for", "episode-selector"); + episodeLabel.textContent = " Select episode: "; + + const episodeSelector = document.createElement("select"); + episodeSelector.id = "episode-selector"; + + const episodeDefault = document.createElement("option"); + episodeDefault.value = ""; + episodeDefault.textContent = "Choose an episode"; + + episodeSelector.appendChild(episodeDefault); + + controls.appendChild(showLabel); + controls.appendChild(showSelector); + controls.appendChild(searchLabel); + controls.appendChild(searchInput); + controls.appendChild(episodeLabel); + controls.appendChild(episodeSelector); + + rootElem.parentNode.insertBefore(controls, rootElem); +} + +async function setup() { + const rootElem = document.getElementById("root"); + + createControls(); - rootElem.textContent = ""; + rootElem.textContent = "Loading TV shows..."; + try { + allShows = await fetchJsonOnce( + "https://api.tvmaze.com/shows" + ); + + allShows.sort((showA, showB) => + showA.name.localeCompare(showB.name, undefined, { + sensitivity: "base", + }) + ); + + const showSelector = document.getElementById("show-selector"); + + allShows.forEach((show) => { + const option = document.createElement("option"); + + option.value = show.id; + option.textContent = show.name; + + showSelector.appendChild(option); + }); + + rootElem.textContent = + "Choose a TV show to display its episodes."; + + setupShowSelector(); setupSearch(); setupEpisodeSelector(); - makePageForEpisodes(allEpisodes); } catch (error) { rootElem.textContent = - "Sorry, we could not load the episodes. Please try again later."; + "Sorry, we could not load the TV shows. Please try again later."; } } From ce9f8554a019fcc756d79591df10d0877827474f Mon Sep 17 00:00:00 2001 From: shafiekwalker7861 Date: Mon, 17 Aug 2026 20:18:32 +0200 Subject: [PATCH 15/20] Prevent duplicate API requests --- script.js | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/script.js b/script.js index 89a8ba0..22f81aa 100644 --- a/script.js +++ b/script.js @@ -4,21 +4,20 @@ let allShows = []; // Stores API results so the same URL is never fetched twice const apiCache = new Map(); -async function fetchJsonOnce(url) { - if (apiCache.has(url)) { - return apiCache.get(url); - } - - const response = await fetch(url); +function fetchJsonOnce(url) { + if (!apiCache.has(url)) { + const request = fetch(url).then((response) => { + if (!response.ok) { + throw new Error(`Could not load data from ${url}`); + } + + return response.json(); + }); - if (!response.ok) { - throw new Error(`Could not load data from ${url}`); + apiCache.set(url, request); } - const data = await response.json(); - apiCache.set(url, data); - - return data; + return apiCache.get(url); } function getEpisodeCode(episode) { From c63a5293de8da43792c826a6a998dafd6b3e342a Mon Sep 17 00:00:00 2001 From: shafiekwalker7861 Date: Tue, 18 Aug 2026 11:41:51 +0200 Subject: [PATCH 16/20] Build Level 500 shows explorer --- index.html | 32 +++-- script.js | 356 ++++++++++++++++++++++++++++++++++++++++------------- style.css | 153 +++++++++++++++++++++-- 3 files changed, 434 insertions(+), 107 deletions(-) diff --git a/index.html b/index.html index 7663129..579d824 100644 --- a/index.html +++ b/index.html @@ -3,26 +3,34 @@ - TV Show Project | Shafiek Walker (shafiekwalker7861) + TV Show Project | Shafiek Walker + -

+ -
-

- Episode data originally provided by - TVMaze.com -

-
+
+ +

- +
+ +
+

+ TV show and episode data provided by + TVMaze.com +

+
- - + \ No newline at end of file diff --git a/script.js b/script.js index 895d50a..58d1b0a 100644 --- a/script.js +++ b/script.js @@ -1,165 +1,353 @@ -// You can edit ALL of the code here - +let allShows = []; let allEpisodes = []; -function getEpisodeCode(episode) { - const seasonNumber = String(episode.season).padStart(2, "0"); - const episodeNumber = String(episode.number).padStart(2, "0"); +const apiCache = new Map(); - return `S${seasonNumber}E${episodeNumber}`; +function fetchJsonOnce(url) { + if (!apiCache.has(url)) { + const request = fetch(url).then((response) => { + if (!response.ok) { + throw new Error(`Could not load data from ${url}`); + } + + return response.json(); + }); + + apiCache.set(url, request); + } + + return apiCache.get(url); } -function createEpisodeCard(episode) { - const episodeCard = document.createElement("div"); - episodeCard.classList.add("episode-card"); - episodeCard.id = `episode-${episode.id}`; +function removeHtml(htmlText) { + const temporaryElement = document.createElement("div"); + temporaryElement.innerHTML = htmlText || ""; - const heading = document.createElement("h2"); - heading.textContent = `${episode.name} - ${getEpisodeCode(episode)}`; + return temporaryElement.textContent || ""; +} - const episodeImage = document.createElement("img"); - episodeImage.src = episode.image.medium; - episodeImage.alt = `Image for ${episode.name}`; +function createShowCard(show) { + const card = document.createElement("article"); + card.className = "show-card"; - const episodeSummary = document.createElement("div"); - episodeSummary.innerHTML = episode.summary; + if (show.image) { + const image = document.createElement("img"); + image.src = show.image.medium; + image.alt = `Poster for ${show.name}`; + card.appendChild(image); + } + + const titleButton = document.createElement("button"); + titleButton.className = "show-title"; + titleButton.textContent = show.name; + + titleButton.addEventListener("click", function () { + showEpisodes(show); + }); + + const details = document.createElement("div"); + details.className = "show-details"; + + const genres = document.createElement("p"); + genres.innerHTML = + `Genres: ${show.genres.join(", ") || "Not available"}`; + + const status = document.createElement("p"); + status.innerHTML = + `Status: ${show.status || "Not available"}`; - episodeCard.appendChild(heading); - episodeCard.appendChild(episodeImage); - episodeCard.appendChild(episodeSummary); + const rating = document.createElement("p"); + rating.innerHTML = + `Rating: ${show.rating.average ?? "Not rated"}`; - return episodeCard; + const runtime = document.createElement("p"); + runtime.innerHTML = + `Runtime: ${ + show.runtime ? `${show.runtime} minutes` : "Not available" + }`; + + const summary = document.createElement("p"); + summary.className = "show-summary"; + summary.textContent = + removeHtml(show.summary) || "No summary available."; + + details.appendChild(titleButton); + details.appendChild(genres); + details.appendChild(status); + details.appendChild(rating); + details.appendChild(runtime); + details.appendChild(summary); + + card.appendChild(details); + + return card; } -function makePageForEpisodes(episodeList) { +function displayShows(showList) { const rootElem = document.getElementById("root"); - const episodeCount = document.getElementById("episode-count"); + const statusText = document.getElementById("status-text"); + rootElem.className = "shows-grid"; rootElem.textContent = ""; - episodeCount.textContent = - `Displaying ${episodeList.length} / ${allEpisodes.length} episodes`; + statusText.textContent = + `Displaying ${showList.length} / ${allShows.length} shows`; - episodeList.forEach((episode) => { - const episodeCard = createEpisodeCard(episode); - rootElem.appendChild(episodeCard); + showList.forEach((show) => { + rootElem.appendChild(createShowCard(show)); }); } -function setupSearch() { - const searchInput = document.createElement("input"); - searchInput.type = "search"; - searchInput.id = "search-input"; - searchInput.placeholder = "Search by name or summary"; +function showShowsPage() { + const backButton = document.getElementById("back-to-shows"); + const controls = document.getElementById("controls"); - const label = document.createElement("label"); - label.setAttribute("for", "search-input"); - label.textContent = "Search episodes: "; + backButton.hidden = true; - const rootElem = document.getElementById("root"); + controls.innerHTML = ` + - rootElem.parentNode.insertBefore(searchInput, rootElem); - rootElem.parentNode.insertBefore(label, searchInput); + + `; - searchInput.addEventListener("input", function () { - const searchTerm = searchInput.value.toLowerCase().trim(); + displayShows(allShows); - const filteredEpisodes = allEpisodes.filter((episode) => { - const episodeName = episode.name.toLowerCase(); - const episodeSummary = (episode.summary || "").toLowerCase(); + const showSearch = document.getElementById("show-search"); + + showSearch.addEventListener("input", function () { + const searchTerm = showSearch.value.toLowerCase().trim(); + + const filteredShows = allShows.filter((show) => { + const showName = show.name.toLowerCase(); + + const showGenres = show.genres + .join(" ") + .toLowerCase(); + + const showSummary = removeHtml(show.summary) + .toLowerCase(); return ( - episodeName.includes(searchTerm) || - episodeSummary.includes(searchTerm) + showName.includes(searchTerm) || + showGenres.includes(searchTerm) || + showSummary.includes(searchTerm) ); }); - makePageForEpisodes(filteredEpisodes); + displayShows(filteredShows); }); } -function setupEpisodeSelector() { +function getEpisodeCode(episode) { + const seasonNumber = String(episode.season).padStart(2, "0"); + const episodeNumber = String(episode.number).padStart(2, "0"); + + return `S${seasonNumber}E${episodeNumber}`; +} + +function createEpisodeCard(episode) { + const card = document.createElement("article"); + card.className = "episode-card"; + card.id = `episode-${episode.id}`; + + const heading = document.createElement("h2"); + heading.textContent = + `${getEpisodeCode(episode)} - ${episode.name}`; + + card.appendChild(heading); + + if (episode.image) { + const image = document.createElement("img"); + image.src = episode.image.medium; + image.alt = `Image for ${episode.name}`; + + card.appendChild(image); + } + + const summary = document.createElement("p"); + summary.textContent = + removeHtml(episode.summary) || "No summary available."; + + card.appendChild(summary); + + return card; +} + +function displayEpisodes(episodeList) { const rootElem = document.getElementById("root"); + const statusText = document.getElementById("status-text"); - const selectorContainer = document.createElement("div"); + rootElem.className = "episodes-grid"; + rootElem.textContent = ""; - const label = document.createElement("label"); - label.setAttribute("for", "episode-selector"); - label.textContent = "Select episode: "; + statusText.textContent = + `Displaying ${episodeList.length} / ${allEpisodes.length} episodes`; - const episodeSelector = document.createElement("select"); - episodeSelector.id = "episode-selector"; + episodeList.forEach((episode) => { + rootElem.appendChild(createEpisodeCard(episode)); + }); +} + +function updateEpisodeSelector() { + const selector = document.getElementById("episode-selector"); + + selector.innerHTML = ""; const defaultOption = document.createElement("option"); defaultOption.value = ""; defaultOption.textContent = "Choose an episode"; - episodeSelector.appendChild(defaultOption); + selector.appendChild(defaultOption); allEpisodes.forEach((episode) => { const option = document.createElement("option"); option.value = episode.id; - option.textContent = `${getEpisodeCode(episode)} - ${episode.name}`; + option.textContent = + `${getEpisodeCode(episode)} - ${episode.name}`; - episodeSelector.appendChild(option); + selector.appendChild(option); }); +} + +function setupEpisodeControls() { + const searchInput = + document.getElementById("episode-search"); + + const episodeSelector = + document.getElementById("episode-selector"); - selectorContainer.appendChild(label); - selectorContainer.appendChild(episodeSelector); + searchInput.addEventListener("input", function () { + const searchTerm = + searchInput.value.toLowerCase().trim(); + + const filteredEpisodes = allEpisodes.filter((episode) => { + const episodeName = + episode.name.toLowerCase(); - rootElem.parentNode.insertBefore(selectorContainer, rootElem); + const episodeSummary = + removeHtml(episode.summary).toLowerCase(); + + return ( + episodeName.includes(searchTerm) || + episodeSummary.includes(searchTerm) + ); + }); + + displayEpisodes(filteredEpisodes); + }); episodeSelector.addEventListener("change", function () { if (episodeSelector.value === "") { return; } - const searchInput = document.getElementById("search-input"); searchInput.value = ""; - makePageForEpisodes(allEpisodes); + displayEpisodes(allEpisodes); const selectedEpisode = document.getElementById( `episode-${episodeSelector.value}` ); - selectedEpisode.scrollIntoView({ - behavior: "smooth", - block: "start", - }); + if (selectedEpisode) { + selectedEpisode.scrollIntoView({ + behavior: "smooth", + block: "start", + }); + } }); } -async function setup() { - const episodeCount = document.getElementById("episode-count"); +async function showEpisodes(show) { + const controls = document.getElementById("controls"); const rootElem = document.getElementById("root"); + const statusText = document.getElementById("status-text"); + const backButton = document.getElementById("back-to-shows"); + + backButton.hidden = false; + + controls.innerHTML = ` +
+

${show.name} Episodes

+ + - episodeCount.textContent = "Loading episodes..."; - rootElem.textContent = "Please wait while episodes are loading..."; + - + + + +
+ `; + + rootElem.textContent = ""; + statusText.textContent = "Loading episodes..."; try { - const response = await fetch( - "https://api.tvmaze.com/shows/82/episodes" - ); + const url = + `https://api.tvmaze.com/shows/${show.id}/episodes`; - if (!response.ok) { - throw new Error("Could not load episode data"); - } + allEpisodes = await fetchJsonOnce(url); - allEpisodes = await response.json(); + updateEpisodeSelector(); + setupEpisodeControls(); + displayEpisodes(allEpisodes); + } catch (error) { + statusText.textContent = + "Unable to load episodes."; - rootElem.textContent = ""; + rootElem.textContent = + "Sorry, we could not load the episodes."; + } +} - setupSearch(); - setupEpisodeSelector(); - makePageForEpisodes(allEpisodes); +async function setup() { + const rootElem = document.getElementById("root"); + const statusText = document.getElementById("status-text"); + const backButton = document.getElementById("back-to-shows"); + + statusText.textContent = "Loading TV shows..."; + rootElem.textContent = "Please wait..."; + + backButton.addEventListener("click", function () { + showShowsPage(); + }); + + try { + allShows = await fetchJsonOnce( + "https://api.tvmaze.com/shows" + ); + + allShows.sort((showA, showB) => + showA.name.localeCompare(showB.name, undefined, { + sensitivity: "base", + }) + ); + + showShowsPage(); } catch (error) { - episodeCount.textContent = "Unable to load episodes."; + statusText.textContent = + "Unable to load TV shows."; + rootElem.textContent = - "Sorry, we could not load the episodes. Please try again later."; + "Sorry, we could not load the TV shows."; } } diff --git a/style.css b/style.css index 7df0e89..4023d2c 100644 --- a/style.css +++ b/style.css @@ -1,3 +1,7 @@ +* { + box-sizing: border-box; +} + body { margin: 0; font-family: Arial, sans-serif; @@ -5,14 +9,70 @@ body { color: #222; } -#episode-count { +.site-header { + background: #1f2937; + color: white; + padding: 24px; + display: flex; + justify-content: space-between; + align-items: center; +} + +.site-header h1 { + margin: 0; + font-size: 30px; +} + +.back-button { + border: none; + background: white; + color: #1f2937; + padding: 10px 16px; + border-radius: 6px; + cursor: pointer; + font-weight: bold; +} + +.back-button:hover { + opacity: 0.9; +} + +.controls { max-width: 1200px; - margin: 20px auto; + margin: 25px auto 10px; padding: 0 20px; + display: flex; + align-items: center; + gap: 10px; + flex-wrap: wrap; +} + +.controls label { font-weight: bold; } -#root { +.controls input, +.controls select { + padding: 10px; + border: 1px solid #ccc; + border-radius: 6px; + font-size: 15px; +} + +#show-search { + width: 320px; + max-width: 100%; +} + +.status-text { + max-width: 1200px; + margin: 15px auto; + padding: 0 20px; + font-weight: bold; +} + +.shows-grid, +.episodes-grid { max-width: 1200px; margin: 0 auto; padding: 20px; @@ -21,30 +81,82 @@ body { gap: 24px; } +.show-card, .episode-card { background: white; - border-radius: 10px; + border-radius: 12px; + overflow: hidden; + box-shadow: 0 3px 12px rgba(0, 0, 0, 0.12); +} + +.show-card { + display: flex; + flex-direction: column; +} + +.show-card > img { + width: 100%; + height: 360px; + object-fit: cover; +} + +.show-details { + padding: 18px; +} + +.show-title { + width: 100%; + border: none; + background: none; + padding: 0; + margin-bottom: 14px; + text-align: left; + font-size: 22px; + font-weight: bold; + cursor: pointer; + color: #1f2937; +} + +.show-title:hover { + text-decoration: underline; +} + +.show-details p { + line-height: 1.5; + margin: 8px 0; +} + +.show-summary { + margin-top: 16px; +} + +.episode-controls { + width: 100%; +} + +.episode-controls h2 { + width: 100%; + margin-top: 0; +} + +.episode-card { padding: 16px; - box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); } .episode-card h2 { font-size: 18px; text-align: center; margin-top: 0; - margin-bottom: 16px; } .episode-card img { width: 100%; - height: auto; display: block; - border-radius: 6px; + border-radius: 8px; } .episode-card p { line-height: 1.5; - font-size: 14px; } footer { @@ -59,13 +171,32 @@ footer a { } @media (max-width: 900px) { - #root { + .shows-grid, + .episodes-grid { grid-template-columns: repeat(2, 1fr); } } @media (max-width: 600px) { - #root { + .site-header { + align-items: flex-start; + gap: 15px; + flex-direction: column; + } + + .shows-grid, + .episodes-grid { grid-template-columns: 1fr; } + + .controls { + align-items: stretch; + flex-direction: column; + } + + .controls input, + .controls select, + #show-search { + width: 100%; + } } \ No newline at end of file From ecefe21cf75372944c5b145fe402f22bc94dbd13 Mon Sep 17 00:00:00 2001 From: Enice-Codes Date: Tue, 18 Aug 2026 15:42:03 +0200 Subject: [PATCH 17/20] completed this level --- levels/level-0.md | 80 +++++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/levels/level-0.md b/levels/level-0.md index 42e681e..acf9f46 100644 --- a/levels/level-0.md +++ b/levels/level-0.md @@ -1,41 +1,41 @@ -# Level 0 - -The goals of level 0 are to: -* Create a GitHub repository with the starter scaffolding in-place. -* Deploy it to **GitHub Pages**. -* Make sure whenever you push changes, your live site will be updated. - -## Fork your repository - -1. Go to https://github.com/CodeYourFuture/Project-TV-Show -2. Fork the repo to your account -3. Do not enable `Include all branches` - -## Deployment to GitHub Pages - -Follow the [CYF GitHub Pages Deployment Guide](https://curriculum.codeyourfuture.io/guides/deploying/ghpages/). - -> [!TIP] -> Deployment to **Netlify** is only required upon reaching **Level 500**. Using GitHub Pages until then helps conserve build credits during the development phase. - -## Get set up on your laptop - -1. Clone your repository. -2. Open your repository in VS Code. -3. Open the `index.html` page in Chrome. -4. Make sure in Chrome you can see the text "Got 73 episode(s)" in red. If you can't, something has gone wrong. -5. Edit `index.html` to include your name and GitHub username in the page title instead of "(My Name (My GitHub username))". - -## Push your changes - -1. Commit your changes to your `index.html` to your git repository (with a clear commit message). -2. Push your changes to your GitHub repository. -3. Check your GitHub Pages URL to ensure the changes are live. - -## Completion criteria - -You have completed level 0 when: -- [ ] You have forked the GitHub repository called `Project-TV-Show` into your account. -- [ ] The `index.html` page on your GitHub project contains your name and GitHub username. -- [ ] Your project is successfully deployed to **GitHub Pages**. +# Level 0 + +The goals of level 0 are to: +* Create a GitHub repository with the starter scaffolding in-place. +* Deploy it to **GitHub Pages**. +* Make sure whenever you push changes, your live site will be updated. + +## Fork your repository + +1. Go to https://github.com/CodeYourFuture/Project-TV-Show +2. Fork the repo to your account +3. Do not enable `Include all branches` + +## Deployment to GitHub Pages + +Follow the [CYF GitHub Pages Deployment Guide](https://curriculum.codeyourfuture.io/guides/deploying/ghpages/). + +> [!TIP] +> Deployment to **Netlify** is only required upon reaching **Level 500**. Using GitHub Pages until then helps conserve build credits during the development phase. + +## Get set up on your laptop + +1. Clone your repository. +2. Open your repository in VS Code. +3. Open the `index.html` page in Chrome. +4. Make sure in Chrome you can see the text "Got 73 episode(s)" in red. If you can't, something has gone wrong. +5. Edit `index.html` to include your name and GitHub username in the page title instead of "(My Name (My GitHub username))". + +## Push your changes + +1. Commit your changes to your `index.html` to your git repository (with a clear commit message). +2. Push your changes to your GitHub repository. +3. Check your GitHub Pages URL to ensure the changes are live. + +## Completion criteria + +You have completed level 0 when: +- [ ] You have forked the GitHub repository called `Project-TV-Show` into your account. +- [ ] The `index.html` page on your GitHub project contains your name and GitHub username. +- [ ] Your project is successfully deployed to **GitHub Pages**. - [ ] Your deployed project has your name and GitHub username in its title. \ No newline at end of file From e5bac946cb8a5a311eb18394c4922fff27181e99 Mon Sep 17 00:00:00 2001 From: Enice-Codes Date: Tue, 18 Aug 2026 15:44:21 +0200 Subject: [PATCH 18/20] completed this level --- levels/level-400.md | 122 ++++++++++++++++++++++---------------------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/levels/level-400.md b/levels/level-400.md index 60ddc9e..943d686 100644 --- a/levels/level-400.md +++ b/levels/level-400.md @@ -1,61 +1,61 @@ -# Level 400 - -For level 400, you should work in the repo of your partner from level 200. - -You do not need to re-add yourself as a collaborator. - -Remember to change to the right directory on your machine, and pull the latest changes from their main branch. - -Before writing any new code, look at their level 300 implementation. - -Compare their implementation to yours. Think: -1. How is it different? -2. What do you prefer about your implementation? -3. What do you prefer about their implementation? -4. What did you learn that you didn't know before? - -They should do the same with your repository. - -Have a discussion about your answers to these questions. In class, together you should give a 3 minute talk about your conclusions. - -## Refactoring - -Feel free to change anything in your codebase which you think will make it easier to work with, or to build new features. - -Make a branch and pull request for yourself, and then have your partner review, making sure they understand the changes made. - -## Adding new functionality - -Level 400 is about expanding beyond one TV show. - -Until now, your site has only showed information about the episode of one TV show. - -But TVmaze has information about lots of TV shows, all in the same format. - -We want to display any of them. - -### Requirements - -1. Add a `select` element to your page so the user can choose a show. -2. When the user first loads the page, make a `fetch` request to https://api.tvmaze.com/shows ([documentation](https://www.tvmaze.com/api#show-index)) to get a list of available shows, and add an entry to the drop-down per show. -3. When a user selects a show, display the episodes for that show, just like the earlier levels of this project. - - You will need to perform a `fetch` to get the episode list. -4. Make sure that your search and episode selector controls still work correctly when you change shows. -5. Your select must list shows in alphabetical order, case-insensitive. -6. During one user's visit to your website, you should never fetch any URL more than once. - -> [!NOTE] -> Be _careful_ when developing with fetch. By default, every time you make a small change to your app it will be restarted by live server - if you are fetching JSON on page load, the JSON will be downloaded again and again. These frequent HTTP requests may lead to the API permanently banning your IP address from further requests, or "throttling" it for some time. Worse, if they don't, they may cause performance issues for the API service we are using. - -Send a pull request to your partner's repo with this functionality. Have them review, and when happy, merge your PR. - -#### Screenshot of minimal version - -Note: Provided your project meets the above requirements, it can **look** however you want. - -Here is one example layout. - -![Screenshot of a website with a drop-down list with the show "Breaking Bad" selected](example-screenshots/example-level-400-1.jpg) - -![Screenshot of a website with a drop-down list showing multiple TV shows](example-screenshots/example-level-400-1.jpg) +# Level 400 + +For level 400, you should work in the repo of your partner from level 200. + +You do not need to re-add yourself as a collaborator. + +Remember to change to the right directory on your machine, and pull the latest changes from their main branch. + +Before writing any new code, look at their level 300 implementation. + +Compare their implementation to yours. Think: +1. How is it different? +2. What do you prefer about your implementation? +3. What do you prefer about their implementation? +4. What did you learn that you didn't know before? + +They should do the same with your repository. + +Have a discussion about your answers to these questions. In class, together you should give a 3 minute talk about your conclusions. + +## Refactoring + +Feel free to change anything in your codebase which you think will make it easier to work with, or to build new features. + +Make a branch and pull request for yourself, and then have your partner review, making sure they understand the changes made. + +## Adding new functionality + +Level 400 is about expanding beyond one TV show. + +Until now, your site has only showed information about the episode of one TV show. + +But TVmaze has information about lots of TV shows, all in the same format. + +We want to display any of them. + +### Requirements + +1. Add a `select` element to your page so the user can choose a show. +2. When the user first loads the page, make a `fetch` request to https://api.tvmaze.com/shows ([documentation](https://www.tvmaze.com/api#show-index)) to get a list of available shows, and add an entry to the drop-down per show. +3. When a user selects a show, display the episodes for that show, just like the earlier levels of this project. + + You will need to perform a `fetch` to get the episode list. +4. Make sure that your search and episode selector controls still work correctly when you change shows. +5. Your select must list shows in alphabetical order, case-insensitive. +6. During one user's visit to your website, you should never fetch any URL more than once. + +> [!NOTE] +> Be _careful_ when developing with fetch. By default, every time you make a small change to your app it will be restarted by live server - if you are fetching JSON on page load, the JSON will be downloaded again and again. These frequent HTTP requests may lead to the API permanently banning your IP address from further requests, or "throttling" it for some time. Worse, if they don't, they may cause performance issues for the API service we are using. + +Send a pull request to your partner's repo with this functionality. Have them review, and when happy, merge your PR. + +#### Screenshot of minimal version + +Note: Provided your project meets the above requirements, it can **look** however you want. + +Here is one example layout. + +![Screenshot of a website with a drop-down list with the show "Breaking Bad" selected](example-screenshots/example-level-400-1.jpg) + +![Screenshot of a website with a drop-down list showing multiple TV shows](example-screenshots/example-level-400-1.jpg) From 73544d2bba04e6a8d1e6f72167431649ddc5d5ba Mon Sep 17 00:00:00 2001 From: shafiekwalker7861 Date: Thu, 20 Aug 2026 17:04:59 +0200 Subject: [PATCH 19/20] Restore Level 400 show selector --- script.js | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/script.js b/script.js index 58d1b0a..41a61f7 100644 --- a/script.js +++ b/script.js @@ -105,6 +105,12 @@ function showShowsPage() { backButton.hidden = true; controls.innerHTML = ` + + + + `; + const showSelector = document.getElementById("show-selector"); + + allShows.forEach((show) => { + const option = document.createElement("option"); + + option.value = show.id; + option.textContent = show.name; + + showSelector.appendChild(option); + }); + + showSelector.addEventListener("change", function () { + if (showSelector.value === "") { + return; + } + + const selectedShow = allShows.find( + (show) => show.id === Number(showSelector.value) + ); + + if (selectedShow) { + showEpisodes(selectedShow); + } + }); + displayShows(allShows); const showSearch = document.getElementById("show-search"); From df810b49d5ce887b1832911a4a960168117a21d7 Mon Sep 17 00:00:00 2001 From: Enice-Codes Date: Fri, 21 Aug 2026 14:25:26 +0200 Subject: [PATCH 20/20] modified files --- index.html | 26 +++- script.js | 374 ++++++++++++++++++++++++++++++++++------------------- style.css | 194 +++++++++++++++++++++++++-- 3 files changed, 446 insertions(+), 148 deletions(-) diff --git a/index.html b/index.html index 13c884b..a9605c8 100644 --- a/index.html +++ b/index.html @@ -4,17 +4,33 @@ TV Show Project | Enice Mutanda(Enice-Codes) + -
-
+ + +
+ +

+ +
+ +
+

+ TV show and episode data provided by + TVMaze.com +

+
- - + \ No newline at end of file diff --git a/script.js b/script.js index 22f81aa..c4f9b3b 100644 --- a/script.js +++ b/script.js @@ -1,7 +1,6 @@ -let allEpisodes = []; let allShows = []; +let allEpisodes = []; -// Stores API results so the same URL is never fetched twice const apiCache = new Map(); function fetchJsonOnce(url) { @@ -20,6 +19,160 @@ function fetchJsonOnce(url) { return apiCache.get(url); } +function removeHtml(htmlText) { + const temporaryElement = document.createElement("div"); + temporaryElement.innerHTML = htmlText || ""; + + return temporaryElement.textContent || ""; +} + +function createShowCard(show) { + const card = document.createElement("article"); + card.className = "show-card"; + + if (show.image) { + const image = document.createElement("img"); + image.src = show.image.medium; + image.alt = `Poster for ${show.name}`; + card.appendChild(image); + } + + const titleButton = document.createElement("button"); + titleButton.className = "show-title"; + titleButton.textContent = show.name; + + titleButton.addEventListener("click", function () { + showEpisodes(show); + }); + + const details = document.createElement("div"); + details.className = "show-details"; + + const genres = document.createElement("p"); + genres.innerHTML = + `Genres: ${(show.genres || []).join(", ") || "Not available"}`; + + const status = document.createElement("p"); + status.innerHTML = + `Status: ${show.status || "Not available"}`; + + const rating = document.createElement("p"); + rating.innerHTML = + `Rating: ${show.rating?.average ?? "Not rated"}`; + + const runtime = document.createElement("p"); + runtime.innerHTML = + `Runtime: ${ + show.runtime ? `${show.runtime} minutes` : "Not available" + }`; + + const summary = document.createElement("p"); + summary.className = "show-summary"; + summary.textContent = + removeHtml(show.summary) || "No summary available."; + + details.appendChild(titleButton); + details.appendChild(genres); + details.appendChild(status); + details.appendChild(rating); + details.appendChild(runtime); + details.appendChild(summary); + + card.appendChild(details); + + return card; +} + +function displayShows(showList) { + const rootElem = document.getElementById("root"); + const statusText = document.getElementById("status-text"); + + rootElem.className = "shows-grid"; + rootElem.textContent = ""; + + statusText.textContent = + `Displaying ${showList.length} / ${allShows.length} shows`; + + showList.forEach((show) => { + rootElem.appendChild(createShowCard(show)); + }); +} + +function showShowsPage() { + const backButton = document.getElementById("back-to-shows"); + const controls = document.getElementById("controls"); + + backButton.hidden = true; + + controls.innerHTML = ` + + + + + + + + `; + + const showSelector = document.getElementById("show-selector"); + + allShows.forEach((show) => { + const option = document.createElement("option"); + + option.value = show.id; + option.textContent = show.name; + + showSelector.appendChild(option); + }); + + showSelector.addEventListener("change", function () { + if (showSelector.value === "") { + return; + } + + const selectedShow = allShows.find( + (show) => show.id === Number(showSelector.value) + ); + + if (selectedShow) { + showEpisodes(selectedShow); + } + }); + + displayShows(allShows); + + const showSearch = document.getElementById("show-search"); + + showSearch.addEventListener("input", function () { + const searchTerm = showSearch.value.toLowerCase().trim(); + + const filteredShows = allShows.filter((show) => { + const showName = show.name.toLowerCase(); + + const showGenres = (show.genres || []) + .join(" ") + .toLowerCase(); + + const showSummary = removeHtml(show.summary) + .toLowerCase(); + + return ( + showName.includes(searchTerm) || + showGenres.includes(searchTerm) || + showSummary.includes(searchTerm) + ); + }); + + displayShows(filteredShows); + }); +} + function getEpisodeCode(episode) { const seasonNumber = String(episode.season).padStart(2, "0"); const episodeNumber = String(episode.number).padStart(2, "0"); @@ -28,84 +181,87 @@ function getEpisodeCode(episode) { } function createEpisodeCard(episode) { - const episodeCode = getEpisodeCode(episode); - - const card = document.createElement("div"); + const card = document.createElement("article"); card.className = "episode-card"; card.id = `episode-${episode.id}`; const heading = document.createElement("h2"); - heading.textContent = `${episodeCode} - ${episode.name}`; + heading.textContent = + `${getEpisodeCode(episode)} - ${episode.name}`; - const image = document.createElement("img"); + card.appendChild(heading); if (episode.image) { + const image = document.createElement("img"); image.src = episode.image.medium; - } - - image.alt = `Image for ${episode.name}`; + image.alt = `Image for ${episode.name}`; - const summary = document.createElement("div"); - summary.innerHTML = episode.summary || "No summary available."; - - card.appendChild(heading); - - if (episode.image) { card.appendChild(image); } + const summary = document.createElement("p"); + summary.textContent = + removeHtml(episode.summary) || "No summary available."; + card.appendChild(summary); return card; } -function makePageForEpisodes(episodeList) { +function displayEpisodes(episodeList) { const rootElem = document.getElementById("root"); + const statusText = document.getElementById("status-text"); + rootElem.className = "episodes-grid"; rootElem.textContent = ""; - const counter = document.createElement("p"); - counter.textContent = + statusText.textContent = `Displaying ${episodeList.length} / ${allEpisodes.length} episodes`; - rootElem.appendChild(counter); - episodeList.forEach((episode) => { - const card = createEpisodeCard(episode); - rootElem.appendChild(card); + rootElem.appendChild(createEpisodeCard(episode)); }); } function updateEpisodeSelector() { - const episodeSelector = document.getElementById("episode-selector"); + const selector = document.getElementById("episode-selector"); - episodeSelector.textContent = ""; + selector.innerHTML = ""; const defaultOption = document.createElement("option"); defaultOption.value = ""; defaultOption.textContent = "Choose an episode"; - episodeSelector.appendChild(defaultOption); + selector.appendChild(defaultOption); allEpisodes.forEach((episode) => { const option = document.createElement("option"); option.value = episode.id; - option.textContent = `${getEpisodeCode(episode)} - ${episode.name}`; + option.textContent = + `${getEpisodeCode(episode)} - ${episode.name}`; - episodeSelector.appendChild(option); + selector.appendChild(option); }); } -function setupSearch() { - const searchInput = document.getElementById("search-input"); +function setupEpisodeControls() { + const searchInput = + document.getElementById("episode-search"); + + const episodeSelector = + document.getElementById("episode-selector"); searchInput.addEventListener("input", function () { - const searchTerm = searchInput.value.toLowerCase().trim(); + const searchTerm = + searchInput.value.toLowerCase().trim(); const filteredEpisodes = allEpisodes.filter((episode) => { - const episodeName = episode.name.toLowerCase(); - const episodeSummary = (episode.summary || "").toLowerCase(); + const episodeName = + episode.name.toLowerCase(); + + const episodeSummary = + removeHtml(episode.summary).toLowerCase(); return ( episodeName.includes(searchTerm) || @@ -113,23 +269,17 @@ function setupSearch() { ); }); - makePageForEpisodes(filteredEpisodes); + displayEpisodes(filteredEpisodes); }); -} - -function setupEpisodeSelector() { - const episodeSelector = document.getElementById("episode-selector"); episodeSelector.addEventListener("change", function () { if (episodeSelector.value === "") { return; } - const searchInput = document.getElementById("search-input"); - searchInput.value = ""; - makePageForEpisodes(allEpisodes); + displayEpisodes(allEpisodes); const selectedEpisode = document.getElementById( `episode-${episodeSelector.value}` @@ -144,95 +294,72 @@ function setupEpisodeSelector() { }); } -async function loadEpisodesForShow(showId) { - const rootElem = document.getElementById("root"); - const searchInput = document.getElementById("search-input"); - - rootElem.textContent = "Loading episodes..."; - searchInput.value = ""; - - try { - const episodeUrl = - `https://api.tvmaze.com/shows/${showId}/episodes`; - - allEpisodes = await fetchJsonOnce(episodeUrl); - - updateEpisodeSelector(); - makePageForEpisodes(allEpisodes); - } catch (error) { - rootElem.textContent = - "Sorry, we could not load the episodes. Please try again later."; - } -} - -function setupShowSelector() { - const showSelector = document.getElementById("show-selector"); - - showSelector.addEventListener("change", function () { - if (showSelector.value === "") { - return; - } - - loadEpisodesForShow(showSelector.value); - }); -} - -function createControls() { +async function showEpisodes(show) { + const controls = document.getElementById("controls"); const rootElem = document.getElementById("root"); + const statusText = document.getElementById("status-text"); + const backButton = document.getElementById("back-to-shows"); - const controls = document.createElement("div"); - - const showLabel = document.createElement("label"); - showLabel.setAttribute("for", "show-selector"); - showLabel.textContent = "Select show: "; - - const showSelector = document.createElement("select"); - showSelector.id = "show-selector"; + backButton.hidden = false; - const showDefault = document.createElement("option"); - showDefault.value = ""; - showDefault.textContent = "Choose a show"; + controls.innerHTML = ` +
+

${show.name} Episodes

- showSelector.appendChild(showDefault); + - const searchLabel = document.createElement("label"); - searchLabel.setAttribute("for", "search-input"); - searchLabel.textContent = " Search episodes: "; + - const searchInput = document.createElement("input"); - searchInput.id = "search-input"; - searchInput.type = "search"; - searchInput.placeholder = "Search by name or summary"; + - const episodeLabel = document.createElement("label"); - episodeLabel.setAttribute("for", "episode-selector"); - episodeLabel.textContent = " Select episode: "; + +
+ `; - const episodeSelector = document.createElement("select"); - episodeSelector.id = "episode-selector"; + rootElem.textContent = ""; + statusText.textContent = "Loading episodes..."; - const episodeDefault = document.createElement("option"); - episodeDefault.value = ""; - episodeDefault.textContent = "Choose an episode"; + try { + const url = + `https://api.tvmaze.com/shows/${show.id}/episodes`; - episodeSelector.appendChild(episodeDefault); + allEpisodes = await fetchJsonOnce(url); - controls.appendChild(showLabel); - controls.appendChild(showSelector); - controls.appendChild(searchLabel); - controls.appendChild(searchInput); - controls.appendChild(episodeLabel); - controls.appendChild(episodeSelector); + updateEpisodeSelector(); + setupEpisodeControls(); + displayEpisodes(allEpisodes); + } catch (error) { + statusText.textContent = + "Unable to load episodes."; - rootElem.parentNode.insertBefore(controls, rootElem); + rootElem.textContent = + "Sorry, we could not load the episodes."; + } } async function setup() { const rootElem = document.getElementById("root"); + const statusText = document.getElementById("status-text"); + const backButton = document.getElementById("back-to-shows"); - createControls(); + statusText.textContent = "Loading TV shows..."; + rootElem.textContent = "Please wait..."; - rootElem.textContent = "Loading TV shows..."; + backButton.addEventListener("click", function () { + showShowsPage(); + }); try { allShows = await fetchJsonOnce( @@ -245,26 +372,13 @@ async function setup() { }) ); - const showSelector = document.getElementById("show-selector"); - - allShows.forEach((show) => { - const option = document.createElement("option"); - - option.value = show.id; - option.textContent = show.name; - - showSelector.appendChild(option); - }); - - rootElem.textContent = - "Choose a TV show to display its episodes."; - - setupShowSelector(); - setupSearch(); - setupEpisodeSelector(); + showShowsPage(); } catch (error) { + statusText.textContent = + "Unable to load TV shows."; + rootElem.textContent = - "Sorry, we could not load the TV shows. Please try again later."; + "Sorry, we could not load the TV shows."; } } diff --git a/style.css b/style.css index de44e6e..4023d2c 100644 --- a/style.css +++ b/style.css @@ -1,34 +1,202 @@ -#root { - color: rgb(39, 38, 38); +* { + box-sizing: border-box; +} + +body { + margin: 0; + font-family: Arial, sans-serif; + background: #f4f4f4; + color: #222; +} + +.site-header { + background: #1f2937; + color: white; + padding: 24px; + display: flex; + justify-content: space-between; + align-items: center; +} + +.site-header h1 { + margin: 0; + font-size: 30px; +} + +.back-button { + border: none; + background: white; + color: #1f2937; + padding: 10px 16px; + border-radius: 6px; + cursor: pointer; + font-weight: bold; +} + +.back-button:hover { + opacity: 0.9; +} + +.controls { + max-width: 1200px; + margin: 25px auto 10px; + padding: 0 20px; display: flex; + align-items: center; + gap: 10px; flex-wrap: wrap; - gap: 20px; +} + +.controls label { + font-weight: bold; +} + +.controls input, +.controls select { + padding: 10px; + border: 1px solid #ccc; + border-radius: 6px; + font-size: 15px; +} + +#show-search { + width: 320px; + max-width: 100%; +} + +.status-text { + max-width: 1200px; + margin: 15px auto; + padding: 0 20px; + font-weight: bold; +} + +.shows-grid, +.episodes-grid { + max-width: 1200px; + margin: 0 auto; padding: 20px; - justify-content: center; + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 24px; +} + +.show-card, +.episode-card { + background: white; + border-radius: 12px; + overflow: hidden; + box-shadow: 0 3px 12px rgba(0, 0, 0, 0.12); +} + +.show-card { + display: flex; + flex-direction: column; +} + +.show-card > img { + width: 100%; + height: 360px; + object-fit: cover; } +.show-details { + padding: 18px; +} + +.show-title { + width: 100%; + border: none; + background: none; + padding: 0; + margin-bottom: 14px; + text-align: left; + font-size: 22px; + font-weight: bold; + cursor: pointer; + color: #1f2937; +} + +.show-title:hover { + text-decoration: underline; +} + +.show-details p { + line-height: 1.5; + margin: 8px 0; +} + +.show-summary { + margin-top: 16px; +} + +.episode-controls { + width: 100%; +} + +.episode-controls h2 { + width: 100%; + margin-top: 0; +} .episode-card { -border: 1px solid whitesmoke; - border-radius: 8px; - padding: 15px; - width: 300px; - + padding: 16px; } .episode-card h2 { + font-size: 18px; text-align: center; - font-size: 16px; margin-top: 0; } .episode-card img { width: 100%; - border-radius: 4px; display: block; + border-radius: 8px; } .episode-card p { - font-size: 14px; - color: #333; + line-height: 1.5; +} + +footer { + max-width: 1200px; + margin: 30px auto; + padding: 20px; + text-align: center; +} + +footer a { + color: inherit; +} + +@media (max-width: 900px) { + .shows-grid, + .episodes-grid { + grid-template-columns: repeat(2, 1fr); + } +} + +@media (max-width: 600px) { + .site-header { + align-items: flex-start; + gap: 15px; + flex-direction: column; + } + + .shows-grid, + .episodes-grid { + grid-template-columns: 1fr; + } + + .controls { + align-items: stretch; + flex-direction: column; + } + + .controls input, + .controls select, + #show-search { + width: 100%; + } } \ No newline at end of file