-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.js
More file actions
146 lines (130 loc) · 4.1 KB
/
Copy pathapp.js
File metadata and controls
146 lines (130 loc) · 4.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// Notes App - simple localStorage-backed notes
const STORAGE_KEY = 'notesapp.notes'
let notes = []
let editingId = null
const el = id => document.getElementById(id)
const searchInput = el('search')
const newBtn = el('newBtn')
const editor = el('editor')
const titleInput = el('noteTitle')
const contentInput = el('noteContent')
const saveBtn = el('saveBtn')
const cancelBtn = el('cancelBtn')
const notesList = el('notesList')
function loadNotes() {
try {
const raw = localStorage.getItem(STORAGE_KEY)
notes = raw ? JSON.parse(raw) : []
} catch (e) {
notes = []
}
}
function saveNotes() {
localStorage.setItem(STORAGE_KEY, JSON.stringify(notes))
}
function renderNotes(filter = '') {
notesList.innerHTML = ''
const f = filter.trim().toLowerCase()
const filtered = notes.filter(n => {
if (!f) return true
return (n.title || '').toLowerCase().includes(f) || (n.content || '').toLowerCase().includes(f)
}).sort((a, b) => b.updated - a.updated)
if (filtered.length === 0) {
notesList.innerHTML = `<div class="empty">No notes yet. Click New Note to add one.</div>`
return
}
for (const n of filtered) {
const card = document.createElement('article')
card.className = 'note-card'
card.innerHTML = `
<div class="note-title">${escapeHtml(n.title||'Untitled')}</div>
<div class="note-body">${escapeHtml(n.content||'')}</div>
<div class="note-meta">${new Date(n.updated).toLocaleString()}</div>
<div class="card-actions">
<button class="action" data-id="${n.id}" data-action="edit">Edit</button>
<button class="action" data-id="${n.id}" data-action="delete">Delete</button>
</div>
`
notesList.appendChild(card)
}
}
function openEditor(note) {
editor.classList.remove('hidden')
editor.setAttribute('aria-hidden', 'false')
if (note) {
editingId = note.id
titleInput.value = note.title || ''
contentInput.value = note.content || ''
} else {
editingId = null
titleInput.value = ''
contentInput.value = ''
}
titleInput.focus()
}
function closeEditor() {
editor.classList.add('hidden')
editor.setAttribute('aria-hidden', 'true')
editingId = null
titleInput.value = ''
contentInput.value = ''
}
function addOrUpdateNote() {
const title = titleInput.value.trim()
const content = contentInput.value.trim()
if (!title && !content) return closeEditor()
if (editingId) {
const idx = notes.findIndex(n => n.id === editingId)
if (idx >= 0) {
notes[idx].title = title
notes[idx].content = content
notes[idx].updated = Date.now()
}
} else {
const note = { id: String(Date.now()) + Math.random().toString(36).slice(2, 6), title, content, updated: Date.now() }
notes.push(note)
}
saveNotes()
renderNotes(searchInput.value)
closeEditor()
}
function deleteNote(id) {
if (!confirm('Delete this note?')) return
notes = notes.filter(n => n.id !== id)
saveNotes()
renderNotes(searchInput.value)
}
function handleCardClick(e) {
const btn = e.target.closest('button[data-action]')
if (!btn) return
const id = btn.dataset.id
const action = btn.dataset.action
if (action === 'edit') {
const note = notes.find(n => n.id === id)
if (note) openEditor(note)
} else if (action === 'delete') {
deleteNote(id)
}
}
function escapeHtml(s) {
return String(s)
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
}
// events
newBtn.addEventListener('click', () => openEditor(null))
cancelBtn.addEventListener('click', closeEditor)
saveBtn.addEventListener('click', addOrUpdateNote)
notesList.addEventListener('click', handleCardClick)
searchInput.addEventListener('input', e => renderNotes(e.target.value))
// keyboard shortcuts
window.addEventListener('keydown', e => {
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'n') {
e.preventDefault();
openEditor(null)
}
})
// init
loadNotes()
renderNotes()