annotate rich_editor/rich_editor.js @ 204:e5aed6c36672

[Notes] Added icons and updated styling a bit. Probalby usable now.
author MrJuneJune <me@mrjunejune.com>
date Sun, 15 Feb 2026 11:02:13 -0800
parents 6cdee35a7ba9
children 240337164a80
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
201
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1 /**
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2 * Rich Editor
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
3 * -----------
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
4 * A vanilla JavaScript rich text editor with:
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
5 * - Text formatting (h1-h6, paragraphs, lists)
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
6 * - Image/file upload via paste, drop, click, or /upload command
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
7 * - Debounced auto-save
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
8 * - Generic callback functions for uploads and saves
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
9 *
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
10 * Usage:
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
11 * const editor = RichEditor.init('editor-container', {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
12 * uploadCallback: async (file) => { return { url: '...', key: '...' }; },
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
13 * saveCallback: async (content) => { console.log('Saved:', content); },
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
14 * debounceMs: 1000,
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
15 * placeholder: 'Start writing...'
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
16 * });
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
17 */
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
18
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
19 const RichEditor = (function() {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
20 'use strict';
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
21
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
22 const DEFAULT_OPTIONS = {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
23 uploadCallback: null,
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
24 saveCallback: null,
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
25 debounceMs: 1000,
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
26 placeholder: 'Start writing... (Use /upload to insert files)',
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
27 cloudFrontUrl: ''
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
28 };
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
29
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
30 function debounce(func, wait) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
31 let timeout;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
32 return function executedFunction(...args) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
33 const later = () => {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
34 clearTimeout(timeout);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
35 func(...args);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
36 };
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
37 clearTimeout(timeout);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
38 timeout = setTimeout(later, wait);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
39 };
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
40 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
41
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
42 function createToolbar(editor) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
43 const toolbar = document.createElement('div');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
44 toolbar.className = 'rich-editor-toolbar';
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
45
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
46 const buttons = [
204
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
47 { cmd: 'h1', label: '', title: 'Heading 1', icons: "/public/icons/h1.png" },
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
48 { cmd: 'h2', label: '', title: 'Heading 2', icons: "/public/icons/h2.png" },
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
49 { cmd: 'h3', label: '', title: 'Heading 3', icons: "/public/icons/h3.png" },
201
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
50 { cmd: 'p', label: '¶', title: 'Paragraph' },
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
51 { cmd: 'ul', label: '•', title: 'Bullet List' },
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
52 { cmd: 'ol', label: '1.', title: 'Numbered List' },
204
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
53 { cmd: 'bold', label: '', title: 'Bold', icons: "/public/icons/bold.png" },
201
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
54 { cmd: 'separator' },
204
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
55 { cmd: 'link', label: '', title: 'Insert Link', icons: "/public/icons/link.png" },
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
56 { cmd: 'notelink', label: '', title: 'Link to Note', icons: "/public/icons/binder.png" },
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
57 { cmd: 'upload', label: '', title: 'Upload File', icons: "/public/icons/clipy.png" },
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
58 { cmd: 'separator' },
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
59 { cmd: 'readonly', label: '', title: 'readonly', icons: "/public/icons/book.png" },
201
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
60 ];
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
61
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
62 buttons.forEach(btn => {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
63 if (btn.cmd === 'separator') {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
64 const sep = document.createElement('span');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
65 sep.className = 'rich-editor-separator';
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
66 toolbar.appendChild(sep);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
67 return;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
68 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
69
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
70 const button = document.createElement('button');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
71 button.type = 'button';
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
72 button.className = 'rich-editor-btn';
204
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
73 if (btn.icons)
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
74 button.style.backgroundImage = `url("${btn.icons}")`;
201
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
75 button.textContent = btn.label;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
76 button.title = btn.title;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
77 button.dataset.cmd = btn.cmd;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
78
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
79 button.addEventListener('click', (e) => {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
80 e.preventDefault();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
81 editor.execCommand(btn.cmd);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
82 });
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
83
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
84 toolbar.appendChild(button);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
85 });
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
86
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
87 return toolbar;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
88 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
89
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
90 function createStyles() {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
91 if (document.getElementById('rich-editor-styles')) return;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
92
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
93 const style = document.createElement('style');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
94 style.id = 'rich-editor-styles';
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
95 style.textContent = `
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
96 .rich-editor-container {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
97 border: 1px solid #ccc;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
98 border-radius: 4px;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
99 overflow: hidden;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
100 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
101
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
102 .rich-editor-toolbar {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
103 display: flex;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
104 flex-wrap: wrap;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
105 gap: 4px;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
106 padding: 8px;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
107 background: #f5f5f5;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
108 border-bottom: 1px solid #ccc;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
109 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
110
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
111 .rich-editor-btn {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
112 padding: 6px 12px;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
113 border: 1px solid #ccc;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
114 border-radius: 4px;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
115 background: #fff;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
116 cursor: pointer;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
117 font-size: 14px;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
118 min-width: 32px;
204
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
119 background-repeat: no-repeat;
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
120 background-position: center;
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
121 background-size: 24px 24px;
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
122 border: none;
201
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
123 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
124
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
125 .rich-editor-btn:hover {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
126 background: #e9e9e9;
204
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
127 background-repeat: no-repeat;
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
128 background-position: center;
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
129 background-size: 24px 24px;
201
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
130 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
131
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
132 .rich-editor-btn:active {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
133 background: #ddd;
204
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
134 background-repeat: no-repeat;
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
135 background-position: center;
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
136 background-size: 24px 24px;
201
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
137 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
138
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
139 .rich-editor-separator {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
140 width: 1px;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
141 background: #ccc;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
142 margin: 0 4px;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
143 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
144
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
145 .rich-editor-content {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
146 min-height: 300px;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
147 padding: 16px;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
148 outline: none;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
149 overflow-y: auto;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
150 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
151
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
152 .rich-editor-content:empty:before {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
153 content: attr(data-placeholder);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
154 color: #999;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
155 pointer-events: none;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
156 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
157
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
158 .rich-editor-content img {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
159 max-width: 100%;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
160 height: auto;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
161 border-radius: 4px;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
162 margin: 8px 0;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
163 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
164
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
165 .rich-editor-content a {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
166 color: #0078ff;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
167 text-decoration: none;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
168 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
169
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
170 .rich-editor-content a:hover {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
171 text-decoration: underline;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
172 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
173
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
174 .rich-editor-content a.note-link {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
175 background: #e8f4ff;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
176 padding: 2px 6px;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
177 border-radius: 3px;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
178 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
179
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
180 .rich-editor-content a.note-link:hover {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
181 background: #d0e8ff;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
182 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
183
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
184 .rich-editor-content .upload-placeholder {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
185 display: inline-block;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
186 padding: 8px 16px;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
187 background: #f0f0f0;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
188 border-radius: 4px;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
189 color: #666;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
190 font-style: italic;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
191 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
192
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
193 .rich-editor-content .upload-placeholder.loading {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
194 padding: 8px 16px;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
195 background: #fffacd;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
196 border-radius: 4px;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
197 animation: pulse 1.5s ease-in-out infinite;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
198 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
199
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
200 @keyframes pulse {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
201 0%, 100% { opacity: 1; }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
202 50% { opacity: 0.6; }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
203 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
204
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
205 .rich-editor-upload-overlay {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
206 position: absolute;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
207 top: 0;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
208 left: 0;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
209 right: 0;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
210 bottom: 0;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
211 background: rgba(0, 120, 255, 0.1);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
212 border: 2px dashed #0078ff;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
213 display: flex;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
214 align-items: center;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
215 justify-content: center;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
216 font-size: 18px;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
217 color: #0078ff;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
218 pointer-events: none;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
219 z-index: 10;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
220 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
221
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
222 .rich-editor-status {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
223 padding: 4px 8px;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
224 font-size: 12px;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
225 color: #666;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
226 background: #f9f9f9;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
227 border-top: 1px solid #eee;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
228 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
229
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
230 .rich-editor-file-input {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
231 display: none;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
232 }
204
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
233
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
234 ol,ul {
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
235 padding: 16px;
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
236 }
201
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
237 `;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
238 document.head.appendChild(style);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
239 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
240
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
241 class Editor {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
242 constructor(elementId, options) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
243 this.options = { ...DEFAULT_OPTIONS, ...options };
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
244 this.container = document.getElementById(elementId);
204
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
245 this.state = { readOnly: false };
201
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
246
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
247 if (!this.container) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
248 throw new Error(`Element with id "${elementId}" not found`);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
249 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
250
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
251 this.init();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
252 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
253
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
254 init() {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
255 createStyles();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
256
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
257 // Create wrapper
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
258 this.wrapper = document.createElement('div');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
259 this.wrapper.className = 'rich-editor-container';
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
260 this.wrapper.style.position = 'relative';
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
261
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
262 // Create toolbar
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
263 this.toolbar = createToolbar(this);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
264 this.wrapper.appendChild(this.toolbar);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
265
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
266 // Create content area
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
267 this.content = document.createElement('div');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
268 this.content.className = 'rich-editor-content';
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
269 this.content.contentEditable = true;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
270 this.content.dataset.placeholder = this.options.placeholder;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
271 this.wrapper.appendChild(this.content);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
272
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
273 // Create status bar
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
274 this.status = document.createElement('div');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
275 this.status.className = 'rich-editor-status';
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
276 this.status.textContent = 'Ready';
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
277 this.wrapper.appendChild(this.status);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
278
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
279 // Create hidden file input
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
280 this.fileInput = document.createElement('input');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
281 this.fileInput.type = 'file';
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
282 this.fileInput.className = 'rich-editor-file-input';
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
283 this.fileInput.multiple = true;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
284 this.fileInput.accept = 'image/*,application/pdf,.doc,.docx,.txt';
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
285 this.wrapper.appendChild(this.fileInput);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
286
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
287 // Add to container
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
288 this.container.appendChild(this.wrapper);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
289
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
290 // Setup event listeners
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
291 this.setupEvents();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
292
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
293 // Setup debounced save
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
294 if (this.options.saveCallback) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
295 this.debouncedSave = debounce(() => {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
296 this.save();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
297 }, this.options.debounceMs);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
298 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
299 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
300
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
301 setupEvents() {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
302 // Input events for auto-save
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
303 this.content.addEventListener('input', () => {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
304 if (this.debouncedSave) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
305 this.setStatus('Editing...');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
306 this.debouncedSave();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
307 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
308 });
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
309
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
310 // Handle paste
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
311 this.content.addEventListener('paste', (e) => {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
312 const items = e.clipboardData?.items;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
313 if (!items) return;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
314
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
315 for (const item of items) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
316 if (item.type.startsWith('image/') || item.kind === 'file') {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
317 e.preventDefault();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
318 const file = item.getAsFile();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
319 if (file) this.uploadFile(file);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
320 return;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
321 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
322 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
323 });
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
324
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
325 // Handle drop
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
326 this.content.addEventListener('dragover', (e) => {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
327 e.preventDefault();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
328 this.showDropOverlay();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
329 });
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
330
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
331 this.content.addEventListener('dragleave', (e) => {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
332 e.preventDefault();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
333 this.hideDropOverlay();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
334 });
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
335
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
336 this.content.addEventListener('drop', (e) => {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
337 e.preventDefault();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
338 this.hideDropOverlay();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
339
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
340 const files = e.dataTransfer?.files;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
341 if (files && files.length > 0) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
342 for (const file of files) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
343 this.uploadFile(file);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
344 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
345 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
346 });
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
347
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
348 // Handle /upload command
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
349 this.content.addEventListener('keydown', (e) => {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
350 if (e.key === 'Enter') {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
351 const selection = window.getSelection();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
352 const node = selection.anchorNode;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
353 if (node && node.textContent) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
354 const text = node.textContent;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
355 if (text.trim() === '/upload') {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
356 e.preventDefault();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
357 node.textContent = '';
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
358 this.triggerFileUpload();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
359 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
360 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
361 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
362 });
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
363
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
364 // File input change
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
365 this.fileInput.addEventListener('change', (e) => {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
366 const files = e.target.files;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
367 if (files && files.length > 0) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
368 for (const file of files) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
369 this.uploadFile(file);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
370 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
371 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
372 this.fileInput.value = '';
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
373 });
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
374
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
375 // Handle keyboard shortcuts
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
376 this.content.addEventListener('keydown', (e) => {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
377 if (e.ctrlKey || e.metaKey) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
378 switch (e.key.toLowerCase()) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
379 case 'b':
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
380 e.preventDefault();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
381 this.execCommand('bold');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
382 break;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
383 case 'i':
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
384 e.preventDefault();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
385 this.execCommand('italic');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
386 break;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
387 case 's':
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
388 e.preventDefault();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
389 this.save();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
390 break;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
391 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
392 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
393 });
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
394 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
395
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
396 showDropOverlay() {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
397 if (this.dropOverlay) return;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
398
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
399 this.dropOverlay = document.createElement('div');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
400 this.dropOverlay.className = 'rich-editor-upload-overlay';
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
401 this.dropOverlay.textContent = 'Drop files here to upload';
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
402 this.wrapper.appendChild(this.dropOverlay);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
403 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
404
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
405 hideDropOverlay() {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
406 if (this.dropOverlay) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
407 this.dropOverlay.remove();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
408 this.dropOverlay = null;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
409 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
410 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
411
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
412 triggerFileUpload() {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
413 this.fileInput.click();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
414 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
415
204
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
416 readOnly() {
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
417 this.state.readOnly = !this.state.readOnly;
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
418
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
419 if (this.state.readOnly)
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
420 {
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
421 this.content.contentEditable = false;
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
422 this.setStatus('Read-only mode');
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
423 const buttons = this.toolbar.querySelectorAll('.rich-editor-btn');
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
424 buttons.forEach(btn => {
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
425 if (btn.dataset.cmd !== 'readonly') {
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
426 btn.disabled = true;
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
427 }
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
428 });
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
429 }
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
430 else
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
431 {
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
432 // Enable editing
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
433 this.content.contentEditable = true;
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
434 this.content.style.backgroundColor = '';
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
435 this.setStatus('Ready');
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
436
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
437 // Enable toolbar buttons
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
438 const buttons = this.toolbar.querySelectorAll('.rich-editor-btn');
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
439 buttons.forEach(btn => {
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
440 btn.disabled = false;
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
441 });
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
442 }
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
443 }
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
444
201
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
445 async uploadFile(file) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
446 if (!this.options.uploadCallback) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
447 console.warn('No upload callback configured');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
448 return;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
449 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
450
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
451 // Insert loading placeholder
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
452 const placeholder = document.createElement('div');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
453 placeholder.className = 'upload-placeholder loading';
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
454 placeholder.textContent = file.type.startsWith('image/')
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
455 ? `Processing ${file.name}... ⏳`
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
456 : `Uploading ${file.name}...`;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
457
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
458 this.insertAtCursor(placeholder);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
459
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
460 this.setStatus(`Uploading ${file.name}...`);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
461
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
462 try {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
463 const result = await this.options.uploadCallback(file);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
464
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
465 if (result && result.url) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
466 // Replace placeholder with actual content
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
467 if (file.type.startsWith('image/')) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
468 const img = document.createElement('img');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
469 img.src = result.url;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
470 img.alt = file.name;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
471 placeholder.replaceWith(img);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
472 } else {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
473 const link = document.createElement('a');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
474 link.href = result.url;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
475 link.textContent = file.name;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
476 link.target = '_blank';
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
477 placeholder.replaceWith(link);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
478 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
479
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
480 this.setStatus(`Uploaded ${file.name}`);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
481 if (this.debouncedSave) this.debouncedSave();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
482 } else {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
483 placeholder.textContent = `Failed to upload ${file.name}`;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
484 placeholder.className = 'upload-placeholder';
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
485 this.setStatus('Upload failed');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
486 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
487 } catch (error) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
488 console.error('Upload error:', error);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
489 placeholder.textContent = `Error: ${error.message}`;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
490 placeholder.className = 'upload-placeholder';
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
491 this.setStatus('Upload error');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
492 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
493 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
494
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
495 insertAtCursor(element) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
496 const selection = window.getSelection();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
497 if (selection.rangeCount > 0) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
498 const range = selection.getRangeAt(0);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
499 range.deleteContents();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
500 range.insertNode(element);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
501 range.setStartAfter(element);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
502 range.collapse(true);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
503 selection.removeAllRanges();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
504 selection.addRange(range);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
505 } else {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
506 this.content.appendChild(element);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
507 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
508 this.content.focus();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
509 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
510
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
511 execCommand(cmd) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
512 this.content.focus();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
513
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
514 switch (cmd) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
515 case 'h1':
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
516 case 'h2':
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
517 case 'h3':
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
518 case 'h4':
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
519 case 'h5':
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
520 case 'h6':
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
521 document.execCommand('formatBlock', false, cmd);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
522 break;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
523 case 'p':
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
524 document.execCommand('formatBlock', false, 'p');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
525 break;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
526 case 'ul':
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
527 document.execCommand('insertUnorderedList', false, null);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
528 break;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
529 case 'ol':
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
530 document.execCommand('insertOrderedList', false, null);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
531 break;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
532 case 'bold':
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
533 document.execCommand('bold', false, null);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
534 break;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
535 case 'italic':
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
536 document.execCommand('italic', false, null);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
537 break;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
538 case 'link':
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
539 this.insertLink();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
540 break;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
541 case 'notelink':
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
542 this.insertNoteLink();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
543 break;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
544 case 'upload':
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
545 this.triggerFileUpload();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
546 break;
204
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
547 case 'readonly':
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
548 this.readOnly();
e5aed6c36672 [Notes] Added icons and updated styling a bit. Probalby usable now.
MrJuneJune <me@mrjunejune.com>
parents: 201
diff changeset
549 break;
201
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
550 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
551
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
552 if (this.debouncedSave) this.debouncedSave();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
553 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
554
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
555 insertLink() {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
556 const url = prompt('Enter URL:');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
557 if (!url) return;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
558
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
559 const selection = window.getSelection();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
560 const selectedText = selection.toString() || url;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
561
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
562 const link = document.createElement('a');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
563 link.href = url;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
564 link.textContent = selectedText;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
565 link.target = '_blank';
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
566
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
567 if (selection.rangeCount > 0) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
568 const range = selection.getRangeAt(0);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
569 range.deleteContents();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
570 range.insertNode(link);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
571 range.setStartAfter(link);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
572 range.collapse(true);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
573 selection.removeAllRanges();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
574 selection.addRange(range);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
575 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
576 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
577
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
578 insertNoteLink() {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
579 const noteId = prompt('Enter note ID (e.g., my-ideas):');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
580 if (!noteId) return;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
581
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
582 const sanitizedId = noteId.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
583 const selection = window.getSelection();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
584 const selectedText = selection.toString() || sanitizedId;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
585
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
586 const link = document.createElement('a');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
587 link.href = '/notes/' + encodeURIComponent(sanitizedId);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
588 link.textContent = selectedText;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
589 link.className = 'note-link';
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
590
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
591 if (selection.rangeCount > 0) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
592 const range = selection.getRangeAt(0);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
593 range.deleteContents();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
594 range.insertNode(link);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
595 range.setStartAfter(link);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
596 range.collapse(true);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
597 selection.removeAllRanges();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
598 selection.addRange(range);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
599 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
600 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
601
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
602 setStatus(text) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
603 this.status.textContent = text;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
604 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
605
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
606 async save() {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
607 if (!this.options.saveCallback) return;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
608
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
609 this.setStatus('Saving...');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
610
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
611 try {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
612 await this.options.saveCallback(this.getContent());
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
613 this.setStatus('Saved');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
614 } catch (error) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
615 console.error('Save error:', error);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
616 this.setStatus('Save failed');
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
617 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
618 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
619
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
620 getContent() {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
621 return this.content.innerHTML;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
622 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
623
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
624 setContent(html) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
625 this.content.innerHTML = html;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
626 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
627
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
628 getText() {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
629 return this.content.textContent;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
630 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
631
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
632 clear() {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
633 this.content.innerHTML = '';
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
634 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
635
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
636 focus() {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
637 this.content.focus();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
638 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
639 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
640
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
641 return {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
642 init: function(elementId, options) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
643 return new Editor(elementId, options);
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
644 }
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
645 };
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
646 })();
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
647
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
648 // Export for module systems
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
649 if (typeof module !== 'undefined' && module.exports) {
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
650 module.exports = RichEditor;
6cdee35a7ba9 [MrJuneJune] notes
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
651 }