diff --git a/src/public/javascripts/context_menu.js b/src/public/javascripts/context_menu.js index 8056c43cf..55fe98edb 100644 --- a/src/public/javascripts/context_menu.js +++ b/src/public/javascripts/context_menu.js @@ -151,16 +151,16 @@ const contextMenu = (function() { treeChanges.deleteNodes(treeService.getSelectedNodes(true)); } else if (ui.cmd === "exportSubTree") { - exportSubTree(node.data.noteId); + exportService.exportSubTree(node.data.noteId); } else if (ui.cmd === "importSubTree") { - importSubTree(node.data.noteId); + exportService.importSubTree(node.data.noteId); } else if (ui.cmd === "collapseSubTree") { treeService.collapseTree(node); } else if (ui.cmd === "forceNoteSync") { - forceNoteSync(node.data.noteId); + syncService.forceNoteSync(node.data.noteId); } else if (ui.cmd === "sortAlphabetically") { treeService.sortAlphabetically(node.data.noteId); diff --git a/src/public/javascripts/export.js b/src/public/javascripts/export.js index b52998cb4..5cd62052b 100644 --- a/src/public/javascripts/export.js +++ b/src/public/javascripts/export.js @@ -1,32 +1,39 @@ "use strict"; -function exportSubTree(noteId) { - const url = utils.getHost() + "/api/export/" + noteId + "?protectedSessionId=" - + encodeURIComponent(protected_session.getProtectedSessionId()); +const exportService = (function () { + function exportSubTree(noteId) { + const url = utils.getHost() + "/api/export/" + noteId + "?protectedSessionId=" + + encodeURIComponent(protected_session.getProtectedSessionId()); - utils.download(url); -} + utils.download(url); + } -let importNoteId; + let importNoteId; -function importSubTree(noteId) { - importNoteId = noteId; + function importSubTree(noteId) { + importNoteId = noteId; - $("#import-upload").trigger('click'); -} + $("#import-upload").trigger('click'); + } -$("#import-upload").change(async function() { - const formData = new FormData(); - formData.append('upload', this.files[0]); + $("#import-upload").change(async function() { + const formData = new FormData(); + formData.append('upload', this.files[0]); - await $.ajax({ - url: baseApiUrl + 'import/' + importNoteId, - headers: server.getHeaders(), - data: formData, - type: 'POST', - contentType: false, // NEEDED, DON'T OMIT THIS - processData: false, // NEEDED, DON'T OMIT THIS + await $.ajax({ + url: baseApiUrl + 'import/' + importNoteId, + headers: server.getHeaders(), + data: formData, + type: 'POST', + contentType: false, // NEEDED, DON'T OMIT THIS + processData: false, // NEEDED, DON'T OMIT THIS + }); + + await treeService.reload(); }); - await treeService.reload(); -}); \ No newline at end of file + return { + exportSubTree, + importSubTree + }; +})(); \ No newline at end of file diff --git a/src/public/javascripts/init.js b/src/public/javascripts/init.js index 20e97d8aa..2c3b7ad6c 100644 --- a/src/public/javascripts/init.js +++ b/src/public/javascripts/init.js @@ -1,250 +1,252 @@ "use strict"; -// hot keys are active also inside inputs and content editables -jQuery.hotkeys.options.filterInputAcceptingElements = false; -jQuery.hotkeys.options.filterContentEditable = false; -jQuery.hotkeys.options.filterTextInputs = false; +const initService = (function() { + // hot keys are active also inside inputs and content editables + jQuery.hotkeys.options.filterInputAcceptingElements = false; + jQuery.hotkeys.options.filterContentEditable = false; + jQuery.hotkeys.options.filterTextInputs = false; -$(document).bind('keydown', 'alt+m', e => { - $(".hide-toggle").toggleClass("suppressed"); + $(document).bind('keydown', 'alt+m', e => { + $(".hide-toggle").toggleClass("suppressed"); - e.preventDefault(); -}); + e.preventDefault(); + }); -// hide (toggle) everything except for the note content for distraction free writing -$(document).bind('keydown', 'alt+t', e => { - const date = new Date(); - const dateString = utils.formatDateTime(date); + // hide (toggle) everything except for the note content for distraction free writing + $(document).bind('keydown', 'alt+t', e => { + const date = new Date(); + const dateString = utils.formatDateTime(date); - link.addTextToEditor(dateString); + link.addTextToEditor(dateString); - e.preventDefault(); -}); + e.preventDefault(); + }); -$(document).bind('keydown', 'f5', () => { - utils.reloadApp(); - - return false; -}); - -$(document).bind('keydown', 'ctrl+r', () => { - utils.reloadApp(); - - return false; -}); - -$(document).bind('keydown', 'ctrl+shift+i', () => { - if (utils.isElectron()) { - require('electron').remote.getCurrentWindow().toggleDevTools(); + $(document).bind('keydown', 'f5', () => { + utils.reloadApp(); return false; - } -}); + }); -$(document).bind('keydown', 'ctrl+f', () => { - if (utils.isElectron()) { - const searchInPage = require('electron-in-page-search').default; - const remote = require('electron').remote; - - const inPageSearch = searchInPage(remote.getCurrentWebContents()); - - inPageSearch.openSearchWindow(); + $(document).bind('keydown', 'ctrl+r', () => { + utils.reloadApp(); return false; - } -}); + }); -$(document).bind('keydown', "ctrl+shift+up", () => { - const node = treeService.getCurrentNode(); - node.navigate($.ui.keyCode.UP, true); + $(document).bind('keydown', 'ctrl+shift+i', () => { + if (utils.isElectron()) { + require('electron').remote.getCurrentWindow().toggleDevTools(); - $("#note-detail").focus(); + return false; + } + }); - return false; -}); + $(document).bind('keydown', 'ctrl+f', () => { + if (utils.isElectron()) { + const searchInPage = require('electron-in-page-search').default; + const remote = require('electron').remote; -$(document).bind('keydown', "ctrl+shift+down", () => { - const node = treeService.getCurrentNode(); - node.navigate($.ui.keyCode.DOWN, true); + const inPageSearch = searchInPage(remote.getCurrentWebContents()); - $("#note-detail").focus(); + inPageSearch.openSearchWindow(); - return false; -}); + return false; + } + }); -$(document).bind('keydown', 'ctrl+-', () => { - if (utils.isElectron()) { - const webFrame = require('electron').webFrame; + $(document).bind('keydown', "ctrl+shift+up", () => { + const node = treeService.getCurrentNode(); + node.navigate($.ui.keyCode.UP, true); - if (webFrame.getZoomFactor() > 0.2) { - webFrame.setZoomFactor(webFrame.getZoomFactor() - 0.1); + $("#note-detail").focus(); + + return false; + }); + + $(document).bind('keydown', "ctrl+shift+down", () => { + const node = treeService.getCurrentNode(); + node.navigate($.ui.keyCode.DOWN, true); + + $("#note-detail").focus(); + + return false; + }); + + $(document).bind('keydown', 'ctrl+-', () => { + if (utils.isElectron()) { + const webFrame = require('electron').webFrame; + + if (webFrame.getZoomFactor() > 0.2) { + webFrame.setZoomFactor(webFrame.getZoomFactor() - 0.1); + } + + return false; + } + }); + + $(document).bind('keydown', 'ctrl+=', () => { + if (utils.isElectron()) { + const webFrame = require('electron').webFrame; + + webFrame.setZoomFactor(webFrame.getZoomFactor() + 0.1); + + return false; + } + }); + + $("#note-title").bind('keydown', 'return', () => $("#note-detail").focus()); + + $(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 sends the request asynchronously and doesn't wait for result + noteEditor.saveNoteIfChanged(); + }); + + // Overrides the default autocomplete filter function to search for matched on atleast 1 word in each of the input term's words + $.ui.autocomplete.filter = (array, terms) => { + if (!terms) { + return array; } - return false; - } -}); + const startDate = new Date(); -$(document).bind('keydown', 'ctrl+=', () => { - if (utils.isElectron()) { - const webFrame = require('electron').webFrame; + const results = []; + const tokens = terms.toLowerCase().split(" "); - webFrame.setZoomFactor(webFrame.getZoomFactor() + 0.1); + for (const item of array) { + const lcLabel = item.label.toLowerCase(); - return false; - } -}); - -$("#note-title").bind('keydown', 'return', () => $("#note-detail").focus()); - -$(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 sends the request asynchronously and doesn't wait for result - noteEditor.saveNoteIfChanged(); -}); - -// Overrides the default autocomplete filter function to search for matched on atleast 1 word in each of the input term's words -$.ui.autocomplete.filter = (array, terms) => { - if (!terms) { - return array; - } - - const startDate = new Date(); - - const results = []; - const tokens = terms.toLowerCase().split(" "); - - for (const item of array) { - const lcLabel = item.label.toLowerCase(); - - const found = tokens.every(token => lcLabel.indexOf(token) !== -1); - if (!found) { - continue; - } - - // this is not completely correct and might cause minor problems with note with names containing this " / " - const lastSegmentIndex = lcLabel.lastIndexOf(" / "); - - if (lastSegmentIndex !== -1) { - const lastSegment = lcLabel.substr(lastSegmentIndex + 3); - - // at least some token needs to be in the last segment (leaf note), otherwise this - // particular note is not that interesting (query is satisfied by parent note) - const foundInLastSegment = tokens.some(token => lastSegment.indexOf(token) !== -1); - - if (!foundInLastSegment) { + const found = tokens.every(token => lcLabel.indexOf(token) !== -1); + if (!found) { continue; } + + // this is not completely correct and might cause minor problems with note with names containing this " / " + const lastSegmentIndex = lcLabel.lastIndexOf(" / "); + + if (lastSegmentIndex !== -1) { + const lastSegment = lcLabel.substr(lastSegmentIndex + 3); + + // at least some token needs to be in the last segment (leaf note), otherwise this + // particular note is not that interesting (query is satisfied by parent note) + const foundInLastSegment = tokens.some(token => lastSegment.indexOf(token) !== -1); + + if (!foundInLastSegment) { + continue; + } + } + + results.push(item); + + if (results.length > 100) { + break; + } } - results.push(item); + console.log("Search took " + (new Date().getTime() - startDate.getTime()) + "ms"); - if (results.length > 100) { - break; - } - } + return results; + }; - console.log("Search took " + (new Date().getTime() - startDate.getTime()) + "ms"); + $(document).tooltip({ + items: "#note-detail a", + content: function(callback) { + const notePath = link.getNotePathFromLink($(this).attr("href")); - return results; -}; + if (notePath !== null) { + const noteId = treeUtils.getNoteIdFromNotePath(notePath); -$(document).tooltip({ - items: "#note-detail a", - content: function(callback) { - const notePath = link.getNotePathFromLink($(this).attr("href")); - - if (notePath !== null) { - const noteId = treeUtils.getNoteIdFromNotePath(notePath); - - noteEditor.loadNote(noteId).then(note => callback(note.detail.content)); - } - }, - close: function(event, ui) - { - ui.tooltip.hover(function() - { - $(this).stop(true).fadeTo(400, 1); + noteEditor.loadNote(noteId).then(note => callback(note.detail.content)); + } }, - function() + close: function(event, ui) { - $(this).fadeOut('400', function() - { - $(this).remove(); - }); + ui.tooltip.hover(function() + { + $(this).stop(true).fadeTo(400, 1); + }, + function() + { + $(this).fadeOut('400', function() + { + $(this).remove(); + }); + }); + } + }); + + window.onerror = function (msg, url, lineNo, columnNo, error) { + const string = msg.toLowerCase(); + + let message = "Uncaught error: "; + + if (string.indexOf("script error") > -1){ + message += 'No details available'; + } + else { + message += [ + 'Message: ' + msg, + 'URL: ' + url, + 'Line: ' + lineNo, + 'Column: ' + columnNo, + 'Error object: ' + JSON.stringify(error) + ].join(' - '); + } + + messaging.logError(message); + + return false; + }; + + $("#logout-button").toggle(!utils.isElectron()); + + $(document).ready(() => { + server.get("script/startup").then(scriptBundles => { + for (const bundle of scriptBundles) { + utils.executeBundle(bundle); + } + }); + }); + + if (utils.isElectron()) { + require('electron').ipcRenderer.on('create-day-sub-note', async function(event, parentNoteId) { + // this might occur when day note had to be created + if (!await treeService.noteExists(parentNoteId)) { + await treeService.reload(); + } + + await treeService.activateNode(parentNoteId); + + setTimeout(() => { + const node = treeService.getCurrentNode(); + + treeService.createNote(node, node.data.noteId, 'into', node.data.isProtected); + }, 500); }); } -}); -window.onerror = function (msg, url, lineNo, columnNo, error) { - const string = msg.toLowerCase(); - - let message = "Uncaught error: "; - - if (string.indexOf("script error") > -1){ - message += 'No details available'; - } - else { - message += [ - 'Message: ' + msg, - 'URL: ' + url, - 'Line: ' + lineNo, - 'Column: ' + columnNo, - 'Error object: ' + JSON.stringify(error) - ].join(' - '); + function uploadAttachment() { + $("#attachment-upload").trigger('click'); } - messaging.logError(message); + $("#upload-attachment-button").click(uploadAttachment); - return false; -}; + $("#attachment-upload").change(async function() { + const formData = new FormData(); + formData.append('upload', this.files[0]); -$("#logout-button").toggle(!utils.isElectron()); + const resp = await $.ajax({ + url: baseApiUrl + 'attachments/upload/' + noteEditor.getCurrentNoteId(), + headers: server.getHeaders(), + data: formData, + type: 'POST', + contentType: false, // NEEDED, DON'T OMIT THIS + processData: false, // NEEDED, DON'T OMIT THIS + }); -$(document).ready(() => { - server.get("script/startup").then(scriptBundles => { - for (const bundle of scriptBundles) { - utils.executeBundle(bundle); - } + await treeService.reload(); + + await treeService.activateNode(resp.noteId); }); -}); - -if (utils.isElectron()) { - require('electron').ipcRenderer.on('create-day-sub-note', async function(event, parentNoteId) { - // this might occur when day note had to be created - if (!await treeService.noteExists(parentNoteId)) { - await treeService.reload(); - } - - await treeService.activateNode(parentNoteId); - - setTimeout(() => { - const node = treeService.getCurrentNode(); - - treeService.createNote(node, node.data.noteId, 'into', node.data.isProtected); - }, 500); - }); -} - -function uploadAttachment() { - $("#attachment-upload").trigger('click'); -} - -$("#upload-attachment-button").click(uploadAttachment); - -$("#attachment-upload").change(async function() { - const formData = new FormData(); - formData.append('upload', this.files[0]); - - const resp = await $.ajax({ - url: baseApiUrl + 'attachments/upload/' + noteEditor.getCurrentNoteId(), - headers: server.getHeaders(), - data: formData, - type: 'POST', - contentType: false, // NEEDED, DON'T OMIT THIS - processData: false, // NEEDED, DON'T OMIT THIS - }); - - await treeService.reload(); - - await treeService.activateNode(resp.noteId); -}); \ No newline at end of file +})(); diff --git a/src/public/javascripts/sync.js b/src/public/javascripts/sync.js index c0e970ddb..43cf217b5 100644 --- a/src/public/javascripts/sync.js +++ b/src/public/javascripts/sync.js @@ -1,24 +1,31 @@ "use strict"; -async function syncNow() { - const result = await server.post('sync/now'); +const syncService = (function() { + async function syncNow() { + const result = await server.post('sync/now'); - if (result.success) { - utils.showMessage("Sync finished successfully."); - } - else { - if (result.message.length > 50) { - result.message = result.message.substr(0, 50); + if (result.success) { + utils.showMessage("Sync finished successfully."); } + else { + if (result.message.length > 50) { + result.message = result.message.substr(0, 50); + } - utils.showError("Sync failed: " + result.message); + utils.showError("Sync failed: " + result.message); + } } -} -$("#sync-now-button").click(syncNow); + $("#sync-now-button").click(syncNow); -async function forceNoteSync(noteId) { - const result = await server.post('sync/force-note-sync/' + noteId); + async function forceNoteSync(noteId) { + const result = await server.post('sync/force-note-sync/' + noteId); - utils.showMessage("Note added to sync queue."); -} \ No newline at end of file + utils.showMessage("Note added to sync queue."); + } + + return { + syncNow, + forceNoteSync + }; +})(); \ No newline at end of file