资源描述
百度编辑器UEditor的插件开发
1.概述
UEditor是由百度web前端研发部开发的所见即所得富文本web编辑器,具有轻量、可定制、注重用户体验等特点,开源基于BSD协议,允许自由使用和修改代码。
2.下载UEditor
截至2013.11.27,最新版本为1.3.5,下面是具体的相关文档的下载地址:
百度官网下载地址:
官方文档资料地址:
官方API地址:
3.源码包文件说明
从官网上下载完整源码包,解压到任意目录,解压后的源码目录结构如下所示:
•_examples:编辑器的示例页面
•dialogs:弹出对话框对应的资源和JS文件
•themes:样式图片和样式文件
•editor.config.js:编辑器的配置文件
•editor.api.js:开发版的所有js文件导入
•editor.all.js:使用版的所有js文件
•lang:语言文件
•jsp、net、php:涉及到服务器端操作的文件
•third-party:第三方插件
4.部署和使用
UEditor可供普通用户使用,同时UEditor的插件机制也为二次开发者提供了自定义插件的开发。
1)在项目的任一文件夹中建立一个用于存放UEditor相关资源和文件的目录。
2)创建简单的编辑器实例,首先在html页面中准备一个dom容器,容器可以是<textareaid="editor"></textarea>或<divid="editor"></div>,也可以是<scripttype="text/plain"id="editor"></script>标签。
3)引入相关文件
1
2
3
4
5
<scripttype="text/javascript"src="editor.config.js"></script>
<!--使用版-->
<!--<scripttype="text/javascript"src="ueditor.all.js"></script>-->
<!--开发版-->
<scripttype="text/javascript"src="editor.api.js"></script>
4)创建编辑器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<scripttype="text/javascript"charset="utf-8">
//通过new操作符实例化编辑器对象
varmyEditor=newbaidu.editor.ui.Editor();
myEditor.render('editor');//渲染dom容器
//使用UE.getEditor()实例化编辑器对象
varmyEditor=UE.getEditor('myEditor');
//通过new操作符实例化编辑器对象并自定义配置项
varmyEditor=newbaidu.editor.ui.Editor({
toolbars:[//自定义工具栏
['FullScreen','Source','Undo','Redo']
],
wordCount:false,//关闭字数统计
elementPathEnabled:false,//关闭elementPath
initialFrameHeight:300//默认的编辑区域高度
});
myEditor.render('editor');
//通过UE.getEditor()实例化编辑器对象并自定义配置项
UE.getEditor('myEditor',{
toolbars:[//自定义工具栏
['FullScreen','Source','Undo','Redo']
],
wordCount:false,//关闭字数统计
elementPathEnabled:false,//关闭elementPath
initialFrameHeight:300//默认的编辑区域高度
})
</script>
说明:使用<textarea>和<scripttype="text/plain">标签做渲染容器,可以在容器中设置编辑器初始化的内容,如:
<textareaid="editor">编辑器初始化的内容</textarea>;
<scripttype="text/plain"id="myEditor">编辑器初始化的内容</script>;
但是如果使用div作为渲染容器,就不可以在标签里设置初始值,但可通过在创建编辑器的时候配置initialContent参数来设置初始值。
5.自定义插件的开发
5.1UEditor的整体架构
UEditor的架构设计采用了传统的分层架构模式,从低到高依次分为核心层、命令插件层和UI层这样三个低耦合的层次。
1)核心层提供了编辑器底层的一些方法和概念,如DOM树操作、Selection、Range等;
2)在核心层之上覆盖的是命令插件层;
3)在命令插件层之上则是UI层。
5.2UEditor的插件机制
从根本上来说,除了核心提供的几个编辑器底层封装类之外,UEditor的全部功能都是通过外挂插件或者是命令(实质上也可以看成特殊的插件)来实现的。UEditor中插件的实质是在编辑器实例下面绑定的一个以插件名字命名的函数,然后通过编辑器实例化过程去执行这个函数,并将实例对象传递到插件内部作为其this对象来完成所有的功能操作。
5.3自定义插件的开发
1)在editor.config.js配置文件中的toolbars项添加插件名,如分页插件:zpagebreak,toolbars:[[..,'zpagebreak']];
2)在editor.config.js配置文件中的labelMap项添加鼠标移入插件提示文字:labelMap:{..,'zpagebreak':'分页'};
3)在_src/ui/editorui.js文件中的命令按钮项btnCmds添加插件名:btnCmds=[..,'zpagebreak'];;
4)插件内部结构
1
2
3
4
5
6
7
8
9
10
11
12
13
UE.plugins[]=function(){
varme=this;
//注册鼠标和键盘事件
me.addListener('mousedown',_mouseDownEvent);
me.addListener('keydown',function(type,evt){...});
me.addListener('mouseup',function(){});
//查询当前命令状态
queryCommandState:function(cmdName){}
//命令执行主体
exeCommand:function(cmdName,myobject){}
//获取命令执行结果
queryCommandValue:function(cmdName){}
};
5)插件具体写法
//editor.selection.getRange()获取选取
//editor类,此类用于初始化的一些设置,比如获取内容,设置高宽,设置编辑器内容等等。
//domUtils类,Dom操作工具包。
//utils类,静态工具函数包
//browser类,此类用于检测浏览器。
//EventBase类,此类用基础事件的注册类,比如鼠标,键盘事件等。
//ajax类,此类用于ajax工具类。
示例1:命令式插件1(分页)
1
2
3
4
5
6
7
8
UE.plugins['zpagebreak']=function(){
varme=this;
mands['zpagebreak']={
execCommand:function(cmdName,myobject){
//命令执行主体略
}
};
};
分页命令插件的执行主体用到的方法大体如下:
1)获取选区
1
varrange=me.selection.getRange();
2)往选区插入分页标识:
1
2
3
4
5
varpageBreakMark=this.document.createElement('span');
UE.dom.domUtils.setAttributes(pageBreakMark,{
'style':'page-break-after:always;'
});
range.insertNode(pageBreakMark);
3)根据分页标识分割内容
1
2
3
4
5
6
7
8
9
10
varcontent=me.getContent(),
pageBreakPos=content.indexOf('page-break-after:always'),
prevContent=content.substring(0,pageBreakPos-13),
nextContent=content.substring(pageBreakPos+27);
me.setContent(prevContent);//给当前编辑器对象设置新内容
//给新编辑器设置内容,需监听新编辑器的ready事件,否则会报错
//varneweditor=....;获取新编辑器实例方法此处略
neweditor.addListener('ready',function(type,evt){
this.setContent(nextContent);
});
4)销毁编辑器
1
currentEditor.destroy();
5)给插件按钮设置样式(每个工具栏按钮都会有一个’edui-for-‘加插件名的样式类名,如分页命名插件的样式类名:edui-for-zpagebreak)。
1
addStyle('.edui-default.edui-toolbardiv.edui-for-zpagebreak.edui-icon'+'{background:url("图片路径")centerno-repeat;}');
示例2:命令式插件2(插入批注)
1
2
3
4
5
6
7
8
UE.plugins['zcomment']=function(){
varme=this;
mands['zcomment']={
execCommand:function(cmdName,myobject){
//命令执行主体略
}
};
};
插入批注命令插件用到的方法大体如下:
1)创建要插入的字符串
1
2
3
varcreatInsertStr=function(uName,time,toCode){
return!toCode?'<spanclass="z-edui-comment"contenteditable="false"edui-comment="true"_uname="'+uName+'"_time="'+time+'">'+'<spancontenteditable="true">请在此输入批注</span>-'+uName+time+'<ititle="删除批注">×</i>'+'</span>':'<cke_commentedui-comment="true"_uname="'+uName+'"_time="'+time+'"><spancontenteditable="true">请在此输入批注</span>-'+uName+time+'<i>×</i></cke_comment>';
}
2)代码视图和设计视图切换时进行相应元素节点的替换
1
2
3
4
5
6
7
8
varswitchImgAndCode=function(root,img2Code){
UE.utils.each(root.getNodesByTagName(img2Code?'span':'cke_comment'),function(node){
if(node.getAttr('edui-comment')){
varhtml=creatInsertStr(node.getAttr('_uname'),node.getAttr('_time'),img2Code);
node.parentNode.replaceChild(UE.uNode.createElement(html),node);
}
})
}
3)设计视图转为源码视图的规则
1
2
3
me.addOutputRule(function(root){
switchImgAndCode(root,true);
});
//源码视图转为设计视图的规则
1
2
3
me.addInputRule(function(root){
switchImgAndCode(root);
});
4)给插件对象添加样式规则
1
2
3
4
me.ready(function(){
UE.utils.cssRule('zcomment','.z-edui-comment{background:url(\''+me.options.UEDITOR_HOME_URL
+'themes/default/images/icon_comment.gif\')no-repeat0center#ff0;border:1pxdotted#fc3;display:inline-block;padding-left:18px;color:#cb9;font-weight:normal;}'+'.z-edui-commentspan{color:#320;}'+'.z-edui-commenti{cursor:pointer;display:inline-block;font-size:16px;line-height:12px;font-weight:bold;color:#C00;padding:2px2px0;}',me.document);
});
5)给插件按钮设置样式
1
addStyle('.edui-default.edui-toolbardiv.edui-for-zcomment.edui-icon'+'{background:url("图片路径")centerno-repeat;}');
示例3:弹出框式插件(插入图片)
1
2
3
4
5
6
UE.plugins['zimage']=function(){
varme=this;
mands['zimage']={
execCommand:function(cmdName,myobject){}
};
};
弹出框式插件的执行主体用到的方法大体如下:
1)实例化弹出框对象dialog,以及相关配置
注:其中dialog宽高配置项由于开发包并未提供,所以需要用户自行扩展,更改源文件_src/ui/dialog.js,此处省略。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
varurl="...."//弹出框文件路径
vardialog=newUE.ui.Dialog({
editor:me,
iframeUrl:url,
width:800,
height:450,
title:"插入图片",
buttons:[
{
className:'edui-okbutton',
label:me.getLang("ok"),
onclick:function(){
dialog.onok(true);
}
},
{
className:'edui-cancelbutton',
label:me.getLang("cancel"),
onclick:function(){
dialog.close(false);
}
}
]
});
dialog.open();
dialog.onok=function(){
vardgSelf=this,
currentEditor=this.editor,
dialogWin=document.getElementById(this.id+'_iframe').contentWindow,
source=dialogWin.$NV("Source"),
title="",
imageLink="",
rela="";
if(source=='upload'){//本地上传图片
dialogWin.uploadSave(function(response){
vardt=response.DT;
if(dt&&dt.Rows){
varrs=dt.Rows;
for(vari=0;i<rs.length;i++){
vardr=rs[i];
title=dr.get("OldName");
imageLink=dr.get("PreviewPrefix")+dr.get("ResourcePath");
imageLink=imageLink.replace(/\/+/g,"/");
rela=dr.get("ResourceID");
varsourceImageLink=dr.get("PreviewPrefix")+dr.get("Path").replace(/\/+/g,"/");
currentEditor.execCommand("insertHTML",template.tmpl({
ImageLink:imageLink,
SourceImageLink:sourceImageLink,
Title:title,
Alt:title,
Rela:rela
}));
}
}
dialogWin.$S("URL","http://");
dialogWin.location.reload();
dlgself.close(false);//图片上传并插入后,关闭弹出框
});
}
};
2)给插件按钮设置样式
1
addStyle('.edui-default.edui-toolbardiv.edui-for-zimage.edui-icon'+'{background:url("图片路径")centerno-repeat;}');
6.其他常用方法
6.1获取工具栏对象
1
vareditor_toolbarbox=me.ui.getDom("toolbarbox");
6.2销毁编辑器
1
2
3
myEditor.destroy();//直接使用destroy()方法
UE.delEditor("容器id");//使用delEditor()方法
UE.getEditor("容器id").destroy();使用getEditor()和destroy()方法
6.3删除所有编辑器实例
1
2
3
4
5
6
7
UE.utils.each(UE.instants,function(editor,index,instants){
If(editor.hasOwnProperty('key')){
editor.destroy();
//或者使用instants[index].destroy();
}
});
UE.instants={};
6.4监听编辑器实例myEditor的focus事件
1
2
3
4
5
6
7
8
9
//监听当前编辑器的window对象
UE.dom.domUtils.on(myEditor.window,'focus',function(){
//....
});
//直接监听当前编辑器
myEditor.addListener("focus",function(){
//...
});
6.5让编辑器选区中的节点被选中
1
2
3
varrange=this.selection.getRange();//获取选区
var$el=$("span.z-edui-comment>span",me.document);//获取元素节点
range.selectNodeContents($el.get(0)).select();//选中元素
注:文章源于泽元软件知识库,此文章只用于学术交流,不用于商业应用。
展开阅读全文