todoapp-mvc
mvc pattern is used.
by shahryar saljoughi
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link href="styles.css" type="text/css" rel="stylesheet">
<link rel="stylesheet" href="js/myIconFramework/styles.css">
<title>Document</title>
</head>
<body>
<p class="title">Todo App</p>
<div class="container">
<div id="rightPanel" >
</div>
<div id="leftPanel">
<input type="text" class="stack-item" id="descriptionInput">
<button class="stack-item button createButton" onclick="addTodo()">New todo</button>
<hr />
<button class="stack-item button yellowButton" onclick="makeVisibleElementsWithClass() & hideElementsWithClass('not-completed')">Completed</button>
<button class="stack-item button yellowButton" onclick="makeVisibleElementsWithClass() & hideElementsWithClass('completed')">Active</button>
<button class="stack-item button yellowButton" onclick="makeVisibleElementsWithClass()">All</button>
</div>
</div>
<!-- order of loading scripts matter!-->
<script src="js/myIconFramework/scripts.js"></script>
<script src="js/model.js"></script>
<script src="js/view.js"></script>
<script src="js/controller.js"></script>
</body>
</html>
CSS
* {
box-sizing: border-box;
font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
}
body {
padding: 10%;
}
.container {
display: flex;
margin: auto;
width: 80%;
flex-direction: row;
}
div#leftPanel {
flex: 1;
display: flex;
flex-direction: column;
flex-shrink: 1;
}
div#rightPanel {
flex: 3;
flex-shrink: 1;
}
input {
padding: 5px;
}
.stack-item {
margin: 7px 0px 7px 0px;
display: block;
}
.createButton {
background-color: rgba(42, 129, 89, 0.486);
color: white;
}
.button {
padding: 10px;
font-weight: bold;
border-radius: 10px;
cursor: pointer;
}
.yellowButton {
background-color: rgba(160, 160, 52, 0.507);
color: white;
}
.yellowButton:hover {
background-color: rgb(104, 104, 7);
}
.createButton:hover {
background-color: rgb(74, 119, 7);
}
.todo {
padding: 10px;
width: 80%;
position: relative; /*this is because it has a child who wants to be absolutely positioned!. */
margin: 10px auto 10px auto;
}
.todo:first-child {
margin: auto;
}
.completed {
border: rgb(4, 129, 71) solid;
border-radius: 10px;
background-color: rgba(4, 129, 71, 0.43);
}
.not-completed {
border: #0000ff6b solid;
border-radius: 10px;
background-color: rgba(6, 110, 230, 0.47);
}
.close {
color: red;
font-weight: bold;
position: absolute;
top: 0px;
right: 0px;
cursor: pointer;
}
.title {
text-align: center;
display: block;
font-size: 50px;
}
.actionsButtonContainer {
width: 30px;
height: 30px;
position: absolute;
right: 5px;
margin: auto;
top: 0px;
z-index: 1;
}
.svg {
width: 100%;
height: 100%;
padding: 0;
}
span[class*="icon"] {
cursor: pointer;
}
.edit-icon {
float: right;
}
.todo-edit-mode {
background-color: rgba(209, 218, 221, 0.329);
border: solid blue 1px;
}
.position-right {
float: right;
}
.hidden {
display: none;
}
@media screen and (max-width: 992px) {
.container {
flex-direction: column;
...
JavaScript
/* models.js */
function createModelsModule() {
let items = [];
/**
* @param {string} todoDescription
*/
function addItem(todoDescription) {
if (!todoDescription) {
return;
}
items.push([description, items.length]);
return items.length -1 ;
}
function removeItem(todoIndex) {
items.splice(todoIndex, todoIndex) ;
}
function getLastItem() {
return items[items.length - 1];
}
return {
removeItem: removeItem,
addItem: addItem,
getLastItem: getLastItem,
getAll: () => items,
}
}
/* views.js */
function createViewsModule() {
var iconsModule = createIconModule();
let panel = document.getElementById("rightPanel");
/**
* @param {{todoDescription: string, todoIndex: number}} todo
*/
function showTodo(todo) {
var newTodo = document.createElement("div");
var textNode = document.createElement("span");
var removeButton = document.createElement("span");
var editButton = document.createElement("span");
var completionCheckbox = document.createElement("input");
newTodo.classList.add("todo", "not-completed", "parent-of-hidden");
removeButton.classList.add("remove-icon", "position-right", "visible-if-parent-hovered");
textNode.classList.add("todo-text");
editButton.classList.add("edit-icon", "visible-if-parent-hovered");
textNode.innerText = todo[0];
completionCheckbox.type = "checkbox";
panel.appendChild(newTodo);
newTodo.appendChild(textNode);
newTodo.appendChild(removeButton);
newTodo.appendChild(editButton);
newTodo.insertBefore(completionCheckbox, newTodo.firstChild);
iconsModule.triggerRendering();
return {
completionCheckBox: completionCheckbox,
removeButton: removeButton,
editButton: editButton,
textNode: textNode,
todoNode: newTodo,
applyCompletedTodoStyle: () => applyCompletedTodoStyle(newTodo),
applyNotCompletedTodoStyle: () =>...