一、简介
百度UEditor编辑器是一款开源(也存在一些小问题)的很实用的超文本编辑器,由于其功能多,强大API支持,得到广泛的使用。很适合自定义编辑功能。
界面:
由于业务需要,要求在知识管理页面的文档编辑器换用百度UEditor,以支持更多的编辑功能。
二、引入UEditor编辑器:
- 百度编辑器官网http://ueditor.baidu.com/website/download.html#ueditor下载源码(支持多种语言的);
- 解压后直接将ueditor文件夹拷贝到自己的工程中:
- 引入依赖包:直接将ueditor/jsp/lib下自带的五个核心jar包,引入自己的工程中即可。
- 千万注意:引入jar包时避免这五个核心jar包冲突(在pom.xml或project structure/Libraries中查看,jar包是否冲突)
若项目是由Maven 来管理jar包的,最好通过在 pom.xml 中引入
报500错误:ueditor/jsp/controller.jsp 无法显示,就是由于jar包冲突问题;也会导致图片无法上传,提示“后端配置项没有正常加载,上传插件不能正常使用!”。
三、实例化编辑器前必须引入依赖:
- 配置文件
<!-- 配置文件 --> <script type="text/javascript" charset="utf-8"> window.UEDITOR_HOME_URL = "<PF:basePath/>view/ueditor/"; //UEDITOR_HOME_URL、config、all这三个顺序不能改变 </script> <script type="text/javascript" charset="utf-8" src="<PF:basePath/>view/ueditor/ueditor.config.js"></script> <script type="text/javascript" charset="utf-8" src="<PF:basePath/>view/ueditor/ueditor.all.js"></script> <script type="text/javascript" charset="utf-8" src="<PF:basePath/>view/ueditor/lang/zh-cn/zh-cn.js"></script>
注意:
UEDITOR_HOME_URL 是ueditor包存放的路径。也可以在ueditor.config.js中配置:
// 为编辑器实例添加一个路径,这个不能被注释
UEDITOR_HOME_URL: URL - 实例化UEditor:
<script>
/*实例化UEditor*/
var editor;
var content;
$(function() {
editor = UE.getEditor('container', {
toolbars: [
['fullscreen', 'imageright', 'imagecenter', '|',
'simpleupload', 'insertimage', 'emotion', 'pagebreak', 'template', '|', 'horizontal'] ],
enableAutoSave: true //启用自动保存
})
editor.ready(function() {
content = $("#contentIdHidden").html();
if(content != null){
UE.getEditor('container').setContent(content, true);
}
$('#completebtn').bind('click', function() { $('#contentId').val(UE.getEditor('container').getContent()); $('#contentIdHidden').html(UE.getEditor('container').getContent());
注意:
2.1、toolbars:[[]] 此处内层中括号[]有N对,工具栏就可以分N行展示,”|”竖线是用于分隔不同类工具标签的作用,原样展示。
2.2、当编辑器render渲染后执行的方法,监听ready事件接口,ready是编辑器进行一些前期的准备工作,大多数实例接口都应该放在该方法中,确保编辑器准备完成才能执行。
2.3、setContent()方法是给编辑器设置内容,第二个参数为true时,不清空原来数据,在最后添加,为false时清空内容再插入内容。
3. 遇到前台无法显示编辑器:
3.1、因为web.xml中配置*.html请求被拦截,(*.jsp , *.action , *.do 区别了解下),所以只能将ueditor文件下有关的html文件都改成jsp文件(个人项目不同);
3.2、jar包冲突(com.baidu.ueditor-1.1.2-edit-1.0.jar 包 和 ueditor-1.1.2.jar 包冲突,解决办法,UEditor需要的五个jar包只从下载的UEditor解压包lib中拷贝,不要自己另外导入)
4. 图片上传路径配置:config.json
"imageUrlPrefix": "", /* 图片访问路径前缀 */ "imagePathFormat": "ueditor/jsp/upload/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
imageUrlPrefix:如果只有一台主机,不需要跨域获取图片就没有必要配置,配空就行;
imagePathFormat:一般都会自定义图片上传路径;
5. 自定义多图上传窗口功能:
<div id="tabhead" class="tabhead"> <%--<span class="tab" data-content-id="remote"><var id="lang_tab_remote"></var></span>--%> <span class="tab focus" data-content-id="upload"><var id="lang_tab_upload"></var></span> <%--<span class="tab" data-content-id="online"><var id="lang_tab_online"></var></span> <span class="tab" data-content-id="search"><var id="lang_tab_search"></var></span>--%> </div>
需求:
只保留了本地图片上传按钮;
ueditor\dialogs\image\image.html
如上注释代码隐藏插入图片、在线管理、图片搜索按钮:
6. 上传图片时,点击多图上传,上传弹框被遮盖了,是由于 UEditor 默认配置中 ueditor.all.js 文件中堆叠zIndex 顺序为999,导致知识编辑界面将图片上传弹框覆盖了,所以将UE.Editor.defaultOptions方法中 zIndex 改为 9999 完美解决。
7. 上传图片
7.1. 自定义图片上传方法PuploadImg,必须重写UE.Editor.prototype.getActionUrl()
很重要!很重要!很重要!
<script> /*重写 getActionUrl,自定义图片上传、保存接口,以js 的方式在配置文件ueditor.all.js、ueditor.config.js之后引入*/ UE.Editor.prototype._bkGetActionUrl = UE.Editor.prototype.getActionUrl; UE.Editor.prototype.getActionUrl = function(action) { if (action == 'uploadscrawl'|| action == 'uploadimage' || action == 'uploadfile') { return "<PF:basePath/>actionImg/PuploadImg.do"; }else { return this._bkGetActionUrl.call(this, action); } } </script>
7.2. action=”uploadimge”对应config.json配置文件中上传图片配置的imageActionName参数,后端上传方法PuploadImg (@RequestParam(value=”upfile”,require=false) MultipartFile file)中upfile 对应config.json配置文件中的imageFiledName
8. 从其他站点复制图片到编辑器内容:远程抓取图片
8.1. 配置:
//设置远程图片是否抓取到本地保存 catchRemoteImageEnable: true //设置是否抓取远程图片
在config.json中自定上传路径:
/* 上传保存路径,可以自定义保存路径和文件名格式 */
"catcherPathFormat": "actionImg/PubFUEditorLoadRemoteImg.do",
8.2. 编辑器页面远程抓取图片处理方法
在ueditor.all.js文件中修改远程抓取图片处理方法:
catcherPathFormat = me.getOpt('catcherPathFormat'); // 获取自定义保存路径
function catchremoteimage(imgs, callbacks) {
...
opt[catcherFieldName] = imgs;
ajax.request(catcherPathFormat, opt);
}
ueditor.all.js远程抓取方法UE.plugins['catchremoteimage']中在获取远程图片链接时是抓取编辑页面中所有的img属性:
var src = ci.getAttribute("_src") || ci.src || "";
if (/^(https?|ftp):/i.test(src) && !test(src, catcherLocalDomain)) {
remoteImages.push(src);
}
获取remoteImage时路径做了初步过滤处理,想自定义过滤抓取,可在config.json中配置:
"catcherLocalDomain": ["127.0.0.1", "localhost", "img.baidu.com"]
8.3. 后端远程图片本地化接口方法
在编辑器页面DocTUEditor.jsp文件中加入远程抓取图片后端处理接口方法:
UE.Editor.prototype._bkGetActionUrl = UE.Editor.prototype.getActionUrl; UE.Editor.prototype.getActionUrl = function(action) { if (action == 'uploadscrawl' || action == 'uploadimage' || action == 'uploadfile') { return "<PF:basePath/>actionImg/PubFUEditorPuploadImg.do"; }else if(action == 'catchimage'){ // 抓取远程图片处理 return "<PF:basePath/>actionImg/ueditorPuploadImg.do"; }else { return this._bkGetActionUrl.call(this, action); } }
注意:
请求参数是资源路径数组(后端处理接口中接入参数String[] source,对应config.json中catchFiledName参数),将远程图片本地化,再上传,自定义回显路径。
后端处理接口:
@RequestMapping(value = "/ueditorPuploadImg.do") @ResponseBody public Map<String, Object> ueditorPuploadImg(String[] source,HttpServletRequest request,HttpSession session) { String[] sources = request.getParameterValues("source[]"); for(String imgSource : sources){ URL fileurl = new URL(imgSource); HttpURLConnection httpUrl = (HttpURLConnection) fileurl.openConnection(); httpUrl.setRequestMethod("GET"); httpUrl.setConnectTimeout(6 * 1000); httpUrl.connect(); // 通过输入流获取图片数据 InputStream inStream = httpUrl.getInputStream();
9. 从word文档中拷贝内容(主要是内容中的图片转存到UEditor编辑器中):
在ueditor.config.js配置文件中默认情况下 ueditor 开启了 XSS 过滤(过滤、输入过滤、输出过滤都有相应的配置开关),任何不在 whitList
白名单上的标签及属性都会在转换时丢失。
这就直接导致了一些需要使用特殊标签或属性的功能直接失效,比如插入音乐、插入锚点、图片转存等。
一种方法就是关闭 XSS 过滤,可以注释掉上述配置或将上述三项设为 false;另一种方案就是将需要的标签及属性添加到白名单。
--- 插入锚点需要给 a 标签添加 name 属性,给 img 标签添加 anchorname 属性
--- 图片转存需要给 img 标签添加 word_img、style 属性
从word中拷贝图片后图片显示:
然后点击工具栏,拷贝图片本地地址,选中指定图片上传;
10. 编辑器导航栏固定:
ueditor编辑器工具栏默认是随窗口自动长高的,编辑框内容过长,工具栏就会被隐藏,不利于操作:
解决办法:在编辑器初始化时设置参数autoHeightEnabled为false
// 是否自动长高,默认true(false:自动添加滚动条,工具导航栏位置固定) autoHeightEnabled: false
11. 预览页面图片显示问题:
由于项目中图片附件等采用的是相对路径,预览页面preview,是直接取的编辑器内容用于展示,所以必须将图片地址挑出来重新拼接完整地址,所以需要对图片附件等路径充完整。
12. 一个页面多个ueditor实例:
之前是一个页面一个编辑器ueditor实例,点击按钮进入编辑器页面,现在需要添加多个编辑器。
为了避免多个编辑器间干扰(第一个实例化的ueditor没有销毁,会影响到第二个编辑器的实例化),肯定是要在实例化ueditor时分配不同的ueditor ID,网上搜索一堆仅仅说了分配不同ID 就ok了,
问题一:但是分配了不同ID,后要么是控制台报错,要么是第一个编辑器可以正常使用,但第二个编辑器内容无法显示,或者显示的内容时第一个编辑器的内容造成冲突;
问题二:冲突问题。有网友给出了
方案1:在每次使用完编辑器后手动销毁ueditor实例(UE.delEditor()或ueditor.destroy()),但是也存在一个问题就是部分浏览器不支持:Uncaught TypeError: Cannot read property 'nodeType' of undefined
方案1:改写uediotr.all.js中的实例化方法,默认是先从instances[id]中获取,没有再实例化:
UE.getEditor = function (id, opt) {
// 实例化前先销毁实例
UE.delEditor(id);
var editor = new UE.ui.Editor(opt);
editor.render(id);
return editor;
};
这个方案确实解决了冲突问题,但又带来了另外一个问题:
当编辑完成退出该编辑器后,但没有保存,想再次进入继续编辑,可想而知会重新实例化一个ueditor,而此时编辑器中的内容也会被初始化,第一次进入编辑的内容被覆盖,所以这个方法不适合我的需求。
所以要求不销毁已经实例化的编辑器达到复用,但又不能冲突:
方案一:考虑共用一个uediotr页面,根据操作类型了区分自定义功能:
if('${editorType}' === '0'){ // 知识编辑 options = { toolbars: [ ['fullscreen', 'source']] } }else if('${editorType}' === '1'){ // 批注编辑 options = { toolbars: [ ['undo', 'redo', '|','bold', 'italic']] } } editor = new UE.ui.Editor(options); editor.render('container'); editor.ready(function() { if('${editorType}' === '0'){ content = $("#contentId").html(); }else if('${editorType}' === '1'){ // 指定编辑器限制字数 editor.setOpt({ maximumWords:1000 }); content = $("#commentId").html(); } if(content != null){ editor.setContent(content, true); } 注意: 这种方案存在一个问题,也是公用ueditor ID,导致内容冲突
方案二:两个ueditor页面,分别实例化。
这两中方案也存在一个问题,第二个(后点击后实例化的)ueditor编辑器无法显示,有网友提示退出编辑器时将文本域areatext 移除:
$('#container').remove();
而且是完全不影响未保存的重复编辑,不会导致覆盖问题。亲测可行。
13. 自定义标签:一键清除格式
13.1、实例化编辑器时在toolbars数组新增一个“myone”自定义标签名;
13.2、找到ueditor.all.js文件中的btnCmds数组,在其中新增一个“myone”字符串;
13.3、添加图标one.png到images图片文件中;
13.4、为自定义标签添加样式;
/*自定义标签*/
.edui-default .edui-toolbar .edui-for-myone .edui-icon {
background-position: -89px 3;
background-image: url("../images/one.png");
}
13.5、在ueditor.all.js文件中仿照其他标签实现自定义标签按钮功能:
UE.plugins[' myone'] = function(){}
第一次写博客,这个编辑器也是很难用 ^_^!!,写的很简单
希望对遇到同样问题的朋友一些提示作用
不足之处欢迎指正交流
感谢众多大神的提示,文章链接已经找不到,无法贴出来,抱歉