Skip to content

Homework#5 [Done] #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions TigranKirakosov/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
index_copy.js
86 changes: 86 additions & 0 deletions TigranKirakosov/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<!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="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600"
rel="stylesheet"
/>
<link rel="stylesheet" href="style.css" />
<title>To-Do App</title>
</head>
<body>
<main>
<section class="application">
<div class="application__title"><span>To-Do List</span></div>
<form class="form-group">
<div class="input-container">
<label class="input-label" for="input-text">
<span>Type a task</span>
<input
type="text"
class="input-text"
id="input-text"
placeholder="What to do?"
/>
<span>Set deadline</span>
<select name="Deadline" id="deadline">
<option value="no deadline">no deadline</option>
<option value="tomorrow">tomorrow</option>
<option value="next week">next week</option>
</select>
<button class="submit-btn">Add</button>
</label>
</div>
<div class="clear-container">
<button class="clear-btn">Clear tasks</button>
</div>
<div class="search-container">
<label for="filter" class="filter-label">
<span>Filter to-do's</span>
<select name="Filter" id="filter">
<option value="no filter">no filter</option>
<option value="no deadline">Deadline: no deadline</option>
<option value="tomorrow">Deadline: tomorrow</option>
<option value="next week">Deadline: next week</option>
<option value="undone">Is done: undone</option>
<option value="done">Is done: done</option>
</select>
<button class="filter-btn">
<i class="fas fa-filter"></i>
</button>
</label>
</div>
</form>
<ul class="collection">
<!-- <li class="collection__item" id="item-0">
<span class="text">Lorem ipsum dolor</span>
<span class="deadline">Deadline: tomorrow</span>
<div class="icons">
<i class="far fa-circle"></i>
<i class="fas fa-backspace"></i>
</div>
</li>
<li class="collection__item" id="item-0">
<span>Lorem ipsum dolor</span>
<div class="icons">
<i class="far fa-check-circle"></i>
<i class="fas fa-backspace"></i>
</div>
</li>
<li class="collection__item" id="item-0">
<span>Lorem ipsum dolor</span>
<div class="icons">
<i class="far fa-circle"></i>
<i class="fas fa-backspace"></i>
</div>
</li> -->
</ul>
</section>
</main>
<script src="index.js"></script>
<script src="https://kit.fontawesome.com/a863ebaea0.js"></script>
</body>
</html>
291 changes: 291 additions & 0 deletions TigranKirakosov/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,291 @@
var UIController = (function() {
var strings;
strings = {
DOM: {
taskInput: '.input-text',
deadlineInput: '#deadline',
submitBtn: '.submit-btn',
filterInput: '#filter',
filterBtn: '.filter-btn',
uncheckedBtn: 'far fa-circle',
checkedBtn: 'far fa-check-circle',
deleteBtn: 'fas fa-backspace',
taskList: '.collection',
clearBtn: '.clear-btn'
},
utils: {
noDeadline: 'no deadline',
undone: 'undone',
done: 'done',
keyCode: 13,
noFilter: 'no filter'
}
};

return {
getInput: function() {
return {
text: document.querySelector(strings.DOM.taskInput).value,
deadline: document.querySelector(strings.DOM.deadlineInput).value,
filterValue: document.querySelector(strings.DOM.filterInput).value
};
},
getDOMStrings: function() {
return strings.DOM;
},
getUtilsStrings: function() {
return strings.utils;
},
deleteListItem: function(selectorID) {
var element;
element = document.querySelector(`#${selectorID}`);
element.parentNode.removeChild(element);
},
toggleTask: function(icon) {
if (icon.className === strings.DOM.checkedBtn) {
icon.className = strings.DOM.uncheckedBtn;
} else if (icon.className === strings.DOM.uncheckedBtn) {
icon.className = strings.DOM.checkedBtn;
}
},
renderTasks: function(tasks) {
var taskList;
var html = '';
taskList = document.querySelector(strings.DOM.taskList);

tasks.forEach(function(task) {
html += `
<li class="collection__item" id="item-${task.id}">
<span class="text">${task.text}</span>
<div class="icons">
<i class="${task.iconClass}"></i>
<i class="fas fa-backspace"></i>
</div>
<span class="deadline">Deadline: ${task.deadline}</span>
</li>
`;
});
taskList.innerHTML = html;
},
clearTasks: function() {
document.querySelector(strings.DOM.taskList).innerHTML = '';
},
clearFields: function() {
document.querySelector(strings.DOM.taskInput).value = '';
document.querySelector(strings.DOM.deadlineInput).value =
strings.utils.noDeadline;
document.querySelector(strings.DOM.taskInput).focus();
}
};
})();

