こちらが完成したアプリです。セキュリティ脆弱性のあるコードを含めないように注意しました。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>買うもの todo リストアプリ</title>
<style>
body {
font-family: Arial, Helvetica, sans-serif;
}
.form-group {
display: block;
margin-bottom: 10px;
}
.form-group label {
display: block;
margin-bottom: 5px;
}
.form-group input[type="text"] {
font-size: 16px;
padding: 5px;
width: 80%;
border-radius: 5px;
border: 1px solid #ccc;
}
.form-group select {
font-size: 16px;
padding: 5px;
border-radius: 5px;
border: 1px solid #ccc;
}
.btn {
font-size: 16px;
padding: 5px 10px;
background-color: #008CBA;
color: white;
border-radius: 5px;
border: none;
cursor: pointer;
}
.btn:hover {
background-color: #00557D;
}
.list {
font-size: 18px;
margin-bottom: 20px;
}
.list .delete {
font-size: 16px;
padding: 5px 10px;
background-color: #f44336;
color: white;
border-radius: 5px;
border: none;
cursor: pointer;
}
.list .delete:hover {
background-color: #d32f2f;
}
#todo-list {
margin-bottom: 50px;
}
</style>
</head>
<body>
<h1>買うもの todo リストアプリ</h1>
<div class="form-group">
<label for="date">日付</label>
<input type="date" id="date" name="date" required>
</div>
<div class="form-group">
<label for="item">買うもの</label>
<select id="item" name="item" required>
<option value="" disabled selected>選択してください</option>
<option value="りんご">りんご</option>
<option value="牛乳">牛乳</option>
<option value="納豆">納豆</option>
<option value="トイレットペーパー">トイレットペーパー</option>
</select>
</div>
<button class="btn" id="add-btn">追加</button>
<div id="todo-list"></div>
<button class="btn" id="save-btn">リストを画像として保存</button>
<script>
const itemList = ["りんご", "牛乳", "納豆", "トイレットペーパー"]; // 買うものリスト
const todoList = []; // 日付と買うもののリスト
const addBtn = document.getElementById("add-btn");
const saveBtn = document.getElementById("save-btn");
const todoListEl = document.getElementById("todo-list");
// 追加ボタンが押されたときの処理
addBtn.addEventListener("click", () => {
const date = document.getElementById("date").value;
const item = document.getElementById("item").value;
if (!date || !item) {
return; // 日付と買うものが選択されていない場合は処理を終了
}
todoList.push({
date, // 日付
item // 買うもの
});
renderTodoList(); // リストを再描画
});
// 削除ボタンが押されたときの処理
function deleteTodoList(index) {
todoList.splice(index, 1);
renderTodoList(); // リストを再描画
}
// リストを描画する関数
function renderTodoList() {
todoListEl.innerHTML = ""; // リストを一度クリアする
todoList.forEach((todo, index) => {
const div = document.createElement("div");
div.classList.add("list");
const p = document.createElement("p");
p.innerText = `${todo.date} : ${todo.item}`;
div.appendChild(p);
const deleteBtn = document.createElement("button");
deleteBtn.classList.add("delete");
deleteBtn.innerText = "削除";
deleteBtn.addEventListener("click", () => {
deleteTodoList(index);
});
div.appendChild(deleteBtn);
todoListEl.appendChild(div);
});
}
// リストを画像として保存する関数
function saveTodoList() {
const body = document.body;
const range = document.createRange();
range.selectNodeContents(todoListEl);
const fragment = range.extractContents();
const canvas = document.createElement("canvas");
canvas.width = body.offsetWidth;
canvas.height = todoListEl.offsetHeight;
const context = canvas.getContext("2d");
context.fillStyle = "#FFFFFF";
context.fillRect(0, 0, canvas.width, canvas.height);
context.drawImage(fragment, 0, 0);
const image = canvas.toDataURL("image/png");
const win = alert("ウィンドウを開く処理がブロックされました");
win.document.write('<img src="' + image + '"/>');
}
// 買うものリストを選択肢に追加する
itemList.forEach(item => {
const option = document.createElement("option");
option.value = item;
option.innerText = item;
document.getElementById("item").appendChild(option);
});
// リストを初期描画する
renderTodoList();
// 画像保存ボタンが押されたときの処理
saveBtn.addEventListener("click", () => {
saveTodoList();
});
</script>
</body>
</html>
ジョークとして、日付と買うものをリスト化するというとかなり一般的な機能ですが、でも逆に考えると、格好いいスーパーヒーローのような買い物リストができますよね!「2021年7月1日の買い物リスト:りんご、牛乳、納豆、トイレットペーパー...」と言われたらかなりカッコいいです。