document.addEventListener('DOMContentLoaded', function() { // Initialize variables let entries = JSON.parse(localStorage.getItem('journalEntries')) || []; const journalContainer = document.getElementById('journal-container'); const addEntryBtn = document.getElementById('add-entry-btn'); // Render existing entries renderEntries(); // Add new entry addEntryBtn.addEventListener('click', () => { const newEntry = { id: Date.now(), date: new Date().toISOString().split('T')[0], title: '', blocks: [ { id: Date.now() + 1, type: 'paragraph', content: '' } ] }; entries.unshift(newEntry); saveEntries(); renderEntries(); }); // Render all entries function renderEntries() { journalContainer.innerHTML = ''; if (entries.length === 0) { journalContainer.innerHTML = `

No journal entries yet

Create your first entry to get started

`; feather.replace(); return; } entries.forEach(entry => { const entryElement = createEntryElement(entry); journalContainer.appendChild(entryElement); }); } // Create entry element function createEntryElement(entry) { const entryDiv = document.createElement('div'); entryDiv.className = 'entry-card bg-white rounded-xl shadow-sm border border-gray-200 overflow-hidden'; entryDiv.innerHTML = `

${entry.title || 'Untitled Entry'}

${formatDate(entry.date)}
${entry.blocks.map(block => createBlockElement(block)).join('')}
`; // Add event listeners const deleteBtn = entryDiv.querySelector('.delete-entry'); deleteBtn.addEventListener('click', () => { entries = entries.filter(e => e.id !== entry.id); saveEntries(); renderEntries(); }); const addBlockBtn = entryDiv.querySelector('.add-block'); addBlockBtn.addEventListener('click', () => { const entryId = parseInt(addBlockBtn.getAttribute('data-id')); const entry = entries.find(e => e.id === entryId); const newBlock = { id: Date.now(), type: 'paragraph', content: '' }; entry.blocks.push(newBlock); saveEntries(); renderEntries(); }); // Add block event listeners const editorContainer = entryDiv.querySelector('.editor-container'); editorContainer.querySelectorAll('[contenteditable]').forEach(element => { element.addEventListener('input', handleContentChange); element.addEventListener('keydown', handleKeyDown); element.addEventListener('blur', handleBlur); }); // Title input listener const titleInput = entryDiv.querySelector('.entry-title'); if (titleInput) { titleInput.addEventListener('input', handleTitleChange); } feather.replace(); return entryDiv; } // Create block element function createBlockElement(block) { switch (block.type) { case 'heading': return `

${block.content}

`; case 'paragraph': return `

${block.content}

`; case 'divider': return `

`; default: return ''; } } // Handle content change function handleContentChange(e) { const blockId = parseInt(e.target.getAttribute('data-block-id')); const entryId = parseInt(e.target.closest('.editor-container').getAttribute('data-id')); const content = e.target.textContent; const entry = entries.find(e => e.id === entryId); if (entry) { const block = entry.blocks.find(b => b.id === blockId); if (block) { block.content = content; saveEntries(); } } } // Handle title change function handleTitleChange(e) { const entryId = parseInt(e.target.closest('.entry-card').querySelector('.editor-container').getAttribute('data-id')); const title = e.target.textContent; const entry = entries.find(e => e.id === entryId); if (entry) { entry.title = title; saveEntries(); } } // Handle keydown events function handleKeyDown(e) { if (e.key === 'Enter') { e.preventDefault(); insertBlockBelow(e.target); } else if (e.key === 'Backspace' && e.target.textContent === '') { e.preventDefault(); deleteBlock(e.target); } } // Handle blur event function handleBlur(e) { if (e.target.textContent === '') { const placeholder = e.target.getAttribute('data-placeholder'); if (placeholder) { e.target.textContent = ''; } } } // Insert block below current block function insertBlockBelow(target) { const blockId = parseInt(target.getAttribute('data-block-id')); const entryId = parseInt(target.closest('.editor-container').getAttribute('data-id')); const entry = entries.find(e => e.id === entryId); if (entry) { const blockIndex = entry.blocks.findIndex(b => b.id === blockId); const newBlock = { id: Date.now(), type: 'paragraph', content: '' }; entry.blocks.splice(blockIndex + 1, 0, newBlock); saveEntries(); renderEntries(); // Focus the new block after rendering setTimeout(() => { const newBlockElement = document.querySelector(`[data-block-id="${newBlock.id}"]`); if (newBlockElement) { const editableElement = newBlockElement.querySelector('[contenteditable]'); if (editableElement) { editableElement.focus(); // Place cursor at the beginning const range = document.createRange(); const sel = window.getSelection(); range.selectNodeContents(editableElement); range.collapse(true); sel.removeAllRanges(); sel.addRange(range); } } }, 0); } } // Delete block function deleteBlock(target) { const blockId = parseInt(target.getAttribute('data-block-id')); const entryId = parseInt(target.closest('.editor-container').getAttribute('data-id')); const entry = entries.find(e => e.id === entryId); if (entry && entry.blocks.length > 1) { const blockIndex = entry.blocks.findIndex(b => b.id === blockId); entry.blocks = entry.blocks.filter(b => b.id !== blockId); saveEntries(); renderEntries(); // Focus the previous block after rendering setTimeout(() => { if (blockIndex > 0) { const prevBlock = entry.blocks[blockIndex - 1]; const prevBlockElement = document.querySelector(`[data-block-id="${prevBlock.id}"]`); if (prevBlockElement) { const range = document.createRange(); const sel = window.getSelection(); range.selectNodeContents(prevBlockElement); range.collapse(false); sel.removeAllRanges(); sel.addRange(range); } } }, 0); } } // Save entries to localStorage function saveEntries() { localStorage.setItem('journalEntries', JSON.stringify(entries)); } // Format date function formatDate(dateString) { const options = { year: 'numeric', month: 'short', day: 'numeric' }; return new Date(dateString).toLocaleDateString(undefined, options); } });