CoolFace
Apppublic

Abhi13-coder/noteblocks-modular-note-magic

sourceHugging Faceupdated 11mo agoView on Hugging Face
0likes
script.js201 linesDownload Raw Back to root
1document.addEventListener('DOMContentLoaded', () => {2    // Sample notes data3    let notes = JSON.parse(localStorage.getItem('notes')) || [];4    let currentNoteId = null;5 6    // DOM elements7    const notesGrid = document.getElementById('notes-grid');8    const newNoteBtn = document.getElementById('new-note-btn');9    const editorModal = document.getElementById('editor-modal');10    const noteTitle = document.getElementById('note-title');11    const editorContent = document.getElementById('editor-content');12    const saveNoteBtn = document.getElementById('save-note');13    const closeEditorBtn = document.getElementById('close-editor');14    const toolbarButtons = document.querySelectorAll('#editor-toolbar button');15 16    // Render all notes17    function renderNotes() {18        notesGrid.innerHTML = '';19        notes.forEach(note => {20            const preview = note.blocks.find(block => block.type === 'paragraph')?.content || 'No content';21            22            const noteElement = document.createElement('div');23            noteElement.className = 'bg-white dark:bg-secondary-700 rounded-lg shadow-md overflow-hidden hover:shadow-lg transition cursor-pointer';24            noteElement.innerHTML = `25                <div class="p-4">26                    <h3 class="font-bold text-lg mb-2 text-secondary-900 dark:text-white">${note.title || 'Untitled Note'}</h3>27                    <p class="text-secondary-600 dark:text-secondary-300 line-clamp-3">${preview}</p>28                </div>29                <div class="px-4 py-2 bg-secondary-50 dark:bg-secondary-800 text-secondary-500 dark:text-secondary-400 text-sm flex justify-between items-center">30                    <span>${new Date(note.updatedAt).toLocaleDateString()}</span>31                    <button class="text-red-500 hover:text-red-700 delete-note" data-id="${note.id}">32                        <i data-feather="trash-2"></i>33                    </button>34                </div>35            `;36            37            noteElement.addEventListener('click', () => openEditor(note.id));38            notesGrid.appendChild(noteElement);39        });40        41        // Add event listeners to delete buttons42        document.querySelectorAll('.delete-note').forEach(btn => {43            btn.addEventListener('click', (e) => {44                e.stopPropagation();45                deleteNote(btn.dataset.id);46            });47        });48        49        feather.replace();50    }51 52    // Create a new note53    function createNewNote() {54        const newNote = {55            id: Date.now().toString(),56            title: '',57            blocks: [{ type: 'paragraph', content: '' }],58            createdAt: new Date(),59            updatedAt: new Date()60        };61        62        notes.unshift(newNote);63        saveNotes();64        openEditor(newNote.id);65    }66 67    // Open editor with note content68    function openEditor(noteId) {69        const note = notes.find(n => n.id === noteId);70        if (!note) return;71        72        currentNoteId = noteId;73        noteTitle.value = note.title;74        editorContent.innerHTML = '';75        76        note.blocks.forEach(block => {77            const blockElement = createBlockElement(block);78            editorContent.appendChild(blockElement);79        });80        81        editorModal.classList.remove('hidden');82        document.body.style.overflow = 'hidden';83    }84 85    // Close editor86    function closeEditor() {87        editorModal.classList.add('hidden');88        document.body.style.overflow = '';89        currentNoteId = null;90    }91 92    // Save note93    function saveNote() {94        if (!currentNoteId) return;95        96        const noteIndex = notes.findIndex(n => n.id === currentNoteId);97        if (noteIndex === -1) return;98        99        const title = noteTitle.value.trim();100        const blocks = [];101        102        // Get all blocks from editor103        editorContent.querySelectorAll('[data-block]').forEach(blockEl => {104            const type = blockEl.dataset.block;105            let content = '';106            107            if (type === 'image') {108                content = blockEl.querySelector('img')?.src || '';109            } else {110                content = blockEl.textContent;111            }112            113            blocks.push({ type, content });114        });115        116        notes[noteIndex] = {117            ...notes[noteIndex],118            title,119            blocks,120            updatedAt: new Date()121        };122        123        saveNotes();124        renderNotes();125    }126 127    // Delete note128    function deleteNote(noteId) {129        if (confirm('Are you sure you want to delete this note?')) {130            notes = notes.filter(note => note.id !== noteId);131            saveNotes();132            renderNotes();133        }134    }135 136    // Save notes to localStorage137    function saveNotes() {138        localStorage.setItem('notes', JSON.stringify(notes));139    }140 141    // Create a block element142    function createBlockElement(block) {143        const blockElement = document.createElement('div');144        blockElement.dataset.block = block.type;145        blockElement.className = `block-${block.type} mb-4`;146        blockElement.contentEditable = true;147        148        switch (block.type) {149            case 'heading':150                blockElement.innerHTML = `<h2>${block.content || 'Heading'}</h2>`;151                break;152            case 'list':153                blockElement.innerHTML = `<ul><li>${block.content || 'List item'}</li></ul>`;154                break;155            case 'image':156                blockElement.innerHTML = `<img src="${block.content || 'https://via.placeholder.com/600x400'}" alt="Image" class="rounded-lg w-full">`;157                break;158            case 'quote':159                blockElement.innerHTML = `<blockquote>${block.content || 'Quote'}</blockquote>`;160                break;161            case 'code':162                blockElement.innerHTML = `<pre><code>${block.content || 'Code'}</code></pre>`;163                break;164            default: // paragraph165                blockElement.textContent = block.content || '';166        }167        168        return blockElement;169    }170 171    // Add block to editor172    function addBlock(type) {173        const block = { type, content: '' };174        const blockElement = createBlockElement(block);175        176        // Add to end of content177        editorContent.appendChild(blockElement);178        179        // Focus the new block180        blockElement.focus();181    }182 183    // Event listeners184    newNoteBtn.addEventListener('click', createNewNote);185    saveNoteBtn.addEventListener('click', saveNote);186    closeEditorBtn.addEventListener('click', closeEditor);187    188    toolbarButtons.forEach(btn => {189        btn.addEventListener('click', () => addBlock(btn.dataset.type));190    });191 192    // Close modal when clicking outside193    editorModal.addEventListener('click', (e) => {194        if (e.target === editorModal) {195            closeEditor();196        }197    });198 199    // Initialize200    renderNotes();201});