mirror of
https://github.com/zadam/trilium.git
synced 2025-10-29 17:26:38 +01:00
note converted to module
This commit is contained in:
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
|
||||
};
|
||||
})();
|
||||
Reference in New Issue
Block a user