localStorageを使用した、簡易メモアプリです。
個人的にスーパーでの食品買い出し用に使いたくて作成。
自分が欲しい機能のみなので、順序入れ替えや個数入力欄などはありません。
各項目左のチェックボックスは単にテキスト背景をグレー表示させるだけのもので特別な機能はありませんが、私は買い物中の購入済みチェック用に使っています。
動作デモ
index.html
<!DOCTYPE html>
<html lang='ja'>
<head>
<meta name='viewport' content='initial-scale=1'>
<meta http-equiv='Cache-Control' content='no-store'>
<meta charset='utf-8'>
<title>メモ</title>
<style>
#list {
margin: 20px 0;
}
button {
font-size: 18px;
}
[type=text] {
font-size: 20px;
margin: 8px;
width: 220px;
}
[type=checkbox]:checked + input {
background-color: #ccc;
}
</style>
</head>
<body>
<button id='allDel'>全削除</button>
<div id='list'></div>
<div><input type='text' id='addText'><button id='addBtn'>登録</button></div>
<template><div><input type='checkbox'><input type='text'><button>削除</button></div></template>
<script>
'use strict';
const list = document.getElementById('list');
const addText = document.getElementById('addText');
const template = document.querySelector('template').innerHTML;
const storageKey = 'memo';
const refreshList = () => {
list.textContent = '';
(JSON.parse(localStorage.getItem(storageKey)) ?? []).forEach(e => {
if (e.text === '') return;
list.insertAdjacentHTML('beforeend', template);
const parent = list.querySelector('div:last-of-type');
parent.querySelector('[type=text]').value = e.text;
parent.querySelector('[type=checkbox]').checked = e.check;
});
};
document.addEventListener('DOMContentLoaded', refreshList);
const addList = () => {
if (addText.value.trim() === '') return;
list.insertAdjacentHTML('beforeend', template);
list.querySelector('div:last-of-type [type=text]').value = addText.value.trim();
addText.value = '';
};
document.getElementById('addBtn').addEventListener('click', () => save());
addText.addEventListener('keydown', ev => ev.key === 'Enter' && save());
list.addEventListener('click', ev => {
const target = ev.target;
const parent = target.closest('div');
if (target.tagName === 'BUTTON' && confirm(`${parent.querySelector('[type=text]').value}を削除しますか`)) {
parent.remove();
saveStorage();
}
});
list.addEventListener('keydown', ev => {
const target = ev.target;
const parent = target.closest('div');
if (target.tagName === 'INPUT' && ev.key === 'Enter' && target.value.trim() === '') {
parent.remove();
saveStorage();
}
});
document.getElementById('allDel').addEventListener('click', () => {
if (confirm('全てのリストを削除しますか')) {
list.textContent = '';
saveStorage();
}
});
const saveStorage = () => {
const listItems = [...list.querySelectorAll('div')];
if (!listItems.length) {
localStorage.removeItem(storageKey);
return;
}
localStorage.setItem(storageKey,
JSON.stringify(listItems.map(e => ({
text: e.querySelector('[type=text]').value.trim(),
check: e.querySelector('[type=checkbox]').checked,
})))
);
};
const save = () => {
addList();
saveStorage();
};
addEventListener('beforeunload', save);
addEventListener('pagehide', save);
addEventListener('storage', refreshList);
</script>
</body>
</html>