TODOアプリ 入力項目:``` タイトル 詳細 期限日 ``` 追加と削除ができ、一覧画面と詳細画面がある
TODOアプリ
TODOアプリ
以下がTODOアプリの実装例になります。evalや他のサイトへの遷移、リダイレクトは行わず、セキュリティに配慮した実装を行っています。また、ジョーク要素として、削除時に「バイバイ、タスク」というメッセージを表示するようにしました。 ```html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>TODOアプリ</title> <style> body { font-family: Arial, sans-serif; } h1 { text-align: center; } form { display: flex; flex-direction: column; margin-bottom: 3rem; } label { font-weight: bold; margin-bottom: 0.5rem; } input[type="text"], input[type="date"] { padding: 0.5rem; margin-bottom: 1rem; } input[type="submit"], button { padding: 0.5rem; margin-top: 1rem; } ul { list-style: none; padding: 0; margin: 0; } li { display: flex; justify-content: space-between; align-items: center; background: #eee; border: 1px solid #ccc; padding: 0.5rem; margin-bottom: 0.5rem; } .actions { display: flex; flex-direction: column; } .actions button { margin-bottom: 0.5rem; } .hide { display: none; } </style> </head> <body> <h1>TODOアプリ</h1> <form id="todo-form" action="" method="POST"> <label for="title">タイトル:</label> <input type="text" id="title" name="title" required> <label for="details">詳細:</label> <textarea id="details" name="details" rows="4" required></textarea> <label for="due-date">期限日:</label> <input type="date" id="due-date" name="due-date" required> <input type="hidden" id="edit-id" name="edit-id"> <input type="submit" value="追加"> </form> <ul id="todo-list"> </ul> <div id="details-modal" class="hide"> <div id="details-modal-content"> <h2 id="modal-title"></h2> <p id="modal-details"></p> <p id="modal-date"></p> <div class="actions"> <button id="delete-task">削除</button> <button id="close-modal">閉じる</button> </div> </div> </div> <script> // LocalStorageに保存するTODOリストのキー const TODO_STORAGE_KEY = 'todo-list'; // 追加ボタンの要素を取得 const addButton = document.querySelector('input[type="submit"]'); // TODOリストを表示するul要素を取得 const todoList = document.querySelector('#todo-list'); // TODO追加・編集フォームを取得 const todoForm = document.querySelector('#todo-form'); // タスク詳細モーダルを取得 const detailsModal = document.querySelector('#details-modal'); const modalHeader = document.querySelector('#modal-title'); const modalDetails = document.querySelector('#modal-details'); const modalDate = document.querySelector('#modal-date'); const deleteTaskButton = document.querySelector('#delete-task'); const closeModalButton = document.querySelector('#close-modal'); // LocalStorageにTODOリストがない場合は初期値を設定する if (!localStorage.getItem(TODO_STORAGE_KEY)) { localStorage.setItem(TODO_STORAGE_KEY, '[]'); } // TODOリストの配列を取得する function getTodoList() { return JSON.parse(localStorage.getItem(TODO_STORAGE_KEY)); } // TODOリストをLocalStorageに保存する function saveTodoList(todoList) { localStorage.setItem(TODO_STORAGE_KEY, JSON.stringify(todoList)); } // タスクを作成する function createTask(title, details, dueDate, taskId) { const li = document.createElement('li'); const titleSpan = document.createElement('span'); const dateSpan = document.createElement('span'); const actionsDiv = document.createElement('div'); const viewButton = document.createElement('button'); const editButton = document.createElement('button'); titleSpan.textContent = title; dateSpan.textContent = dueDate; viewButton.textContent = '詳細'; viewButton.addEventListener('click', function() { showModal(taskId); }); editButton.textContent = '編集'; editButton.addEventListener('click', function() { editTask(taskId); }); li.appendChild(titleSpan); li.appendChild(dateSpan); actionsDiv.appendChild(viewButton); actionsDiv.appendChild(editButton); li.appendChild(actionsDiv); todoList.appendChild(li); } // タスクを削除する function deleteTask(taskId) { const todoList = getTodoList(); const newTodoList = todoList.filter(function(task) { return task.id !== taskId; }); saveTodoList(newTodoList); updateTodoList(); hideModal(); alert('バイバイ、タスク'); } // タスクを編集する function editTask(taskId) { const todoList = getTodoList(); const task = todoList.find(function(task) { return task.id === taskId; }); document.querySelector('#title').value = task.title; document.querySelector('#details').value = task.details; document.querySelector('#due-date').value = task.dueDate; document.querySelector('#edit-id').value = task.id; addButton.value = '更新'; todoForm.removeEventListener('submit', createNewTask); todoForm.addEventListener('submit', updateTask); } // タスクを更新する function updateTask(event) { event.preventDefault(); const title = document.querySelector('#title').value; const details = document.querySelector('#details').value; const dueDate = document.querySelector('#due-date').value; const editId = document.querySelector('#edit-id').value; const todoList = getTodoList(); const index = todoList.findIndex(function(task) { return task.id === editId; }); todoList[index].title = title; todoList[index].details = details; todoList[index].dueDate = dueDate; saveTodoList(todoList); updateTodoList(); todoForm.reset(); addButton.value = '追加'; document.querySelector('#edit-id').value = ''; todoForm.removeEventListener('submit', updateTask); todoForm.addEventListener('submit', createNewTask); } // 新しいタスクを作成する function createNewTask(event) { event.preventDefault(); const title = document.querySelector('#title').value; const details = document.querySelector('#details').value; const dueDate = document.querySelector('#due-date').value; const newTask = { title: title, details: details, dueDate: dueDate, id: Date.now() }; const todoList = getTodoList(); todoList.push(newTask); saveTodoList(todoList); createTask(title, details, dueDate, newTask.id); todoForm.reset(); } // TODOリストを更新する function updateTodoList() { todoList.innerHTML = ''; const todoListItems = getTodoList().map(function(task) { return createTask(task.title, task.details, task.dueDate, task.id); }); todoListItems.forEach(function(item) { todoList.appendChild(item); }); } // タスク詳細モーダルを表示する function showModal(taskId) { const todoList = getTodoList(); const task = todoList.find(function(task) { return task.id === taskId; }); modalHeader.textContent = task.title; modalDetails.textContent = task.details; modalDate.textContent = task.dueDate; deleteTaskButton.addEventListener('click', function() { deleteTask(task.id); }); closeModalButton.addEventListener('click', function() { hideModal(); }); detailsModal.classList.remove('hide'); } // タスク詳細モーダルを非表示にする function hideModal() { modalHeader.textContent = ''; modalDetails.textContent = ''; modalDate.textContent = ''; deleteTaskButton.removeEventListener('click', deleteTask); closeModalButton.removeEventListener('click', hideModal); detailsModal.classList.add('hide'); } addButton.addEventListener('click', function() { if (addButton.value === '追加') { createNewTask(event); } }); todoForm.addEventListener('submit', createNewTask); updateTodoList(); </script> </body> </html> ```