var LSController = (function(UICtrl) {
var tasks, toggleTaskState, DOM, UTILS;
DOM = UICtrl.getDOMStrings();
UTILS = UICtrl.getUtilsStrings();
if (
localStorage.getItem('tasks') === null ||
localStorage.getItem('tasks') === '' ||
localStorage.getItem('tasks') === []
) {
tasks = [];
} else {
tasks = JSON.parse(localStorage.getItem('tasks'));
}

toggleTaskState = function() {
if (this.isDone === UTILS.undone) {
this.isDone = UTILS.done;
this.iconClass = DOM.checkedBtn;
} else if (this.isDone === UTILS.done) {
this.isDone = UTILS.undone;
this.iconClass = DOM.uncheckedBtn;
}
};

return {
getTasksFromLS: function() {
return tasks;
},
addToLS: function(task) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why both functions - addTask and addToLS are public api of storageController? - I think you need to extract all logic that is responsible for interactions with localStorage to separated controller/service and use it inside your storageController

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do that, valuable suggestion, should've separated the logic

tasks.push(task);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why addToLS function makes more than just add task to LS? - in fact, you sync your internal state firstly and then add new state to LS. I think you need to move this logic to addTask function. current implementation of addTask function better to rename to smth like createTask

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, will fix that

localStorage.setItem('tasks', JSON.stringify(tasks));
},
deleteFromLS: function(id) {
var ids, index;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again - I don't think deleteFromLS is good naming for this function - you delete task from internal state, and just update localStorage value

ids = tasks.map(function(current) {
return current.id;
});
index = ids.indexOf(id);
if (index !== -1) {
tasks.splice(index, 1);
}
localStorage.setItem('tasks', JSON.stringify(tasks));
},
toggleTask: function(id) {
var ids, index;
ids = tasks.map(function(current) {
return current.id;
});
index = ids.indexOf(id);
if (index !== -1) {
toggleTaskState.call(tasks[index]);
}
localStorage.setItem('tasks', JSON.stringify(tasks));
},
clearLS: function() {
tasks = [];
localStorage.setItem('tasks', []);
}
};
})(UIController);

var storageController = (function(UICtrl, LSCtrl) {
var Task, tasks, DOM, UTILS;
DOM = UICtrl.getDOMStrings();
UTILS = UICtrl.getUtilsStrings();
tasks = LSCtrl.getTasksFromLS();

Task = function(id, text, deadline) {
this.id = id;
this.text = text;
this.deadline = deadline;
this.isDone = UTILS.undone;
this.iconClass = DOM.uncheckedBtn;
};

Task.prototype.toggleState = function() {
if (this.isDone === UTILS.undone) {
this.isDone = UTILS.done;
this.iconClass = DOM.checkedBtn;
} else if (this.isDone === UTILS.done) {
this.isDone = UTILS.undone;
this.iconClass = DOM.uncheckedBtn;
}
};

return {
getTasks: function() {
return tasks;
},
createTask: function(text, deadline) {
var newTask, ID;
if (tasks.length > 0) ID = tasks[tasks.length - 1].id + 1;
else ID = 0;
newTask = new Task(ID, text, deadline);
return newTask;
},
updateTasks: function() {
tasks = LSCtrl.getTasksFromLS();
}
};
})(UIController, LSController);

var controller = (function(UICtrl, storageCtrl, LSCtrl) {
var DOM = UICtrl.getDOMStrings();
var UTILS = UICtrl.getUtilsStrings();
var setUpEventListeners = function() {
document.addEventListener('DOMContentLoaded', ctrlDisplayTasks);
document
.querySelector(DOM.submitBtn)
.addEventListener('click', ctrlAddTask);
document.addEventListener('keypress', function(event) {
if (event.keyCode === UTILS.keyCode || event.which === UTILS.keyCode) {
ctrlAddTask();
event.preventDefault();
}
});
document
.querySelector(DOM.taskList)
.addEventListener('click', ctrlDeleteTask);
document
.querySelector(DOM.taskList)
.addEventListener('click', ctrlToggleTask);
document
.querySelector(DOM.filterBtn)
.addEventListener('click', ctrlFilterTasks);
document
.querySelector(DOM.clearBtn)
.addEventListener('click', ctrlClearTasks);
};
var ctrlDisplayTasks = function() {
var tasks;
tasks = LSCtrl.getTasksFromLS();
UICtrl.renderTasks(tasks);
};
var ctrlAddTask = function() {
var input, newTask;
event.preventDefault();
input = UICtrl.getInput();
if (input.text !== '') {
newTask = storageCtrl.createTask(input.text, input.deadline, input.state);
LSCtrl.addToLS(newTask);
ctrlDisplayTasks();
UICtrl.clearFields();
}
};
var ctrlDeleteTask = function(event) {
var itemID;
if (event.target.className === DOM.deleteBtn) {
itemID = event.target.parentNode.parentNode.id;
}
if (itemID) {
var itemInfo = getItemInfo(itemID);
LSCtrl.deleteFromLS(itemInfo.ID);
UICtrl.deleteListItem(itemID);
}
};
var ctrlToggleTask = function(event) {
var itemID, icon;
if (
event.target.className === DOM.uncheckedBtn ||
event.target.className === DOM.checkedBtn
) {
itemID = event.target.parentNode.parentNode.id;
icon = event.target;
}
if (itemID) {
var itemInfo = getItemInfo(itemID);
LSCtrl.toggleTask(itemInfo.ID);
UICtrl.toggleTask(icon);
}
};
var getItemInfo = function(stringID) {
splitID = stringID.split('-');
type = splitID[0];
ID = +splitID[1];
return {
type: type,
ID: ID
};
};
var ctrlFilterTasks = function() {
var tasks, filterValue, filteredTasks;
tasks = LSCtrl.getTasksFromLS();
filterValue = document.querySelector(DOM.filterInput).value;
filteredTasks = tasks.filter(function(task) {
return task.deadline == filterValue || task.isDone == filterValue;
});
if (filterValue === UTILS.noFilter) {
ctrlDisplayTasks();
} else {
UICtrl.renderTasks(filteredTasks);
}
event.preventDefault();
};
var ctrlClearTasks = function() {
event.preventDefault();
LSCtrl.clearLS();
storageCtrl.updateTasks();
UICtrl.clearTasks();
document.querySelector(DOM.filterInput).value = UTILS.noFilter;
};

return {
init: function() {
setUpEventListeners();
}
};
})(UIController, storageController, LSController);

controller.init();
Loading