Skip to content

Display movies playing in the theaters, that are fetched from themoviedb.org API in a friendly way.

Notifications You must be signed in to change notification settings

Zabzuki/movie-to-watch

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Movie to watch

How to install and run

  1. Download the example or clone the repo
  2. Open index.html document and Go Live (Live Server extension on VSCode).
  3. Ready to use!

Description

movie-to-watch display movies playing in the theaters, that are fetched from themoviedb.org API in a friendly way. Users are able to browse through the latest movies using inifinite scrolling without waiting any new HTTP GET request, to render content. Every movie is clickable where the <div> content extends in an performant way, where details like trailer, reviews, similar movies are presented (if they exist). There is also added an <input> field where user can search for specific movies.

  • In the below GIF can see the infinity scroll functionality and the expand option with the relevant results of each movie.

  • In the below GIF you can also see the search option of a movie and the infinity scroll / expand option of the results.

Technologies

  1. Vanilla JavaScript (Web Components)
  2. HTML5
  3. CSS

Architecture

The app follows the component based architecture and consists of five main parts.

  1. appModule is the main file which contains the definition of the base component (<app-root>) and the rest of the components that are used (listItem, reviewItem, similarItem).
  2. appComponent is the file where the container of the web application is first created. The most important parts that are applied are the search <input> and the reusable listItem component which is wrapped with the "infinity scrolling" functinality.
  3. reviewItem, similarItem components that works the same like listItem, which means that are all reusable.
  4. movieService where the communication with the API and all the HTTP GET requests of the application are applied.
  5. utils which is a generic file where scrolling process gets observed / unobserved in different files of the application.

Definition of rendered Elements

The appModule contains the definition of the defineElements() method where all the components present in the application are defined there.

export class AppModule {
  static defineElements() {
    window.customElements.define("app-root", AppComponent);
    window.customElements.define("list-item", ListItem);
    window.customElements.define("review-item", ReviewItem);
    window.customElements.define("similar-item", SimilarItem);
  }
}

Web Components Structure

The appComponent forms the main body of the application, which contains the basic code which is required. Furthermore appComponent is the only component exposed in the index.html as <app-root>. In the below example template element is created and then in the HTML list-items are rendered as a <div> tag which is rendered as an external reusable component.

const appTemplate = document.createElement("template");
appTemplate.innerHTML = `
    <style>
        @import url('./src/appComponent.css')
    </style>
    <div class="list-container">
        <span class="title" >Latest Movies</span>
        <form class="search-container">
            <input type="text" class="search-input" name="movieName" placeholder="Search">
            </input>
            <input type="submit" value="Search" class="search-btn"></input>
        </form>
        <div class="scroller">
            <div class="list-items"></div>
            <div class="sentinel"></div>
        </div>
    </div>
`;

After the creation of HTML, getNewestMovies() (HTTP GET) call returns the newest movies which are mapped and a list-item created with the createElement("list-item).

renderMovies(movies) {
    .
    .
    .
    movies.map((movie) => {
      let listItem = document.createElement("list-item");
      listItem.id = movie.id;
      listItem.movie = movie;
      this.listItems.appendChild(listItem);
    });
    this.listItems.appendChild(this.sentinel);
  }

Infinity Scrolling

For the infinity scrolling process a <div> named sentinel added exactly after the listItem, reviewItem, similarItem. Then the IntersectionObserver observe when the sentinel gets rendered and then a new HTTP GET request applied. The observe / unobserve happens in the same way in three different places so a generic file with the name utils hosting functions for both cases.

In the setUpScrollListeners gets passed arguments like self just to inform function where should look up for "this". sentinel that when gets rendered entry.interesctionRatio becomes 1 so the corresponding callback applied based on the process and params where the search value used for scrolling cases like a movie search.

export const setUpScrollListeners = (self, sentinel, callback, params) => {
  let intersectionObserver = new IntersectionObserver((entries) => {
    if (entries.some((entry) => entry.intersectionRatio > 0)) {
      callback.call(self, params);
    }
  });
  intersectionObserver.observe(sentinel);
  return intersectionObserver;
};

tearDownScrollListeners similarly gets intersectionObserver from setUpScrollListeners and sentinel, too. Then sentinel just gets unobserved just to be able setUpScrollListeners applied again in different usage after the already rendered results gets cleared.

export const tearDownScrollListeners = (intersectionObserver, sentinel) => {
  intersectionObserver.unobserve(sentinel);
};

tearDownScrollListeners is called in cases like when tear down and return zero results.

Todos

  1. Unit tests
  2. Mobile friendly
  3. Error handling
  4. Empty state
  5. Memory cache

Useful Links

About

Display movies playing in the theaters, that are fetched from themoviedb.org API in a friendly way.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published