From 014b7ea0116657ed9f5b00966939cd099591ed00 Mon Sep 17 00:00:00 2001 From: David Gridley Date: Fri, 21 Sep 2018 09:57:32 +0100 Subject: [PATCH 1/6] created html, css and js files --- index.html | 0 src/index.js | 0 style.css | 0 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 index.html create mode 100644 src/index.js create mode 100644 style.css diff --git a/index.html b/index.html new file mode 100644 index 00000000..e69de29b diff --git a/src/index.js b/src/index.js new file mode 100644 index 00000000..e69de29b diff --git a/style.css b/style.css new file mode 100644 index 00000000..e69de29b From d24e215b65fa966d02277b36171f37b21618c68a Mon Sep 17 00:00:00 2001 From: David Gridley Date: Fri, 21 Sep 2018 16:59:32 +0100 Subject: [PATCH 2/6] written almost all base functionality, including search, additional info, pagination --- images/noimage.png | Bin 0 -> 18632 bytes index.html | 31 ++++++++ src/index.js | 180 +++++++++++++++++++++++++++++++++++++++++++++ style.css | 3 + 4 files changed, 214 insertions(+) create mode 100644 images/noimage.png diff --git a/images/noimage.png b/images/noimage.png new file mode 100644 index 0000000000000000000000000000000000000000..73cc6df92e9720a1b229079f329a7f0eb8cc3ce4 GIT binary patch literal 18632 zcmV*GKxw~;P)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00002 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 + + + + + + + + Movie Quest + + +
+
+
+
+
+ + + +
+
+
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/index.js b/src/index.js index e69de29b..62b33ee3 100644 --- a/src/index.js +++ b/src/index.js @@ -0,0 +1,180 @@ +//e2c4cd31 API Key +const apiKey = "e2c4cd31"; + +//Global HTML references +const resultsContainer = document.querySelector(".results__container") +const searchForm = document.querySelector(".search__form"); +const searchBox = document.querySelector(".search__box"); +const pageButtonContainer = document.querySelector(".page__container"); +const pageButtons = document.querySelectorAll(".page__button"); + +//Global variables +let currentSearch = ""; + + + + + // INITIAL FETCH AND PAGINATION + + +//Fetch results function +function fetchResults(url) { + fetch(url) + .then(response => response.json()) + .then(function(body){ + resultTemplate(body.Search); + pagination(body, body.Search); + }) +}; + +//Automatically paginates per amount of returns +function pagination(totalReturn, returnArr){ + const pagesRequired = Math.ceil(totalReturn.totalResults / returnArr.length); + for (let i = 1; i <= pagesRequired; i++){ + const button = document.createElement("button"); + button.className = "page__button"; + button.textContent = i; + pageButtonContainer.appendChild(button); + } +}; + + + + + // PAGE POPULATION + + +//Creates result template +function resultTemplate(arr) { + let results = arr.map(function(film){ + let poster = (film.Poster === "N/A") ? "images/noimage.png" : film.Poster; + let movieItem = + `
+

${film.Title}

(${film.Year})

