diff --git a/public/assets/js/bridge/blocks-standard.js b/public/assets/js/bridge/blocks-standard.js
index 6dad268..78b254d 100644
--- a/public/assets/js/bridge/blocks-standard.js
+++ b/public/assets/js/bridge/blocks-standard.js
@@ -107,7 +107,27 @@
// BUTTON (Registriert als 'std-button')
addOrUpdate(bm, 'std-button', { label:'Button (Basis)',
content:`Button` });
-
+
+ // TABLE (Registriert als 'std-table')
+ addOrUpdate(bm, 'std-table', { label:'Tabelle (Basis)',
+ content:`
+
+ | Spalte A |
+ Spalte B |
+ Spalte C |
+
+
+ | Zeile 1 |
+ ... |
+ ... |
+
+
+ | Zeile 2 |
+ ... |
+ ... |
+
+
` });
+
// DIVIDER (Registriert als 'std-divider')
addOrUpdate(bm, 'std-divider',{ label:'Trenner (Basis)',
content:`
` });
diff --git a/public/editor/bridge-core.js b/public/editor/bridge-core.js
index 699edd8..0d89397 100644
--- a/public/editor/bridge-core.js
+++ b/public/editor/bridge-core.js
@@ -319,6 +319,8 @@
const modal = editor.Modal;
if (!modal) return;
+ if (editor.__bridgeRteModalOpen) return;
+ editor.__bridgeRteModalOpen = true;
const doc = document;
const container = doc.createElement('div');
@@ -498,10 +500,14 @@
if (component.set) {
component.set('content', html);
component.trigger && component.trigger('change:content');
+ component.trigger && component.trigger('change:components');
}
if (component.view && component.view.render) {
component.view.render();
}
+ if (editor && typeof editor.trigger === 'function') {
+ editor.trigger('component:update', component);
+ }
} catch {}
modal.close();
});
@@ -512,6 +518,16 @@
modal.setTitle('Richtext Editor');
modal.setContent(container);
+ const mdl = modal.getModel && modal.getModel();
+ if (mdl && typeof mdl.set === 'function') {
+ mdl.set('closeOnEsc', false);
+ mdl.set('closeOnClick', false);
+ }
+ if (typeof modal.onceClose === 'function') {
+ modal.onceClose(() => {
+ editor.__bridgeRteModalOpen = false;
+ });
+ }
modal.open();
};
@@ -581,7 +597,7 @@
});
if (!(rte.get && rte.get('bridge-open-richtext'))) {
rte.add('bridge-open-richtext', {
- icon: 'RTE',
+ icon: '',
attributes: { title: 'Richtext Editor' },
result: () => {
const component = editor.getSelected && editor.getSelected();
@@ -614,13 +630,33 @@
'bridge-placeholder',
]);
- editor.on('component:selected', (model) => ensureTextToolbarButton(editor, model));
+ let lastTextSelection = { id: null, ts: 0 };
+ editor.on('component:selected', (model) => {
+ ensureTextToolbarButton(editor, model);
+ if (!model || !model.is || !model.is('text')) return;
+ const now = Date.now();
+ if (lastTextSelection.id === model.cid && (now - lastTextSelection.ts) < 450) {
+ openRichTextModal(editor, model);
+ }
+ lastTextSelection = { id: model.cid, ts: now };
+ });
editor.on('component:add', (model) => ensureTextToolbarButton(editor, model));
editor.on('component:dblclick', (model) => {
if (model && model.is && model.is('text')) {
openRichTextModal(editor, model);
}
});
+ editor.on('canvas:frame:load', () => {
+ const body = editor.Canvas && editor.Canvas.getBody && editor.Canvas.getBody();
+ if (!body || body.__bridgeRteDblclickBound) return;
+ body.__bridgeRteDblclickBound = true;
+ body.addEventListener('dblclick', () => {
+ const selected = editor.getSelected && editor.getSelected();
+ if (selected && selected.is && selected.is('text')) {
+ openRichTextModal(editor, selected);
+ }
+ }, true);
+ });
};
const loadDynamicFonts = async () => {