Reputation: 1595
I've implemented simple todo list http://jsfiddle.net/tw9p9sw3/ with possibility add/remove todo's.
(function (todoApp) {
'use strict';
todoApp.todoItemValue = '';
function _appendListNode() {
var listNode = document.createElement('li');
listNode.className = 'list-group-item';
listNode.appendChild(document.createTextNode(todoApp.todoItemValue));
listNode.appendChild(_createRemoveItemButton());
todoList.appendChild(listNode);
}
function _createRemoveItemButton() {
var removeButtonNode = document.createElement('a'),
removeButtonLabel = 'Remove';
removeButtonNode.className = 'badge';
removeButtonNode.appendChild(document.createTextNode(removeButtonLabel));
return removeButtonNode;
}
function _addItem() {
todoApp.todoItemValue = document.getElementById('todoInput').value;
_appendListNode();
document.getElementById('todoInput').value = '';
}
function _removeItem() {
var nodeToRemove = this.parentNode;
this.parentNode.parentNode.removeChild(nodeToRemove);
}
function _addEventHandlers() {
document.getElementById('todoListForm').addEventListener('submit', function (event) {
event.preventDefault();
_addItem();
});
/*
* Used delegated event cause todo list is not static,
* so we don't need to add events for remove buttons each time after DOM of todo list have changed
*/
document.getElementById('todoList').addEventListener('click', function (event) {
if (event.target && event.target.nodeName === 'A') {
event.preventDefault();
_removeItem.call(event.target);
}
});
}
todoApp.init = function () {
_addEventHandlers();
};
}(window.todoApp = window.todoApp || {}));
//////////////////////////////////////////////////////////
// INITIALIZATION
//////////////////////////////////////////////////////////
document.onload = todoApp.init();
The question is how to re-make this todo list as independent component so for example I could inject/instanciate it twice on the same page and there should be no conflicts between todo list instances.
Upvotes: 1
Views: 151
Reputation: 586
Basically you need to create TodoList class, so you can create instances of this class, as suggested in coments use OO programming.
Here is code:
var TodoListComponent = (function () {
'use strict';
var todoListTemplate = '<div>' +
'<div class="todo-list">' +
'<div class="form-container">' +
'<form role="form" class="todoListForm">' +
'<div class="form-group">' +
'<label for="todoInput">Add todo item</label>' +
'<input type="text" class="form-control todoInput" required>' +
'</div>' +
'<button type="submit" class="btn btn-success">Submit</button>' +
'</form>' +
'</div>' +
'<div class="list-container">' +
'<ul class="list-group todoList">' +
'<li class="list-group-item list-group-item-success">Todo list</li>' +
'</ul>' +
'</div>' +
'</div>' +
'</div>';
function TodoList() {
this.initialize = function() {
this.$el = $(todoListTemplate);
this.todoItemValue = '';
this._initEvents();
}
this._initEvents = function() {
var self = this;
this.$el.find('.todoListForm').on('submit', function (event) {
event.preventDefault();
self._addItem();
});
/*
* Used delegated event cause todo list is not static,
* so we don't need to add events for remove buttons each time after DOM of todo list have changed
*/
this.$el.find('.todoList').on('click', function (event) {
if (event.target && event.target.nodeName === 'A') {
event.preventDefault();
self._removeItem.call(event.target);
}
});
}
this._appendListNode = function () {
var listNode = $('<li>');
listNode.addClass('list-group-item');
listNode.text(this.todoItemValue);
listNode.append(this._createRemoveItemButton());
this.$el.find('.todoList').append(listNode);
}
this._createRemoveItemButton = function () {
var removeButtonNode = $('<a>'),
removeButtonLabel = 'Remove';
removeButtonNode.addClass('badge');
removeButtonNode.text(removeButtonLabel);
return removeButtonNode;
}
this._addItem = function() {
var input = this.$el.find('.todoInput');
this.todoItemValue = input.val();
this._appendListNode();
input.val('');
}
this._removeItem = function() {
var nodeToRemove = this.parentNode;
this.parentNode.parentNode.removeChild(nodeToRemove);
}
this.render = function() {
return this;
}
this.initialize();
}
return TodoList;
}());
//////////////////////////////////////////////////////////
// INITIALIZATION
//////////////////////////////////////////////////////////
var todoList1 = new TodoListComponent();
var todoList2 = new TodoListComponent();
$('body').append(todoList1.render().$el);
$('body').append(todoList2.render().$el);
And jsfiddle link: http://jsfiddle.net/tw9p9sw3/10/
This works, but what if you want to use data, send items somewhere or else, then you probably will get it via DOM which is bad and messy.
Try to use Backbone where DOM used only for representation, and data is held by Javascript.
Here is example:
http://backbonejs.org/docs/todos.html
Upvotes: 1