Skip to content

Instantly share code, notes, and snippets.

@zaru
Last active May 9, 2020 12:50
Show Gist options
  • Save zaru/2d7b3c456ac5475eb92ff687b4415cd1 to your computer and use it in GitHub Desktop.
Save zaru/2d7b3c456ac5475eb92ff687b4415cd1 to your computer and use it in GitHub Desktop.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style type="text/css">
.todo-done {
text-decoration: line-through;
}
</style>
</head>
<body>
<ul id="todo-list"></ul>
<template id="todo-template">
<li><span></span><button>done</button></li>
</template>
<input type="text" name="new-todo"><button id="add-todo">add</button>
<script>
function done(node) {
// 打ち消し線の CSS を適用して完了したように見せる
const parent = node.target.closest('li');
parent.classList.add('todo-done');
// 完了済みにデータを更新する
const id = parent.id.replace('todo-', '');
updateById(id, { done: true });
}
function add() {
// 入力フォームから、入力したテキストを取得
const input = document.querySelector('input[name="new-todo"]');
const text = input.value;
// 入力フォームのテキストはもう必要ないので空にする
input.value = '';
// ToDo のデータを作成する
const data = build(text);
// ToDo を表示する
show(data);
// LocalStorage に保存する
save(data);
}
function show(data) {
// テンプレートを読み込む
const template = document.querySelector('#todo-template');
const todoList = document.querySelector('#todo-list');
// テンプレートから、新しい ToDo を作成する(テキスト設定と done ボタンのイベント設定)
const clone = document.importNode(template.content, true);
clone.querySelector('li').id = `todo-${data.id}`;
clone.querySelector('span').textContent = data.todo;
clone.querySelector('button').addEventListener('click', done);
// もし完了の場合は、完了スタイルのクラスを追加する
if (data.done) {
clone.querySelector('li').classList.add('todo-done');
}
// 実際に表示させる
todoList.appendChild(clone);
}
// ToDo のデータを生成する
function build(text) {
const todo = getAllTodoList();
return {
id: getLatestID(todo),
todo: text,
done: false
}
}
// 最新の ID を取得する
function getLatestID(data) {
if (data.length > 0) {
return Math.max(...data.map(v => v.id)) + 1;
}
return 1;
}
// 渡された ToDo のデータを保存する
function save(data) {
const todoList = getAllTodoList();
todoList.push(data);
localStorage.setItem('todo', JSON.stringify(todoList));
}
// 指定された ID の ToDo のデータを更新する
function updateById(id, data) {
const todoList = getAllTodoList();
const index = todoList.findIndex(v => v.id === parseInt(id));
if (index) {
for (let [key, value] of Object.entries(data)) {
todoList[index][key] = value;
}
//TODO: 例外処理
localStorage.setItem('todo', JSON.stringify(todoList));
}
}
// 保存されている全ての ToDo を取得する
function getAllTodoList() {
const todoList = localStorage.getItem('todo');
//TODO: 例外処理
return todoList ? JSON.parse(todoList) : [];
}
// 全ての ToDo を表示する
function showAllTodoList() {
const todoList = getAllTodoList();
todoList.forEach(data => show(data));
}
// add ボタンのイベント設定
const addTodoButton = document.getElementById('add-todo');
addTodoButton.addEventListener('click', add);
showAllTodoList();
</script>
</body>
</html>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style type="text/css">
.todo-done {
text-decoration: line-through;
}
</style>
</head>
<body>
<ul id="todo"></ul>
<template id="todo-template">
<li><span></span><button>done</button></li>
</template>
<input type="text" name="new-todo"><button id="add-todo">add</button>
<script>
function done(node) {
// 打ち消し線の CSS を適用して完了したように見せる
node.target.closest('li').classList.add('todo-done');
}
function add() {
// 入力フォームから、入力したテキストを取得
const input = document.querySelector('input[name="new-todo"]');
const text = input.value;
// 入力フォームのテキストはもう必要ないので空にする
input.value = '';
// テンプレートを読み込む
const template = document.querySelector('#todo-template');
const todo = document.querySelector('#todo');
// テンプレートから、新しい ToDo を作成する(テキスト設定と done ボタンのイベント設定)
const clone = document.importNode(template.content, true);
clone.querySelector('span').textContent = text;
clone.querySelector('button').addEventListener('click', done);
// 実際に表示させる
todo.appendChild(clone);
}
// add ボタンのイベント設定
const addTodoButton = document.getElementById('add-todo');
addTodoButton.addEventListener('click', add);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment