富文本編輯改用CKE

This commit is contained in:
2026-05-18 17:48:30 +08:00
parent f6af8c9a98
commit 9be9d5d924
5 changed files with 197 additions and 8 deletions

View File

@@ -1211,6 +1211,7 @@
patchPageTree(); patchPageTree();
patchI18n(); patchI18n();
enableSaveBtn(); enableSaveBtn();
initCKEditorOverride();
}); });
} else { } else {
patchSaveAjax(); patchSaveAjax();
@@ -1219,5 +1220,116 @@
patchPageTree(); patchPageTree();
patchI18n(); patchI18n();
enableSaveBtn(); enableSaveBtn();
initCKEditorOverride();
}
// ── 動態載入並覆寫 CKEditor ───────────────────────────────────────
function initCKEditorOverride() {
const script = document.createElement("script");
script.src = "https://cdn.ckeditor.com/4.22.1/full-all/ckeditor.js";
script.onload = () => {
// 隱藏版本過期警告
if (CKEDITOR.config) {
CKEDITOR.config.versionCheck = false;
}
const ckeditorOptions = {
extraPlugins: "sharedspace",
removePlugins: "exportpdf", // 解決 exportpdf-no-token-url 錯誤
sharedSpaces: {
top: "#wysiwyg-editor",
}
};
// 覆寫 Vvveb 原生的 WysiwygEditor改用 Vanilla JS
Vvveb.WysiwygEditor = {
isActive: false,
oldValue: '',
doc: false,
editor: false,
toolbar: false,
init: function(doc) {
this.doc = doc;
this.toolbar = document.getElementById('wysiwyg-editor');
if (this.toolbar) {
this.toolbar.classList.remove("default-editor");
this.toolbar.classList.add("ckeditor");
this.toolbar.innerHTML = '';
}
},
edit: function(element) {
this.element = element;
this.isActive = true;
this.oldValue = element.innerHTML;
Vvveb.Builder.selectPadding = 10;
element.setAttribute('contenteditable', true);
element.setAttribute('spellcheckker', false);
CKEDITOR.disableAutoInline = true;
ckeditorOptions.sharedSpaces.top = this.toolbar;
if (this.editor) {
try { this.editor.destroy(); } catch(e) {}
}
this.editor = CKEDITOR.inline(element, ckeditorOptions);
if (this.toolbar) {
this.toolbar.style.display = "block";
}
},
destroy: function(element) {
this.isActive = false;
if (this.editor) {
try {
this.editor.destroy();
} catch (e) {
console.warn("[my-editor] CKEditor destroy error", e);
}
this.editor = false;
}
if (element) {
element.removeAttribute('contenteditable');
element.removeAttribute('spellcheckker');
// 清除 CKEditor 殘留屬性,避免破壞 DOM 導致 VvvebJs 報錯
element.classList.remove('cke_editable', 'cke_editable_inline', 'cke_focus');
// 嘗試修復 Vvveb.Builder.selectedEl 為 null 的問題
if (typeof Vvveb.Builder !== "undefined" && !Vvveb.Builder.selectedEl) {
Vvveb.Builder.selectedEl = element;
}
}
if (this.toolbar) {
this.toolbar.style.display = "none";
}
const node = this.element || element;
if (node && Vvveb.Undo) {
Vvveb.Undo.addMutation({
type: 'characterData',
target: node,
oldValue: this.oldValue,
newValue: node.innerHTML
});
}
}
};
// 嘗試立即初始化,以綁定 `#wysiwyg-editor` 元素
if (typeof Vvveb !== "undefined" && Vvveb.Builder && Vvveb.Builder.iframe) {
Vvveb.WysiwygEditor.init(Vvveb.Builder.iframe.contentDocument);
}
console.log("[my-editor] CKEditor 4 external override injected successfully.");
};
document.head.appendChild(script);
} }
})(); })();

View File

@@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" =""><head> <html lang="en" =""="" =""><head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content=""> <meta name="description" content="">
@@ -23,7 +23,7 @@
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-lg-12 text-center"> <div class="col-lg-12 text-center">
<h1 class="mt-5">About Us page</h1> <h1 class="mt-5">About&nbsp; Coolpage</h1>
<p class="lead">Start by dragging components to page or double click to edit text</p> <p class="lead">Start by dragging components to page or double click to edit text</p>
</div> </div>
</div> </div>

View File

@@ -0,0 +1,33 @@
<!DOCTYPE html>
<html lang="en" =""><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>My page</title>
<!-- Bootstrap core CSS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>
<style>
html, body
{
width:100%;
height:100%;
}
</style>
<style id="vvvebjs-styles"></style></head>
<body>
<!-- Page Content -->
<div class="container">
<div class="row">
<div class="col-lg-12 text-center">
<h1 class="mt-5">Bootstrap 5 Editedstart page</h1>
<p class="lead">Start by dragging components to page or double click to edit text</p>
</div>
</div>
</div>
</body></html>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,33 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>My page</title>
<!-- Bootstrap core CSS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>
<style>
html, body
{
width:100%;
height:100%;
}
</style>
</head>
<body>
<!-- Page Content -->
<div class="container">
<div class="row">
<div class="col-lg-12 text-center">
<h1 class="mt-5">Bootstrap 5 start page</h1>
<p class="lead">Start by dragging components to page or double click to edit text</p>
</div>
</div>
</div>
</body>
</html>