本文的目的是介绍ckeditor内联保存/提交的详细情况,我们将通过专业的研究、有关数据的分析等多种方式,同时也不会遗漏关于@ckeditor/ckeditor5-angular的图片上传、AJAXF
本文的目的是介绍ckeditor内联保存/提交的详细情况,我们将通过专业的研究、有关数据的分析等多种方式,同时也不会遗漏关于@ckeditor/ckeditor5-angular 的图片上传、AJAX FCKEditor Rich Editor整合篇、CKEditor 5 v29.0.0 发布,已支持内联图片、CKEDITOR 5 使内联小部件可编辑的知识。
本文目录一览:- ckeditor内联保存/提交
- @ckeditor/ckeditor5-angular 的图片上传
- AJAX FCKEditor Rich Editor整合篇
- CKEditor 5 v29.0.0 发布,已支持内联图片
- CKEDITOR 5 使内联小部件可编辑
ckeditor内联保存/提交
我不知道如何从CKEditor实例中获取已编辑的数据并将其发布到url。
我在看这样的东西:
http://nightly.ckeditor.com/3995/samples/inlineall.html
而且我不知道如何保存更改。我可以将要编辑的新数据连同要编辑的元素的ID一起发布到PHP吗?
与此类似:
editor.on(''configLoaded'', function(){ // do some stuff});
我希望我可以做这样的事情:
editor.on(''clickAway'', function(e){ id = e.id(); // do some ajax stuff});
但是我似乎在任何地方都找不到任何东西。
有没有人知道如何做到这一点?
谢谢。
答案1
小编典典我敢肯定有很多方法可以做到这一点,但这是我的解决方案。我正在使用Smarty模板引擎,但是该技术也应适用于普通HTML。
首先,这是一些存储在我的模板文件“ dog_fleas.tpl”中的HTML的示例:
<script type="text/javascript" src="/js/ckeditor/ckeditor.js"></script><script type="text/javascript" src="/js/admin/mycms.js"></script><div> <div id="flea-blurb" tpl="/templates/dog_fleas.tpl" contenteditable="true"> <h1>My Dog Has Fleas</h1> <p>This text is editable via the CMS!</p> </div> <p>This text is not editable</p></div>
处理内联编辑的javascript(mycms.js)是:
$(document).ready(function() { CKEDITOR.disableAutoInline = true; $("div[contenteditable=''true'']" ).each(function( index ) { var content_id = $(this).attr(''id''); var tpl = $(this).attr(''tpl''); CKEDITOR.inline( content_id, { on: { blur: function( event ) { var data = event.editor.getData(); var request = jQuery.ajax({ url: "/admin/cms-pages/inline-update", type: "POST", data: { content : data, content_id : content_id, tpl : tpl }, dataType: "html" }); } } } ); });});
上面的代码做了几件事:
- 它将所有具有contenteditable =“ true”属性的div标记转换为内联可编辑。
- 内容编辑后(模糊),可编辑元素ID,tpl文件名和已编辑内容通过ajax调用发送到服务器。
在我的情况下,tpl属性对于识别正在编辑的文件是必需的。元素ID指定要修改的元素。
尽管我的示例仅包含一个可编辑区域,但是此代码在单个文件中支持多个可编辑区域。
在服务器端,这是我的PHP代码。我使用的是框架,因此我的$ this-> _ POST()函数可能看起来有点不寻常,但希望您能明白:
// Get the posted parameters $new_content = $this->_POST(''content''); $content_id = $this->_POST(''content_id''); $tpl_filename = $this->_POST(''tpl''); // Get the contents of the .tpl file to edit $file_contents = file_get_contents(APPPATH . ''views'' . $tpl_filename); // create revision as a backup in case of emergency $revised_filename = str_replace(''/'', ''.'', $tpl_filename); $revised_filename = ltrim ($revised_filename, ''.''); file_put_contents(APPPATH . ''views/templates/revisions/'' . $revised_filename . ''.'' . time(), $file_contents); // Prepare to match the DIV tag // Credit to: http://stackoverflow.com/questions/5355452/using-a-regular-expression-to-match-a-div-block-having-a-specific-id $re = ''% # Match a DIV element having id="content". <div\b # Start of outer DIV start tag. [^>]*? # Lazily match up to id attrib. \bid\s*+=\s*+ # id attribute name and = ([\''"]?+) # $1: Optional quote delimiter. \b'' . $content_id . ''\b # specific ID to be matched. (?(1)\1) # If open quote, match same closing quote [^>]*+> # remaining outer DIV start tag. ( # $2: DIV contents. (may be called recursively!) (?: # Non-capture group for DIV contents alternatives. # DIV contents option 1: All non-DIV, non-comment stuff... [^<]++ # One or more non-tag, non-comment characters. # DIV contents option 2: Start of a non-DIV tag... | < # Match a "<", but only if it (?! # is not the beginning of either /?div\b # a DIV start or end tag, | !-- # or an HTML comment. ) # Ok, that < was not a DIV or comment. # DIV contents Option 3: an HTML comment. | <!--.*?--> # A non-SGML compliant HTML comment. # DIV contents Option 4: a nested DIV element! | <div\b[^>]*+> # Inner DIV element start tag. (?2) # Recurse group 2 as a nested subroutine. </div\s*> # Inner DIV element end tag. )*+ # Zero or more of these contents alternatives. ) # End 2$: DIV contents. </div\s*> # Outer DIV end tag. %isx''; if (preg_match($re, $file_contents, $matches)) { $content_to_replace = $matches[0]; $replacement_content = $content_to_replace; // Replace the inner content of $replacement_content with $new_content $replacement_content = preg_replace(''/(<div(?:.*?)>)(?:.*)(<\/div>)/msi'',"$1" . $new_content . "$2", $replacement_content); // Now replace the content_to_replace with $replacement content in the HTML $new_file_contents = str_replace($content_to_replace, $replacement_content, $file_contents); // write out the new .tpl file file_put_contents(APPPATH . ''views'' . $tpl_filename, $new_file_contents); }
上面的PHP代码基本上是加载HTML,使用适当的ID定位div标签,然后用通过ajax调用向下发送的内容替换该div标签的内容。然后将HTML重新保存到服务器。我还提供了一些代码来存储备份修订版本,以防万一万一出了问题。
我意识到正则表达式并不总是最好的解决方案。就我而言,由于我的HTML内容不是有效的HTML,因此很难使用PHP
Dom对象模型。如果您的系统比我的系统简单,则可以考虑使用Dom对象模型。
我希望这有帮助!
@ckeditor/ckeditor5-angular 的图片上传
在使用@ckeditor/ckeditor5-build-decoupled-document 的文章模板时,图片上传功能未实现UploadAdapter而无法上传,解决办法:自己实现一个文件上传适配器。本本已base64格式上传为例
1、实现Base64UploadAdapter
export class Base64UploadAdapter {
public reader = new FileReader();
loader: any;
constructor(loader: any) {
this.loader = loader;
}
public upload() {
return new Promise((resolve, reject) => {
const reader = this.reader;
reader.addEventListener(''load'', () => {
resolve({ default: reader.result });
});
reader.addEventListener(''error'', err => {
reject(err);
});
reader.addEventListener(''abort'', () => {
reject();
});
this.loader.file.then((file: Blob) => {
reader.readAsDataURL(file);
});
});
}
public abort() {
this.reader.abort();
}
}
2、在CKEditor的 onRead事件中注入
public onReady(editor: any) {
editor.ui.getEditableElement().parentElement.insertBefore(
editor.ui.view.toolbar.element,
editor.ui.getEditableElement()
);
editor.plugins.get(''FileRepository'').createUploadAdapter = function (loader: any) {
return new Base64UploadAdapter(loader);
};
}
注意:不要使用@ckeditor/ckeditor5-upload下的UploadAdapter,会造成重复引用
AJAX FCKEditor Rich Editor整合篇
至于FCKEditor的各种用法我就不在这里一一列举,网上有很多相关的文章,它也自带了不错的sample,可以非常容易加入到我们自己的项目中去。
不过在Ajax应用中如何使用FCKEditor控件呢?这个FCKEditor好像没有提供相应的答案,因为Ajax都是采用的无刷新提交,而FCKEditor只能在Form提交方式下使用,为什么这样说呢,那我们还得从FCKEditor的执行流程说起。
FCKEditor的编辑器实际上是一个IFrame,每次在创建一个FCKEditor实体的时候,都会新建一个IFrame,然后各种toolbar和编辑区都塞到这个IFrame中去了,在IFrame外面必须有一个对应的input元素(这个一般是一个textarea,FCKEditor中称之为LinkedField),这样就可以将textarea中的已有的内容导入到编辑器中,或者将编辑好的内容更新到LinkedField中。那FCKEditor中的内容是何时保存到对应的LinkedField中去的呢?开始我没有看源码,以为是在FCKEditor中的内容发生改变的时候同时更新LinkedField的,后来发现不是,如果是这样的话,那我们就可以很容易在ajax中使用FCKEditor了。那到底是什么时候做到与LinkedField同步的呢?答案肯定是在form执行submit事件之前,要在submit之前做到更新唯一的方式就是通过attachEvent方式将更新的回调函数绑定到onsubmit事件上,然后通过一定的方式在submit之前调用绑定的函数。因此就在FCKEditor提供的核心js文件中查找onsubmit,后来在fckeditorcode_ie.js文件找到了onsubmit关键字(这里不得不提到的一点,FCKEditor虽然做到了开源,但是对于他们的javascript源代码还是有所保留的,里面的很多核心js文件都进行了混淆重排,不过这个也不能怪人家不厚道,为了方便查看源代码,吐血推荐采用MyEclipse的document format功能进行格式化处理,这样基本上可以对里面的结构一目了然了)。
相关代码如下,首先是在FCKEditor初始化的时候:
function FCK_EditingArea_OnLoad() {
FCK.EditorWindow = FCK.EditingArea.Window;
FCK.EditorDocument = FCK.EditingArea.Document;
FCK.InitializeBehaviors();
FCK.OnAfterSetHTML();
if (FCK.Status != FCK_STATUS_NOTLOADED) {
return;
}
FCK.ResetIsDirty();
FCKTools.AttachToLinkedFieldFormSubmit(FCK.UpdateLinkedField); // 开始做绑定
FCK.SetStatus(FCK_STATUS_ACTIVE);
}
然后是submit提交前的处理:
FCKTools.AttachToLinkedFieldFormSubmit = function (A) {
var B = FCK.LinkedField.form;
if (!B) {
return;
}
if (FCKbrowserInfo.IsIE) {
B.attachEvent("onsubmit",A); // 将更新处理绑定到form的onsubmit事件上
} else {
B.addEventListener("submit",A,false);
}
if (!B.updateFCKeditor) {
B.updateFCKeditor = new Array();
}
B.updateFCKeditor[B.updateFCKeditor.length] = A;
if (!B.originalSubmit && (typeof (B.submit) == "function" || (!B.submit.tagName && !B.submit.length))) {
B.originalSubmit = B.submit;
B.submit = FCKTools_SubmitReplacer;
}
};
FCK.UpdateLinkedField = function () {
FCK.LinkedField.value = FCK.GetXHTML(FCKConfig.FormatOutput); // 将FCKEditor编辑的内容取出来,这里是我们关心的重点
FCK.Events.FireEvent("OnAfterLinkedFieldUpdate");
};
OK,大致过程我们基本上已经了解了,至于FCKEditor是如何在执行onsubmit之前执行绑定的更新处理的,暂且不表。
不过这里对FCKEditor的几个对象类需要了解一下,一个是FCKConfig(保存一些相关的配置信息),FCK(取编辑器中编辑的内容需要用到的)。这些类都存活在编辑器所在的IFrame页面之中,在LinkedField所在的页面是无法访问到的。
下面是我们的使用代码,这里是通过js创建FCKEditor实例的方式。
首先定义一个全局的FCKEditor对象:
var oFCKEditor = null;
var oFCKEditor = null;
在页面初始化之后(一般是在body的onload事件中完成)创建oFCKEditor对象
oFCKeditor = new FCKeditor( 'frmEntity_editor_content'/*LinkedField元素id*/,'100%;','400px','Default') ;
oFCKeditor.BasePath = "${request.getcontextpath()}/editor/" ;
oFCKeditor.ReplaceTextarea() ;
oFCKeditor = new FCKeditor( 'frmEntity_editor_content'/*LinkedField元素id*/,'Default') ;
oFCKeditor.BasePath = "${request.getcontextpath()}/editor/" ;
oFCKeditor.ReplaceTextarea() ;
接下来是在执行ajax请求提交前的处理:
var inputElementId = "frmEntity_editor_content"; // LinkedField元素id
var frameElement = eval(inputElementId + "___Frame"); // 用来嵌入FCKEditor的IFrame的id
var inputElement = eval(inputElementId);
inputElement.value = frameElement.window.FCK.GetXHTML(frameElement.window.FCKConfig.FormatOutput); // 取得FCKEditor中的内容同步到LinkedField中去
// 收集提交内容,执行ajax请求
....
var inputElementId = "frmEntity_editor_content"; // LinkedField元素id
var frameElement = eval(inputElementId + "___Frame"); // 用来嵌入FCKEditor的IFrame的id
var inputElement = eval(inputElementId);
inputElement.value = frameElement.window.FCK.GetXHTML(frameElement.window.FCKConfig.FormatOutput); // 取得FCKEditor中的内容同步到LinkedField中去
// 收集提交内容,执行ajax请求
....
这个就是我的整合过程,其实还是挺简单的,不过碰到一个问题,就是在打开页面之后,输入焦点总是停留在FCKEditor的编辑区里面,而FCKEditor自己提供的例子里面不会出现这个情况,写法也没有什么区别,不知道问题出在哪里,有知道原因的朋友告知一声。
Java免费学习Java自学网http://www.javalearns.com
关注微信号:javalearns 随时随地学Java
或扫一扫
随时随地学Java
CKEditor 5 v29.0.0 发布,已支持内联图片
CKEditor 5 是一个强大的富文本编辑器框架,具有模块化架构、现代集成和协作编辑等功能。CKEditor 5 v29.0.0 正式发布,更新内容如下:
这个版本引入了几个新的功能:
- 内联图片——支持单个区块中的多个图片;
- 查找和替换功能;
- 经典编辑器的源代码编辑功能;
- 创建新的代码块时会记住语言;
- 通用 HTML 支持功能;
还有一些错误修复:
- 移除格式功能不会再重置图片大小;
- 嵌套的标记高亮将不会破坏鼠标的文本选择;
更多详情可查看:https://github.com/ckeditor/ckeditor5/releases/tag/v29.0.0
CKEDITOR 5 使内联小部件可编辑
如何解决CKEDITOR 5 使内联小部件可编辑?
有什么方法可以使内联小部件可编辑? 我已经尝试了 ck5 官方页面(可以在 here 中找到)的教程,我设法将其修改为如下图所示。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)
关于ckeditor内联保存/提交的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于@ckeditor/ckeditor5-angular 的图片上传、AJAX FCKEditor Rich Editor整合篇、CKEditor 5 v29.0.0 发布,已支持内联图片、CKEDITOR 5 使内联小部件可编辑的相关知识,请在本站寻找。
本文标签: