2018-03-28 10:42:46 +08:00
|
|
|
import libraryLoader from "./library_loader.js";
|
2018-03-27 12:22:02 +08:00
|
|
|
import noteDetailService from './note_detail.js';
|
2018-11-15 21:51:09 +08:00
|
|
|
import treeService from './tree.js';
|
2019-01-27 20:10:03 +08:00
|
|
|
import attributeService from "./attributes.js";
|
2018-03-27 12:22:02 +08:00
|
|
|
|
2018-11-08 17:30:35 +08:00
|
|
|
const $component = $('#note-detail-text');
|
2018-03-27 12:22:02 +08:00
|
|
|
|
|
|
|
let textEditor = null;
|
|
|
|
|
2018-03-28 09:46:38 +08:00
|
|
|
async function show() {
|
2018-03-27 12:22:02 +08:00
|
|
|
if (!textEditor) {
|
2018-03-28 10:42:46 +08:00
|
|
|
await libraryLoader.requireLibrary(libraryLoader.CKEDITOR);
|
2018-03-27 12:22:02 +08:00
|
|
|
|
2019-03-05 05:36:46 +08:00
|
|
|
// CKEditor since version 12 needs the element to be visible before initialization. At the same time
|
|
|
|
// we want to avoid flicker - i.e. show editor only once everything is ready. That's why we have separate
|
|
|
|
// display of $component in both branches.
|
|
|
|
$component.show();
|
|
|
|
|
2018-08-28 21:03:23 +08:00
|
|
|
// textEditor might have been initialized during previous await so checking again
|
|
|
|
// looks like double initialization can freeze CKEditor pretty badly
|
|
|
|
if (!textEditor) {
|
2019-03-05 05:39:44 +08:00
|
|
|
textEditor = await BalloonEditor.create($component[0], {
|
|
|
|
placeholder: "Type the content of your note here ..."
|
|
|
|
});
|
2018-03-27 12:22:02 +08:00
|
|
|
|
2018-09-03 22:05:28 +08:00
|
|
|
onNoteChange(noteDetailService.noteChanged);
|
2018-08-28 21:03:23 +08:00
|
|
|
}
|
2018-03-27 12:22:02 +08:00
|
|
|
}
|
|
|
|
|
2019-01-27 20:10:03 +08:00
|
|
|
textEditor.isReadOnly = await isReadOnly();
|
|
|
|
|
2018-11-08 17:30:35 +08:00
|
|
|
$component.show();
|
2019-03-05 05:36:46 +08:00
|
|
|
|
2019-03-15 03:21:27 +08:00
|
|
|
textEditor.setData(noteDetailService.getActiveNote().noteContent.content);
|
2018-03-27 12:22:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
function getContent() {
|
|
|
|
let content = textEditor.getData();
|
|
|
|
|
|
|
|
// if content is only tags/whitespace (typically <p> </p>), then just make it empty
|
|
|
|
// this is important when setting new note to code
|
|
|
|
if (jQuery(content).text().trim() === '' && !content.includes("<img")) {
|
|
|
|
content = '';
|
|
|
|
}
|
|
|
|
|
|
|
|
return content;
|
|
|
|
}
|
|
|
|
|
2019-01-27 20:10:03 +08:00
|
|
|
async function isReadOnly() {
|
|
|
|
const attributes = await attributeService.getAttributes();
|
|
|
|
|
|
|
|
return attributes.some(attr => attr.type === 'label' && attr.name === 'readOnly');
|
|
|
|
}
|
|
|
|
|
2018-03-27 12:22:02 +08:00
|
|
|
function focus() {
|
2018-11-08 17:30:35 +08:00
|
|
|
$component.focus();
|
2018-03-27 12:22:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
function getEditor() {
|
|
|
|
return textEditor;
|
|
|
|
}
|
|
|
|
|
2018-09-03 22:05:28 +08:00
|
|
|
function onNoteChange(func) {
|
|
|
|
textEditor.model.document.on('change:data', func);
|
|
|
|
}
|
|
|
|
|
2018-11-15 21:51:09 +08:00
|
|
|
$component.on("dblclick", "img", e => {
|
|
|
|
const $img = $(e.target);
|
|
|
|
const src = $img.prop("src");
|
|
|
|
|
|
|
|
const match = src.match(/\/api\/images\/([A-Za-z0-9]+)\//);
|
|
|
|
|
|
|
|
if (match) {
|
|
|
|
const noteId = match[1];
|
|
|
|
|
|
|
|
treeService.activateNote(noteId);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
window.open(src, '_blank');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2018-03-27 12:22:02 +08:00
|
|
|
export default {
|
2018-03-28 09:46:38 +08:00
|
|
|
show,
|
2018-03-27 12:22:02 +08:00
|
|
|
getEditor,
|
|
|
|
getContent,
|
2018-09-03 22:05:28 +08:00
|
|
|
focus,
|
2018-10-31 19:29:01 +08:00
|
|
|
onNoteChange,
|
|
|
|
cleanup: () => {
|
|
|
|
if (textEditor) {
|
|
|
|
textEditor.setData('');
|
|
|
|
}
|
2018-12-24 16:47:00 +08:00
|
|
|
},
|
|
|
|
scrollToTop: () => $component.scrollTop(0)
|
2018-03-27 12:22:02 +08:00
|
|
|
}
|