Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Ignore vscode files
.vscode
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# JavaScript Project - App
Find Your Movie App

# API source
https://imdb-api.com/api#SearchMovie-header

# How to use

Enter the title of the film you want to find in the search field.
Wait a few seconds.
Then click on the film you like to view more information about it.
In addition to the first search suggestions, you will get other suggested movies based on the category of the movie you selected.
You can navigate through your search results and suggestions using the pagination buttons.
Binary file added assets/cinema.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
74 changes: 74 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="description" content="Web App based on IMDb API" />
<meta name="keywords" content="HTML, CSS, JavaScript" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="author" content="Emilia" />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@900&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="styles/style.css" />
<link rel="stylesheet" href="styles/loader.css" />
<title>movie app</title>
</head>

<body>
<h1 id="appname">
Find. <br />
Your. <br />
Movie.
</h1>

<!-- input for search movie -->
<input
type="text"
id="search-movie"
name="searchTxt"
placeholder="movie title"
/>
<!-- search results movies -->
<div id="movies">
<div class="loader-container">
<div class="loader">Loading...</div>
</div>
<div id="results-movies" class="results-movies"></div>
</div>

<div id="pagination-results" class="pagination">
<button class="prev-btn" id="previous"><span>&#8592;</span></button>
page
<div id="current-page" class="bold"></div>
of
<div id="total-pages" class="bold"></div>
<button class="next-btn" id="next"><span>&#8594;</span></button>
</div>

<div id="clicked-movie-id"></div>

<ul id="genres-list"></ul>
<!-- suggested movies -->
<div id="suggested-movies">
<div class="loader-container">
<div class="loader">Loading...</div>
</div>
<div id="suggested-results" class="results-genres"></div>
</div>

<div id="pagination-suggestions" class="pagination">
<button class="prev-btn" id="prev-bt"><span>&#8592;</span></button>
page
<div id="cur-page" class="bold"></div>
of
<div id="tot-pages" class="bold"></div>
<button class="next-btn" id="next-bt"><span>&#8594;</span></button>
</div>

<script type="module" src="scripts/main.js"></script>
<script type="module" src="scripts/pagination.js"></script>
<!-- <script type="module" src="/pagination-suggestions.js"></script> -->
<script type="module" src="scripts/scrolling.js"></script>
</body>
</html>
Empty file removed main.js
Empty file.
281 changes: 281 additions & 0 deletions scripts/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,281 @@
"use strict";
import loadPaging from "./pagination.js";
import loadPagingSuggestions from "./pagination-suggestions.js";
import scrollToDetailBox from "./scrolling.js";

