Skip to content

Instantly share code, notes, and snippets.

@11joselu
Created June 21, 2017 17:09
Show Gist options
  • Save 11joselu/d50405ecd88adffb5e6e1d5d752565d3 to your computer and use it in GitHub Desktop.
Save 11joselu/d50405ecd88adffb5e6e1d5d752565d3 to your computer and use it in GitHub Desktop.
Todo App with Jquery
<!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 rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css'/>
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
html, body {
background-color: #f9f9f9;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
font-family: 'Roboto', Helvetica, Arial, sans-serif;
}
header {
text-align: center;
background-color: #32b868;
color: #fff;
}
header h1 {
padding: 1em;
}
header h1 small {
font-size: .4em;
color: #a4fbc7;
}
main {
width: 60%;
margin: 0 auto;
background-color: #5d6360;
}
form {
text-align: center;
}
input[type="text"] {
width: 50%;
display: inline-block;
padding: .6em;
margin-top: 2em;
border: none;
outline: none;
}
input[type="submit"] {
border: none;
outline: none;
padding: .7em;
background-color: #32b868;
color: #fff;
}
li {
list-style: none;
}
#app {
margin: 1em;
overflow: hidden;
}
#app ul li {
margin: 1em;
display: block;
padding: 1em;
color: #ececec;
border-left: 6px solid #32b868;
background-color: #6b6b6b;
}
#app ul li.todo__done {
background-color: #5d6360;
}
#app ul li.todo__done span {
text-decoration: line-through;
}
#app ul li .fa {
color: #ff5722;
cursor: pointer;
}
</style>
</head>
<body>
<main>
<header>
<h1>Todo App <small>jQuery</small></h1>
</header>
<form id="todo-form">
<input type="text" name="todo" id="todo-input">
<input type="submit" value="Save">
</form>
<div id="app"></div>
</main>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="javascript/app.js"></script>
</body>
</html>
(function ($) {
'use strict';
const TODO_ATTRIBUTE_ID = 'todo-';
/**
* Generate Random UUID
*/
function guid() {
function _p8(s) {
var p = (Math.random().toString(16) + "000000000").substr(2, 8);
return s ? "-" + p.substr(0, 4) + "-" + p.substr(4, 4) : p;
}
return _p8() + _p8(true) + _p8(true) + _p8();
}
/**
* Return todos sample json data
*/
const getTodos = () => {
return [{
_id: guid(),
title: "Learn Vue.js 2.x",
done: false
}, {
_id: guid(),
title: "Learn How git rebase works",
done: false
}, {
_id: guid(),
title: "Kill to Jose Barato",
done: true
}];
};
/**
* Find todo into todos Array
* @param {array} todos
* @param {string} id
*/
const findTodoByID = (todos, id) => {
return todos.find((todo) => todo._id === id);
};
/**
* Return ID (data-attribute) from element
* @param {HTMLNode} elem
*/
const getID = (elem) => {
return $(elem).parent().attr(`data-id`).split(TODO_ATTRIBUTE_ID)[1]
};
/**
* Toggle class into checkbox parent element
* @param {HTMLNode} elem
* @param {boolean} isChecked
* @param {string} klass
*/
const toggleParentClass = (elem, isChecked, klass = "todo__done") => {
if (isChecked) {
$(elem).parent().addClass(klass);
} else {
$(elem).parent().removeClass(klass);
}
};
/**
* Checkbox change event
* - Add class into parent by status
* @param {array} todos
*/
const onChangeTodo = (todos) => {
return (evt) => {
const elem = evt.target;
const id = getID(elem);
const todo = findTodoByID(todos, id);
const isChecked = $(elem).prop("checked");
todo.done = isChecked;
toggleParentClass(elem, isChecked);
};
};
/**
* Remove event listener
* - Split from todos by id
* @param {array} todos
*/
const onRemoveTodo = (todos) => {
return (evt) => {
const elem = evt.target;
const id = getID(elem);
const indexTodo = todos.findIndex((todo) => todo._id === id);
if (indexTodo => 0) {
todos.splice(indexTodo, 1);
$(elem).parent().remove();
}
}
};
/**
* Create todo element
* @param {object} todo
*/
const createTodoElement = (todo) => {
return (
`<li data-id="${TODO_ATTRIBUTE_ID}${todo._id}" class="${(todo.done)? 'todo__done' : ''}">
<input type="checkbox" ${ (todo.done)? 'checked': ''} />
<span>${todo.title}</span>
<i class="fa fa-trash"></i>
</li>`
);
};
/**
* Create new todo and push into todos array
* - Clean events
* @param {array} todos
* @param {string} title
*/
const addTodo = (todos, title) => {
const todo = {
_id: guid(),
title,
done: false
};
todos.push(todo);
$('ul', '#app').append(createTodoElement(todo));
addIconEvents(todos);
addCheckboxEvents(todos)
};
const renderTodos = (todos) => {
const todosHTML = todos.map(createTodoElement).join("");
return (`
<ul>
${todosHTML}
</ul>
`);
};
const addIconEvents = (todos) => {
const app = $('#app');
const removeEvt = onRemoveTodo(todos);
$('.fa-trash', app).unbind();
$('.fa-trash', app).click(removeEvt);
};
const addCheckboxEvents = (todos) => {
const app = $('#app');
const changeEvt = onChangeTodo(todos);
$('input[type="checkbox"]', app).unbind();
$('input[type="checkbox"]', app).change(changeEvt);
};
const rerenderTodos = (todos) => {
const app = $('#app');
app.empty();
app.append(renderTodos(todos));
addCheckboxEvents(todos);
addIconEvents(todos);
}
const todos = getTodos();
rerenderTodos(todos);
$('#todo-form').submit(function (evt) {
evt.preventDefault();
const todoValue = $('#todo-input').val();
addTodo(todos, todoValue);
$('#todo-input').val('')
});
})(jQuery);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment