| 
									
										
										
										
											2017-11-04 19:38:50 -04:00
										 |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  | const noteEditor = (function() { | 
					
						
							| 
									
										
										
										
											2017-11-04 19:28:49 -04:00
										 |  |  |     const treeEl = $("#tree"); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |     const noteTitleEl = $("#note-title"); | 
					
						
							|  |  |  |     const noteDetailEl = $('#note-detail'); | 
					
						
							|  |  |  |     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 noteChangeDisabled = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let isNoteChanged = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function getCurrentNote() { | 
					
						
							|  |  |  |         return currentNote; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function getCurrentNoteId() { | 
					
						
							|  |  |  |         return currentNote ? currentNote.detail.note_id : null; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function getCurrentNoteLoadTime() { | 
					
						
							| 
									
										
										
										
											2017-11-04 21:02:56 -04:00
										 |  |  |         return currentNote ? currentNote.loadTime : null; | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function noteChanged() { | 
					
						
							|  |  |  |         if (noteChangeDisabled) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         isNoteChanged = true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-05 10:06:49 -05:00
										 |  |  |     async function reload() { | 
					
						
							|  |  |  |         // no saving here
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await loadNoteToEditor(getCurrentNoteId()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async function switchToNote(noteId) { | 
					
						
							|  |  |  |         if (getCurrentNoteId() !== noteId) { | 
					
						
							|  |  |  |             await saveNoteIfChanged(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             await loadNoteToEditor(noteId); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |     async function saveNoteIfChanged() { | 
					
						
							|  |  |  |         if (!isNoteChanged) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const note = noteEditor.getCurrentNote(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         updateNoteFromInputs(note); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-04 18:18:55 -04:00
										 |  |  |         encryption.encryptNoteIfNecessary(note); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         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(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-04 22:18:36 -04:00
										 |  |  |         treeUtils.getNodeByKey(note.detail.note_id).setTitle(title); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         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!"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function createNewTopLevelNote() { | 
					
						
							| 
									
										
										
										
											2017-11-04 19:28:49 -04:00
										 |  |  |         let rootNode = treeEl.fancytree("getRootNode"); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         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
 | 
					
						
							| 
									
										
										
										
											2017-11-04 18:18:55 -04:00
										 |  |  |         if (!encryption || !encryption.isEncryptionAvailable()) { | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |             encryption = 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const newNoteName = "new note"; | 
					
						
							| 
									
										
										
										
											2017-11-04 18:18:55 -04:00
										 |  |  |         const newNoteNameEncryptedIfNecessary = encryption > 0 ? encryption.encryptString(newNoteName) : newNoteName; | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         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) { | 
					
						
							| 
									
										
										
										
											2017-11-04 22:18:36 -04:00
										 |  |  |         const node = treeUtils.getNodeByKey(note.detail.note_id); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |         node.toggleClass("encrypted", note.detail.encryption > 0); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function setNoteBackgroundIfEncrypted(note) { | 
					
						
							|  |  |  |         if (note.detail.encryption > 0) { | 
					
						
							| 
									
										
										
										
											2017-11-04 18:18:55 -04:00
										 |  |  |             $(".note-editable").addClass("encrypted"); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |             encryptButton.hide(); | 
					
						
							|  |  |  |             decryptButton.show(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							| 
									
										
										
										
											2017-11-04 18:18:55 -04:00
										 |  |  |             $(".note-editable").removeClass("encrypted"); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |             encryptButton.show(); | 
					
						
							|  |  |  |             decryptButton.hide(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         setTreeBasedOnEncryption(note); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async function loadNoteToEditor(noteId) { | 
					
						
							| 
									
										
										
										
											2017-11-04 21:02:56 -04:00
										 |  |  |         currentNote = await $.get(baseApiUrl + 'notes/' + noteId); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (newNoteCreated) { | 
					
						
							|  |  |  |             newNoteCreated = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             noteTitleEl.focus().select(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-04 21:02:56 -04:00
										 |  |  |         await encryption.ensureEncryptionIsAvailable(currentNote.detail.encryption > 0, false); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         noteDetailWrapperEl.show(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // this may fal if the dialog has not been previously opened
 | 
					
						
							|  |  |  |         try { | 
					
						
							|  |  |  |             encryptionPasswordDialogEl.dialog('close'); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         catch(e) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         encryptionPasswordEl.val(''); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-04 21:02:56 -04:00
										 |  |  |         encryption.decryptNoteIfNecessary(currentNote); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-04 21:02:56 -04:00
										 |  |  |         noteTitleEl.val(currentNote.detail.note_title); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         noteChangeDisabled = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Clear contents and remove all stored history. This is to prevent undo from going across notes
 | 
					
						
							|  |  |  |         noteDetailEl.summernote('reset'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-04 21:02:56 -04:00
										 |  |  |         noteDetailEl.summernote('code', currentNote.detail.note_text); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         document.location.hash = noteId; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-04 21:02:56 -04:00
										 |  |  |         recentNotes.addRecentNote(noteId, currentNote.detail.note_id); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         noteChangeDisabled = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-04 21:02:56 -04:00
										 |  |  |         setNoteBackgroundIfEncrypted(currentNote); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async function loadNote(noteId) { | 
					
						
							|  |  |  |         const note = await $.get(baseApiUrl + 'notes/' + noteId); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-04 18:18:55 -04:00
										 |  |  |         if (note.detail.encryption > 0 && !encryption.isEncryptionAvailable()) { | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-04 18:18:55 -04:00
										 |  |  |         encryption.decryptNoteIfNecessary(note); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         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)
 | 
					
						
							| 
									
										
										
										
											2017-11-04 18:18:55 -04:00
										 |  |  |         $(".note-editable").attr("tabindex", 2); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setInterval(saveNoteIfChanged, 5000); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return { | 
					
						
							| 
									
										
										
										
											2017-11-05 10:06:49 -05:00
										 |  |  |         reload, | 
					
						
							|  |  |  |         switchToNote, | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |         saveNoteIfChanged, | 
					
						
							|  |  |  |         updateNoteFromInputs, | 
					
						
							|  |  |  |         saveNoteToServer, | 
					
						
							|  |  |  |         createNewTopLevelNote, | 
					
						
							|  |  |  |         createNote, | 
					
						
							|  |  |  |         setNoteBackgroundIfEncrypted, | 
					
						
							|  |  |  |         setTreeBasedOnEncryption, | 
					
						
							|  |  |  |         loadNoteToEditor, | 
					
						
							|  |  |  |         loadNote, | 
					
						
							|  |  |  |         getCurrentNote, | 
					
						
							|  |  |  |         getCurrentNoteId, | 
					
						
							|  |  |  |         getCurrentNoteLoadTime | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | })(); |