Here is the official demo of TodoList. You can run it live here :
TodoList.
Try it on your phone, and see how fast it is.
Features : multilines fields and localstorage.
<html lang="de"> <head> <meta charset="utf-8"> <title>title</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="https://efpage.de/DML/DML_homepage/lib/DML-min.js"></script> </head> <body> <script> let todos = []; // List of todos const _w = "width: 100%; max-width: 450px;" const _ba = _top+"min-height: 22px; width: 100%; border: none; resize: none; background-color: rgba(0,0,0,0); font-size: 20px; font-family: sans-serif;" /*------------------------------------------------------ count active todos ------------------------------------------------------*/ function countTodos() { let _active = 0; todos.forEach(function (todo) {if (!todo.cb.checked) _active++;}) activecount.textContent = "Active: " + _active; count.textContent = "Total: " + todos.length } /*------------------------------------------------------ save data ------------------------------------------------------*/ function saveData() { localStorage.setItem("todocount", todos.length) todos.forEach(function (todo, i) { localStorage.setItem("todo" + i, todo.ta.value) localStorage.setItem("state" + i, todo.cb.checked) }) countTodos() } /*------------------------------------------------------ read old data ------------------------------------------------------*/ function readData(area) { let n = localStorage.getItem("todocount"); for (let i = 0; i < n; i++) { let content = localStorage.getItem("todo" + i); if (content) if (content.trim() != "") { let todo = new todoObj(area, content); todo.cb.checked = (localStorage.getItem("state" + i) != "false") todo.ta.style.height = todo.ta.scrollHeight + "px"; todo.setState(); } } countTodos() } /*------------------------------------------------------ Make new todo Element and clear input get workarea and textarea with content (will be cleared) ------------------------------------------------------*/ function mknew(workarea, ta) { if (ta.value != "") { new todoObj(workarea, ta.value); ta.value = ''; ta.autosize() } saveData() countTodos() } /**************************************************************************************** Class "todo" creates a new todo in area ****************************************************************************************/ class todoObj { constructor(area, content) { todos.push(this); // Add Element to todo array selectBase(area); // start inside area // Create a todo box this.todo = selectBase(div("", "display: flex; position: relative; border-top: solid; border-width: 1px; ")) this.cb = checkbox("", "flex: 0 0 30px;align-self: center;"); this.ta = expandableTextarea(content, _ba); // Create input area // Invisible Delete-Button to remove element this.bt = button("x", "height: 28px; opacity: 0.0; transition: opacity 0.5s; " + " position: absolute; right: 10px; " + _top + _shadow); this.bt.onclick = this.delete.bind(this) // Set event functions this.ta.addEventListener("blur", saveData); // Save data on exit this.cb.onclick = () => { this.setState(); saveData(); } // Save data on state change this.todo.onmouseenter = () => { this.bt.style.opacity = 1 } this.todo.onmouseleave = () => { this.bt.style.opacity = 0 } // run once to show state this.setState(); unselectBase(2) } // Class funcitons: /*------------------------------------------------------ set state color of the input area ------------------------------------------------------*/ setState() { this.ta.style.backgroundColor = (this.cb.checked ? "#f0f0e0" : "#ffe"); this.ta.style.textDecoration = (this.cb.checked ? "line-through" : "none"); } /*------------------------------------------------------ Delete todo Object ------------------------------------------------------*/ delete() { todos = todos.filter(todo => todo != this) // Delete this element from list this.todo.remove(); delete (this) saveData(); } } // end todo class /**************************************************************************************** Create page content ****************************************************************************************/ div(h1("todos", "Text-align: center; text-shadow: 2px 2px 4px #444;" + _red), _w); selectBase(div("", _w + " background-color: #ffe; " + _border + _radius + _bigPadding + _shadow)); // Top Input field let ta = expandableTextarea("", { "placeholder": "What to do ?", "style":_ba}) // Area for Todos let workarea = div(); // footer hr("margin: 3px auto;") selectBase(div("", "display: flex; justify-content: space-between; font-size: 80%;")) let count = span("count"); let activecount = span("activecount"); unselectBase(2) /**************************************************************************************** Events to create new todos ****************************************************************************************/ // Create new Todos on Return or exit ta.onkeypress = (event) => { if (event.which == 13) { event.preventDefault(); // Remove CR from input mknew(workarea, ta) } } ta.onblur = () => { mknew(workarea, ta) } readData(workarea) /**************************************************************************************** save Data before unload ****************************************************************************************/ window.onbeforeunload = saveData; </script> </body> </html>
Top comments (0)