script.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. const API_BASE = '/api/notes';
  2. let currentNoteId = null;
  3. let autoSaveTimeout = null;
  4. let lastSavedContent = '';
  5. // Initialize on page load
  6. function init() {
  7. const urlParams = new URLSearchParams(window.location.search);
  8. const idFromUrl = urlParams.get('id');
  9. if (idFromUrl) {
  10. loadNoteById(idFromUrl);
  11. } else {
  12. // Create a new note immediately if no ID in URL
  13. newNote();
  14. }
  15. // Set up auto-save on content change
  16. const noteContent = document.getElementById('noteContent');
  17. noteContent.addEventListener('input', handleContentChange);
  18. // Handle Enter key in ID input
  19. document.getElementById('noteIdInput').addEventListener('keypress', function(e) {
  20. if (e.key === 'Enter') {
  21. loadNoteFromInput();
  22. }
  23. });
  24. }
  25. // Handle content change for auto-save
  26. function handleContentChange() {
  27. const content = document.getElementById('noteContent').value;
  28. // Clear existing timeout
  29. if (autoSaveTimeout) {
  30. clearTimeout(autoSaveTimeout);
  31. }
  32. // Use 3-second debounce for all saves
  33. autoSaveTimeout = setTimeout(() => {
  34. autoSave(content);
  35. }, 3000);
  36. }
  37. // Auto-save function
  38. async function autoSave(content) {
  39. // Don't save if content hasn't changed
  40. if (content === lastSavedContent) {
  41. return;
  42. }
  43. try {
  44. if (currentNoteId) {
  45. // Update existing note
  46. await fetch(API_BASE, {
  47. method: 'PUT',
  48. headers: {
  49. 'Content-Type': 'application/json',
  50. },
  51. body: JSON.stringify({
  52. id: currentNoteId,
  53. content: content
  54. })
  55. });
  56. } else {
  57. // Create new note
  58. const response = await fetch(API_BASE, {
  59. method: 'POST',
  60. headers: {
  61. 'Content-Type': 'application/json',
  62. },
  63. body: JSON.stringify({
  64. note: content
  65. })
  66. });
  67. if (response.ok) {
  68. const note = await response.json();
  69. currentNoteId = note.id;
  70. // Update URL with new note ID
  71. const url = new URL(window.location);
  72. url.searchParams.set('id', note.id);
  73. window.history.replaceState({}, '', url);
  74. // Show note ID in header
  75. showNoteId(note.id);
  76. }
  77. }
  78. lastSavedContent = content;
  79. } catch (error) {
  80. // Silently fail - no user feedback needed as per requirements
  81. console.error('Auto-save failed:', error);
  82. }
  83. }
  84. // Load note by ID
  85. async function loadNoteById(id) {
  86. try {
  87. const response = await fetch(`${API_BASE}/${id}`);
  88. if (response.ok) {
  89. const note = await response.json();
  90. currentNoteId = note.id;
  91. // Update content
  92. document.getElementById('noteContent').value = note.content;
  93. lastSavedContent = note.content;
  94. // Update URL
  95. const url = new URL(window.location);
  96. url.searchParams.set('id', note.id);
  97. window.history.replaceState({}, '', url);
  98. // Show note ID in header
  99. showNoteId(note.id);
  100. }
  101. } catch (error) {
  102. // Silently fail - no user feedback
  103. console.error('Failed to load note:', error);
  104. }
  105. }
  106. // Show note ID in header
  107. function showNoteId(id) {
  108. const noteIdDisplay = document.getElementById('noteIdDisplay');
  109. noteIdDisplay.textContent = id;
  110. noteIdDisplay.style.display = 'inline-block';
  111. }
  112. // Hide note ID in header
  113. function hideNoteId() {
  114. document.getElementById('noteIdDisplay').style.display = 'none';
  115. }
  116. // Create new note
  117. async function newNote() {
  118. // Create empty note immediately to get an ID
  119. try {
  120. const response = await fetch(API_BASE, {
  121. method: 'POST',
  122. headers: {
  123. 'Content-Type': 'application/json',
  124. },
  125. body: JSON.stringify({
  126. note: ''
  127. })
  128. });
  129. if (response.ok) {
  130. const note = await response.json();
  131. currentNoteId = note.id;
  132. lastSavedContent = '';
  133. // Clear content
  134. document.getElementById('noteContent').value = '';
  135. // Update URL with new note ID
  136. const url = new URL(window.location);
  137. url.searchParams.set('id', note.id);
  138. window.history.replaceState({}, '', url);
  139. // Show note ID in header
  140. showNoteId(note.id);
  141. // Focus on content area
  142. document.getElementById('noteContent').focus();
  143. }
  144. } catch (error) {
  145. console.error('Failed to create new note:', error);
  146. }
  147. }
  148. // Show ID input overlay
  149. function showIdInput() {
  150. document.getElementById('idInputOverlay').classList.remove('hidden');
  151. document.getElementById('noteIdInput').focus();
  152. }
  153. // Hide ID input overlay
  154. function hideIdInput() {
  155. document.getElementById('idInputOverlay').classList.add('hidden');
  156. document.getElementById('noteIdInput').value = '';
  157. }
  158. // Load note from input
  159. function loadNoteFromInput() {
  160. const id = document.getElementById('noteIdInput').value.trim();
  161. if (id) {
  162. hideIdInput();
  163. loadNoteById(id);
  164. }
  165. }
  166. // Initialize when page loads
  167. window.addEventListener('load', init);