+ +
+ `; + return movieItem; + }) + populateResults(results); +}; + +//Populates results container +function populateResults(arr) { + resultsContainer.innerHTML = arr.join().replace(/,/g, " "); +}; + + + + + // SEARCH FUNCTION + + +//Event listener for search feature +searchForm.addEventListener("submit", function(event) { + event.preventDefault(); + currentSearch = searchBox.value; + updatePage(searchBox.value, 1); +}); + +//Formats search values for url +function formatSearchTerm(term) { + return term.split(" ").join("+"); +}; + + // CONTENT CLEARING FUNCTIONS + + + + +//Clears page of current results when updated +function clearResults() { + const previousItems = document.querySelectorAll(".search__result"); + previousItems.forEach(node => { + node.parentNode.removeChild(node); + }) +}; + +//Clears current page buttons when updated +function clearPages() { + const previousPages = document.querySelectorAll(".page__button"); + previousPages.forEach(node => { + node.parentNode.removeChild(node); + }) +} + + + + + + // GENERATING NEW URLS + + + +//Event listener for page numbers +pageButtonContainer.addEventListener("click", function(event){ + updatePage(null, event.target.textContent); +}); + + +//Accepts new search term and/or page number and submits new url to fetch function +function updatePage(term, page){ + clearPages(); + clearResults(); + const formattedTerm = (term === null) ? currentSearch : formatSearchTerm(term) + const searchUrl = `http://www.omdbapi.com/?s=${formattedTerm}&page=${page}&type=movie&apikey=${apiKey}`; + fetchResults(searchUrl); +}; + + + + // MOVIE INFO GENERATOR + +resultsContainer.addEventListener("click", function(event) { + if (event.target.closest(".search__result").classList.contains(".movie__info") === false) { + fetchMovieInfo(event.target.closest(".search__result").id); + } else if (event.target.closest(".search__result").classList.contains(".movie__info") === true){ + console.log("Hello") + } +}) + +function fetchMovieInfo(id) { + const movieUrl = `http://www.omdbapi.com/?i=${id}&apikey=${apiKey}`; + fetch(movieUrl) + .then(response => response.json()) + .then(body => movieInfoTempate(body)); +} + +function movieInfoTempate(movie) { + const ratings = movie.Ratings.map(rating => { + return `
  • ${rating.Source}: ${rating.Value}
  • ` + }) + const movieInfo = + ` +
    ${movie.Genre}

    +

    Director

    +

    ${movie.Director}

    +

    Written by

    +

    ${movie.Writer}

    +

    Cast

    +

    ${movie.Actors}

    +

    Synopsis

    +

    ${movie.Plot}

    +

    Accolades

    +

    ${movie.Awards}

    +

    Ratings

    +
      ${ratings.join().replace(/,/g, " ")}
    +

    Run Time

    +

    ${movie.Runtime}

    +
    + `; + appendMovieInfo(movieInfo, movie); +} + + +function appendMovieInfo(info, movie) { + const targetMovie = document.getElementById(movie.imdbID); + targetMovie.innerHTML = targetMovie.innerHTML + info; +} + diff --git a/style.css b/style.css index e69de29b..9e9b99d0 100644 --- a/style.css +++ b/style.css @@ -0,0 +1,3 @@ +body { + font-family: 'Poppins', sans-serif; +} \ No newline at end of file From ddd5d8a4dae86368265925cbfe754167caab50c5 Mon Sep 17 00:00:00 2001 From: David Gridley Date: Sun, 23 Sep 2018 17:49:32 +0100 Subject: [PATCH 3/6] updated css and functionality --- .DS_Store | Bin 0 -> 6148 bytes images/.DS_Store | Bin 0 -> 6148 bytes images/moviequestlogo.png | Bin 0 -> 22447 bytes index.html | 3 +- src/index.js | 26 ++++++++++---- style.css | 72 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 93 insertions(+), 8 deletions(-) create mode 100644 .DS_Store create mode 100644 images/.DS_Store create mode 100644 images/moviequestlogo.png diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..523b81ca3bd0dec203a5fb4ae7f513c62d4eed01 GIT binary patch literal 6148 zcmeHK!H&}~5FNK=*C|5ufV6we1&Kpdwc3hBLP()>4|_mD1i=B&ZqiiSNZDl7q?Dx; z<-$k6AMh!B0UyE#z#H4FniQ@GA&)eEp7D%hKfAR}L}Ijv21Feql2FEmgW@;B?W|kU zFrHnYP<>1(KTfhqm}KErv~~Q84Dj0RP)z3(&>2kQ>WMk7aXZF%YbD-|DAycdEJs>8L$jk25JoOb;pG=dIn34>|(!q0svcVv!Kp5 zAV$}qXRy?W7KqTPK%FYg6GP~9_+1m{87wvGbQ0$AAKTkmI2Gaf5m`kjs5WmQ!;1k*5vrCb)lzF7LF@5UZtR-j$*{} eQM?aT0>8@@pl7hu2oJeV8&}6Cyq8kXjfX# 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
    +
    -
    +
    diff --git a/src/index.js b/src/index.js index 62b33ee3..5b0ab28e 100644 --- a/src/index.js +++ b/src/index.js @@ -11,7 +11,9 @@ const pageButtons = document.querySelectorAll(".page__button"); //Global variables let currentSearch = ""; +const firstSearch = `http://www.omdbapi.com/?s=star+wars&y=2018&page=1&type=movie&apikey=${apiKey}` +fetchResults(firstSearch); // INITIAL FETCH AND PAGINATION @@ -52,6 +54,7 @@ function resultTemplate(arr) { `

    ${film.Title}

    (${film.Year})

    +

    More info...

    `; return movieItem; @@ -130,13 +133,20 @@ function updatePage(term, page){ // MOVIE INFO GENERATOR + resultsContainer.addEventListener("click", function(event) { - if (event.target.closest(".search__result").classList.contains(".movie__info") === false) { - fetchMovieInfo(event.target.closest(".search__result").id); - } else if (event.target.closest(".search__result").classList.contains(".movie__info") === true){ - console.log("Hello") - } -}) + if ((Array.from(event.target.closest(".search__result").childNodes).some(node => node.className === "movie__info") === true)) { + let infoToggle = document.getElementById(`info${event.target.closest(".search__result").id}`); + infoToggle.classList.toggle("movie__info--closed"); + } else if ((Array.from(event.target.closest(".search__result").childNodes).some(node => node.className === "movie__info--closed") === true)) { + let infoToggle = document.getElementById(`info${event.target.closest(".search__result").id}`); + infoToggle.classList.toggle("movie__info"); + } else if ((Array.from(event.target.closest(".search__result").childNodes).some(node => node.className === "movie__info" || node.className === "movie__info--closed") === false)) { + fetchMovieInfo(event.target.closest(".search__result").id); + } + +}) + function fetchMovieInfo(id) { const movieUrl = `http://www.omdbapi.com/?i=${id}&apikey=${apiKey}`; @@ -151,7 +161,7 @@ function movieInfoTempate(movie) { }) const movieInfo = ` -

    ${movie.Genre}

    Director

    ${movie.Director}

    @@ -167,9 +177,11 @@ function movieInfoTempate(movie) {
      ${ratings.join().replace(/,/g, " ")}

    Run Time

    ${movie.Runtime}

    +
    Less Info...
    `; appendMovieInfo(movieInfo, movie); + } diff --git a/style.css b/style.css index 9e9b99d0..7b2110ea 100644 --- a/style.css +++ b/style.css @@ -1,3 +1,75 @@ body { font-family: 'Poppins', sans-serif; +} + +main { + display: grid; + grid-template-columns: 100%; + + min-width: 100vw; + min-height: 100vh; +} + +header { + height: 300px; +} + +header img { + width: 100vw; + height: 100%; + +} + +.search__container{ + border: 3px solid #DAA520; + height: 36px; + position: static; +} + +form { + display: grid; + grid-template-columns: 4fr 1fr; +} + +form input { + height: 30px +} + +.results__container { + display: grid; + grid-template-columns: 1fr; + color: white; + margin-top: 10px; + grid-gap: 5px; +} + +.search__result { + width: 98vw; + justify-self: center; + justify-content: center; + border: 3px solid #DAA520; + padding-left: 5px; + padding-bottom: 5px; + background-color: #90DDF0; +} + +div img { + padding-left: 25vw; + justify-self: center; +} + +.movie__info { + padding: 0; +} + +.movie__info--closed { + display: none; +} + +@media (min-width: 768px) { + +} + +@media (min-width: 960px) { + } \ No newline at end of file From eecb89ba1036086af86b99732961a72c1ed81efb Mon Sep 17 00:00:00 2001 From: David Gridley Date: Mon, 24 Sep 2018 09:27:40 +0100 Subject: [PATCH 4/6] added favourite functionality, modified event listener for movie information --- README.md | 51 +++++-------------- index.html | 7 ++- src/brief.md | 54 ++++++++++++++++++++ src/index.js | 70 ++++++++++++++++++++------ style.css | 137 +++++++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 261 insertions(+), 58 deletions(-) create mode 100644 src/brief.md diff --git a/README.md b/README.md index c08139f4..6a71fe2d 100644 --- a/README.md +++ b/README.md @@ -1,54 +1,29 @@ --- path: "/project-cinema" -date: "2018-05-28" +date: "2018-09-24" title: "Project cinema" --- -# Project Cinema +# Movie Quest -We want to create a movie search engine. To power it we will use the [Open Movie Database](http://www.omdbapi.com) API. +The aim of this project, titled "Movie Quest", is to create a search application for users to be able to find films that they like or are interested in viewing, and to show them relevent information about said film. Movie Quest has been designed to fit the mobile phone screen primarily, but has also been designed to react responsively to the size of the user's device, making it also appropriate for tablet or desktop. -To start using the OMDB API you will first need to sign up with them to receive and API key. The key issued to you will allow you 1000 requests per day and you will need to include this key as part of every request. +The project utilizes the [Open Movie Database](http://www.omdbapi.com) to fetch relvent data on a search term that the user inputs into the search function. On page load, the application retrieves information about films from the Star Wars franchise that were released in 2018. From there, the user can use the search feature to look for films. -To get started, fork and clone this repo. Please submit a pull request after your first commit and push commits regularly. +If the user wants to find out more information about a film they see, they can click on the "More info" button. This button makes a seperate call to the API to retrieve more detailed information about each film, using the film's IMDB id that is displayed in the ID attribute of each search result. If the API recieves a fetch request that specifies a film by ID, it returns specific information about that film only. -You should complete as many of the following tasks as you can. +Once the user searches for a film, the application will display page numbers at the bottom so that the user can look through multiple pages of enteries. The function that creates these pages will look at how many results have been returned by the API, divide that number by how many entries there are by page, and dynamically generate page buttons accordingly. -- [ ] Work using mobile first, that is create the mobile version first and add tablet and desktop versions after. -- [ ] Create an HTML page which should have a `form` at the top which contains a text input and a submit button. Below it should have a placeholder element for the returned results. -- [ ] Use JavaScript to capture the `submit` event in your search form, extract the query string from the text input and use that to make an API call to the Open Movie Database API to search for films which match the query string using `fetch`. `console.log` the results -- [ ] Display the data returned by the API including title, year and poster picture +If a user finds a film that they like or would want to see, they can then add that film to their favourites list. The application adds a button to each search result which, when clicked, will take the name of the film that the button belongs to and store it in a seperate area on the page. -**Movie details** +In order to make continual improvements to Movie Quest, I would like to impliment these changes in the future: -- [ ] Adjust your layout to create room for a detailed view of movie information -- [ ] Capture clicks on your movie results items and use that information to make another request to the API for detailed movie information. Using event delegation will help you here. `console.log` the returned result -- [ ] Display the detailed movie result in the in the details view you created earlier -- [ ] Make your design responsive and ensure it looks great at different screen widths +- Limit the viewable amount of page buttons for each search in order to clean up the bottom of the application. -**Your own feature** +- Have favourite be savable so that they remain after a page refresh. -- [ ] Implement any feature you would find useful or interesting +- Have favourites be rankable so that the user can be placed in preference order. -**Stretch goals** +- Impliment functionality so that movie information can be displayed or hidden at the user's request, without having to make seperate API calls for each entry. -- [ ] Implement pagination so that users can navigate between all movies in search results rather than just the first ten -- [ ] Create a favourites list. It's up to you how you would add items to favourites. You could add a button or otherwise. Display a list of favourites somewhere on your page. -- [ ] Make the favourites list sortable. Add `up` and `down` buttons to your favourites which on click will move the result in relevant direction -- [ ] Save favourites locally using `localStorage` so that favourites persist in browser after refresh -- [ ] Let's create a search preview. It should listen for change events on input events and submit a search request with current query string. Display the search preview results in an absolute positioned container just below the search box. -Hint: You may want to kick of the searching after at least 3 characters have been typed. - -## Objectives - -* We want to see great looking webpages that work well at all screen widths -* Your code should have consistent indentation and sensible naming -* Use lots of concise, reusable functions with a clear purpose -* Add code comments where it is not immediately obvious what your code does -* Your code should not throw errors and handle edge cases gracefully. For example not break if server fails to return expected results -* Use BEM methodology to style your page -* Try to use pure functions as much as possible, but keep in mind it will not be possible to make all functions pure. - -## README.md - -When finished, include a README.md in your repo. Someone who is not familiar with the project should be able to look at it and understand what it is and what to do with it. Explain functionality created, mention any outstanding issues and possible features you would include if you had more time. List technologies used to create the app. Include a screenshot of your app in the README. +- Add a "Popular Films" feature that will provide search results for predetermened search terms based on popular films or film series. \ No newline at end of file diff --git a/index.html b/index.html index fc40e72b..b5ea8ab3 100644 --- a/index.html +++ b/index.html @@ -20,7 +20,12 @@
    -
    +
    +
    +
      Favourites:
    +
    +
    +
    diff --git a/src/brief.md b/src/brief.md new file mode 100644 index 00000000..e51906ff --- /dev/null +++ b/src/brief.md @@ -0,0 +1,54 @@ +--- +path: "/project-cinema" +date: "2018-05-28" +title: "Project cinema" +--- + +# Project Cinema + +We want to create a movie search engine. To power it we will use the [Open Movie Database](http://www.omdbapi.com) API. + +To start using the OMDB API you will first need to sign up with them to receive and API key. The key issued to you will allow you 1000 requests per day and you will need to include this key as part of every request. + +To get started, fork and clone this repo. Please submit a pull request after your first commit and push commits regularly. + +You should complete as many of the following tasks as you can. + +- [x] Work using mobile first, that is create the mobile version first and add tablet and desktop versions after. +- [x] Create an HTML page which should have a `form` at the top which contains a text input and a submit button. Below it should have a placeholder element for the returned results. +- [x] Use JavaScript to capture the `submit` event in your search form, extract the query string from the text input and use that to make an API call to the Open Movie Database API to search for films which match the query string using `fetch`. `console.log` the results +- [x] Display the data returned by the API including title, year and poster picture + +**Movie details** + +- [x] Adjust your layout to create room for a detailed view of movie information +- [x] Capture clicks on your movie results items and use that information to make another request to the API for detailed movie information. Using event delegation will help you here. `console.log` the returned result +- [x] Display the detailed movie result in the in the details view you created earlier +- [x] Make your design responsive and ensure it looks great at different screen widths + +**Your own feature** + +- [ ] Implement any feature you would find useful or interesting + +**Stretch goals** + +- [x] Implement pagination so that users can navigate between all movies in search results rather than just the first ten +- [x] Create a favourites list. It's up to you how you would add items to favourites. You could add a button or otherwise. Display a list of favourites somewhere on your page. +- [ ] Make the favourites list sortable. Add `up` and `down` buttons to your favourites which on click will move the result in relevant direction +- [ ] Save favourites locally using `localStorage` so that favourites persist in browser after refresh +- [ ] Let's create a search preview. It should listen for change events on input events and submit a search request with current query string. Display the search preview results in an absolute positioned container just below the search box. +Hint: You may want to kick of the searching after at least 3 characters have been typed. + +## Objectives + +* We want to see great looking webpages that work well at all screen widths +* Your code should have consistent indentation and sensible naming +* Use lots of concise, reusable functions with a clear purpose +* Add code comments where it is not immediately obvious what your code does +* Your code should not throw errors and handle edge cases gracefully. For example not break if server fails to return expected results +* Use BEM methodology to style your page +* Try to use pure functions as much as possible, but keep in mind it will not be possible to make all functions pure. + +## README.md + +When finished, include a README.md in your repo. Someone who is not familiar with the project should be able to look at it and understand what it is and what to do with it. Explain functionality created, mention any outstanding issues and possible features you would include if you had more time. List technologies used to create the app. Include a screenshot of your app in the README. diff --git a/src/index.js b/src/index.js index 5b0ab28e..eb7858f1 100644 --- a/src/index.js +++ b/src/index.js @@ -52,9 +52,11 @@ function resultTemplate(arr) { let poster = (film.Poster === "N/A") ? "images/noimage.png" : film.Poster; let movieItem = `
    -

    ${film.Title}

    (${film.Year})

    +

    ${film.Title}

    + +

    (${film.Year})

    -

    More info...

    +
    `; return movieItem; @@ -65,6 +67,8 @@ function resultTemplate(arr) { //Populates results container function populateResults(arr) { resultsContainer.innerHTML = arr.join().replace(/,/g, " "); + addFavouriteListener(); + addInfoListener(); }; @@ -134,20 +138,28 @@ function updatePage(term, page){ // MOVIE INFO GENERATOR -resultsContainer.addEventListener("click", function(event) { - if ((Array.from(event.target.closest(".search__result").childNodes).some(node => node.className === "movie__info") === true)) { - let infoToggle = document.getElementById(`info${event.target.closest(".search__result").id}`); - infoToggle.classList.toggle("movie__info--closed"); - } else if ((Array.from(event.target.closest(".search__result").childNodes).some(node => node.className === "movie__info--closed") === true)) { - let infoToggle = document.getElementById(`info${event.target.closest(".search__result").id}`); - infoToggle.classList.toggle("movie__info"); - } else if ((Array.from(event.target.closest(".search__result").childNodes).some(node => node.className === "movie__info" || node.className === "movie__info--closed") === false)) { - fetchMovieInfo(event.target.closest(".search__result").id); - } - -}) +//Listener for clicks on movie coontainers to either fetch information or trigger class toggles to hide previously displayed information from view (Only working in part, works the first time and then generates another lot of information, before then triggering toggle again) +function addInfoListener() { + const moreInfo = document.querySelectorAll(".more__info__button"); + moreInfo.forEach(button => { + button.addEventListener("click", function(event) { + if ((Array.from(event.target.parentNode.childNodes).some(node => node.className === "movie__info--closed") === false)) { + fetchMovieInfo(event.target.parentNode.id); + } else if ((Array.from(event.target.parentNode.childNodes).some(node => node.className === "movie__info") === false)) { + fetchMovieInfo(event.target.parentNode.id); + } else if ((Array.from(event.target.parentNode.childNodes).some(node => node.className === "movie__info--closed") === true)) { + let infoToggle = document.getElementById(`info${event.target.parentNode.id}`); + infoToggle.classList.toggle("movie__info"); + } else if ((Array.from(event.target.parentNode.childNodes).some(node => node.className === "movie__info--closed") === true)) { + let infoToggle = document.getElementById(`info${event.target.parentNode.id}`); + infoToggle.classList.toggle("movie__info"); + } + }) + }) +} +//Fetches movie information when even is triggered function fetchMovieInfo(id) { const movieUrl = `http://www.omdbapi.com/?i=${id}&apikey=${apiKey}`; fetch(movieUrl) @@ -155,6 +167,7 @@ function fetchMovieInfo(id) { .then(body => movieInfoTempate(body)); } +//Creates template for additional infomormation function movieInfoTempate(movie) { const ratings = movie.Ratings.map(rating => { return `
  • ${rating.Source}: ${rating.Value}
  • ` @@ -177,16 +190,41 @@ function movieInfoTempate(movie) {
      ${ratings.join().replace(/,/g, " ")}

    Run Time

    ${movie.Runtime}

    -
    Less Info...
    `; appendMovieInfo(movieInfo, movie); } - +//Adds movie information to html of target movie's container function appendMovieInfo(info, movie) { const targetMovie = document.getElementById(movie.imdbID); targetMovie.innerHTML = targetMovie.innerHTML + info; } + + + + // FAVOURITE FEATURE + + + +//Event listener for favourite buttons +function addFavouriteListener() { + const favButton = document.querySelectorAll(".fav__button"); + favButton.forEach(button => { + button.addEventListener("click", function(event) { + const favourite = document.createElement("li"); + favourite.className = "favourite__item" + favourite.textContent = Array.from(event.target.parentNode.childNodes)[1].textContent; + appendFavouriteItem(favourite); + }) + }) +} + + +//Add's favourite item to list +function appendFavouriteItem(item) { + const favouriteContainer = document.querySelector(".favourites__list"); + favouriteContainer.appendChild(item); +} \ No newline at end of file diff --git a/style.css b/style.css index 7b2110ea..bfc0ab34 100644 --- a/style.css +++ b/style.css @@ -20,6 +20,10 @@ header img { } +p { + display: grid; +} + .search__container{ border: 3px solid #DAA520; height: 36px; @@ -35,6 +39,23 @@ form input { height: 30px } +.favourites { + display: grid; + border: 5px solid #DAA520; + margin-top: 10px; + background-color: #90DDF0; + color: white; +} + +ul { + padding-left: 20px; +} + +.favourites--on { + display: grid; +} + + .results__container { display: grid; grid-template-columns: 1fr; @@ -44,21 +65,74 @@ form input { } .search__result { + display: grid; + grid-template-columns: 9fr 1fr; + align-items: center; width: 98vw; - justify-self: center; - justify-content: center; border: 3px solid #DAA520; padding-left: 5px; padding-bottom: 5px; background-color: #90DDF0; } +div h2{ + display: grid; + justify-self: center; + font-size: 2em; + margin-bottom: 3px; + border-bottom: 3px solid #DAA520; +} + +.fav__button { + height: 40px; + width: 40px; + border-radius: 4px; + font-size: 1.5em; + background-color: #DAA520; + color: white; + display: grid; + justify-self: center; +} + +.movie_date { + grid-column-start: 1; + grid-column-end: 3; + display: grid; + justify-self: center; + margin-top: 3px; + border-bottom: 3px solid #DAA520; +} + div img { - padding-left: 25vw; justify-self: center; + padding-top: 10px; + padding-bottom: 10px; + width: 60%; + grid-column-start: 1; + grid-column-end: 3; +} + +div h4 { + justify-self: center; + margin: 5px; + padding:3px; + border: 2px solid white; +} + +.more__info__button { + display: grid; + justify-self: center; + width: 200px; + height: 30px; + background-color: #DAA520; + color: white; + font-weight: 800; + font-size: 1.1em } .movie__info { + grid-column-start: 1; + grid-column-end: 3; padding: 0; } @@ -66,8 +140,65 @@ div img { display: none; } +.favourites__list { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-template-rows: auto; + justify-self: center; + +} + +.favourite__item { + display: grid; + justify-self: center; + list-style: none; + padding-left: 2px; + border: 1px solid #DAA520; + background-color: #DAA520; + border-radius: 5px; + margin: 4px; + font-size: 0.8em; +} + @media (min-width: 768px) { + .content { + display: grid; + grid-template-columns: 1fr 4fr; + grid-gap: 4px; + width: 100vw; + } + + .search__result { + width: 79vw + } + + .favourites { + display: grid; + justify-self: start; + width: 18vw; + min-height: 400px; + height: 10%; + } + .favourites__list { + display: grid; + grid-template-columns: 1fr; + grid-template-rows: repeat(10, 70px); + justify-self: start; + + } + .favourite__item { + display: grid; + justify-self: center; + list-style: none; + padding-left: 2px; + border: 1px solid #DAA520; + background-color: #DAA520; + border-radius: 5px; + margin: 4px; + font-size: 0.8em; + height: 60% + } } @media (min-width: 960px) { From 3666a71a7f52e5624b747904f4d089df1d8cc549 Mon Sep 17 00:00:00 2001 From: David Gridley Date: Mon, 24 Sep 2018 09:43:59 +0100 Subject: [PATCH 5/6] updated README --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index 6a71fe2d..2ab5bacd 100644 --- a/README.md +++ b/README.md @@ -8,14 +8,31 @@ title: "Project cinema" The aim of this project, titled "Movie Quest", is to create a search application for users to be able to find films that they like or are interested in viewing, and to show them relevent information about said film. Movie Quest has been designed to fit the mobile phone screen primarily, but has also been designed to react responsively to the size of the user's device, making it also appropriate for tablet or desktop. +**Design Objectives** + +With this project I endevoured to keep all JavaScript to be function-oriented, using many short, concise functions to carry out specific processes, which are then used as callback functions within other functions. I also tried to make sure that each function involved as little mutation as possible in order prevent problems with source information. + +In terms of UI design, this was the first project in which I tried to use CSS Grid to form page layout. While I did find this easier to impliment, I feel my inexperience with Grid lead to a slightly boxy and less sleek layout, although the page is still fully responseive. + +**API** + The project utilizes the [Open Movie Database](http://www.omdbapi.com) to fetch relvent data on a search term that the user inputs into the search function. On page load, the application retrieves information about films from the Star Wars franchise that were released in 2018. From there, the user can use the search feature to look for films. +**Film Description** + If the user wants to find out more information about a film they see, they can click on the "More info" button. This button makes a seperate call to the API to retrieve more detailed information about each film, using the film's IMDB id that is displayed in the ID attribute of each search result. If the API recieves a fetch request that specifies a film by ID, it returns specific information about that film only. +**Pagination** + Once the user searches for a film, the application will display page numbers at the bottom so that the user can look through multiple pages of enteries. The function that creates these pages will look at how many results have been returned by the API, divide that number by how many entries there are by page, and dynamically generate page buttons accordingly. +**Favourites Feature** + If a user finds a film that they like or would want to see, they can then add that film to their favourites list. The application adds a button to each search result which, when clicked, will take the name of the film that the button belongs to and store it in a seperate area on the page. + +**Future Goals And Ideas To Be Implimented** + In order to make continual improvements to Movie Quest, I would like to impliment these changes in the future: - Limit the viewable amount of page buttons for each search in order to clean up the bottom of the application. From 4399c234b82995bcd6355df2445bb1dae083005e Mon Sep 17 00:00:00 2001 From: David Gridley Date: Mon, 24 Sep 2018 11:30:59 +0100 Subject: [PATCH 6/6] final changes to css --- style.css | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/style.css b/style.css index bfc0ab34..3908e067 100644 --- a/style.css +++ b/style.css @@ -140,17 +140,22 @@ div h4 { display: none; } +.favourites { + display: grid; + justify-self: start; +} + .favourites__list { display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; grid-template-rows: auto; - justify-self: center; + justify-self: start; } .favourite__item { display: grid; - justify-self: center; + justify-self: start; list-style: none; padding-left: 2px; border: 1px solid #DAA520;