Voice-Controlled Note-Taker

Voice-Controlled Note-Taker

Click 'Start Listening' and begin speaking to transcribe your notes.

${date.toLocaleString()}

${note.content}

`; elements.notes.list.appendChild(card); }); }; // --- CORE LOGIC & EVENT HANDLERS --- const handleRecordClick = () => { if (!recognition) return; state.isListening = !state.isListening; if (state.isListening) { recognition.start(); } else { recognition.stop(); } }; if (recognition) { recognition.onstart = () => { state.isListening = true; elements.dashboard.recordBtn.textContent = 'Stop Listening'; elements.dashboard.recordBtn.classList.add('recording'); elements.dashboard.statusText.textContent = 'Listening...'; }; recognition.onend = () => { state.isListening = false; elements.dashboard.recordBtn.textContent = 'Start Listening'; elements.dashboard.recordBtn.classList.remove('recording'); elements.dashboard.statusText.textContent = 'Stopped.'; }; recognition.onresult = (event) => { let interimTranscript = ''; let finalTranscript = ''; for (let i = event.resultIndex; i < event.results.length; ++i) { if (event.results[i].isFinal) { finalTranscript += event.results[i][0].transcript; } else { interimTranscript += event.results[i][0].transcript; } } // Append final results with a space if (finalTranscript) { elements.dashboard.noteTextarea.value += finalTranscript + ' '; } }; } const handleSaveNote = () => { const content = elements.dashboard.noteTextarea.value.trim(); if (content) { state.notes.push({ id: Date.now(), content: content, timestamp: new Date().getTime() }); elements.dashboard.noteTextarea.value = ''; renderNotes(); alert('Note saved!'); } }; const handleNotesListClick = (e) => { const id = e.target.dataset.id; if (!id) return; if (e.target.classList.contains('delete-btn')) { state.notes = state.notes.filter(note => note.id != id); renderNotes(); } if (e.target.classList.contains('download-btn')) { const noteToDownload = state.notes.find(note => note.id == id); downloadNoteAsPDF(noteToDownload); } }; const downloadNoteAsPDF = async (note) => { if (!note) return; const { jsPDF } = window.jspdf; // Create a temporary element for professional PDF formatting const pdfContainer = document.createElement('div'); pdfContainer.style.cssText = 'position:absolute; left:-9999px; width:700px; padding:40px; background:#fff; font-family:sans-serif; color:#000;'; const date = new Date(note.timestamp); pdfContainer.innerHTML = `

Note

Saved on: ${date.toLocaleString()}

${note.content}

`; document.body.appendChild(pdfContainer); const canvas = await html2canvas(pdfContainer, { scale: 2 }); document.body.removeChild(pdfContainer); const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'portrait', unit: 'px', format: [canvas.width, canvas.height] }); pdf.addImage(imgData, 'PNG', 0, 0, canvas.width, canvas.height); pdf.save(`note-${note.id}.pdf`); }; // --- INITIALIZATION --- const initialize = () => { if (!SpeechRecognition) { elements.dashboard.unsupportedMsg.classList.remove('hidden'); elements.dashboard.recordBtn.disabled = true; elements.dashboard.saveNoteBtn.disabled = true; } Object.keys(elements.tabs).forEach(id => elements.tabs[id].addEventListener('click', () => switchTab(id))); elements.nav.next.addEventListener('click', () => { const i = tabs.indexOf(currentTab); if (i < tabs.length - 1) switchTab(tabs[i + 1]); }); elements.nav.prev.addEventListener('click', () => { const i = tabs.indexOf(currentTab); if (i > 0) switchTab(tabs[i - 1]); }); elements.dashboard.recordBtn.addEventListener('click', handleRecordClick); elements.dashboard.saveNoteBtn.addEventListener('click', handleSaveNote); elements.notes.list.addEventListener('click', handleNotesListClick); updateNavButtons(); renderNotes(); }; initialize(); });
Scroll to Top