// jsDOC
function TodoApp(opt) {// лучше использовать полное options
this.elem = opt.elem;
this.taskList = new TaskList(this.elem);
this.input = this.elem.find('.todo-name');
this.elem.on('submit', '.todo-form', $.proxy(this.onFormSubmit, this)) //пропущена ;. Почему не просто this.onFormSubmit.bind(this)?
}
TodoApp.prototype = {
constructor: TodoApp,
onFormSubmit: function() { // параметр e
if(this.input.val().trim() === '') { // this.input.val() в переменную, тк используется 2 раза.
return false; // нет! только e.preventDefault. return false аналогично вызову e.preventDefault() и e.stopPropagation(), использовать stopPropagation плохой тон.
}
this.taskList.addTask(this.input.val());
this.input.val('');
return false;
}
};
function TaskList(el) {
var that = this;
this.el = el; // el, elem - определись уже. к тому же el - это jQuery переменная, jQuery переменные лучше обозначать используя префикс $ (например, $el)
this.list = el.find('.todo-list');
this.tasks = [];
this.list.on('dblclick', '.todo-task', function(e) { // неправильный подход. TaskList должен содержать коллекцию Task и оперерировать уже ими. Так что dbclick должен слушать и обарабывать Task.
var task = $(e.currentTarget).data('task');
var newName = prompt('', task.name);
task.edit(newName);
});
this.list.on('change', '.todo-check', function(e) {
var task = $(e.currentTarget).parent().data('task'); // parent() - зло
task.onCheckChange();
});
this.list.on('click', '.todo-x', $.proxy(this.onXClick, this)); // это должно быть у Task во вьюхе
this.el.on('click', '.todo-remove', $.proxy(this.onRemoveClick, this)) // ;
}
TaskList.prototype = {
constructor: TaskList,
addTask: function(name) {
var li = $('<li/>').addClass('todo-task animated flash'); // неее. Должен быть TaskView, который будет этой хренью заниматься. А здесь должн создаваться модель Task и на основе модели TaskView
this.list.append(li);
var task = new Task(li, name);
this.tasks.push(task);
li.data('task', task); // не понятно, зачем засовывать в this.task и в data элемента. косяк
console.log(this.tasks);
},
onXClick: function(e) {
var task = $(e.currentTarget).parent('li').data('task');
task.li.remove();
this.tasks.forEach(function(e,i,a) {
if(e === task) {
a.splice(i,1)
}
})
},
onRemoveClick: function() {
var that = this; // лишнее
var oldTasks = that.tasks;
that.tasks = [];
oldTasks.forEach(function(e) { // можно использовать bind(this), либо передать конекст 3-им аргументом
if(e.done) {
$(e.li).remove(); // ну и опять же, здесь должно быть вызов модели Task
}else {
that.tasks.push(e);
}
})
}
};
function Task(li ,name) {
this.li = li;
this.name = name;
this.done = false;
this.renderTask();
}
Task.prototype = {
constructor: Task,
renderTask: function() {
this.li.html('<input type="checkbox" class="todo-check"> ' +this.name+ '<span class="todo-x"> X </span>');
},
edit: function(newName) {
if(this.done) {
this.done = false;
this.li.removeClass('done') // ;
}
this.name = newName;
this.renderTask();
},
onCheckChange: function() {
this.li.toggleClass('done');
this.done = !this.done;
}
};
new TodoApp({
elem: $('.todo') // ;
});
Вторую половину смотрел уже слабо, устал)