console
const todoFormEl = document.querySelector("#todo-form");
const todoInputEl = document.querySelector("#todo-input");
const todoListEl = document.querySelector("#todo-list");
function buildUniqueId(prefix = "prefix") {
return prefix + "-" + Math.floor(Math.random() * Date.now());
}
function createTask(name) {
return {
name,
id: buildUniqueId("todo")
};
}
const state = {
taskName: "",
tasks: [
{
id: "todo-0",
name: "Learn some frameworks!"
}
]
};
function init() {
todoInputEl.addEventListener("change", handleInputChange);
todoFormEl.addEventListener("submit", handleFormSubmit);
renderInput();
renderTodoList();
}
function renderInput() {
todoInputEl.value = state.taskName;
}
function renderTodoList() {
const frag = document.createDocumentFragment();
state.tasks.forEach((task) => {
const item = buildTodoItemEl(task.id, task.name);
frag.appendChild(item);
});
while (todoListEl.lastChild) {
todoListEl.removeChild(todoListEl.lastChild);
}
todoListEl.appendChild(frag);
}
function buildTodoItemEl(id, name) {
const item = document.createElement("li");
const span = document.createElement("span");
const textContent = document.createTextNode(name);
span.appendChild(textContent);
item.id = id;
item.appendChild(span);
item.appendChild(buildDeleteButtonEl(id));
return item;
}
function buildDeleteButtonEl(id) {
const button = document.createElement("button");
const textContent = document.createTextNode("Delete");
button.setAttribute("type", "button");
button.addEventListener("click", handleTodoDeleteButtonClick.bind(null, id));
button.appendChild(textContent);
return button;
}
function handleInputChange(e) {
state.taskName = e.target.value;
}
function handleFormSubmit(e) {
e.preventDefault();
state.tasks = [...state.tasks, createTask(state.taskName)];
state.taskName = "";
renderInput();
renderTodoList();
}
function handleTodoDeleteButtonClick(id) {
state.tasks = state.tasks.filter((t) => t.id !== id);
renderTodoList();
}
document.addEventListener("DOMContentLoaded", init);
<h1>TodoMatic</h1>
<form id="todo-form">
<label for="todo-input">
What needs to be done?
</label>
<input type="text" id="todo-input" name="mozTodoDemoItemName" autocomplete="on" />
<button type="submit">
Add
</button>
</form>
<ul id="todo-list"></ul>
<ul>
<li v-for="task in tasks" v-bind:key="task.id">
<span>{{task.name}}</span>
<button type="button">Delete</button>
</li>
</ul>
*,
*::before,
*::after {
box-sizing: border-box;
}
* + * {
margin-top: 0.4rem;
}
::-moz-focus-inner {
border-style: none;
padding: 0;
}
:focus {
outline: 3px solid hsl(215, 100%, 34%);
outline-offset: .2rem;
}
html {
font-size: 62.5%;
}
body {
font-size: 2rem;
line-height: 1.25;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
color: hsl(0, 0, 13%);
width: 95%;
max-width: 30em;
padding-bottom: 2em;
margin: 0 auto;
}
button,
input[type="text"] {
font-size: 100%;
line-height: 1.15;
font-family: inherit;
margin: 0;
padding: 0.5rem;
border: 1px solid #707070;
border-radius: 2px;
}
* + button {
margin-left: 0.4rem;
}
label {
display: table;
}
ul {
margin-top: 1.6rem;
padding-left: 2em;
}
label + input[type="text"] {
margin-top: 0.4rem;
}