litespeed.js
Version:
Lite & fast micro javascript framework that is easy to learn
265 lines (238 loc) • 12.1 kB
HTML
<html>
<head>
<meta charset="utf-8">
<title>Litespeed.js</title>
<link rel="icon" type="image/png" href="/favicon.png">
<meta name="description" content="Sample Litespeed.js application">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5" />
<link href="https://cdn.jsdelivr.net/npm/todomvc-app-css@2.2.0/index.css" rel="stylesheet" />
</head>
<body>
<section class="todoapp" data-ls-router>
<header class="header">
<h1>todos</h1>
<form data-tasks-add>
<input name="task" type="text" autocomplete="off" required class="new-todo" placeholder="What needs to be done?" autofocus>
</form>
</header>
<section class="main" data-ls-if="0 < {{tasks.list.length}}">
<input id="toggle-all" class="toggle-all" type="checkbox" data-tasks-complete-all>
<label for="toggle-all">Mark all as complete</label>
<ul class="todo-list" data-ls-loop="tasks.list" data-ls-as="task">
<li data-ls-attrs="class={{task.completed|completed}}" data-tasks-edit="{{task.id}}" data-ls-if="true == {{task.completed|show}} && {{tasks.filter}}">
<div class="view">
<input class="toggle" type="checkbox" data-ls-bind="{{task.completed}}">
<label data-ls-bind="{{task.title}}"></label>
<button type="button" class="destroy" data-tasks-remove="{{task.id}}"></button>
</div>
<input name="edit" class="edit" data-ls-bind="{{task.title}}" title="">
</li>
</ul>
</section>
<footer class="footer">
<span class="todo-count"><strong data-ls-bind="{{tasks.remaining|pluralize}}"></strong></span>
<ul class="filters">
<li>
<a href="" data-tasks-selected="">All</a>
</li>
<li>
<a href="#active" data-tasks-selected="#active">Active</a>
</li>
<li>
<a href="#completed" data-tasks-selected="#completed">Completed</a>
</li>
</ul>
<button data-ls-if="0 < ({{tasks.list.length}} - {{tasks.remaining}})" class="clear-completed" data-tasks-clear-completed>Clear completed</button>
</footer>
</section>
<footer class="info">
<p>Double-click to edit a todo</p>
<p>Created by <a href="https://twitter.com/eldadfux">Eldad Fux</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer>
<script>
(function (window) {
"use strict";
document.addEventListener("DOMContentLoaded", function() {
let head = document.getElementsByTagName('head')[0];
let script = document.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.src = 'scripts/litespeed.js';
script.onload = function() {
let ENTER_KEY = 'Enter', STORAGE_KEY = 'todos-litespeed-0.2';
window.ls.router
.add('/', { // Default
controller: function (tasks) {
tasks.showAll();
}
})
.add('#completed', {
controller: function (tasks) {
tasks.showCompleted();
}
})
.add('#active', {
controller: function (tasks) {
tasks.showActive();
}
})
;
window.ls.container
.set('tasks', function () {
let data = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]');
return {
title: 'TODO App',
filter: 'all',
list: data,
remaining: 0,
add: function (task) {
task.id = this.list.length + Math.random().toString();
this.list.push(task);
},
remove: function (key) {
for(let i = 0; i < this.list.length; i++) {
if (this.list[i].id === key) {
return this.list.splice(i, 1);
}
}
},
toggle: function (value) {
let list = [];
this.list.forEach(function(task) {
let node = Object.assign({}, task);
node.completed = value;
list.push(node);
});
this.list = list;
list = null;
},
showAll: function () {
this.filter = 'all';
},
showCompleted: function () {
this.filter = 'completed';
},
showActive: function () {
this.filter = 'active';
},
clearCompleted: function () {
this.list = this.list.filter(function (task) {
return !task.completed;
})
}
}
}, true)
;
window.ls.container.get('tasks').__watch = function(tasks) {
localStorage.setItem(STORAGE_KEY, JSON.stringify(tasks.list));
tasks.filter = tasks.filter + '';
tasks.remaining = tasks.list.filter(function (task) {return (!task.completed)}).length;
};
window.ls.filter
.add('show', function ($value, tasks) {
$value = ($value === true || $value === 'true');
switch (tasks.filter) {
case 'completed':
return $value;
case 'active':
return !$value;
}
return true;
})
.add('completed', function ($value) {
return ($value) ? 'completed' : '';
})
.add('pluralize', function ($value) {
return $value + ' ' + (('1' === $value) ? 'item' : 'items') + ' left';
})
;
window.ls.view
.add({
selector: 'data-tasks-add',
controller: function(element, tasks) {
element.addEventListener('submit', function (event) {
event.preventDefault();
tasks.add({completed: false, title: element.task.value});
element.reset();
});
}
})
.add({
selector: 'data-tasks-remove',
controller: function(element, tasks, expression) {
let id = expression.parse(element.dataset['tasksRemove']);
element.addEventListener('click', function () {
tasks.remove(id);
});
}
})
.add({
selector: 'data-tasks-complete-all',
controller: function(element, tasks) {
element.addEventListener('click', function () {
tasks.toggle(element.checked);
});
}
})
.add({
selector: 'data-tasks-clear-completed',
controller: function(element, tasks) {
element.addEventListener('click', function () {
tasks.clearCompleted();
});
}
})
.add({
selector: 'data-tasks-edit',
controller: function(element, tasks, expression) {
let id = expression.parse(element.dataset['tasksEdit']);
let input = element.getElementsByClassName('edit')[0];
element.addEventListener('dblclick', function () {
if(element.classList.contains('editing')) {
element.classList.remove('editing');
}
else {
element.classList.add('editing');
input.focus();
}
});
input.addEventListener('blur', function () {
element.classList.remove('editing');
});
input.addEventListener('keydown', function (e) {
if (e.code === ENTER_KEY) {
element.classList.remove('editing');
}
if(input.value === '') {
tasks.remove(id);
}
});
}
})
.add({
selector: 'data-tasks-selected',
controller: function(element, router) {
let filter = element.dataset['tasksSelected'] || '';
let check = function () {
if(filter === router.hash) {
element.classList.add('selected');
}
else {
element.classList.remove('selected');
}
};
document.addEventListener('state-changed', check);
check();
}
})
;
window.ls.run(window);
};
head.appendChild(script);
});
}(window));
</script>
</body>
</html>