window.addEventListener("DOMContentLoaded", () => {
const apiKey = "k_pgd93xda"; // first api key
// const apiKey = "k_28x30ddn"; // third api key
// const apiKey = "k_n2nfzz4l"; // second api key
const insideDetailBox = document.getElementById("clicked-movie-id");
const inputSearchMovie = document.getElementById("search-movie");
const searchResultsMoviesContainer = document.getElementById("movies");
const searchResultsMovies = document.getElementById("results-movies");
const genresList = document.getElementById("genres-list");
const suggestedResultsListContainer =
document.getElementById("suggested-movies");
const suggestedResultsList = document.getElementById("suggested-results");
const urlAPI = `https://imdb-api.com/en/API/SearchMovie/${apiKey}`;
const urlDetailsAPI = `https://imdb-api.com/en/API/Title/${apiKey}`;
const advancedSearchUrl = `https://imdb-api.com/API/AdvancedSearch/${apiKey}`;

window.onload = function () {
document.getElementById("pagination-results").style.display = "none";
document.getElementById("pagination-suggestions").style.display = "none";
};

function init() {
inputSearchMovie.addEventListener("keyup", debounce(getMovies, 300));
// event listener on click movie id from titles list
searchResultsMovies.addEventListener("click", async (event) => {
const movieID = event.target.closest("a").id;
await getDetails(movieID);
scrollToDetailBox();
});
// event listener on click movie id for genres movies
suggestedResultsList.addEventListener("click", async (event) => {
const movieID = event.target.closest("a").id;
await getDetails(movieID);
scrollToDetailBox();
});
}
init();

// wait for execute
function debounce(callback, delay) {
let timeout;
return function () {
clearTimeout(timeout);
timeout = setTimeout(callback, delay);
};
}

// clear html target
function clearHtml(target) {
target.innerHTML = "";
}

//show loader
function showLoader(target) {
const loader = target.getElementsByClassName("loader-container");
loader[0].classList.add("visible");
}
// hide loader
function hideLoader(target) {
const loader = target.getElementsByClassName("loader-container");
loader[0].classList.remove("visible");
}

// search results
async function getMovies(movie) {
showLoader(searchResultsMoviesContainer);
const movieValue = inputSearchMovie.value;
const results = await fetch(`${urlAPI}/${movieValue}`)
.then((response) => response.json())
.then((data) => data.results)
.then((results) => {
hideLoader(searchResultsMoviesContainer);
document.getElementById("pagination-results").style.display = "flex";
// add pagintion
loadPaging(results.length, (pagingOptions) => {
clearHtml(searchResultsMovies);
const newArray = pageArraySplit(results, pagingOptions);
createMoviesDOM(newArray, searchResultsMovies);
});
})
.catch((error) => console.log(error));
}

// create movie list in DOM
function createMoviesDOM(movies, htmlTarget) {
for (const movie of movies) {
const movieElement = document.createElement("div");
movieElement.classList.add("selected-movie");
movieElement.setAttribute("id", "click-movie");
movieElement.innerHTML = `<a id="${movie.id}">${movie.title}</a>`;
movieElement.style.backgroundImage = `url(${movie.image})`;
movieElement.style.backgroundSize = "cover";
htmlTarget.appendChild(movieElement);
// movie title
const movieElementTitle = document.createElement("p");
movieElementTitle.classList.add("results-movies-title");
movieElementTitle.setAttribute("id", "click-movie");
movieElementTitle.innerHTML = `<a id="${movie.id}">${movie.title}</a>`;
movieElement.appendChild(movieElementTitle);
}
}

// get id from selected movie link and create div with details
async function getDetails(movieId) {
const details = await fetch(`${urlDetailsAPI}/${movieId}`)
.then((response) => response.json())
.then((data) => {
clearHtml(insideDetailBox);
createMovieDetailsDom(data);
if (data.genreList) {
const genres = transformGenresToApiParam(data.genreList); // " "
showSuggestions(genres);
}
})
.catch((error) => new Error("Details not found"));
}

// create selected from API details
function createMovieDetailsDom(data) {
insideDetailBox.classList.add("detail-conatiner");
//image
if (data.image) {
const detailBoxImage = document.createElement("div");
const title = data.title ? data.title : "";
detailBoxImage.innerHTML = `<img src="${data.image}" alt="${title}">`;
detailBoxImage.classList.add("movie-image");
detailBoxImage.classList.add("box-left");
insideDetailBox.appendChild(detailBoxImage);
}
//rightBox
const detailBoxRight = document.createElement("div");
detailBoxRight.classList.add("box-right");
insideDetailBox.append(detailBoxRight);
//title
if (data.title) {
const detailBox = document.createElement("div");
detailBox.innerHTML = `${data.title}`;
detailBox.classList.add("title");
detailBoxRight.appendChild(detailBox);
}
//plot
if (data.plot) {
const detailBoxPlot = document.createElement("p");
detailBoxPlot.innerHTML = `${data.plot}`;
detailBoxPlot.classList.add("plot");
detailBoxRight.appendChild(detailBoxPlot);
}
//rating
if (data.imDbRating) {
const ratingIMDb = document.createElement("p");
ratingIMDb.innerHTML = `IMDb Rating`;
ratingIMDb.classList.add("rating-title");
detailBoxRight.appendChild(ratingIMDb);
const detailBoxRating = document.createElement("p");
detailBoxRating.innerHTML = `${data.imDbRating} / 10`;
detailBoxRating.classList.add("rating");
detailBoxRight.appendChild(detailBoxRating);
}
// year
if (data.year) {
const detailBoxYear = document.createElement("p");
detailBoxYear.innerHTML = `Year: ${data.year}`;
detailBoxYear.classList.add("year");
detailBoxRight.appendChild(detailBoxYear);
}
// genres
if (data.genres) {
const detailBoxGenres = document.createElement("p");
detailBoxGenres.innerHTML = `${data.genres}`;
detailBoxGenres.classList.add("genres");
detailBoxGenres.id = "genres";
detailBoxRight.appendChild(detailBoxGenres);
}
// list genres
if (data.genreList) {
createGenresDom(data.genreList, genresList);
}
// languages
if (data.languages) {
const detailBoxLanguages = document.createElement("p");
detailBoxLanguages.innerHTML = `${data.languages}`;
detailBoxLanguages.classList.add("movie-languages");
detailBoxRight.appendChild(detailBoxLanguages);
}
//stars
if (data.starList) {
createStars(data.starList, detailBoxRight);
}
//awards
if (data.awards) {
const detailBoxAwards = document.createElement("p");
detailBoxAwards.innerHTML = `${data.awards}`;
detailBoxAwards.classList.add("movie-awards");
detailBoxRight.appendChild(detailBoxAwards);
}
//runtimeStr
if (data.runtimeStr) {
const detailBoxRuntimeStr = document.createElement("p");
detailBoxRuntimeStr.innerHTML = `${data.runtimeStr}`;
detailBoxRuntimeStr.classList.add("runtime-str");
detailBoxRight.appendChild(detailBoxRuntimeStr);
}
//trailer
if (data.trailer) {
const detailBoxTrailer = document.createElement("a");
detailBoxTrailer.innerHTML = `${data.trailer}`;
detailBoxTrailer.classList.add("trailer");
detailBoxRight.appendChild(detailBoxTrailer);
}
}

// list with movie's stars
function createStars(stars, box) {
const detailBoxStars = document.createElement("ul");
detailBoxStars.classList.add("stars");
box.appendChild(detailBoxStars);

for (const star of stars) {
const starElement = document.createElement("li");
starElement.innerHTML = star.name;
detailBoxStars.appendChild(starElement);
}
}

//suggested movies
async function showSuggestions(genres) {
showLoader(suggestedResultsListContainer);
const suggestions = await fetch(`${advancedSearchUrl}/?genres=${genres}`)
.then((response) => response.json())
.then((data) => data.results)
.then((results) => {
hideLoader(suggestedResultsListContainer);
document.getElementById("pagination-suggestions").style.display =
"flex";
loadPagingSuggestions(results.length, (pagingOptions) => {
clearHtml(suggestedResultsList);
const newArray = pageArraySplit(results, pagingOptions);
createMoviesDOM(newArray, suggestedResultsList);
});
})
.catch((error) => new Error("Suggestions not found"));
}

// transform genres to api param
function transformGenresToApiParam(genres) {
const forSuggestionsGenres = genres.map((genre) => {
return genre.value;
});
return forSuggestionsGenres.join().toLowerCase();
}

// create div with genres in DOM
function createGenresDom(genres) {
const genresElement = document.getElementById("genres-list");
genresElement.classList.add("genres-suggestions");
genresElement.innerHTML = "";
const suggestionsHeader = document.createElement("h2");
suggestionsHeader.innerHTML = `Other suggested movies`;
genresElement.appendChild(suggestionsHeader);
for (const genre of genres) {
const genreElement = document.createElement("li");
genreElement.classList.add("single-genre");
genreElement.innerHTML = `${genre.value}`;
genresElement.appendChild(genreElement);
}
}
// pagination for search results
function pageArraySplit(array, pagingOptions) {
const currentPageNumber = pagingOptions.currentPageNumber;
const perPage = pagingOptions.perPage;
const startingIndex = (currentPageNumber - 1) * perPage;
const endingIndex = startingIndex + perPage;

return array.slice(startingIndex, endingIndex);
}
});
Loading