Skip to content

Instantly share code, notes, and snippets.

@marsicdev
Created October 31, 2017 21:30
Show Gist options
  • Save marsicdev/8eaf48c987f13b7e9a0efc2984413ea6 to your computer and use it in GitHub Desktop.
Save marsicdev/8eaf48c987f13b7e9a0efc2984413ea6 to your computer and use it in GitHub Desktop.
Movie list full application with modules example
var dataController = (function () {
var data = {
movies: [],
totalMoviesLength: 0
};
// Movie constructor
function Movie(title, length, genre) {
this.title = title;
this.length = length;
this.genre = genre;
}
Movie.prototype.getInfo = function () {
return this.title + ", duration: " + this.length + "min, genre: " + getGenreAbbreviation(this.genre);
}
// Private functions used within this module
// Not exposed to the public
function getGenreAbbreviation(genreStr) {
var firstIndex = 0;
var lastIndex = genreStr.length - 1
var output = genreStr.charAt(firstIndex) + genreStr.charAt(lastIndex);
return output.toUpperCase();
}
function calculateTotalLength() {
var total = 0;
// Iterate trough movies and calculate length
data.movies.forEach(function (currentMovie) {
total += currentMovie.length;
});
// Set our new total to our data object
data.totalMoviesLength = total;
}
// Functions to be exported to public
function addMovie(title, length, genre) {
var movie = new Movie(title, parseFloat(length), genre);
data.movies.push(movie);
return movie;
}
function getTotalLength() {
// calculate total data before returning
calculateTotalLength();
return data.totalMoviesLength;
}
// This is only for TEST
function logData() {
console.log(data);
}
return {
addMovie: addMovie,
getTotalLength: getTotalLength,
// ONLY FOR TEST
log: logData
};
})();
var UIController = (function () {
var DOMStrings = {
inputTitle: '.movie-title',
inputLength: '.movie-length',
selectGenre: '.genre-select',
containerMovieList: '.movie-list ul',
containerError: '.movie-error',
buttonAddMovie: '.create-movie',
formElement: 'form',
containerTotalLength: '.total-length span'
}
function collectInput() {
var titleElement = document.querySelector(DOMStrings.inputTitle);
var lengthElement = document.querySelector(DOMStrings.inputLength);
var genreSelectElement = document.querySelector(DOMStrings.selectGenre);
var genreOptionElement = genreSelectElement.options[genreSelectElement.selectedIndex];
var result = {
title: titleElement.value,
length: lengthElement.value,
genre: genreOptionElement.value
}
return result;
}
function displayListItem(movie) {
var listEl = document.querySelector(DOMStrings.containerMovieList);
var htmlItem = "<li>" + movie.getInfo(); + "</li>"
listEl.insertAdjacentHTML('beforeend', htmlItem);
}
function clearFormInputs() {
// Reset forma data
document.querySelector(DOMStrings.formElement).reset();
// Reset error if any
document.querySelector(DOMStrings.containerError).textContent = "";
// Set focus to title input
document.querySelector(DOMStrings.inputTitle).focus();
}
function showError(input) {
var errorMsg = 'Unknown error!';
if (!input.title) {
errorMsg = "Enter title!"
} else if (!input.length) {
errorMsg = "Enter length!"
} else if (!input.genre) {
errorMsg = "Select genre!"
}
document.querySelector(DOMStrings.containerError).textContent = errorMsg;
}
function displayTotalLength(tLength) {
// If length is not passed set default value
tLength = tLength || '-';
document.querySelector(DOMStrings.containerTotalLength).textContent = String(tLength);
}
function getDOMStrings() {
return DOMStrings;
}
return {
getInput: collectInput,
displayListItem: displayListItem,
displayTotalLength: displayTotalLength,
getDOMStrings: getDOMStrings,
clearInputs: clearFormInputs,
displayError: showError
};
})();
var mainController = (function (dataCtrl, UICtrl) {
function setupEventListeners() {
var DOM = UICtrl.getDOMStrings();
document.querySelector(DOM.buttonAddMovie).addEventListener('click', function () {
ctrlAddMovieItem();
});
document.addEventListener('keydown', function (event) {
if (event.keyCode === 13) {
ctrlAddMovieItem();
}
});
}
function ctrlUpdateTotalLength() {
// 1. Get calculated length
var totalLength = dataCtrl.getTotalLength();
// 2. Update the UI with new total length
UICtrl.displayTotalLength(totalLength);
}
function ctrlAddMovieItem() {
// 1. get form data (UI)
var input = UICtrl.getInput();
// console.log(input);
// 1.1 Validate data validity
if (!input.title || !input.length || !input.genre) {
// throw new Error('Something bad happened');
// alert("Error!")
UICtrl.displayError(input);
return;
}
// 2. Add movie to list
var movie = dataCtrl.addMovie(input.title, input.length, input.genre);
// console.log(movie);
// 3. Clear form inputs
UICtrl.clearInputs();
// 4. show list on UI
UICtrl.displayListItem(movie);
// 5. Update total length UI
ctrlUpdateTotalLength();
}
return {
init: function () {
console.log("App has started");
setupEventListeners();
}
}
})(dataController, UIController);
mainController.init();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Movie list</title>
<link rel="stylesheet" href="./main.css">
</head>
<body>
<br>
<h1>Movie list</h1>
<br>
<form>
<fieldset name="movie">
<p>Movie</p>
<fieldset>
<!-- Title input -->
<label>Title</label>
<input type="text" name="movie-title" class="movie-title" placeholder="Title" required>
<!-- Movie length input -->
<label>Length (min)</label>
<input type="number" name="movie-length" class="movie-length" placeholder="Length in min" required>
<!-- Genre select dropdown -->
<select name="genre-select" class="genre-select">
<option value="">-</option>
<option value="drama">Drama</option>
<option value="action">Action</option>
<option value="horror">Horror</option>
<option value="commedy">Commedy</option>
<option value="advanture">Advanture</option>
</select>
<!-- Error message initialy empty -->
<div class="movie-error error"></div>
<!-- Create movie button -->
<input type="button" class="create-movie" value="ADD MOVIE">
<!-- Movie list placeholder -->
<div class="movie-list">
<ul>
<!-- here items -->
</ul>
</div>
</fieldset>
<div class="total-length">All movies lenght:
<span>-</span>
</div>
</form>
<!-- Include out JS file -->
<script src="./app.js"></script>
</body>
</html>
form {
margin: auto;
width: 70%;
}
h1 {
margin: auto;
text-align: center;
}
input[type=button], input[type=submit], input[type=reset] {
background-color: #4CAF50;
border: none;
color: white;
padding: 16px 32px;
text-decoration: none;
margin: 4px 2px;
cursor: pointer;
font-size: 12pt;
width: 100%;
}
input[type=text], input[type=number], input[type=date] {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
font-size: 12pt;
box-sizing: border-box;
}
select, option {
width: 100%;
height: 40px;
font-size: 12pt;
padding: 16px 20px;
border: none;
margin: 10px 0;
padding: 5px;
border-radius: 0px;
box-sizing: border-box;
}
.error {
color: tomato;
padding: 5px;
height: 15px;
}
.total-length {
padding: 10px;
float: right;
font-size: larger;
}
.total-length span {
font-weight: bold;
color: blue;
}
ul {
background-color: #eeeeed;
}
ul li {
padding: 10px 15px;
margin-left: -40px;
list-style: none;
}
ul li:first-child {
/* border-top: 1px solid #4CAF50; */
}
ul li:nth-child(even) {
background-color: #ffffff;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment