Commit 6f3db0f0 authored by Florian Fesseler's avatar Florian Fesseler Committed by Sindre Sorhus

Close GH-109: Update VanillaJS app

parent 341bbfeb
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-weight: inherit;
font-style: inherit;
font-size: 100%;
font-family: inherit;
vertical-align: baseline;
}
body {
line-height: 1;
color: black;
background: white;
}
ol, ul {
list-style: none;
}
a img {
border: none;
}
html {
background: #eeeeee;
}
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
line-height: 1.4em;
background: #eeeeee;
color: #333333;
}
#todoapp {
width: 480px;
margin: 0 auto 40px;
background: white;
padding: 20px;
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 5px 6px 0;
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 5px 6px 0;
-o-box-shadow: rgba(0, 0, 0, 0.2) 0 5px 6px 0;
box-shadow: rgba(0, 0, 0, 0.2) 0 5px 6px 0;
}
#todoapp h1 {
font-size: 36px;
font-weight: bold;
text-align: center;
padding: 20px 0 30px 0;
line-height: 1;
}
#create-todo {
position: relative;
}
#create-todo input {
width: 466px;
font-size: 24px;
font-family: inherit;
line-height: 1.4em;
border: 0;
outline: none;
padding: 6px;
border: 1px solid #999999;
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
-o-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
}
#create-todo span {
position: absolute;
z-index: 999;
width: 170px;
left: 50%;
margin-left: -85px;
}
#todo-list {
margin-top: 10px;
}
#todo-list li {
padding: 12px 20px 11px 0;
position: relative;
font-size: 24px;
line-height: 1.1em;
border-bottom: 1px solid #cccccc;
}
#todo-list li:after {
content: "\0020";
display: block;
height: 0;
clear: both;
overflow: hidden;
visibility: hidden;
}
#todo-list li.editing {
padding: 0;
border-bottom: 0;
}
#todo-list .editing .display,
#todo-list .edit {
display: none;
}
#todo-list .editing .edit {
display: block;
}
#todo-list .editing input {
width: 444px;
font-size: 24px;
font-family: inherit;
margin: 0;
line-height: 1.6em;
border: 0;
outline: none;
padding: 10px 7px 0px 27px;
border: 1px solid #999999;
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
-o-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
}
#todo-list .check {
position: relative;
top: 9px;
margin: 0 10px 0 7px;
float: left;
}
#todo-list .done .todo-content {
text-decoration: line-through;
color: #777777;
}
#todo-list .todo-destroy {
position: absolute;
right: 5px;
top: 14px;
display: none;
cursor: pointer;
width: 20px;
height: 20px;
background: url(../../TodoMVC/todo-example/backbone/css/destroy.png) no-repeat 0 0;
}
#todo-list li:hover .todo-destroy {
display: block;
}
#todo-list .todo-destroy:hover {
background-position: 0 -20px;
}
#todo-stats {
*zoom: 1;
margin-top: 10px;
color: #777777;
}
#todo-stats:after {
content: "\0020";
display: block;
height: 0;
clear: both;
overflow: hidden;
visibility: hidden;
}
#todo-stats .todo-count {
float: left;
}
#todo-stats .todo-count .number {
font-weight: bold;
color: #333333;
}
#todo-stats .todo-clear {
float: right;
}
#todo-stats .todo-clear a {
color: #777777;
font-size: 12px;
}
#todo-stats .todo-clear a:visited {
color: #777777;
}
#todo-stats .todo-clear a:hover {
color: #336699;
}
#instructions {
width: 520px;
margin: 10px auto;
color: #777777;
text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;
text-align: center;
}
#instructions a {
color: #336699;
}
#credits {
width: 520px;
margin: 30px auto;
color: #999;
text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;
text-align: center;
}
#credits a {
color: #888;
}
/*
* François 'cahnory' Germain
*/
.ui-tooltip, .ui-tooltip-top, .ui-tooltip-right, .ui-tooltip-bottom, .ui-tooltip-left {
color:#ffffff;
cursor:normal;
display:-moz-inline-stack;
display:inline-block;
font-size:12px;
font-family:arial;
padding:.5em 1em;
position:relative;
text-align:center;
text-shadow:0 -1px 1px #111111;
-webkit-border-top-left-radius:4px ;
-webkit-border-top-right-radius:4px ;
-webkit-border-bottom-right-radius:4px ;
-webkit-border-bottom-left-radius:4px ;
-khtml-border-top-left-radius:4px ;
-khtml-border-top-right-radius:4px ;
-khtml-border-bottom-right-radius:4px ;
-khtml-border-bottom-left-radius:4px ;
-moz-border-radius-topleft:4px ;
-moz-border-radius-topright:4px ;
-moz-border-radius-bottomright:4px ;
-moz-border-radius-bottomleft:4px ;
border-top-left-radius:4px ;
border-top-right-radius:4px ;
border-bottom-right-radius:4px ;
border-bottom-left-radius:4px ;
-o-box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;
-moz-box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;
-khtml-box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;
-webkit-box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;
box-shadow:0 1px 2px #000000, inset 0 0 0 1px #222222, inset 0 2px #666666, inset 0 -2px 2px #444444;
background-color:#3b3b3b;
background-image:-moz-linear-gradient(top,#555555,#222222);
background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#555555),color-stop(1,#222222));
filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#555555,EndColorStr=#222222);
-ms-filter:progid:DXImageTransform.Microsoft.gradient(startColorStr=#555555,EndColorStr=#222222);
}
.ui-tooltip:after, .ui-tooltip-top:after, .ui-tooltip-right:after, .ui-tooltip-bottom:after, .ui-tooltip-left:after {
content:"\25B8";
display:block;
font-size:2em;
height:0;
line-height:0;
position:absolute;
}
.ui-tooltip:after, .ui-tooltip-bottom:after {
color:#2a2a2a;
bottom:0;
left:1px;
text-align:center;
text-shadow:1px 0 2px #000000;
-o-transform:rotate(90deg);
-moz-transform:rotate(90deg);
-khtml-transform:rotate(90deg);
-webkit-transform:rotate(90deg);
width:100%;
}
.ui-tooltip-top:after {
bottom:auto;
color:#4f4f4f;
left:-2px;
top:0;
text-align:center;
text-shadow:none;
-o-transform:rotate(-90deg);
-moz-transform:rotate(-90deg);
-khtml-transform:rotate(-90deg);
-webkit-transform:rotate(-90deg);
width:100%;
}
.ui-tooltip-right:after {
color:#222222;
right:-0.375em;
top:50%;
margin-top:-.05em;
text-shadow:0 1px 2px #000000;
-o-transform:rotate(0);
-moz-transform:rotate(0);
-khtml-transform:rotate(0);
-webkit-transform:rotate(0);
}
.ui-tooltip-left:after {
color:#222222;
left:-0.375em;
top:50%;
margin-top:.1em;
text-shadow:0 -1px 2px #000000;
-o-transform:rotate(180deg);
-moz-transform:rotate(180deg);
-khtml-transform:rotate(180deg);
-webkit-transform:rotate(180deg);
}
/*the following changes require some cleanup and integration with the above.**/
/* line 9 */
/* line 17 */
#todoapp {
background: white;
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
-o-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
-moz-border-radius-bottomleft: 5px;
-webkit-border-bottom-left-radius: 5px;
-o-border-bottom-left-radius: 5px;
-ms-border-bottom-left-radius: 5px;
-khtml-border-bottom-left-radius: 5px;
border-bottom-left-radius: 5px;
-moz-border-radius-bottomright: 5px;
-webkit-border-bottom-right-radius: 5px;
-o-border-bottom-right-radius: 5px;
-ms-border-bottom-right-radius: 5px;
-khtml-border-bottom-right-radius: 5px;
border-bottom-right-radius: 5px;
}
/* line 24 */
/* line 32 */
#todoapp .content #create-todo {
position: relative;
}
/* line 34 */
#todoapp .content #create-todo input {
font-size: 24px;
font-family: inherit;
line-height: 1.4em;
border: 0;
outline: none;
padding: 6px;
border: 1px solid #999999;
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
-o-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
}
/* line 47 */
#todoapp .content #create-todo span {
position: absolute;
z-index: 999;
width: 170px;
left: 50%;
margin-left: -85px;
opacity: 0;
}
/* line 55 */
#todoapp .content ul#todo-list {
margin-top: 10px;
}
/* line 57 */
#todoapp .content ul#todo-list li {
padding: 15px 20px 15px 0;
position: relative;
font-size: 24px;
border-bottom: 1px solid #cccccc;
*zoom: 1;
cursor: move;
}
/* line 22, /opt/ree/lib/ruby/gems/1.8/gems/compass-0.10.5/frameworks/compass/stylesheets/compass/utilities/general/_clearfix.scss */
#todoapp .content ul#todo-list li:after {
content: "\0020";
display: block;
height: 0;
clear: both;
overflow: hidden;
visibility: hidden;
}
/* line 64 */
#todoapp .content ul#todo-list li.editing {
padding: 0;
border-bottom: 0;
}
/* line 67 */
#todoapp .content ul#todo-list li.editing .todo-input {
display: block;
width: 466px;
font-size: 24px;
font-family: inherit;
line-height: 1.4em;
border: 0;
outline: none;
padding: 6px;
border: 1px solid #999999;
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
-o-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
}
/* line 79 */
#todoapp .content ul#todo-list li.editing .todo-content {
display: none;
}
/* line 81 */
#todoapp .content ul#todo-list li.editing .todo-check {
display: none;
}
/* line 83 */
#todoapp .content ul#todo-list li.editing .todo-destroy {
display: none !important;
}
/* line 85 */
#todoapp .content ul#todo-list li .todo-input {
display: none;
}
/* line 87 */
#todoapp .content ul#todo-list li .todo-check {
position: relative;
top: 6px;
margin: 0 10px 0 7px;
float: left;
}
/* line 93 */
#todoapp .content ul#todo-list li.done .todo-content {
text-decoration: line-through;
color: #777777;
}
/* line 96 */
#todoapp .content ul#todo-list li .todo-destroy {
position: absolute;
right: 0px;
top: 16px;
display: none;
cursor: pointer;
width: 20px;
height: 20px;
}
/* line 106 */
#todoapp .content ul#todo-list li:hover .todo-destroy {
display: block;
}
/* line 109 */
#todoapp #todo-stats {
*zoom: 1;
margin-top: 10px;
color: #555555;
-moz-border-radius-bottomleft: 5px;
-webkit-border-bottom-left-radius: 5px;
-o-border-bottom-left-radius: 5px;
-ms-border-bottom-left-radius: 5px;
-khtml-border-bottom-left-radius: 5px;
border-bottom-left-radius: 5px;
-moz-border-radius-bottomright: 5px;
-webkit-border-bottom-right-radius: 5px;
-o-border-bottom-right-radius: 5px;
-ms-border-bottom-right-radius: 5px;
-khtml-border-bottom-right-radius: 5px;
border-bottom-right-radius: 5px;
background: #f4fce8;
border-top: 1px solid #ededed;
padding: 0 20px;
line-height: 36px;
}
/* line 22, /opt/ree/lib/ruby/gems/1.8/gems/compass-0.10.5/frameworks/compass/stylesheets/compass/utilities/general/_clearfix.scss */
#todoapp #todo-stats:after {
content: "\0020";
display: block;
height: 0;
clear: both;
overflow: hidden;
visibility: hidden;
}
/* line 118 */
#todoapp #todo-stats .todo-count {
float: left;
}
/* line 120 */
#todoapp #todo-stats .todo-count .number {
font-weight: bold;
color: #555555;
}
/* line 123 */
#todoapp #todo-stats .todo-clear {
float: right;
}
/* line 125 */
#todoapp #todo-stats .todo-clear a {
display: block;
line-height: 20px;
text-decoration: none;
-moz-border-radius: 12px;
-webkit-border-radius: 12px;
-o-border-radius: 12px;
-ms-border-radius: 12px;
-khtml-border-radius: 12px;
border-radius: 12px;
background: rgba(0, 0, 0, 0.1);
color: #555555;
font-size: 11px;
margin-top: 8px;
padding: 0 10px 1px;
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
-o-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
}
/* line 136 */
#todoapp #todo-stats .todo-clear a:hover {
background: rgba(0, 0, 0, 0.15);
-moz-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0;
-webkit-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0;
-o-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0;
box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0;
}
/* line 139 */
#todoapp #todo-stats .todo-clear a:active {
position: relative;
top: 1px;
}
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<link href="css/todos.css" rel="stylesheet" type="text/css"> <meta charset="utf-8">
<script src="js/todo.js"></script> <title>VanillaJS • TodoMVC</title>
<script src="js/json2.js"></script> <link rel="stylesheet" href="../../assets/base.css">
</head> </head>
<body onload="bodyLoadHandler()"> <body>
<div id="todoapp"> <section id="todoapp">
<header id="header">
<div class="title">
<h1>Todos</h1> <h1>Todos</h1>
</div> <input id="new-todo" placeholder="What needs to be done?" autofocus>
</header>
<div class="content">
<div id="create-todo"> <section id="main">
<input id="new-todo" placeholder="What needs to be done?" onkeypress="newTodoKeyPressHandler(event)"> <input id="toggle-all" type="checkbox" >
<span class="ui-tooltip-top" style="display:none;">Press Enter to save this task</span> <label for="toggle-all">Mark all as complete</label>
</div>
<div id="todos">
<ul id="todo-list"> <ul id="todo-list">
</ul> </ul>
</div> </section>
<div id="todo-stats">
</div> <footer id="footer">
</div> <span id="todo-count"></span>
<button id="clear-completed">Clear completed</button>
</footer>
</section>
<footer id="info">
<p>Double-click to edit a todo.</p>
<p>Created by <a href="http://twitter.com/ffesseler">Florian Fesseler</a></p>
<p>Cleanup, edits: <a href="http://github.com/boushley">Aaron Boushley</a>.</p>
</footer>
</div> <!-- scripts here -->
<script src="js/app.js"></script>
</body> </body>
</html> </html>
var todos = [],
stat = {},
ENTER_KEY = 13;
window.addEventListener( "load", windowLoadHandler, false );
function Todo( title, completed ) {
this.id = getUuid();
this.title = title;
this.completed = completed;
}
function Stat() {
this.todoLeft = 0;
this.todoCompleted = 0;
this.totalTodo = 0;
}
function windowLoadHandler() {
loadTodos();
refreshData();
addEventListeners();
}
function addEventListeners() {
document.getElementById( 'new-todo' ).addEventListener( "keypress", newTodoKeyPressHandler, false );
document.getElementById( 'toggle-all' ).addEventListener( "change", toggleAllChangeHandler, false );
}
function inputEditTodoKeyPressHandler( event ) {
var inputEditTodo,
trimmedText,
todoId;
inputEditTodo = event.target;
trimmedText = inputEditTodo.value.trim();
todoId = event.target.id.slice( 6 );
if ( trimmedText ) {
if ( event.keyCode === ENTER_KEY ) {
editTodo( todoId, trimmedText );
}
}
else {
removeTodoById( todoId );
refreshData();
}
}
function inputEditTodoBlurHandler( event ) {
var inputEditTodo,
todoId;
inputEditTodo = event.target;
todoId = event.target.id.slice( 6 );
editTodo( todoId, inputEditTodo.value );
}
function newTodoKeyPressHandler( event ) {
if ( event.keyCode === ENTER_KEY ) {
addTodo( document.getElementById( 'new-todo' ).value );
}
}
function toggleAllChangeHandler( event ) {
for ( var i in todos ) {
todos[i].completed = event.target.checked;
}
refreshData();
}
function spanDeleteClickHandler( event ) {
removeTodoById( event.target.getAttribute( 'data-todo-id' ) );
refreshData();
}
function hrefClearClickHandler() {
removeTodosCompleted();
refreshData();
}
function todoContentHandler( event ) {
var todoId,
div,
inputEditTodo;
todoId = event.target.getAttribute( 'data-todo-id' );
div = document.getElementById( 'li_'+todoId );
div.className = 'editing';
inputEditTodo = document.getElementById( 'input_' + todoId );
inputEditTodo.focus();
}
function checkboxChangeHandler( event ) {
var checkbox,
todo;
checkbox = event.target;
todo = getTodoById( checkbox.getAttribute( 'data-todo-id' ) );
todo.completed = checkbox.checked;
refreshData();
}
function loadTodos() {
if ( !localStorage.getItem( 'todos-vanillajs' ) ) {
localStorage.setItem( 'todos-vanillajs', JSON.stringify( [] ) );
}
todos = JSON.parse( localStorage.getItem( 'todos-vanillajs' ) );
}
function addTodo( text ) {
var trimmedText = text.trim();
if ( trimmedText ) {
var todo = new Todo( trimmedText, false );
todos.push( todo );
refreshData();
}
}
function editTodo( todoId, text ) {
var i;
for ( i=0; i < todos.length; i++ ) {
if ( todos[i].id === todoId ) {
todos[i].title = text;
}
}
refreshData();
}
function removeTodoById( id ) {
var i;
for ( i=0; i < todos.length; i++ ) {
if ( todos[i].id === id ) {
todos.splice( i, 1 );
}
}
}
function removeTodosCompleted() {
var i = todos.length-1;
while ( i >= 0 ) {
if ( todos[i].completed ) {
todos.splice( i, 1 );
}
--i;
}
}
function getTodoById( id ) {
var i;
for ( i=0; i < todos.length; i++ ) {
if ( todos[i].id === id ) {
return todos[i];
}
}
}
function refreshData() {
saveTodos();
computeStats();
redrawTodosUI();
redrawStatsUI();
changeToggleAllCheckboxState();
}
function saveTodos() {
localStorage.setItem( 'todos-vanillajs', JSON.stringify( todos ) );
}
function computeStats() {
var i;
stat = new Stat();
stat.totalTodo = todos.length;
for ( i=0; i < todos.length; i++ ) {
if ( todos[i].completed ) {
stat.todoCompleted += 1;
}
}
stat.todoLeft = stat.totalTodo - stat.todoCompleted;
}
function redrawTodosUI() {
var ul,
todo,
checkbox,
label,
deleteLink,
divDisplay,
inputEditTodo,
li,
i;
ul = document.getElementById( 'todo-list' );
document.getElementById( 'main' ).style.display = todos.length ? 'block' : 'none';
ul.innerHTML = "";
document.getElementById( 'new-todo' ).value = '';
for ( i= 0; i < todos.length; i++ ) {
todo = todos[i];
//create checkbox
checkbox = document.createElement( 'input' );
checkbox.className = 'toggle';
checkbox.setAttribute( 'data-todo-id', todo.id );
checkbox.type = 'checkbox';
checkbox.addEventListener( 'change', checkboxChangeHandler );
//create div text
label = document.createElement( 'label' );
label.setAttribute( 'data-todo-id', todo.id );
label.appendChild( document.createTextNode( todo.title ) );
//create delete button
deleteLink = document.createElement( 'button' );
deleteLink.className = 'destroy';
deleteLink.setAttribute( 'data-todo-id', todo.id );
deleteLink.addEventListener( 'click', spanDeleteClickHandler );
//create divDisplay
divDisplay = document.createElement( 'div' );
divDisplay.className = 'view';
divDisplay.setAttribute( 'data-todo-id', todo.id );
divDisplay.appendChild( checkbox );
divDisplay.appendChild( label );
divDisplay.appendChild( deleteLink );
divDisplay.addEventListener( 'dblclick', todoContentHandler );
//create todo input
inputEditTodo = document.createElement( 'input' );
inputEditTodo.id = 'input_' + todo.id;
inputEditTodo.className = 'edit';
inputEditTodo.value = todo.title;
inputEditTodo.addEventListener( 'keypress', inputEditTodoKeyPressHandler );
inputEditTodo.addEventListener( 'blur', inputEditTodoBlurHandler );
//create li
li = document.createElement( 'li' );
li.id = 'li_' + todo.id;
li.appendChild( divDisplay );
li.appendChild( inputEditTodo );
if ( todo.completed )
{
li.className += 'complete';
checkbox.checked = true;
}
ul.appendChild( li );
}
}
function changeToggleAllCheckboxState() {
var toggleAll = document.getElementById( 'toggle-all' );
if ( stat.todoCompleted === todos.length ) {
toggleAll.checked = true;
} else {
toggleAll.checked = false;
}
}
function redrawStatsUI() {
removeChildren( document.getElementsByTagName( 'footer' )[ 0 ] );
document.getElementById( 'footer' ).style.display = todos.length ? 'block' : 'none';
if ( stat.todoCompleted > 0 ) {
drawTodoClear();
}
if ( stat.totalTodo > 0 ) {
drawTodoCount();
}
}
function drawTodoCount() {
var number,
theText,
remaining;
// Create remaining count
number = document.createElement( 'strong' );
number.innerHTML = stat.todoLeft;
theText = ' item';
if ( stat.todoLeft !== 1 ) {
theText += 's';
}
theText += ' left';
remaining = document.createElement( 'span' );
remaining.id = 'todo-count';
remaining.appendChild( number );
remaining.appendChild( document.createTextNode( theText ) );
document.getElementsByTagName( 'footer' )[ 0 ].appendChild( remaining );
}
function drawTodoClear() {
var buttonClear = document.createElement( 'button' );
buttonClear.id = 'clear-completed';
buttonClear.addEventListener( 'click', hrefClearClickHandler );
buttonClear.innerHTML = 'Clear completed (' + stat.todoCompleted + ')';
document.getElementsByTagName( 'footer' )[ 0 ].appendChild( buttonClear );
}
function removeChildren( node ) {
while ( node.firstChild ) {
node.removeChild( node.firstChild );
}
}
function getUuid() {
var uuid = '',
i,
random;
for ( i = 0; i < 32; i++ ) {
random = Math.random() * 16 | 0;
if ( i === 8 || i === 12 || i === 16 || i === 20 ) {
uuid += '-';
}
uuid += ( i === 12 ? 4 : (i === 16 ? (random & 3 | 8) : random) ).toString( 16 );
}
return uuid;
}
/* json2.js
* 2008-01-17
* Public Domain
* No warranty expressed or implied. Use at your own risk.
* See http://www.JSON.org/js.html
*/
if(!this.JSON){JSON=function(){function f(n){return n<10?'0'+n:n;}
Date.prototype.toJSON=function(){return this.getUTCFullYear()+'-'+
f(this.getUTCMonth()+1)+'-'+
f(this.getUTCDate())+'T'+
f(this.getUTCHours())+':'+
f(this.getUTCMinutes())+':'+
f(this.getUTCSeconds())+'Z';};var m={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'};function stringify(value,whitelist){var a,i,k,l,r=/["\\\x00-\x1f\x7f-\x9f]/g,v;switch(typeof value){case'string':return r.test(value)?'"'+value.replace(r,function(a){var c=m[a];if(c){return c;}
c=a.charCodeAt();return'\\u00'+Math.floor(c/16).toString(16)+
(c%16).toString(16);})+'"':'"'+value+'"';case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null';}
if(typeof value.toJSON==='function'){return stringify(value.toJSON());}
a=[];if(typeof value.length==='number'&&!(value.propertyIsEnumerable('length'))){l=value.length;for(i=0;i<l;i+=1){a.push(stringify(value[i],whitelist)||'null');}
return'['+a.join(',')+']';}
if(whitelist){l=whitelist.length;for(i=0;i<l;i+=1){k=whitelist[i];if(typeof k==='string'){v=stringify(value[k],whitelist);if(v){a.push(stringify(k)+':'+v);}}}}else{for(k in value){if(typeof k==='string'){v=stringify(value[k],whitelist);if(v){a.push(stringify(k)+':'+v);}}}}
return'{'+a.join(',')+'}';}}
return{stringify:stringify,parse:function(text,filter){var j;function walk(k,v){var i,n;if(v&&typeof v==='object'){for(i in v){if(Object.prototype.hasOwnProperty.apply(v,[i])){n=walk(i,v[i]);if(n!==undefined){v[i]=n;}}}}
return filter(k,v);}
if(/^[\],:{}\s]*$/.test(text.replace(/\\./g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){j=eval('('+text+')');return typeof filter==='function'?walk('',j):j;}
throw new SyntaxError('parseJSON');}};}();}
\ No newline at end of file
var tasks = [];
var stat;
/**************************/
/* MODEL /
/**************************/
function Todo(name, done) {
this.id = uuid();
this.name = name;
this.done = done;
}
function Stat() {
this.todoLeft = 0;
this.todoCompleted = 0;
this.totalTodo = 0;
}
/**************************/
/* EVENT HANDLERS /
/**************************/
function bodyLoadHandler() {
loadTasks();
refreshData();
}
function inputEditTodoKeyPressHandler(event) {
var inputEditTodo = event.target;
var taskId = event.target.id.slice(6);
if (event.keyCode === 13) {
editTask(taskId, inputEditTodo.value);
}
}
function newTodoKeyPressHandler(event) {
if (event.keyCode === 13) {
addTask(document.getElementById("new-todo").value);
}
}
function spanDeleteClickHandler(event) {
removeTaskById(event.target.id);
refreshData();
}
function hrefClearClickHandler() {
removeTasksDone();
refreshData();
}
function todoContentHandler(event) {
var taskId = event.target.id;
var div = document.getElementById("li_"+taskId);
div.className = "editing";
var inputEditTodo = document.getElementById("input_"+taskId);
inputEditTodo.focus();
}
function checkboxChangeHandler(event) {
var checkbox = event.target;
var todo = getTodoById(checkbox.id);
todo.done = checkbox.checked;
refreshData();
}
/**************************/
/* ACTIONS /
/**************************/
function loadTasks() {
if (!localStorage.todo) {
localStorage.todo = JSON.stringify([]);
}
tasks = JSON.parse(localStorage['todo']);
}
function addTask(text) {
var todo = new Todo(text, false);
tasks.push(todo);
refreshData();
}
function editTask(taskId, text) {
for (var i=0; i < tasks.length; i++) {
if (tasks[i].id === taskId) {
tasks[i].name = text;
}
}
refreshData();
}
function removeTaskById(id) {
for (var i=0; i < tasks.length; i++) {
if (tasks[i].id === id) {
tasks.splice(i, 1);
}
}
}
function removeTasksDone() {
for (var i=tasks.length-1; i >= 0; --i) {
if (tasks[i].done) {
tasks.splice(i, 1);
}
}
}
function getTodoById(id) {
for (var i=0; i < tasks.length; i++) {
if (tasks[i].id === id) {
return tasks[i];
}
}
}
function refreshData() {
saveTasks();
computeStats();
redrawTasksUI();
redrawStatsUI();
}
function saveTasks() {
localStorage['todo'] = JSON.stringify(tasks);
}
function computeStats() {
stat = new Stat();
stat.totalTodo = tasks.length;
for (var i=0; i < tasks.length; i++) {
if (tasks[i].done) {
stat.todoCompleted += 1;
}
}
stat.todoLeft = stat.totalTodo - stat.todoCompleted;
}
/**************************/
/* DRAWING /
/**************************/
function redrawTasksUI() {
var ul = document.getElementById("todo-list");
var todo;
removeChildren(ul);
document.getElementById("new-todo").value = "";
for (var i= 0; i < tasks.length; i++) {
todo = tasks[i];
//create checkbox
var checkbox = document.createElement("input");
checkbox.className = "check";
checkbox.id = todo.id;
checkbox.type = "checkbox";
checkbox.addEventListener("change", checkboxChangeHandler);
//create div text
var divText = document.createElement("div");
divText.className = "todo-content";
divText.id = todo.id;
divText.appendChild(document.createTextNode(todo.name));
divText.addEventListener("dblclick", todoContentHandler);
//create delete button
var spanDelete = document.createElement("span");
spanDelete.className = "todo-destroy";
spanDelete.id = todo.id;
spanDelete.addEventListener("click", spanDeleteClickHandler);
//create divDisplay
var divDisplay = document.createElement("div");
divDisplay.className = "display";
divDisplay.appendChild(checkbox);
divDisplay.appendChild(divText);
divDisplay.appendChild(spanDelete);
//create div todo
var divTodo = document.createElement("div");
divTodo.className = "todo ";
divTodo.appendChild(divDisplay);
//create todo input
var inputEditTodo = document.createElement("input");
inputEditTodo.id = "input_" + todo.id;
inputEditTodo.type = "text";
inputEditTodo.className = "todo-input";
inputEditTodo.value = todo.name;
inputEditTodo.addEventListener("keypress", inputEditTodoKeyPressHandler);
//create div edit
var divEdit = document.createElement("div");
divEdit.className = "edit";
divEdit.appendChild(inputEditTodo);
//create li
var li = document.createElement("li");
li.id = "li_" + todo.id;
li.appendChild(divTodo);
li.appendChild(divEdit);
if (todo.done)
{
divTodo.className += "done";
checkbox.checked = true;
}
ul.appendChild(li);
}
}
function redrawStatsUI() {
removeChildren(document.getElementById("todo-stats"))
if (stat.totalTodo > 0) {
drawTodoCount();
}
if (stat.todoCompleted > 0) {
drawTodoClear();
}
}
function drawTodoCount() {
//create span number
var spanNumber = document.createElement("span");
spanNumber.className = "number";
spanNumber.innerHTML = stat.todoLeft;
//create span word
var spanWord = document.createElement("span");
spanWord.className = "word";
spanWord.innerHTML = " item";
if (stat.todoLeft > 1) {
spanWord.innerHTML += "s";
}
var spanTodoCount = document.createElement("span");
spanTodoCount.className = "todo-count";
spanTodoCount.appendChild(spanNumber);
spanTodoCount.appendChild(spanWord);
spanTodoCount.innerHTML += " left.";
document.getElementById("todo-stats").appendChild(spanTodoCount);
}
function drawTodoClear() {
//create a href
var hrefClear = document.createElement("a");
hrefClear.href = "#";
hrefClear.addEventListener("click", hrefClearClickHandler);
hrefClear.innerHTML = "Clear ";
//create span number done
var spanNumberDone = document.createElement("span");
spanNumberDone.className = "number-done";
spanNumberDone.innerHTML = stat.todoCompleted;
hrefClear.appendChild(spanNumberDone);
hrefClear.innerHTML += " completed ";
//create span word
var spanWordDone = document.createElement("span");
spanWordDone.className = "word-done";
spanWordDone.innerHTML = " item";
if (stat.todoCompleted > 1) {
spanWordDone.innerHTML += "s";
}
hrefClear.appendChild(spanWordDone);
var spanTodoClear = document.createElement("span");
spanTodoClear.className = "todo-clear";
spanTodoClear.appendChild(hrefClear);
document.getElementById("todo-stats").appendChild(spanTodoClear);
}
function removeChildren(node) {
while (node.hasChildNodes()) {
node.removeChild(node.firstChild);
}
}
/**************************/
/* UTILS /
/**************************/
function uuid() {
var uuid = "", i, random;
for (i = 0; i < 32; i++) {
random = Math.random() * 16 | 0;
if (i == 8 || i == 12 || i == 16 || i == 20) {
uuid += "-"
}
uuid += (i == 12 ? 4 : (i == 16 ? (random & 3 | 8) : random)).toString(16);
}
return uuid;
}
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment