Skip to content
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
57 changes: 57 additions & 0 deletions public/dist/scripts/Main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
(function () {

let TodoMain = TODO_APP.components.TodoMain;
let AddTodos = TODO_APP.components.AddTodos;
let TodoList = TODO_APP.components.TodoList;
let TodoActionsBar = TODO_APP.components.TodoActionsBar;

function init() {

let todoMain = new TodoMain();
let addTodos = new AddTodos();
let todoList = new TodoList();
let todoActionsBar = new TodoActionsBar();


addTodos
.on('newTodo',
function (todoData) {
todoList.createItem(todoData);
}
)
.on('markAsReadyAll',
function () {
todoList.markAsReadyAll();
}
);

function itemsCountWatcher() {
let itemsCount = todoList.getItemsCount();

if (itemsCount !== 0) {
todoMain.showFullInterface();
} else {
todoMain.hideFullInterface();
}

todoActionsBar.setItemsCount(itemsCount);
}

todoList.on('itemAdd', itemsCountWatcher)
.on('itemDelete', itemsCountWatcher);

todoActionsBar.on(
'clearCompleted',
function () {
todoList.removeCompletedItems();
}
);

todoActionsBar.on('filterSelected', function (filterId) {
todoList.setFilter(filterId);
});

}

document.addEventListener('DOMContentLoaded', init);
}());
7 changes: 7 additions & 0 deletions public/dist/scripts/TODO_APP.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
(function () {
window.TODO_APP = {
utils: {},
modules: {},
components: {}
};
}());
58 changes: 58 additions & 0 deletions public/dist/scripts/components/AddTodos.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
(function () {
let extendConstructor = TODO_APP.utils.extendConstructor;
let Eventable = TODO_APP.modules.Eventable;

const ENTER_KEY_CODE = 13;

const TODOS_TODO_INPUT_SELECTOR = '.js-todos-todo-input';
const TODOS_SELECT_ALL_SELECTOR = '.js-todos-select-all';

/**
* @implements {EventListener}
* @extends {Eventable}
* @constructor
*/
function AddTodosConstructor() {
this._todoInput = document.querySelector(TODOS_TODO_INPUT_SELECTOR);
this._todoSelectAll = document.querySelector(TODOS_SELECT_ALL_SELECTOR);

this._todoInput.addEventListener('keypress', this);
this._todoSelectAll.addEventListener('click', this);

this._initEventable();
}

extendConstructor(AddTodosConstructor, Eventable);


AddTodosConstructor.prototype._markAsReadyAll = function () {
return this.trigger('markAsReadyAll');
};

AddTodosConstructor.prototype._addItem = function () {
let todoInputValue = this._todoInput.value.trim();

if (todoInputValue.length !== 0) {
this._todoInput.value = '';
}

return this.trigger('newTodo', {
text: todoInputValue
});
};

AddTodosConstructor.prototype.handleEvent = function (e) {
switch (e.type) {
case 'click':
this._markAsReadyAll();
break;
case 'keypress':
if (e.keyCode === ENTER_KEY_CODE) {
this._addItem();
}
break;
}
};

TODO_APP.components.AddTodos = AddTodosConstructor;
}());
54 changes: 54 additions & 0 deletions public/dist/scripts/components/Filter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
(function () {
let Eventable = TODO_APP.modules.Eventable;
let extendConstructor = TODO_APP.utils.extendConstructor;

const ACTIVE_FILTER_MODIFICATOR = '__active';

/**
* @param {HTMLElement} domRoot
* @constructor
* @implements {EventListener}
*/
function FilterConstructor(domRoot) {
this._initEventable();

let filters = this._filters = domRoot.querySelectorAll('.filter');
this._currentActive = null;

for (let i = filters.length; i--;) {
filters[i].addEventListener('click', this);
if (filters[i].classList.contains(ACTIVE_FILTER_MODIFICATOR)) {
this._currentActive = filters[i];
}
}
}

extendConstructor(FilterConstructor, Eventable);

let filterConstructorPrototype = FilterConstructor.prototype;

/**
* @param {HTMLElement} filterElement
* @return {FilterConstructor}
* @private
*/
filterConstructorPrototype._setFilter = function (filterElement) {
if (this._currentActive !== filterElement) {
this._currentActive.classList.remove(ACTIVE_FILTER_MODIFICATOR);
filterElement.classList.add(ACTIVE_FILTER_MODIFICATOR);
this._currentActive = filterElement;
this.trigger('filterSelected', filterElement.getAttribute('data-filter'));
}
return this;
};

filterConstructorPrototype.handleEvent = function (e) {
switch (e.type) {
case 'click':
this._setFilter(e.target);
break;
}
};

TODO_APP.components.Filter = FilterConstructor;
}());
63 changes: 63 additions & 0 deletions public/dist/scripts/components/TodoActionsBar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
(function () {
let extendConstructor = TODO_APP.utils.extendConstructor;
let getTextNode = TODO_APP.utils.getTextNode;
let Eventable = TODO_APP.modules.Eventable;
let Filter = TODO_APP.components.Filter;

/**
* @constructor
* @implements {EventListener}
*/
function TodoActionsBarConstructor() {
this._initEventable();

this._counterNode = document.querySelector('.js-todos-actions-bar_counter');
this._counterNodeText = getTextNode(this._counterNode);
this._clearCompletedNode = document.querySelector('.js-todos-actions-bar_clear-completed');

this._clearCompletedNode.addEventListener('click', this);

this._filters = new Filter(document.querySelector('.js-todos-actions-bar_filter'));

this._filters.on('filterSelected', this._onFilterSelected, this);
}

extendConstructor(TodoActionsBarConstructor, Eventable);

let todoActionsBarConstructorPrototype = TodoActionsBarConstructor.prototype;

todoActionsBarConstructorPrototype._onFilterSelected = function (filterId) {
this.trigger('filterSelected', filterId);
};

/**
* @return {TodoActionsBarConstructor}
* @private
*/
todoActionsBarConstructorPrototype._clearCompleted = function () {
this.trigger('clearCompleted');
return this;
};

/**
* @param {Number} count
* @return {TodoActionsBarConstructor}
*/
todoActionsBarConstructorPrototype.setItemsCount = function (count) {
this._counterNodeText.nodeValue = count + ' item' + (count === 0 ? '' : 's') + ' left';
return this;
};

/**
* @param {Event} e
*/
todoActionsBarConstructorPrototype.handleEvent = function (e) {
switch (e.type) {
case 'click':
this._clearCompleted();
break;
}
};

TODO_APP.components.TodoActionsBar = TodoActionsBarConstructor;
}());
141 changes: 141 additions & 0 deletions public/dist/scripts/components/TodoItem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
(function () {
let Eventable = TODO_APP.modules.Eventable;
let extendConstructor = TODO_APP.utils.extendConstructor;

let templatesEngine = TODO_APP.modules.templatesEngine;

const READY_MODIFICATOR = '__ready';
const HIDDEN_MODIFICATOR = '__hide';

/**
* @param itemData
* @implements {EventListener}
* @constructor
*/
function TodoItemConstructor(itemData) {
this._initEventable();

let templateResult = templatesEngine.todoItem({
text: itemData.text
});

this._root = templateResult.root;
this._markReady = templateResult.markReady;
this._removeAction = templateResult.removeAction;
this._text = templateResult.text;

this.model = {
id: itemData.id,
isReady: itemData.isReady || false,
text: itemData.text
};

if (itemData.isReady) {
this._setReadyModificator(true);
}

this._markReady.addEventListener('change', this);
this._removeAction.addEventListener('click', this);
this._text.addEventListener('input', this);
}

extendConstructor(TodoItemConstructor, Eventable);

let todoItemConstructorPrototype = TodoItemConstructor.prototype;

/**
* @param {HTMLElement} parent
* @return {TodoItemConstructor}
*/
todoItemConstructorPrototype.render = function (parent) {
parent.appendChild(this._root);
return this;
};

/**
* @param {Event} e
*/
todoItemConstructorPrototype.handleEvent = function (e) {
switch (e.type) {
case 'change':
this.setReady(this._markReady.checked);
break;
case 'click':
if (e.target === this._removeAction) {
this.remove();
}
break;
case 'input':
this.setText(this._text.innerText);
break;
}
};

/**
* @param {String} text
* @return {TodoItemConstructor}
*/
todoItemConstructorPrototype.setText = function (text) {
if (this.model.text !== text) {
this._text.innerHTML = text;
this.model.text = text;
this.trigger('change', this.model);
}
return this;
};

/**
* @param {Boolean} isReady
* @return {TodoItemConstructor}
* @private
*/
todoItemConstructorPrototype._setReadyModificator = function (isReady) {
if (isReady) {
this._root.classList.add(READY_MODIFICATOR);
} else {
this._root.classList.remove(READY_MODIFICATOR);
}
return this;
};

/**
* @param {Boolean} isReady
* @return {TodoItemConstructor}
*/
todoItemConstructorPrototype.setReady = function (isReady) {
if (isReady !== this.model.isReady) {
this._markReady.checked = isReady;
this.model.isReady = isReady;
this._setReadyModificator(isReady);
this.trigger('change', this.model);
}
return this;
};

/**
* @return {TodoItemConstructor}
*/
todoItemConstructorPrototype.remove = function () {
this._root.parentNode.removeChild(this._root);
this.trigger('remove', this.model.id);
return this;
};

/**
* @return {TodoItemConstructor}
*/
todoItemConstructorPrototype.show = function () {
this._root.classList.remove(HIDDEN_MODIFICATOR);
return this;
};

/**
* @return {TodoItemConstructor}
*/
todoItemConstructorPrototype.hide = function () {
this._root.classList.add(HIDDEN_MODIFICATOR);
return this;
};

TODO_APP.components.TodoItem = TodoItemConstructor;
}());
Loading