Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,23 @@ _English:_ MBlock lets you create an unlimited number of data blocks within a si

> Please note: The examples are valid for MForm version 8 and higher. MBlock now requires the bloecks addon (^5.2.0) for modern drag & drop functionality.

## 🚨 Hinweis für markitup- und ckeditor-Nutzer
## 🚨 Hinweis für markitup- und ckeditor4-Nutzer

Copy & Paste funktioniert leider nicht!
Copy & Paste funktioniert leider nicht mit markitup und CKEditor 4!

Es sollte in den betreffenden Modulen deaktiviert werden.
**Gut zu wissen:** CKEditor 5 (CKE5) wird vollständig unterstützt und funktioniert einwandfrei mit Copy & Paste.

**Technischer Hintergrund:** CKEditor 4 und markitup verwenden ältere Initialisierungsmechanismen, die beim Klonen von Blöcken nicht korrekt repliziert werden können. CKEditor 5 hingegen nutzt eine moderne API, die eine vollständige Wiederherstellung nach dem Kopieren ermöglicht.

Für markitup und CKEditor 4 sollte Copy & Paste in den betreffenden Modulen deaktiviert werden:

Beispiel
```
echo MBlock::show(1, $form, [
'min' => 1, // Minimale Anzahl Items (werden initial angezeigt)
'max' => 10, // Maximale Anzahl Items
'template' => 'modern', // Template-Name
'copy_paste' => false, // Copy & Paste aktivieren
'copy_paste' => false, // Copy & Paste deaktivieren für markitup/CKEditor4
'online_offline' => true // Online/Offline Toggle , hidden field muss angelegt sein.
]);
```
Expand Down
64 changes: 63 additions & 1 deletion assets/mblock.js
Original file line number Diff line number Diff line change
Expand Up @@ -1821,10 +1821,72 @@ var MBlockClipboard = {
const wrapper = item.closest('.mblock_wrapper');
const moduleType = this.getModuleType(wrapper);

/**
* 🔧 FIX FOR ISSUE: CKE5 Problem beim Kopieren
*
* Problem: When copying a block with CKEditor5, the editor UI is removed from
* the original block and not restored, breaking the editor functionality.
*
* Root Cause: jQuery's clone(true, true) clones the entire DOM structure including
* the CKEditor5 UI elements (.ck-editor), which interferes with the editor instance.
*
* Solution: Temporarily detach CKEditor5 UI elements before cloning, then reattach
* them after cloning completes. This ensures:
* - The original block's CKEditor5 instance remains intact
* - The clone only contains the textarea (which gets reinitialized on paste)
* - Other blocks are not affected
*
* Technical Details:
* - CKEditor5 replaces textareas with a complex UI structure (.ck-editor)
* - We use jQuery's .detach() to temporarily remove UI (preserves events/data)
* - After cloning, we reattach UI to original position using stored references
* - Error handling ensures graceful failure if DOM structure changes
*/

// Store references to CKE5 editor UI elements that need to be preserved
const cke5Editors = [];
item.find('.cke5-editor').each(function() {
const $textarea = $(this);
const $ckeUI = $textarea.next('.ck-editor');

if ($ckeUI.length) {
// Store reference to the CKE UI element and its position
cke5Editors.push({
textarea: $textarea,
ckeUI: $ckeUI,
parent: $ckeUI.parent(),
nextSibling: $ckeUI.next()
});

// Temporarily detach the CKE UI from DOM (but don't destroy it)
$ckeUI.detach();
console.log('MBlock Copy: Temporarily detached CKE5 UI for', $textarea.attr('id'));
}
});

// Clone item completely
// Clone item completely (now without CKE5 UI elements)
const clonedItem = item.clone(true, true);

// Restore CKEditor5 UI elements to original block
cke5Editors.forEach(editor => {
try {
// Verify parent still exists and is in the DOM before reattachment
if (editor.parent && editor.parent.length && document.contains(editor.parent[0])) {
// Reattach the CKE UI element to its original position
if (editor.nextSibling && editor.nextSibling.length) {
editor.ckeUI.insertBefore(editor.nextSibling);
} else {
editor.parent.append(editor.ckeUI);
}
console.log('MBlock Copy: Restored CKE5 UI for', editor.textarea.attr('id'));
} else {
console.warn('MBlock Copy: Parent element no longer exists, cannot restore CKE5 UI');
}
} catch (error) {
console.error('MBlock Copy: Error restoring CKE5 UI:', error);
}
});

// Convert selectpicker elements back to plain select elements for clean copying
this.convertSelectpickerToPlainSelect(clonedItem);

Expand Down
3 changes: 1 addition & 2 deletions assets/mblock.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion assets/mblock.min.js.map

Large diffs are not rendered by default.