Created
October 31, 2017 21:30
-
-
Save marsicdev/8eaf48c987f13b7e9a0efc2984413ea6 to your computer and use it in GitHub Desktop.
Movie list full application with modules example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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