trilium/src/public/javascripts/services/note_detail_text.js

98 lines
2.7 KiB
JavaScript
Raw Normal View History

2018-03-28 10:42:46 +08:00
import libraryLoader from "./library_loader.js";
import treeService from './tree.js';
2019-05-02 04:19:29 +08:00
class NoteDetailText {
/**
2019-05-09 01:55:24 +08:00
* @param {TabContext} ctx
2019-05-02 04:19:29 +08:00
*/
constructor(ctx) {
2019-05-02 05:06:18 +08:00
this.ctx = ctx;
2019-05-09 01:55:24 +08:00
this.$component = ctx.$tabContent.find('.note-detail-text');
2019-05-02 04:19:29 +08:00
this.textEditor = null;
this.$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');
}
})
}
2019-05-12 18:58:55 +08:00
async render() {
2019-05-02 04:19:29 +08:00
if (!this.textEditor) {
await libraryLoader.requireLibrary(libraryLoader.CKEDITOR);
2019-05-02 04:19:29 +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.
this.$component.show();
2019-03-05 05:36:46 +08:00
2019-05-02 04:19:29 +08:00
// textEditor might have been initialized during previous await so checking again
// looks like double initialization can freeze CKEditor pretty badly
if (!this.textEditor) {
this.textEditor = await BalloonEditor.create(this.$component[0], {
placeholder: "Type the content of your note here ..."
});
2019-05-04 20:34:03 +08:00
this.onNoteChange(() => this.ctx.noteChanged());
2019-05-02 04:19:29 +08:00
}
}
2019-05-02 05:06:18 +08:00
this.textEditor.isReadOnly = await this.isReadOnly();
2019-05-02 04:19:29 +08:00
this.$component.show();
2019-05-04 06:16:41 +08:00
this.textEditor.setData(this.ctx.note.content);
}
2019-05-02 04:19:29 +08:00
getContent() {
let content = this.textEditor.getData();
2019-05-02 04:19:29 +08:00
// if content is only tags/whitespace (typically <p>&nbsp;</p>), then just make it empty
// this is important when setting new note to code
if (jQuery(content).text().trim() === '' && !content.includes("<img")) {
content = '';
}
2019-05-02 04:19:29 +08:00
return content;
}
2019-05-02 04:19:29 +08:00
async isReadOnly() {
const attributes = await this.ctx.attributes.getAttributes();
2019-05-02 04:19:29 +08:00
return attributes.some(attr => attr.type === 'label' && attr.name === 'readOnly');
}
2019-05-02 04:19:29 +08:00
focus() {
this.$component.focus();
}
2019-05-02 04:19:29 +08:00
getEditor() {
return this.textEditor;
}
2019-05-02 04:19:29 +08:00
onNoteChange(func) {
this.textEditor.model.document.on('change:data', func);
}
2019-05-02 04:19:29 +08:00
cleanup() {
if (this.textEditor) {
this.textEditor.setData('');
}
}
2019-05-02 04:19:29 +08:00
scrollToTop() {
this.$component.scrollTop(0);
}
2019-05-02 04:19:29 +08:00
}
export default NoteDetailText