First commit
This commit is contained in:
188
Lab 8/funs.js
Executable file
188
Lab 8/funs.js
Executable file
@@ -0,0 +1,188 @@
|
||||
/* STEP 1: Given a movie object, copy its title into a new field called
|
||||
* textContent and return the movie.
|
||||
*
|
||||
* @param {object} movie A movie object from the JSON data set
|
||||
*/
|
||||
function setTitleContent(movie) {
|
||||
movie.textContent = movie.title;
|
||||
return movie;
|
||||
}
|
||||
|
||||
/* STEP 2: Given a movie object, append the remaining fields into the
|
||||
* textContent field. Each function should append only the relevant field.
|
||||
* Chaining them together would create a textContent string such as the
|
||||
* following:
|
||||
* Mad Max: Fury Road (2015) - 120 minutes [8.1]
|
||||
* Make sure to include the correct spacing and punctuation marks.
|
||||
*
|
||||
* @param {object} movie A movie object from the JSON data set with the
|
||||
* title already copied into the movie.textContent field.
|
||||
*/
|
||||
function appendYear(movie) {
|
||||
movie.textContent = movie.textContent.concat(` (${movie.year})`);
|
||||
return movie;
|
||||
}
|
||||
|
||||
function appendRuntime(movie) {
|
||||
movie.textContent = movie.textContent.concat(` - ${movie.runtime} minutes`);
|
||||
return movie;
|
||||
}
|
||||
|
||||
function appendRating(movie) {
|
||||
movie.textContent = movie.textContent.concat(` [${movie.rating}]`);
|
||||
return movie;
|
||||
}
|
||||
|
||||
/* STEP 3: Return a closure (arrow function) that takes a movie argument
|
||||
* and compares its .rating field with this function's rating argument.
|
||||
* Return true if the movie's rating satisfies this minimum criterion.
|
||||
* Note that you need to call parseFloat on the movie.rating field because
|
||||
* JSON data defaults to a string type.
|
||||
*
|
||||
* @param {number} rating The minimum movie rating that will cause the
|
||||
* closure to return true for a movie.
|
||||
*/
|
||||
function setMinRating(rating) {
|
||||
// If the minimum rating value passed in the query string is NaN,
|
||||
// the closure should always evaluate to false.
|
||||
// Whether or not this is desireable is up to the designer
|
||||
|
||||
const minRating = Number.parseFloat(rating);
|
||||
return (movie) => Number.parseFloat(movie.rating) >= minRating;
|
||||
}
|
||||
|
||||
/* STEP 3: Complete the following functions just as you did setMinRating.
|
||||
* You'll need to use parseInt instead of parseFloat, because these are
|
||||
* all integer values.
|
||||
*/
|
||||
function setMinYear(year) {
|
||||
const minYear = Number.parseFloat(year);
|
||||
return (movie) => Number.parseFloat(movie.year) >= minYear;
|
||||
}
|
||||
|
||||
function setMaxYear(year) {
|
||||
const maxYear = Number.parseFloat(year);
|
||||
return (movie) => Number.parseFloat(movie.year) <= maxYear;
|
||||
}
|
||||
|
||||
function setMinTime(mins) {
|
||||
const minMins = Number.parseFloat(mins);
|
||||
return (movie) => Number.parseFloat(movie.runtime) >= minMins;
|
||||
}
|
||||
|
||||
function setMaxTime(mins) {
|
||||
const maxMins = Number.parseFloat(mins);
|
||||
return (movie) => Number.parseFloat(movie.runtime) <= maxMins;
|
||||
}
|
||||
|
||||
/* buildItem - Helper function that creates a DOM <li> element, adds the
|
||||
* list-group-item class, and inserts the movie's text content. Do not
|
||||
* modify.
|
||||
*
|
||||
* @param {object} movie The movie object to create as a list item
|
||||
* @param {object} list The <ul> to add the item to
|
||||
*/
|
||||
function buildItem(movie, list) {
|
||||
let item = document.createElement("li");
|
||||
item.classList.add("list-group-item");
|
||||
item.textContent = movie.textContent;
|
||||
list.append(item);
|
||||
}
|
||||
|
||||
(async function () {
|
||||
// STEP 1: Start your anonymous initialization function here. Be sure to
|
||||
// end the file with the needed syntax to call the function.
|
||||
|
||||
// FIRST CODE IN THE INITIALIZATION FUNCTION
|
||||
|
||||
// Get the <ul> object from the HTML (do not modify)
|
||||
let ul = document.querySelector("#target");
|
||||
|
||||
// Set default values (do not modify)
|
||||
let minYear = 0;
|
||||
let maxYear = 3000;
|
||||
let minTime = 0;
|
||||
let maxTime = 500;
|
||||
let minRating = 0.0;
|
||||
|
||||
// Get the query string and split it into an array of distinct queries.
|
||||
// (do not modify)
|
||||
// For example, given index.html?minyear=1990&minrating=9.0, the query
|
||||
// variable is the array [ 'minyear=1990', 'minrating=9.0' ]
|
||||
let query = window.location.search.substring(1); //.split('&');
|
||||
if (query !== "") {
|
||||
query = query.split("&");
|
||||
} else {
|
||||
query = undefined;
|
||||
}
|
||||
|
||||
// KEEP THIS HARD-CODED TO AVOID CORS ISSUES
|
||||
const hostname = "https://w3.cs.jmu.edu/kirkpams/343/labs/lab8";
|
||||
const url = `${hostname}/data.json`;
|
||||
|
||||
// STEP 1: Fetch the JSON data from the URL. If the query string is empty
|
||||
// (i.e., query is undefined), grab just the first 10 data entries. Given
|
||||
// this array, use .map to call setTitleContent on each entry and .forEach
|
||||
// to call buildItem for each. You may NOT use a traditional loop (e.g.,
|
||||
// for-of, while, etc.) for this lab.
|
||||
//
|
||||
// STEP 2: Extend the movie's textContent by using .map with the additional
|
||||
// functions to append the year, runtime, and rating values.
|
||||
//
|
||||
// STEP 3: If the query variable is defined, then the URL contains a query
|
||||
// string of criteria. Use the criteria specified in the query string to
|
||||
// filter the data. Each criterion would be of the form minyear=2000, with
|
||||
// the criteria being minyear, maxyear, mintime, maxtime, or minrating. Use
|
||||
// the values here to change the default minYear, etc., listed above. Note
|
||||
// that you will need to use parseInt or parseFloat to convert the query
|
||||
// string value into a number.
|
||||
//
|
||||
// Once you've processed all of the filter criteria, run the full JSON data
|
||||
// set through these using .filter, then use .map and .forEach as before to
|
||||
// generate the data.
|
||||
|
||||
// END OF THE INITIALIZATION FUNCTION
|
||||
|
||||
// ! Important caveat of this implementation, there is no specification for
|
||||
// ! how to handle situations where the same query param is passed multiple
|
||||
// ! times, or when query params contradict each other.
|
||||
// ! This implementation sequentially applies filters for every query param
|
||||
// ! regardless of the other conditions in list of query params.
|
||||
|
||||
let movieData = await fetch(url)
|
||||
.then((response) => response.json())
|
||||
.catch(() => null);
|
||||
if (!movieData) return;
|
||||
|
||||
// In order to constrain all current and potential future filter functions
|
||||
// to a singular interface all filter functions will accept a single string
|
||||
// parameter (the query value).
|
||||
// Any parsing of this string will be handled by the individual filter functions.
|
||||
|
||||
const filterMap = {
|
||||
minyear: setMinYear,
|
||||
maxyear: setMaxYear,
|
||||
mintime: setMinTime,
|
||||
maxtime: setMaxTime,
|
||||
minrating: setMinRating,
|
||||
};
|
||||
|
||||
query?.forEach((queryString) => {
|
||||
const [name, value] = queryString.split("=");
|
||||
|
||||
if (name in filterMap) {
|
||||
movieData = movieData.filter(filterMap[name](value));
|
||||
}
|
||||
});
|
||||
|
||||
if (!query) {
|
||||
movieData = movieData.slice(0, 10);
|
||||
}
|
||||
|
||||
movieData
|
||||
.map(setTitleContent)
|
||||
.map(appendYear)
|
||||
.map(appendRuntime)
|
||||
.map(appendRating)
|
||||
.forEach((movie) => buildItem(movie, ul));
|
||||
})();
|
||||
Reference in New Issue
Block a user