comparison 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
comparison
equal deleted inserted replaced
203:92a57bd716c1 204:e5aed6c36672
42 function createToolbar(editor) { 42 function createToolbar(editor) {
43 const toolbar = document.createElement('div'); 43 const toolbar = document.createElement('div');
44 toolbar.className = 'rich-editor-toolbar'; 44 toolbar.className = 'rich-editor-toolbar';
45 45
46 const buttons = [ 46 const buttons = [
47 { cmd: 'h1', label: 'H1', title: 'Heading 1' }, 47 { cmd: 'h1', label: '', title: 'Heading 1', icons: "/public/icons/h1.png" },
48 { cmd: 'h2', label: 'H2', title: 'Heading 2' }, 48 { cmd: 'h2', label: '', title: 'Heading 2', icons: "/public/icons/h2.png" },
49 { cmd: 'h3', label: 'H3', title: 'Heading 3' }, 49 { cmd: 'h3', label: '', title: 'Heading 3', icons: "/public/icons/h3.png" },
50 { cmd: 'p', label: 'ΒΆ', title: 'Paragraph' }, 50 { cmd: 'p', label: 'ΒΆ', title: 'Paragraph' },
51 { cmd: 'ul', label: 'β€’', title: 'Bullet List' }, 51 { cmd: 'ul', label: 'β€’', title: 'Bullet List' },
52 { cmd: 'ol', label: '1.', title: 'Numbered List' }, 52 { cmd: 'ol', label: '1.', title: 'Numbered List' },
53 { cmd: 'bold', label: '', title: 'Bold', icons: "/public/icons/bold.png" },
53 { cmd: 'separator' }, 54 { cmd: 'separator' },
54 { cmd: 'bold', label: 'B', title: 'Bold' }, 55 { cmd: 'link', label: '', title: 'Insert Link', icons: "/public/icons/link.png" },
55 { cmd: 'italic', label: 'I', title: 'Italic' }, 56 { cmd: 'notelink', label: '', title: 'Link to Note', icons: "/public/icons/binder.png" },
57 { cmd: 'upload', label: '', title: 'Upload File', icons: "/public/icons/clipy.png" },
56 { cmd: 'separator' }, 58 { cmd: 'separator' },
57 { cmd: 'link', label: 'πŸ”—', title: 'Insert Link' }, 59 { cmd: 'readonly', label: '', title: 'readonly', icons: "/public/icons/book.png" },
58 { cmd: 'notelink', label: 'πŸ“', title: 'Link to Note' },
59 { cmd: 'upload', label: 'πŸ“Ž', title: 'Upload File' }
60 ]; 60 ];
61 61
62 buttons.forEach(btn => { 62 buttons.forEach(btn => {
63 if (btn.cmd === 'separator') { 63 if (btn.cmd === 'separator') {
64 const sep = document.createElement('span'); 64 const sep = document.createElement('span');
68 } 68 }
69 69
70 const button = document.createElement('button'); 70 const button = document.createElement('button');
71 button.type = 'button'; 71 button.type = 'button';
72 button.className = 'rich-editor-btn'; 72 button.className = 'rich-editor-btn';
73 if (btn.icons)
74 button.style.backgroundImage = `url("${btn.icons}")`;
73 button.textContent = btn.label; 75 button.textContent = btn.label;
74 button.title = btn.title; 76 button.title = btn.title;
75 button.dataset.cmd = btn.cmd; 77 button.dataset.cmd = btn.cmd;
76 78
77 button.addEventListener('click', (e) => { 79 button.addEventListener('click', (e) => {
112 border-radius: 4px; 114 border-radius: 4px;
113 background: #fff; 115 background: #fff;
114 cursor: pointer; 116 cursor: pointer;
115 font-size: 14px; 117 font-size: 14px;
116 min-width: 32px; 118 min-width: 32px;
119 background-repeat: no-repeat;
120 background-position: center;
121 background-size: 24px 24px;
122 border: none;
117 } 123 }
118 124
119 .rich-editor-btn:hover { 125 .rich-editor-btn:hover {
120 background: #e9e9e9; 126 background: #e9e9e9;
127 background-repeat: no-repeat;
128 background-position: center;
129 background-size: 24px 24px;
121 } 130 }
122 131
123 .rich-editor-btn:active { 132 .rich-editor-btn:active {
124 background: #ddd; 133 background: #ddd;
134 background-repeat: no-repeat;
135 background-position: center;
136 background-size: 24px 24px;
125 } 137 }
126 138
127 .rich-editor-separator { 139 .rich-editor-separator {
128 width: 1px; 140 width: 1px;
129 background: #ccc; 141 background: #ccc;
216 } 228 }
217 229
218 .rich-editor-file-input { 230 .rich-editor-file-input {
219 display: none; 231 display: none;
220 } 232 }
233
234 ol,ul {
235 padding: 16px;
236 }
221 `; 237 `;
222 document.head.appendChild(style); 238 document.head.appendChild(style);
223 } 239 }
224 240
225 class Editor { 241 class Editor {
226 constructor(elementId, options) { 242 constructor(elementId, options) {
227 this.options = { ...DEFAULT_OPTIONS, ...options }; 243 this.options = { ...DEFAULT_OPTIONS, ...options };
228 this.container = document.getElementById(elementId); 244 this.container = document.getElementById(elementId);
245 this.state = { readOnly: false };
229 246
230 if (!this.container) { 247 if (!this.container) {
231 throw new Error(`Element with id "${elementId}" not found`); 248 throw new Error(`Element with id "${elementId}" not found`);
232 } 249 }
233 250
394 411
395 triggerFileUpload() { 412 triggerFileUpload() {
396 this.fileInput.click(); 413 this.fileInput.click();
397 } 414 }
398 415
416 readOnly() {
417 this.state.readOnly = !this.state.readOnly;
418
419 if (this.state.readOnly)
420 {
421 this.content.contentEditable = false;
422 this.setStatus('Read-only mode');
423 const buttons = this.toolbar.querySelectorAll('.rich-editor-btn');
424 buttons.forEach(btn => {
425 if (btn.dataset.cmd !== 'readonly') {
426 btn.disabled = true;
427 }
428 });
429 }
430 else
431 {
432 // Enable editing
433 this.content.contentEditable = true;
434 this.content.style.backgroundColor = '';
435 this.setStatus('Ready');
436
437 // Enable toolbar buttons
438 const buttons = this.toolbar.querySelectorAll('.rich-editor-btn');
439 buttons.forEach(btn => {
440 btn.disabled = false;
441 });
442 }
443 }
444
399 async uploadFile(file) { 445 async uploadFile(file) {
400 if (!this.options.uploadCallback) { 446 if (!this.options.uploadCallback) {
401 console.warn('No upload callback configured'); 447 console.warn('No upload callback configured');
402 return; 448 return;
403 } 449 }
496 this.insertNoteLink(); 542 this.insertNoteLink();
497 break; 543 break;
498 case 'upload': 544 case 'upload':
499 this.triggerFileUpload(); 545 this.triggerFileUpload();
500 break; 546 break;
547 case 'readonly':
548 this.readOnly();
549 break;
501 } 550 }
502 551
503 if (this.debouncedSave) this.debouncedSave(); 552 if (this.debouncedSave) this.debouncedSave();
504 } 553 }
505 554