Welcome to Coding Torque! Are you ready to build a powerful and feature-rich Movie App using HTML, CSS, and JavaScript? In this tutorial, we will guide you through the process of creating a dynamic and interactive web application that allows you to browse and search through the vast IMDB database of films. You’ll learn how to use APIs to access and display data from external sources, and you’ll also learn how to add search functionality and other advanced features to your app. Whether you’re a beginner or an experienced coder, this project is sure to challenge and engage you. So let’s get started!
Before we start, here are some JavaScript Games you might like to create:
1.Ā Snake Game using JavaScript
2.Ā 2D Bouncing Ball Game using JavaScript
3.Ā Rock Paper Scissor Game using JavaScript
4.Ā Tic Tac Toe Game using JavaScript
5. Whack a Mole Game using JavaScript
I would recommend you don’t just copy and paste the code, just look at the code and type by understanding it.
HTML CodeĀ
Starter Template
<!doctype html> <html lang="en"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- CSS --> <link rel="stylesheet" href="style.css"> <title>Movie App using JavaScript - @code.scientist x @codingtorque</title> </head> <body> <!-- Further code here --> <script src="script.js"></script> </body> </html>
Paste the below code in your <body>
tag
<div class="wrapper"> <div class="search-block"> <a href="/"> <h1>TheMovieDB</h1> </a> <form id="search-form"> <input type="text" id="query" placeholder="Search movies..." /> <button class="btn" type="submit">Search</button> </form> </div> <div class="row" id="root"></div> </div>
Output Till Now
CSS CodeĀ
Create a fileĀ style.css and paste the code below.
* { margin: 0; box-sizing: border-box; outline: none; } body { color: white; font-family: "microsoft yahei", arial, -apple-system, BlinkMacSystemFont, "segoe ui", roboto, oxygen, cantarell, "helvetica neue", ubuntu, sans-serif; background: #080823; } .btn { color: white; cursor: pointer; text-decoration: none; padding: 6px 8px; border: 1px solid rgba(255, 255, 255, 0.5); transition: inherit; } .btn:hover { background: #06c3dd; border-color: #06c3dd; } .row { display: flex; max-width: 1200px; gap: 15px; flex-direction: row; flex-wrap: wrap; justify-content: center; } .wrapper { width: 100%; min-height: 100vh; padding: 15px 0; display: flex; justify-content: flex-start; align-items: center; flex-direction: column; } .wrapper .card { position: relative; font-size: 14px; line-height: 21px; width: 285px; height: 360px; overflow: hidden; transition: 0.5s ease all; } .wrapper .card .card-content { width: 100%; position: absolute; bottom: 0; left: 0; padding: 50px 10px 7px; background-image: linear-gradient( 180deg, rgba(51, 55, 69, 0), rgba(16, 21, 40, 0.95) ); transition: inherit; } .wrapper .card .card-content .card-cont-header { padding: 8px 0; display: flex; justify-content: space-between; align-items: center; } .wrapper .card .card-content .describe { max-height: 0; opacity: 0; border-top: 1px solid rgba(255, 255, 255, 0.1); overflow: hidden; transition: inherit; } .wrapper .card:hover { cursor: pointer; } .wrapper .card:hover .card-content { background-image: linear-gradient(180deg, rgba(51, 55, 69, 0) 0, #101528 48%); } .wrapper .card:hover .btn { background: #06c3dd; border-color: #06c3dd; } .wrapper .card:hover .describe { max-height: 200px; padding: 8px 0; opacity: 1; } .search-block { width: 100%; display: flex; justify-content: space-between; flex-wrap: wrap; max-width: 1200px; align-items: center; margin-bottom: 15px; margin: 15px 0 30px 0; } .search-block #search-form { display: flex; max-width: 400px; } .search-block input { width: 100%; max-width: 400px; padding: 15px; border-radius: 0; border: none; background: rgba(255, 255, 255, 0.75); } .search-block .btn { width: 120px; background: rgba(255, 255, 255, 0.25); border: 1px solid lightgray; } .search-block .btn:hover { background: rgba(255, 255, 255, 0.5); border: 1px solid white; } .btn-load { background-color: skyblue; padding: 10px 25px; border: none; margin-top: 15px; } a { color: white; text-decoration: none; }
Output Till Now
JavaScript CodeĀ
const apiKey = "YOUR_API_KEY" const URL = "https://api.themoviedb.org/3/discover/movie?sort_by=popularity.desc&api_key=YOUR_API_KEY&page=1"const imgURL = "https://image.tmdb.org/t/p/w1280" const searchURL = "https://api.themoviedb.org/3/search/movie?&api_key=YOUR_API_KEY&query=" const form = document.getElementById("search-form") const query = document.getElementById("query") const root = document.getElementById("root") let movies = [], page = 1, inSearchPage = false // Fetch json data from URL async function fetchData(URL) { try { const data = await fetch(URL).then((res) => res.json()) return data } catch (error) { console.log(error.message) return null } } const fetchAndShowResults = async (URL) => { const data = await fetchData(URL) data && showResults(data.results) } const getSpecificPage = (page) => { const URL = `https://api.themoviedb.org/3/discover/movie?sort_by=popularity.desc&api_key=${apiKey}&page=${page}` fetchAndShowResults(URL) } const movieCard = (movie) => `<div class="col"> <div class="card"> <a class="card-media" href="./img-01.jpeg"> <img src="${movie.poster_path}" alt="PUBG Mobile" width="100%" /> </a> <div class="card-content"> <div class="card-cont-header"> <div class="cont-left"> <h3 style="font-weight: 600">${movie.original_title}</h3> <span style="color: #12efec">${movie.release_date}</span> </div> <div class="cont-right"> <a href="${movie.poster_path}" target="_blank" class="btn">See image</a> </div> </div> <div class="describe"> ${movie.overview} </div> </div> </div> </div>` const showResults = (items) => { let content = !inSearchPage ? root.innerHTML : "" if (items && items.length > 0) { items.map((item) => { let { poster_path, original_title, release_date, overview } = item if (poster_path) { poster_path = imgURL + poster_path } else { poster_path = "./img-01.jpeg" } if (original_title.length > 15) { original_title = original_title.slice(0, 15) + "..." } if (!overview) { overview = "No overview yet..." } if (!release_date) { release_date = "No release date" } const movieItem = { poster_path, original_title, release_date, overview, } content += movieCard(movieItem) }) } else { content += "<p>Something went wrong!</p>" } root.innerHTML = content // Inject content to root } const handleLoadMore = () => { getSpecificPage(++page) } const detectEndAndLoadMore = (e) => { let el = document.documentElement if ( !inSearchPage && el.scrollTop + el.clientHeight == el.scrollHeight ) { console.log("BINGO!") handleLoadMore() } } form.addEventListener("submit", async (e) => { inSearchPage = true e.preventDefault() const searchTerm = query.value searchTerm && fetchAndShowResults(searchURL + searchTerm) query.value = "" }) window.addEventListener("scroll", detectEndAndLoadMore) function init() { inSearchPage = false fetchAndShowResults(URL) } init();