| 
									
										
										
										
											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'); | 
					
						
							| 
									
										
										
										
											2017-11-14 22:21:56 -05:00
										 |  |  |     const protectButton = $("#protect-button"); | 
					
						
							|  |  |  |     const unprotectButton = $("#unprotect-button"); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |     const noteDetailWrapperEl = $("#note-detail-wrapper"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await saveNoteToServer(note); | 
					
						
							| 
									
										
										
										
											2017-11-14 22:50:56 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (note.detail.is_protected) { | 
					
						
							|  |  |  |             protected_session.touchProtectedSession(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function parseHtml(contents, note) { | 
					
						
							|  |  |  |         note.links = []; | 
					
						
							|  |  |  |         note.images = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         note.detail.note_text = contents; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-14 21:54:12 -05:00
										 |  |  |         if (!note.detail.is_protected) { | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |             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: () => { | 
					
						
							| 
									
										
										
										
											2017-11-08 22:33:08 -05:00
										 |  |  |                 showError("Error saving the note!"); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |             } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         isNoteChanged = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-08 22:33:08 -05:00
										 |  |  |         showMessage("Saved!"); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-14 22:21:56 -05:00
										 |  |  |     async function createNote(node, parentKey, target, isProtected) { | 
					
						
							|  |  |  |         // if isProtected isn't available (user didn't enter password yet), then note is created as unencrypted
 | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |         // but this is quite weird since user doesn't see where the note is being created so it shouldn't occur often
 | 
					
						
							| 
									
										
										
										
											2017-11-14 22:36:36 -05:00
										 |  |  |         if (!isProtected || !protected_session.isProtectedSessionAvailable()) { | 
					
						
							| 
									
										
										
										
											2017-11-14 22:21:56 -05:00
										 |  |  |             isProtected = false; | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const newNoteName = "new note"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const result = await $.ajax({ | 
					
						
							|  |  |  |             url: baseApiUrl + 'notes/' + parentKey + '/children' , | 
					
						
							|  |  |  |             type: 'POST', | 
					
						
							|  |  |  |             data: JSON.stringify({ | 
					
						
							| 
									
										
										
										
											2017-11-14 22:21:56 -05:00
										 |  |  |                 note_title: newNoteName, | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |                 target: target, | 
					
						
							|  |  |  |                 target_note_id: node.key, | 
					
						
							| 
									
										
										
										
											2017-11-14 22:21:56 -05:00
										 |  |  |                 is_protected: isProtected | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |             }), | 
					
						
							|  |  |  |             contentType: "application/json" | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const newNode = { | 
					
						
							|  |  |  |             title: newNoteName, | 
					
						
							|  |  |  |             key: result.note_id, | 
					
						
							|  |  |  |             note_id: result.note_id, | 
					
						
							| 
									
										
										
										
											2017-11-14 22:21:56 -05:00
										 |  |  |             is_protected: isProtected, | 
					
						
							|  |  |  |             extraClasses: isProtected ? "protected" : "" | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         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(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-08 22:33:08 -05:00
										 |  |  |         showMessage("Created!"); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-14 22:21:56 -05:00
										 |  |  |     function setTreeBasedOnProtectedStatus(note) { | 
					
						
							| 
									
										
										
										
											2017-11-04 22:18:36 -04:00
										 |  |  |         const node = treeUtils.getNodeByKey(note.detail.note_id); | 
					
						
							| 
									
										
										
										
											2017-11-14 22:21:56 -05:00
										 |  |  |         node.toggleClass("protected", note.detail.is_protected); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-14 22:21:56 -05:00
										 |  |  |     function setNoteBackgroundIfProtected(note) { | 
					
						
							| 
									
										
										
										
											2017-11-14 21:54:12 -05:00
										 |  |  |         if (note.detail.is_protected) { | 
					
						
							| 
									
										
										
										
											2017-11-14 22:21:56 -05:00
										 |  |  |             $(".note-editable").addClass("protected"); | 
					
						
							|  |  |  |             protectButton.hide(); | 
					
						
							|  |  |  |             unprotectButton.show(); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							| 
									
										
										
										
											2017-11-14 22:21:56 -05:00
										 |  |  |             $(".note-editable").removeClass("protected"); | 
					
						
							|  |  |  |             protectButton.show(); | 
					
						
							|  |  |  |             unprotectButton.hide(); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-14 22:21:56 -05:00
										 |  |  |         setTreeBasedOnProtectedStatus(note); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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-14 22:36:36 -05:00
										 |  |  |         await protected_session.ensureProtectedSession(currentNote.detail.is_protected, false); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-14 22:50:56 -05:00
										 |  |  |         if (currentNote.detail.is_protected) { | 
					
						
							|  |  |  |             protected_session.touchProtectedSession(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |         noteDetailWrapperEl.show(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-14 22:21:56 -05:00
										 |  |  |         setNoteBackgroundIfProtected(currentNote); | 
					
						
							| 
									
										
										
										
											2017-11-06 22:21:11 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         showAppIfHidden(); | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async function loadNote(noteId) { | 
					
						
							|  |  |  |         const note = await $.get(baseApiUrl + 'notes/' + noteId); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         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, | 
					
						
							| 
									
										
										
										
											2017-11-14 22:21:56 -05:00
										 |  |  |         setNoteBackgroundIfProtected, | 
					
						
							| 
									
										
										
										
											2017-11-04 17:54:27 -04:00
										 |  |  |         loadNote, | 
					
						
							|  |  |  |         getCurrentNote, | 
					
						
							|  |  |  |         getCurrentNoteId, | 
					
						
							|  |  |  |         getCurrentNoteLoadTime | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | })(); |