diff --git a/public/assets/js/bridge/blocks-placeholder.js b/public/assets/js/bridge/blocks-placeholder.js
index 04a288e..4263b24 100644
--- a/public/assets/js/bridge/blocks-placeholder.js
+++ b/public/assets/js/bridge/blocks-placeholder.js
@@ -150,22 +150,9 @@ const refreshPlaceholderComponent = (component) => {
return (payload.key || 'PLATZHALTER').toUpperCase();
};
-const buildPlaceholderHTML = (payload) => {
- const type = payload.type === 'database' ? 'database' : 'custom';
- const attrs = [
- `data-gjs-type="${PLACEHOLDER_COMPONENT}"`,
- `data-placeholder-type="${type}"`,
- `contenteditable="false"`,
- `class="${INLINE_PLACEHOLDER_CLASS}"`,
- ];
- if (type === 'database') {
- attrs.push(`data-placeholder-table="${payload.table || ''}"`);
- attrs.push(`data-placeholder-column="${payload.column || ''}"`);
- } else {
- attrs.push(`data-placeholder-key="${payload.key || ''}"`);
- }
+ const buildPlaceholderText = (payload) => {
const label = buildPlaceholderLabel(payload);
- return `{{${label}}}`;
+ return `{{${label}}}`;
};
const buildField = (labelText, control) => {
@@ -201,24 +188,7 @@ const buildPlaceholderHTML = (payload) => {
return comps;
};
- const reparseTextComponent = (component, editor) => {
- if (!component || typeof component.components !== 'function') return;
- const viewEl = component.view && component.view.el;
- if (!viewEl) return;
- const comps = buildTextnodeComponents(viewEl);
- try {
- if (comps.length) {
- component.components(comps);
- }
- if (component.em && typeof component.em.trigger === 'function') {
- component.em.trigger('component:update', component);
- } else if (editor && typeof editor.trigger === 'function') {
- editor.trigger('component:update', component);
- }
- } catch (err) {
- log('PLACEHOLDER ERROR', `Reparsing des Text-Elements fehlgeschlagen: ${err && err.message ? err.message : err}`, 'red', 'error');
- }
- };
+ const reparseTextComponent = () => {};
const captureRteSelection = (rteInstance) => {
const doc = rteInstance && rteInstance.doc
@@ -247,7 +217,7 @@ const buildPlaceholderHTML = (payload) => {
}
};
- const insertPlaceholderIntoSelection = (rteInstance, html) => {
+ const insertTextIntoSelection = (rteInstance, text) => {
const doc = rteInstance && rteInstance.doc
? rteInstance.doc
: (rteInstance && rteInstance.el && rteInstance.el.ownerDocument) || document;
@@ -258,70 +228,20 @@ const buildPlaceholderHTML = (payload) => {
if (!range) return false;
range.deleteContents();
- const temp = doc.createElement('div');
- temp.innerHTML = html;
- const fragment = doc.createDocumentFragment();
- while (temp.firstChild) {
- fragment.appendChild(temp.firstChild);
- }
- range.insertNode(fragment);
- range.collapse(false);
+ const textNode = doc.createTextNode(text);
+ range.insertNode(textNode);
+ range.setStartAfter(textNode);
+ range.collapse(true);
sel.removeAllRanges();
sel.addRange(range);
return true;
};
- const insertCaretMarker = (rteInstance, markerId) => {
- if (!markerId) return false;
- const markerHtml = ``;
- if (insertPlaceholderIntoSelection(rteInstance, markerHtml)) {
- return true;
- }
- if (rteInstance && typeof rteInstance.insertHTML === 'function') {
- rteInstance.insertHTML(markerHtml);
- return true;
- }
- if (typeof document !== 'undefined' && document.execCommand) {
- document.execCommand('insertHTML', false, markerHtml);
- return true;
- }
- return false;
- };
+ const insertCaretMarker = () => false;
- const removeMarkerFromComponent = (component, markerId, editor) => {
- if (!component || !markerId) return false;
- const viewEl = component.view && component.view.el;
- if (!viewEl) return false;
- const selector = `[${PLACEHOLDER_MARKER_ATTR}="${markerId}"]`;
- const marker = viewEl.querySelector(selector);
- if (!marker || !marker.parentNode) return false;
- marker.parentNode.removeChild(marker);
- reparseTextComponent(component, editor);
- return true;
- };
+ const removeMarkerFromComponent = () => false;
- const replaceMarkerWithPlaceholder = (component, markerId, payload, editor) => {
- if (!component || !markerId) return false;
- const viewEl = component.view && component.view.el;
- if (!viewEl) return false;
- const marker = viewEl.querySelector(`[${PLACEHOLDER_MARKER_ATTR}="${markerId}"]`);
- if (!marker) return false;
- if (typeof document === 'undefined') return false;
- const temp = document.createElement('div');
- temp.innerHTML = buildPlaceholderHTML(payload);
- const placeholderNode = temp.firstElementChild || temp.firstChild;
- if (!placeholderNode) return false;
- if (typeof marker.replaceWith === 'function') {
- marker.replaceWith(placeholderNode);
- } else if (marker.parentNode) {
- marker.parentNode.insertBefore(placeholderNode, marker);
- marker.parentNode.removeChild(marker);
- } else {
- return false;
- }
- reparseTextComponent(component, editor);
- return true;
- };
+ const replaceMarkerWithPlaceholder = () => false;
const openPlaceholderModal = (editor, component, opts = {}) => {
if (!editor) return;
@@ -641,59 +561,27 @@ const buildPlaceholderHTML = (payload) => {
log('PLACEHOLDER ERROR', 'Keine Text-Selektion gefunden. Bitte Cursor setzen und erneut versuchen.', 'red', 'error');
return;
}
- const markerId = `bridge-placeholder-marker-${Date.now()}-${Math.random().toString(36).slice(2)}`;
const restoreSelection = () => restoreRteSelection(selectionSnapshot);
- let markerInserted = false;
- if (restoreSelection()) {
- markerInserted = insertCaretMarker(rteInstance, markerId);
- if (markerInserted) {
- setTimeout(() => reparseTextComponent(target, editor), 0);
- }
- }
- const cleanupMarker = () => {
- if (markerInserted) {
- removeMarkerFromComponent(target, markerId, editor);
- markerInserted = false;
- }
- };
openPlaceholderModal(editor, null, {
onCancel: () => {
- cleanupMarker();
if (rteInstance && typeof rteInstance.focus === 'function') {
setTimeout(() => rteInstance.focus(), 0);
}
},
onSubmit: (payload) => {
- if (editor) {
- editor.__bridgePlaceholderSuppressAdd = (editor.__bridgePlaceholderSuppressAdd || 0) + 1;
+ if (!restoreSelection()) {
+ log('PLACEHOLDER ERROR', 'Cursor-Position konnte nicht wiederhergestellt werden.', 'red', 'error');
+ return false;
}
- let replaced = false;
- if (markerInserted) {
- replaced = replaceMarkerWithPlaceholder(target, markerId, payload, editor);
- }
- if (!replaced && restoreSelection()) {
- const html = buildPlaceholderHTML(payload);
- if (insertPlaceholderIntoSelection(rteInstance, html)) {
- setTimeout(() => reparseTextComponent(target, editor), 0);
- replaced = true;
- }
- }
- if (!replaced) {
- cleanupMarker();
- const viewEl = target.view && target.view.el;
- if (viewEl) {
- viewEl.insertAdjacentHTML('beforeend', buildPlaceholderHTML(payload));
- reparseTextComponent(target, editor);
- replaced = true;
- } else {
- log('PLACEHOLDER ERROR', 'Placeholder konnte nicht eingefügt werden (kein Ziel).', 'red', 'error');
- return false;
- }
+ const text = buildPlaceholderText(payload);
+ if (!insertTextIntoSelection(rteInstance, text)) {
+ log('PLACEHOLDER ERROR', 'Placeholder konnte nicht eingefügt werden.', 'red', 'error');
+ return false;
}
if (rteInstance && typeof rteInstance.focus === 'function') {
setTimeout(() => rteInstance.focus(), 0);
}
- return replaced;
+ return true;
}
});
},
@@ -1048,8 +936,6 @@ const buildPlaceholderHTML = (payload) => {
function register(editor) {
log('EXECUTION', `Starte Placeholder-Registrierung für ${TARGET_CAT_ID}.`, '#DAA520');
const bm = editor.BlockManager;
- ensurePlaceholderComponent(editor);
- ensureTextSupportsPlaceholders(editor);
if (!placeholderSchemaStore.promise && placeholderSchemaStore.status !== false) {
fetchPlaceholderSchema().catch(() => {});
}
@@ -1069,33 +955,6 @@ const buildPlaceholderHTML = (payload) => {
if (!editor.__bridgePlaceholderEventsBound) {
editor.__bridgePlaceholderEventsBound = true;
-
- editor.on('component:dblclick', (cmp) => {
- if (cmp && cmp.is && cmp.is(PLACEHOLDER_COMPONENT)) {
- openPlaceholderModal(editor, cmp);
- return false;
- }
- return undefined;
- });
-
- editor.on('component:add', (cmp) => {
- if (!cmp || !cmp.is || !cmp.is(PLACEHOLDER_COMPONENT)) return;
- if (editor.__bridgePlaceholderSuppressAdd) {
- editor.__bridgePlaceholderSuppressAdd = Math.max(0, (editor.__bridgePlaceholderSuppressAdd || 1) - 1);
- return;
- }
- if (window.__GJS_IS_PARSING) return;
- if (cmp.__bridgePlaceholderPrompted) return;
- cmp.__bridgePlaceholderPrompted = true;
- cmp.__bridgePlaceholderNew = true;
- setTimeout(() => openPlaceholderModal(editor, cmp, {
- onCancel: () => {
- if (cmp.__bridgePlaceholderNew) {
- safeRemoveComponent(cmp);
- }
- }
- }), 50);
- });
}
const bindRteButton = () => ensureRtePlaceholderButton(editor);
diff --git a/public/editor/bridge-core.js b/public/editor/bridge-core.js
index ff38211..518891a 100644
--- a/public/editor/bridge-core.js
+++ b/public/editor/bridge-core.js
@@ -371,7 +371,31 @@
}
});
}
- // Placeholder-Plugin entfernt: kein Fallback-Laden.
+ const ensurePlaceholderRte = () => {
+ if (ed.__bridgePlaceholderActive) {
+ return true;
+ }
+ if (window.BridgeBlocksPlaceholder && typeof window.BridgeBlocksPlaceholder.register === 'function') {
+ try {
+ window.BridgeBlocksPlaceholder.register(ed);
+ ed.__bridgePlaceholderActive = true;
+ log('PLACEHOLDER SYNC', 'Placeholder-RTE aktiv.', 'lime');
+ } catch (err) {
+ log('PLACEHOLDER ERROR', `Placeholder-RTE Fehler: ${err.message}`, 'red', 'error');
+ }
+ return true;
+ }
+ return false;
+ };
+ if (!ensurePlaceholderRte()) {
+ const fallbackSrc = B.BASE_PATH_BRIDGE + 'blocks-placeholder.js';
+ log('PLACEHOLDER LOAD', 'Placeholder-RTE wird geladen.', '#B45309', 'warn');
+ loadScript(fallbackSrc, () => {
+ if (!ensurePlaceholderRte()) {
+ log('PLACEHOLDER ERROR', 'Placeholder-RTE konnte nicht initialisiert werden.', 'red', 'error');
+ }
+ });
+ }
// ---------------------------------------------------
log('INIT API', 'API-Elemente werden nun durch das Plugin bridge-blocks-api geladen. (ASYNCHRON)', 'orange');