UNPKG

litespeed.js

Version:

Lite & fast micro javascript framework that is easy to learn

265 lines (238 loc) 12.1 kB
<!DOCTYPE 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>