mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 10:26:08 +01:00 
			
		
		
		
	note converted to module
This commit is contained in:
		| @@ -54,10 +54,10 @@ const contextMenuSetup = { | |||||||
|             const parentKey = getParentKey(node); |             const parentKey = getParentKey(node); | ||||||
|             const encryption = getParentEncryption(node); |             const encryption = getParentEncryption(node); | ||||||
|  |  | ||||||
|             createNote(node, parentKey, 'after', encryption); |             noteEditor.createNote(node, parentKey, 'after', encryption); | ||||||
|         } |         } | ||||||
|         else if (ui.cmd === "insertChildNote") { |         else if (ui.cmd === "insertChildNote") { | ||||||
|             createNote(node, node.key, 'into'); |             noteEditor.createNote(node, node.key, 'into'); | ||||||
|         } |         } | ||||||
|         else if (ui.cmd === "encryptSubTree") { |         else if (ui.cmd === "encryptSubTree") { | ||||||
|             encryptSubTree(node.key); |             encryptSubTree(node.key); | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ const noteHistory = (function() { | |||||||
|     let historyItems = []; |     let historyItems = []; | ||||||
|  |  | ||||||
|     async function showCurrentNoteHistory() { |     async function showCurrentNoteHistory() { | ||||||
|         await showNoteHistoryDialog(glob.currentNote.detail.note_id); |         await showNoteHistoryDialog(noteEditor.getCurrentNoteId()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async function showNoteHistoryDialog(noteId, noteHistoryId) { |     async function showNoteHistoryDialog(noteId, noteHistoryId) { | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ const recentNotes = (function() { | |||||||
|     function addRecentNote(noteTreeId, noteContentId) { |     function addRecentNote(noteTreeId, noteContentId) { | ||||||
|         setTimeout(() => { |         setTimeout(() => { | ||||||
|             // we include the note into recent list only if the user stayed on the note at least 5 seconds |             // we include the note into recent list only if the user stayed on the note at least 5 seconds | ||||||
|             if (noteTreeId === glob.currentNote.detail.note_id || noteContentId === glob.currentNote.detail.note_id) { |             if (noteTreeId === noteEditor.getCurrentNoteId() || noteContentId === noteEditor.getCurrentNoteId()) { | ||||||
|                 // if it's already there, remove the note |                 // if it's already there, remove the note | ||||||
|                 list = list.filter(note => note !== noteTreeId); |                 list = list.filter(note => note !== noteTreeId); | ||||||
|  |  | ||||||
| @@ -35,7 +35,7 @@ const recentNotes = (function() { | |||||||
|         selectBoxEl.find('option').remove(); |         selectBoxEl.find('option').remove(); | ||||||
|  |  | ||||||
|         // remove the current note |         // remove the current note | ||||||
|         const recNotes = list.filter(note => note !== glob.currentNote.detail.note_id); |         const recNotes = list.filter(note => note !== noteEditor.getCurrentNoteId()); | ||||||
|  |  | ||||||
|         $.each(recNotes, (key, valueNoteId) => { |         $.each(recNotes, (key, valueNoteId) => { | ||||||
|             const noteTitle = getFullName(valueNoteId); |             const noteTitle = getFullName(valueNoteId); | ||||||
|   | |||||||
| @@ -12,7 +12,7 @@ function handleEncryption(requireEncryption, modal) { | |||||||
|             open: () => { |             open: () => { | ||||||
|                 if (!modal) { |                 if (!modal) { | ||||||
|                     // dialog steals focus for itself, which is not what we want for non-modal (viewing) |                     // dialog steals focus for itself, which is not what we want for non-modal (viewing) | ||||||
|                     getNodeByKey(glob.currentNote.detail.note_id).setFocus(); |                     getNodeByKey(noteEditor.getCurrentNoteId()).setFocus(); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
| @@ -117,8 +117,8 @@ $("#encryption-password-form").submit(() => { | |||||||
| function resetEncryptionSession() { | function resetEncryptionSession() { | ||||||
|     glob.dataKey = null; |     glob.dataKey = null; | ||||||
|  |  | ||||||
|     if (glob.currentNote.detail.encryption > 0) { |     if (noteEditor.getCurrentNote().detail.encryption > 0) { | ||||||
|         loadNoteToEditor(glob.currentNote.detail.note_id); |         noteEditor.loadNoteToEditor(noteEditor.getCurrentNoteId()); | ||||||
|  |  | ||||||
|         for (const noteId of glob.allNoteIds) { |         for (const noteId of glob.allNoteIds) { | ||||||
|             const note = getNodeByKey(noteId); |             const note = getNodeByKey(noteId); | ||||||
| @@ -240,17 +240,17 @@ function encryptNote(note) { | |||||||
| async function encryptNoteAndSendToServer() { | async function encryptNoteAndSendToServer() { | ||||||
|     await handleEncryption(true, true); |     await handleEncryption(true, true); | ||||||
|  |  | ||||||
|     const note = glob.currentNote; |     const note = noteEditor.getCurrentNote(); | ||||||
|  |  | ||||||
|     updateNoteFromInputs(note); |     noteEditor.updateNoteFromInputs(note); | ||||||
|  |  | ||||||
|     encryptNote(note); |     encryptNote(note); | ||||||
|  |  | ||||||
|     await saveNoteToServer(note); |     await noteEditor.saveNoteToServer(note); | ||||||
|  |  | ||||||
|     await changeEncryptionOnNoteHistory(note.detail.note_id, true); |     await changeEncryptionOnNoteHistory(note.detail.note_id, true); | ||||||
|  |  | ||||||
|     setNoteBackgroundIfEncrypted(note); |     noteEditor.setNoteBackgroundIfEncrypted(note); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function changeEncryptionOnNoteHistory(noteId, encrypt) { | async function changeEncryptionOnNoteHistory(noteId, encrypt) { | ||||||
| @@ -287,17 +287,17 @@ async function changeEncryptionOnNoteHistory(noteId, encrypt) { | |||||||
| async function decryptNoteAndSendToServer() { | async function decryptNoteAndSendToServer() { | ||||||
|     await handleEncryption(true, true); |     await handleEncryption(true, true); | ||||||
|  |  | ||||||
|     const note = glob.currentNote; |     const note = noteEditor.getCurrentNote(); | ||||||
|  |  | ||||||
|     updateNoteFromInputs(note); |     noteEditor.updateNoteFromInputs(note); | ||||||
|  |  | ||||||
|     note.detail.encryption = 0; |     note.detail.encryption = 0; | ||||||
|  |  | ||||||
|     await saveNoteToServer(note); |     await noteEditor.saveNoteToServer(note); | ||||||
|  |  | ||||||
|     await changeEncryptionOnNoteHistory(note.detail.note_id, false); |     await changeEncryptionOnNoteHistory(note.detail.note_id, false); | ||||||
|  |  | ||||||
|     setNoteBackgroundIfEncrypted(note); |     noteEditor.setNoteBackgroundIfEncrypted(note); | ||||||
| } | } | ||||||
|  |  | ||||||
| function decryptNoteIfNecessary(note) { | function decryptNoteIfNecessary(note) { | ||||||
| @@ -327,11 +327,11 @@ async function encryptSubTree(noteId) { | |||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
|         note => { |         note => { | ||||||
|             if (note.detail.note_id === glob.currentNote.detail.note_id) { |             if (note.detail.note_id === noteEditor.getCurrentNoteId()) { | ||||||
|                 loadNoteToEditor(note.detail.note_id); |                 noteEditor.loadNoteToEditor(note.detail.note_id); | ||||||
|             } |             } | ||||||
|             else { |             else { | ||||||
|                 setTreeBasedOnEncryption(note); |                 noteEditor.setTreeBasedOnEncryption(note); | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
| @@ -354,11 +354,11 @@ async function decryptSubTree(noteId) { | |||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
|         note => { |         note => { | ||||||
|             if (note.detail.note_id === glob.currentNote.detail.note_id) { |             if (note.detail.note_id === noteEditor.getCurrentNoteId()) { | ||||||
|                 loadNoteToEditor(note.detail.note_id); |                 noteEditor.loadNoteToEditor(note.detail.note_id); | ||||||
|             } |             } | ||||||
|             else { |             else { | ||||||
|                 setTreeBasedOnEncryption(note); |                 noteEditor.setTreeBasedOnEncryption(note); | ||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -24,7 +24,7 @@ $(document).bind('keydown', 'alt+t', () => { | |||||||
| $(window).on('beforeunload', () => { | $(window).on('beforeunload', () => { | ||||||
|     // this makes sure that when user e.g. reloads the page or navigates away from the page, the note's content is saved |     // this makes sure that when user e.g. reloads the page or navigates away from the page, the note's content is saved | ||||||
|     // this sends the request asynchronously and doesn't wait for result |     // this sends the request asynchronously and doesn't wait for result | ||||||
|     saveNoteIfChanged(); |     noteEditor.saveNoteIfChanged(); | ||||||
| }); | }); | ||||||
|  |  | ||||||
| // Overrides the default autocomplete filter function to search for matched on atleast 1 word in each of the input term's words | // Overrides the default autocomplete filter function to search for matched on atleast 1 word in each of the input term's words | ||||||
| @@ -62,10 +62,10 @@ $.ui.autocomplete.filter = (array, terms) => { | |||||||
| $(document).tooltip({ | $(document).tooltip({ | ||||||
|     items: ".note-editable a", |     items: ".note-editable a", | ||||||
|     content: function(callback) { |     content: function(callback) { | ||||||
|         const noteId = getNoteIdFromLink($(this).attr("href")); |         const noteId = link.getNoteIdFromLink($(this).attr("href")); | ||||||
|  |  | ||||||
|         if (noteId !== null) { |         if (noteId !== null) { | ||||||
|             loadNote(noteId).then(note => callback(note.detail.note_text)); |             noteEditor.loadNote(noteId).then(note => callback(note.detail.note_text)); | ||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
|     close: function(event, ui) |     close: function(event, ui) | ||||||
|   | |||||||
| @@ -63,6 +63,7 @@ const link = (function() { | |||||||
|  |  | ||||||
|     return { |     return { | ||||||
|         getNodeIdFromLabel, |         getNodeIdFromLabel, | ||||||
|  |         getNoteIdFromLink, | ||||||
|         createNoteLink |         createNoteLink | ||||||
|     }; |     }; | ||||||
| })(); | })(); | ||||||
| @@ -1,237 +0,0 @@ | |||||||
| const tags = { |  | ||||||
|     1: "<b>", |  | ||||||
|     2: "</b>", |  | ||||||
|     3: "<i>", |  | ||||||
|     4: "</i>", |  | ||||||
|     5: "<u>", |  | ||||||
|     6: "</u>", |  | ||||||
|     9: "<s>", |  | ||||||
|     10: "</s>" |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| let noteChangeDisabled = false; |  | ||||||
|  |  | ||||||
| let isNoteChanged = false; |  | ||||||
|  |  | ||||||
| function noteChanged() { |  | ||||||
|     if (noteChangeDisabled) { |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     isNoteChanged = true; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| async function saveNoteIfChanged() { |  | ||||||
|     if (!isNoteChanged) { |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     const note = glob.currentNote; |  | ||||||
|  |  | ||||||
|     updateNoteFromInputs(note); |  | ||||||
|  |  | ||||||
|     encryptNoteIfNecessary(note); |  | ||||||
|  |  | ||||||
|     await saveNoteToServer(note); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| setInterval(saveNoteIfChanged, 5000); |  | ||||||
|  |  | ||||||
| $(document).ready(() => { |  | ||||||
|     $("#note-title").on('input', () => { |  | ||||||
|         noteChanged(); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     $('#note-detail').summernote({ |  | ||||||
|         airMode: true, |  | ||||||
|         height: 300, |  | ||||||
|         callbacks: { |  | ||||||
|             onChange: noteChanged |  | ||||||
|         } |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     // so that tab jumps from note title (which has tabindex 1) |  | ||||||
|     $(".note-editable").attr("tabindex", 2); |  | ||||||
| }); |  | ||||||
|  |  | ||||||
| function parseHtml(contents, note) { |  | ||||||
|     note.links = []; |  | ||||||
|     note.images = []; |  | ||||||
|  |  | ||||||
|     note.detail.note_text = contents; |  | ||||||
|  |  | ||||||
|     if (!note.detail.encryption) { |  | ||||||
|         const linkRegexp = /<a[^>]+?href="[^"]*kapp#([A-Za-z0-9]{22})"[^>]*?>[^<]+?<\/a>/g; |  | ||||||
|         let match; |  | ||||||
|  |  | ||||||
|         while (match = linkRegexp.exec(contents)) { |  | ||||||
|             console.log("adding link for " + match[1]); |  | ||||||
|  |  | ||||||
|             note.links.push({ |  | ||||||
|                 note_id: note.detail.note_id, |  | ||||||
|                 target_note_id: match[1] |  | ||||||
|             }); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function updateNoteFromInputs(note) { |  | ||||||
|     let contents = $('#note-detail').summernote('code'); |  | ||||||
|  |  | ||||||
|     parseHtml(contents, note); |  | ||||||
|  |  | ||||||
|     let title = $('#note-title').val(); |  | ||||||
|  |  | ||||||
|     getNodeByKey(note.detail.note_id).setTitle(title); |  | ||||||
|  |  | ||||||
|     note.detail.note_title = title; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| async function saveNoteToServer(note) { |  | ||||||
|     await $.ajax({ |  | ||||||
|         url: baseApiUrl + 'notes/' + note.detail.note_id, |  | ||||||
|         type: 'PUT', |  | ||||||
|         data: JSON.stringify(note), |  | ||||||
|         contentType: "application/json", |  | ||||||
|         error: () => { |  | ||||||
|             error("Error saving the note!"); |  | ||||||
|         } |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     isNoteChanged = false; |  | ||||||
|  |  | ||||||
|     message("Saved!"); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| glob.currentNote = null; |  | ||||||
| glob.currentNoteLoadTime = null; |  | ||||||
|  |  | ||||||
| function createNewTopLevelNote() { |  | ||||||
|     let rootNode = glob.tree.fancytree("getRootNode"); |  | ||||||
|  |  | ||||||
|     createNote(rootNode, "root", "into"); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| let newNoteCreated = false; |  | ||||||
|  |  | ||||||
| async function createNote(node, parentKey, target, encryption) { |  | ||||||
|     // if encryption isn't available (user didn't enter password yet), then note is created as unencrypted |  | ||||||
|     // but this is quite weird since user doesn't see where the note is being created so it shouldn't occur often |  | ||||||
|     if (!encryption || !isEncryptionAvailable()) { |  | ||||||
|         encryption = 0; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     const newNoteName = "new note"; |  | ||||||
|     const newNoteNameEncryptedIfNecessary = encryption > 0 ? encryptString(newNoteName) : newNoteName; |  | ||||||
|  |  | ||||||
|     const result = await $.ajax({ |  | ||||||
|         url: baseApiUrl + 'notes/' + parentKey + '/children' , |  | ||||||
|         type: 'POST', |  | ||||||
|         data: JSON.stringify({ |  | ||||||
|             note_title: newNoteNameEncryptedIfNecessary, |  | ||||||
|             target: target, |  | ||||||
|             target_note_id: node.key, |  | ||||||
|             encryption: encryption |  | ||||||
|         }), |  | ||||||
|         contentType: "application/json" |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     const newNode = { |  | ||||||
|         title: newNoteName, |  | ||||||
|         key: result.note_id, |  | ||||||
|         note_id: result.note_id, |  | ||||||
|         encryption: encryption, |  | ||||||
|         extraClasses: encryption ? "encrypted" : "" |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     glob.allNoteIds.push(result.note_id); |  | ||||||
|  |  | ||||||
|     newNoteCreated = true; |  | ||||||
|  |  | ||||||
|     if (target === 'after') { |  | ||||||
|         node.appendSibling(newNode).setActive(true); |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
|         node.addChildren(newNode).setActive(true); |  | ||||||
|  |  | ||||||
|         node.folder = true; |  | ||||||
|         node.renderTitle(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     message("Created!"); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function setTreeBasedOnEncryption(note) { |  | ||||||
|     const node = getNodeByKey(note.detail.note_id); |  | ||||||
|     node.toggleClass("encrypted", note.detail.encryption > 0); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function setNoteBackgroundIfEncrypted(note) { |  | ||||||
|     if (note.detail.encryption > 0) { |  | ||||||
|         $(".note-editable").addClass("encrypted"); |  | ||||||
|         $("#encrypt-button").hide(); |  | ||||||
|         $("#decrypt-button").show(); |  | ||||||
|     } |  | ||||||
|     else { |  | ||||||
|         $(".note-editable").removeClass("encrypted"); |  | ||||||
|         $("#encrypt-button").show(); |  | ||||||
|         $("#decrypt-button").hide(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     setTreeBasedOnEncryption(note); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| async function loadNoteToEditor(noteId) { |  | ||||||
|     const note = await $.get(baseApiUrl + 'notes/' + noteId); |  | ||||||
|     glob.currentNote = note; |  | ||||||
|     glob.currentNoteLoadTime = Math.floor(new Date().getTime() / 1000); |  | ||||||
|  |  | ||||||
|     if (newNoteCreated) { |  | ||||||
|         newNoteCreated = false; |  | ||||||
|  |  | ||||||
|         $("#note-title").focus().select(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     await handleEncryption(note.detail.encryption > 0, false); |  | ||||||
|  |  | ||||||
|     $("#note-detail-wrapper").show(); |  | ||||||
|  |  | ||||||
|     // this may fal if the dialog has not been previously opened |  | ||||||
|     try { |  | ||||||
|         $("#encryption-password-dialog").dialog('close'); |  | ||||||
|     } |  | ||||||
|     catch(e) {} |  | ||||||
|  |  | ||||||
|     $("#encryption-password").val(''); |  | ||||||
|  |  | ||||||
|     decryptNoteIfNecessary(note); |  | ||||||
|  |  | ||||||
|     $("#note-title").val(note.detail.note_title); |  | ||||||
|  |  | ||||||
|     noteChangeDisabled = true; |  | ||||||
|  |  | ||||||
|     // Clear contents and remove all stored history. This is to prevent undo from going across notes |  | ||||||
|     $('#note-detail').summernote('reset'); |  | ||||||
|  |  | ||||||
|     $('#note-detail').summernote('code', note.detail.note_text); |  | ||||||
|  |  | ||||||
|     document.location.hash = noteId; |  | ||||||
|  |  | ||||||
|     recentNotes.addRecentNote(noteId, note.detail.note_id); |  | ||||||
|  |  | ||||||
|     noteChangeDisabled = false; |  | ||||||
|  |  | ||||||
|     setNoteBackgroundIfEncrypted(note); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| async function loadNote(noteId) { |  | ||||||
|     const note = await $.get(baseApiUrl + 'notes/' + noteId); |  | ||||||
|  |  | ||||||
|     if (note.detail.encryption > 0 && !isEncryptionAvailable()) { |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     decryptNoteIfNecessary(note); |  | ||||||
|  |  | ||||||
|     return note; |  | ||||||
| } |  | ||||||
							
								
								
									
										267
									
								
								public/javascripts/note_editor.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										267
									
								
								public/javascripts/note_editor.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,267 @@ | |||||||
|  | const noteEditor = (function() { | ||||||
|  |     const noteTitleEl = $("#note-title"); | ||||||
|  |     const noteDetailEl = $('#note-detail'); | ||||||
|  |     const noteEditableEl = $(".note-editable"); | ||||||
|  |     const encryptButton = $("#encrypt-button"); | ||||||
|  |     const decryptButton = $("#decrypt-button"); | ||||||
|  |     const noteDetailWrapperEl = $("#note-detail-wrapper"); | ||||||
|  |     const encryptionPasswordDialogEl = $("#encryption-password-dialog"); | ||||||
|  |     const encryptionPasswordEl = $("#encryption-password"); | ||||||
|  |  | ||||||
|  |     let currentNote = null; | ||||||
|  |     let currentNoteLoadTime = null; | ||||||
|  |  | ||||||
|  |     let noteChangeDisabled = false; | ||||||
|  |  | ||||||
|  |     let isNoteChanged = false; | ||||||
|  |  | ||||||
|  |     function getCurrentNote() { | ||||||
|  |         return currentNote; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     function getCurrentNoteId() { | ||||||
|  |         return currentNote ? currentNote.detail.note_id : null; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     function getCurrentNoteLoadTime() { | ||||||
|  |         return currentNoteLoadTime; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     function noteChanged() { | ||||||
|  |         if (noteChangeDisabled) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         isNoteChanged = true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     async function saveNoteIfChanged() { | ||||||
|  |         if (!isNoteChanged) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         const note = noteEditor.getCurrentNote(); | ||||||
|  |  | ||||||
|  |         updateNoteFromInputs(note); | ||||||
|  |  | ||||||
|  |         encryptNoteIfNecessary(note); | ||||||
|  |  | ||||||
|  |         await saveNoteToServer(note); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     function parseHtml(contents, note) { | ||||||
|  |         note.links = []; | ||||||
|  |         note.images = []; | ||||||
|  |  | ||||||
|  |         note.detail.note_text = contents; | ||||||
|  |  | ||||||
|  |         if (!note.detail.encryption) { | ||||||
|  |             const linkRegexp = /<a[^>]+?href="[^"]*app#([A-Za-z0-9]{22})"[^>]*?>[^<]+?<\/a>/g; | ||||||
|  |             let match; | ||||||
|  |  | ||||||
|  |             while (match = linkRegexp.exec(contents)) { | ||||||
|  |                 console.log("adding link for " + match[1]); | ||||||
|  |  | ||||||
|  |                 note.links.push({ | ||||||
|  |                     note_id: note.detail.note_id, | ||||||
|  |                     target_note_id: match[1] | ||||||
|  |                 }); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     function updateNoteFromInputs(note) { | ||||||
|  |         const contents = noteDetailEl.summernote('code'); | ||||||
|  |  | ||||||
|  |         parseHtml(contents, note); | ||||||
|  |  | ||||||
|  |         const title = noteTitleEl.val(); | ||||||
|  |  | ||||||
|  |         getNodeByKey(note.detail.note_id).setTitle(title); | ||||||
|  |  | ||||||
|  |         note.detail.note_title = title; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     async function saveNoteToServer(note) { | ||||||
|  |         await $.ajax({ | ||||||
|  |             url: baseApiUrl + 'notes/' + note.detail.note_id, | ||||||
|  |             type: 'PUT', | ||||||
|  |             data: JSON.stringify(note), | ||||||
|  |             contentType: "application/json", | ||||||
|  |             error: () => { | ||||||
|  |                 error("Error saving the note!"); | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         isNoteChanged = false; | ||||||
|  |  | ||||||
|  |         message("Saved!"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     currentNote = null; | ||||||
|  |     currentNoteLoadTime = null; | ||||||
|  |  | ||||||
|  |     function createNewTopLevelNote() { | ||||||
|  |         let rootNode = glob.tree.fancytree("getRootNode"); | ||||||
|  |  | ||||||
|  |         createNote(rootNode, "root", "into"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     let newNoteCreated = false; | ||||||
|  |  | ||||||
|  |     async function createNote(node, parentKey, target, encryption) { | ||||||
|  |         // if encryption isn't available (user didn't enter password yet), then note is created as unencrypted | ||||||
|  |         // but this is quite weird since user doesn't see where the note is being created so it shouldn't occur often | ||||||
|  |         if (!encryption || !isEncryptionAvailable()) { | ||||||
|  |             encryption = 0; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         const newNoteName = "new note"; | ||||||
|  |         const newNoteNameEncryptedIfNecessary = encryption > 0 ? encryptString(newNoteName) : newNoteName; | ||||||
|  |  | ||||||
|  |         const result = await $.ajax({ | ||||||
|  |             url: baseApiUrl + 'notes/' + parentKey + '/children' , | ||||||
|  |             type: 'POST', | ||||||
|  |             data: JSON.stringify({ | ||||||
|  |                 note_title: newNoteNameEncryptedIfNecessary, | ||||||
|  |                 target: target, | ||||||
|  |                 target_note_id: node.key, | ||||||
|  |                 encryption: encryption | ||||||
|  |             }), | ||||||
|  |             contentType: "application/json" | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         const newNode = { | ||||||
|  |             title: newNoteName, | ||||||
|  |             key: result.note_id, | ||||||
|  |             note_id: result.note_id, | ||||||
|  |             encryption: encryption, | ||||||
|  |             extraClasses: encryption ? "encrypted" : "" | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |         glob.allNoteIds.push(result.note_id); | ||||||
|  |  | ||||||
|  |         newNoteCreated = true; | ||||||
|  |  | ||||||
|  |         if (target === 'after') { | ||||||
|  |             node.appendSibling(newNode).setActive(true); | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             node.addChildren(newNode).setActive(true); | ||||||
|  |  | ||||||
|  |             node.folder = true; | ||||||
|  |             node.renderTitle(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         message("Created!"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     function setTreeBasedOnEncryption(note) { | ||||||
|  |         const node = getNodeByKey(note.detail.note_id); | ||||||
|  |         node.toggleClass("encrypted", note.detail.encryption > 0); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     function setNoteBackgroundIfEncrypted(note) { | ||||||
|  |         if (note.detail.encryption > 0) { | ||||||
|  |             noteEditableEl.addClass("encrypted"); | ||||||
|  |             encryptButton.hide(); | ||||||
|  |             decryptButton.show(); | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             noteEditableEl.removeClass("encrypted"); | ||||||
|  |             encryptButton.show(); | ||||||
|  |             decryptButton.hide(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         setTreeBasedOnEncryption(note); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     async function loadNoteToEditor(noteId) { | ||||||
|  |         const note = await $.get(baseApiUrl + 'notes/' + noteId); | ||||||
|  |         currentNote = note; | ||||||
|  |         currentNoteLoadTime = Math.floor(new Date().getTime() / 1000); | ||||||
|  |  | ||||||
|  |         if (newNoteCreated) { | ||||||
|  |             newNoteCreated = false; | ||||||
|  |  | ||||||
|  |             noteTitleEl.focus().select(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         await handleEncryption(note.detail.encryption > 0, false); | ||||||
|  |  | ||||||
|  |         noteDetailWrapperEl.show(); | ||||||
|  |  | ||||||
|  |         // this may fal if the dialog has not been previously opened | ||||||
|  |         try { | ||||||
|  |             encryptionPasswordDialogEl.dialog('close'); | ||||||
|  |         } | ||||||
|  |         catch(e) {} | ||||||
|  |  | ||||||
|  |         encryptionPasswordEl.val(''); | ||||||
|  |  | ||||||
|  |         decryptNoteIfNecessary(note); | ||||||
|  |  | ||||||
|  |         noteTitleEl.val(note.detail.note_title); | ||||||
|  |  | ||||||
|  |         noteChangeDisabled = true; | ||||||
|  |  | ||||||
|  |         // Clear contents and remove all stored history. This is to prevent undo from going across notes | ||||||
|  |         noteDetailEl.summernote('reset'); | ||||||
|  |  | ||||||
|  |         noteDetailEl.summernote('code', note.detail.note_text); | ||||||
|  |  | ||||||
|  |         document.location.hash = noteId; | ||||||
|  |  | ||||||
|  |         recentNotes.addRecentNote(noteId, note.detail.note_id); | ||||||
|  |  | ||||||
|  |         noteChangeDisabled = false; | ||||||
|  |  | ||||||
|  |         setNoteBackgroundIfEncrypted(note); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     async function loadNote(noteId) { | ||||||
|  |         const note = await $.get(baseApiUrl + 'notes/' + noteId); | ||||||
|  |  | ||||||
|  |         if (note.detail.encryption > 0 && !isEncryptionAvailable()) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         decryptNoteIfNecessary(note); | ||||||
|  |  | ||||||
|  |         return note; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     $(document).ready(() => { | ||||||
|  |         noteTitleEl.on('input', () => { | ||||||
|  |             noteChanged(); | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         noteDetailEl.summernote({ | ||||||
|  |             airMode: true, | ||||||
|  |             height: 300, | ||||||
|  |             callbacks: { | ||||||
|  |                 onChange: noteChanged | ||||||
|  |             } | ||||||
|  |         }); | ||||||
|  |  | ||||||
|  |         // so that tab jumps from note title (which has tabindex 1) | ||||||
|  |         noteEditableEl.attr("tabindex", 2); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     setInterval(saveNoteIfChanged, 5000); | ||||||
|  |  | ||||||
|  |     return { | ||||||
|  |         saveNoteIfChanged, | ||||||
|  |         updateNoteFromInputs, | ||||||
|  |         saveNoteToServer, | ||||||
|  |         createNewTopLevelNote, | ||||||
|  |         createNote, | ||||||
|  |         setNoteBackgroundIfEncrypted, | ||||||
|  |         setTreeBasedOnEncryption, | ||||||
|  |         loadNoteToEditor, | ||||||
|  |         loadNote, | ||||||
|  |         getCurrentNote, | ||||||
|  |         getCurrentNoteId, | ||||||
|  |         getCurrentNoteLoadTime | ||||||
|  |     }; | ||||||
|  | })(); | ||||||
| @@ -5,8 +5,8 @@ async function checkStatus() { | |||||||
|         contentType: "application/json", |         contentType: "application/json", | ||||||
|         data: JSON.stringify({ |         data: JSON.stringify({ | ||||||
|             treeLoadTime: glob.treeLoadTime, |             treeLoadTime: glob.treeLoadTime, | ||||||
|             currentNoteId: glob.currentNote ? glob.currentNote.detail.note_id : null, |             currentNoteId: noteEditor.getCurrentNoteId(), | ||||||
|             currentNoteDateModified: glob.currentNoteLoadTime |             currentNoteDateModified: noteEditor.getCurrentNoteLoadTime() | ||||||
|         }), |         }), | ||||||
|         statusCode: { |         statusCode: { | ||||||
|             401: () => { |             401: () => { | ||||||
|   | |||||||
| @@ -3,10 +3,10 @@ const keybindings = { | |||||||
|         const parentKey = getParentKey(node); |         const parentKey = getParentKey(node); | ||||||
|         const encryption = getParentEncryption(node); |         const encryption = getParentEncryption(node); | ||||||
|  |  | ||||||
|         createNote(node, parentKey, 'after', encryption); |         noteEditor.createNote(node, parentKey, 'after', encryption); | ||||||
|     }, |     }, | ||||||
|     "ctrl+insert": node => { |     "ctrl+insert": node => { | ||||||
|         createNote(node, node.key, 'into', node.data.encryption); |         noteEditor.createNote(node, node.key, 'into', node.data.encryption); | ||||||
|     }, |     }, | ||||||
|     "del": node => { |     "del": node => { | ||||||
|         deleteNode(node); |         deleteNode(node); | ||||||
| @@ -95,7 +95,7 @@ function initFancyTree(notes, startNoteId) { | |||||||
|         activate: (event, data) => { |         activate: (event, data) => { | ||||||
|             const node = data.node.data; |             const node = data.node.data; | ||||||
|  |  | ||||||
|             saveNoteIfChanged().then(() => loadNoteToEditor(node.note_id)); |             noteEditor.saveNoteIfChanged().then(() => noteEditor.loadNoteToEditor(node.note_id)); | ||||||
|         }, |         }, | ||||||
|         expand: (event, data) => { |         expand: (event, data) => { | ||||||
|             setExpandedToServer(data.node.key, true); |             setExpandedToServer(data.node.key, true); | ||||||
| @@ -219,7 +219,7 @@ function collapseTree() { | |||||||
| $(document).bind('keydown', 'alt+c', collapseTree); | $(document).bind('keydown', 'alt+c', collapseTree); | ||||||
|  |  | ||||||
| function scrollToCurrentNote() { | function scrollToCurrentNote() { | ||||||
|     const node = getNodeByKey(glob.currentNote.detail.note_id); |     const node = getNodeByKey(noteEditor.getCurrentNoteId()); | ||||||
|  |  | ||||||
|     if (node) { |     if (node) { | ||||||
|         node.makeVisible({scrollIntoView: true}); |         node.makeVisible({scrollIntoView: true}); | ||||||
|   | |||||||
| @@ -33,7 +33,7 @@ | |||||||
|       </div> |       </div> | ||||||
|  |  | ||||||
|       <div class="hide-toggle" style="grid-area: tree-actions"> |       <div class="hide-toggle" style="grid-area: tree-actions"> | ||||||
|         <a onclick="createNewTopLevelNote()" title="Create new top level note" class="icon-action"> |         <a onclick="noteEditor.createNewTopLevelNote()" title="Create new top level note" class="icon-action"> | ||||||
|           <img src="images/icons/file-plus.png" alt="Create new top level note"/> |           <img src="images/icons/file-plus.png" alt="Create new top level note"/> | ||||||
|         </a> |         </a> | ||||||
|  |  | ||||||
| @@ -270,7 +270,7 @@ | |||||||
|     <script src="javascripts/context_menu.js"></script> |     <script src="javascripts/context_menu.js"></script> | ||||||
|  |  | ||||||
|     <!-- Note detail --> |     <!-- Note detail --> | ||||||
|     <script src="javascripts/note.js"></script> |     <script src="javascripts/note_editor.js"></script> | ||||||
|     <script src="javascripts/encryption.js"></script> |     <script src="javascripts/encryption.js"></script> | ||||||
|  |  | ||||||
|     <!-- dialogs --> |     <!-- dialogs --> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user