相关文章推荐
留胡子的电影票  ·  org.springframework.jd ...·  2 年前    · 
奔放的水煮肉  ·  android - Difference ...·  2 年前    · 

关于CKEditor4.5.6的使用,自定义toolbar配置,上传图片案例(SpringMVC+MyBatis案例),自定义行高,去编辑器的中内容,将编辑器中内容设置到指定的位置等

文件内容如下:

CKEDITOR.editorConfig = function( config ) {
// Define changes to default configuration here. For example:
// config.language = 'fr';
// config.uiColor = '#AADC6E';
config.toolbarGroups = [
{ name: 'document', groups: [ 'mode', 'document', 'doctools' ] },
{ name: 'clipboard', groups: [ 'clipboard', 'undo' ] },
{ name: 'editing', groups: [ 'find', 'selection', 'spellchecker', 'editing' ] },
{ name: 'forms', groups: [ 'forms' ] },
{ name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] },
'/',
{ name: 'links', groups: [ 'links' ] },
{ name: 'insert', groups: [ 'insert' ] },
{ name: 'colors', groups: [ 'colors' ] },
{ name: 'styles', groups: [ 'styles' ] },
{ name: 'tools', groups: [ 'tools' ] },
{ name: 'paragraph', groups: [ 'list', 'blocks', 'bidi', 'align', 'indent', 'paragraph' ] },
{ name: 'others', groups: [ 'others' ] },
{ name: 'about', groups: [ 'about' ] }
];
// config.removeButtons = 'Source,Save,Templates,Cut,Undo,Find,Scayt,SelectAll,Paste,Copy,Redo,NewPage,Preview,Print,Form,Bold,RemoveFormat,Link,Image,TextColor,Outdent,JustifyLeft,BidiLtr,Blockquote,NumberedList,UIColor,lineheight';
config.line_height ='8px;9px;10px;11px;12px;13px;14px;15px;16px;17px;18px;19px;20px;21px;22px;23px;24px;25px;26px;27px;28px;29px;30px;31px;32px;33px;34px;35px;36px;37px;38px;39px;40px;41px;42px;43px;44px;45px;46px;47px;48px;49px;50px;51px;52px;53px;54px;55px;56px;57px;58px;59px;60px;61px;62px;63px;64px;65px;66px;67px;68px;69px;70px;71px;72px;';
config.skin = 'office2013';
config.extraPlugins='imagepaste';
config.pasteFromWordRemoveFontStyles = false;
config.pasteFromWordRemoveStyles = false;
config.extraPlugins = 'uploadwidget';
config.extraPlugins = 'notificationaggregator';
config.extraPlugins = 'notification';
config.extraPlugins = 'uploadimage';
config.extraPlugins = 'toolbar';
config.extraPlugins = 'button';
config.extraPlugins = 'filetools';
config.extraPlugins = 'clipboard';
config.extraPlugins = 'dialog';
config.extraPlugins = 'dialogui';
config.extraPlugins = 'widget';
config.extraPlugins = 'lineutils';
config.extraPlugins = 'widget';
config.SecureImageUploads = true;
config.image_previewText=' '; //预览区域显示内容
//config.filebrowserUploadUrl: "import/ckeditorUploadFile.action";
config.filebrowserImageUploadUrl = basePath + "/import/ckeditorUploadFile.action?type=Image"; //待会要上传的action或servlet

};

关于图片上传部分可以参考:

http://blog.csdn.net/itmyhome1990/article/details/17264627

实现过程中的一个案例

* name : tuzuoquan

* mail : tuzq@XXXX.cn

* date :2016/01/13

* version :1.0

* description:XXXXXX 对应的 js

* CopyRight (C) 2015-12-31

if (CKEDITOR.env.ie && CKEDITOR.env.version < 9)

CKEDITOR.tools.enableHtml5Elements(document);

* 编辑器对应的操作方法

* 关于在线编辑器的文档: http://sdk.ckeditor.com/samples/resize.html

var CKEDITORHandler = ( function ($) {

return {

* 初始化参数配置

ckeditorConfig: function (){

// 去掉开始进来的时候自动添加 BR

CKEDITOR.config.enterMode = CKEDITOR.ENTER_BR;

// 去掉开始进来的时候自动添加 P

CKEDITOR.config.shiftEnterMode = CKEDITOR.ENTER_P;

CKEDITOR.config.font_names= ' 微软雅黑 ; 宋体 ; 新宋体 ; 黑体 ; 隶书 ; 幼圆 ; 楷体 _GB2312; 仿宋 _GB2312; 方正舒体 ; 方正姚体 ; 华文隶书 ; 华文新魏 ; 华文行楷 ;sans-serif;Arial;Comic Sans MS;Courier New;Tahoma;Times New Roman;Verdana;'

CKEDITOR.config.line_height= "1em;1.1em;1.2em;1.3em;1.4em;1.5em" ;

* 初始化工具条的相关信息

initToolBar: function (){

CKEDITOR.config.toolbar = 'Full' ;

* 其中 (" - ") 为空间栏的水平分割, ("/") 为换行

* 以下: Full 表示的所有的操作

CKEDITOR.config.toolbar_Full =

{ name: 'document' , groups: [ 'mode' , 'document' , 'doctools' ] },

{ name: 'clipboard' , groups: [ 'clipboard' , 'undo' ] },

{ name: 'editing' , groups: [ 'find' , 'selection' , 'spellchecker' , 'editing' ] },

{ name: 'forms' , groups: [ 'forms' ] },

{ name: 'basicstyles' , groups: [ 'basicstyles' , 'cleanup' ] },

'/' ,

{ name: 'links' , groups: [ 'links' ] },

{ name: 'insert' , groups: [ 'insert' ] },

{ name: 'colors' , groups: [ 'colors' ] },

{ name: 'styles' , groups: [ 'styles' ] },

{ name: 'tools' , groups: [ 'tools' ] },

{ name: 'paragraph' , groups: [ 'list' , 'blocks' , 'bidi' , 'align' , 'indent' , 'paragraph' ] },

{ name: 'others' , groups: [ 'others' ] },

{ name: 'about' , groups: [ 'about' ] }

CKEDITOR.config.toolbar_Basic =

[ 'Source' , 'Preview' ],

[ 'Cut' , 'Copy' , 'Paste' , 'PasteText' , 'PasteFromWord' , '-' , 'SpellChecker' ],

[ 'Undo' , 'Redo' , '-' , 'Find' , 'Replace' , '-' , 'SelectAll' , 'RemoveFormat' ],

[ 'Form' , 'Checkbox' , 'Radio' , 'TextField' , 'Textarea' , 'Select' , 'Button' , 'ImageButton' , 'HiddenField' ],

[ 'Bold' , 'Italic' , 'Underline' , 'Strike' , '-' , 'Subscript' , 'Superscript' ],

[ 'NumberedList' , 'BulletedList' , '-' , 'Outdent' , 'Indent' ],

[ 'JustifyLeft' , 'JustifyCenter' , 'JustifyRight' , 'JustifyBlock' ],

[ 'Link' , 'Unlink' , 'Anchor' ],

[ 'Image' , 'Flash' , 'Table' , 'SpecialChar' ],

[ 'Styles' , 'Format' , 'Font' , 'FontSize' ],

[ 'TextColor' , 'BGColor' ],

[ 'lineheight' ]

* 在线编辑器的初始化过程

* textContent : 表示的是文本组件的内容

init: function (textContent){

// 注意:这里的 tpl -content-editor 是编辑器对应的 id

if (CKEDITOR.instances.tplContentEditor) {

var editor = CKEDITOR.instances[ "tplContentEditor" ];

//console.log("1------------------------------------------");

//console.log(editor.getData());

//editor.setData(editor.setData(textContent));

//console.log("2------------------------------------------");

// 销毁编辑器,然后新增一个

if (editor) editor.destroy( true );

CKEDITORHandler.ckeditorConfig();

// 初始化工具栏

CKEDITORHandler.initToolBar();

CKEDITOR.replace( "tplContentEditor" ,

toolbar: 'Basic' ,

height: '300' ,

width: 'auto'

// 为编辑器设置内容

CKEDITOR.instances.tplContentEditor.setData(textContent);

* 2 、判断一个字符串变量是否为空

* 如果不为空:返回 true

* 如果为空 : 返回 false

isNotBlank: function (variable){

return (variable != null && typeof (variable) != "undefined" && variable != undefined && variable != "" ) ? true : false ;

* 通过编辑的 icon 获得组件元素 , 查找父元素,直到找到含有 className 这个类选择器的元素停止

* domEle : 表示的是编辑的元素

* str1 这个原始的字符串中的 str2 全部换成 str3

* str1 : 最原始的字符串

* str2 : 要被替换的字符串

* str3 : 最终替换成的字符串

* 此外可以增加 String 对象的原型方法:

* String.prototype.replaceAll = function(str2,str3){

* return this.replace(new RegExp(str2," gm "),str3);

replaceAll: function (str1,str2,str3) {

var newStr = str1;

if ( this .isNotBlank(str1)) {

// 其中 gm 中的 g 表示 " 执行全局匹配 ( 查找所有匹配而非在找到第一个匹配后停止 )"

// 其中 gm 中的 m 表示执行多行匹配

newStr = str1.replace( new RegExp(str2, "gm" ),str3);

return newStr;

* 清除样式

removeCss: function (id,childPathOfSelectedElement,cssType){

// 替换原来的 css 样式

var oldStyleCss = $( "#generatedCss" ).html().replace(

new RegExp( "#" + id + childPathOfSelectedElement + ".*?{.*" +cssType+ ".*?}" ), "" );

oldStyleCss = this .replaceAll(oldStyleCss, "\r\n" , "" );

$( "#generatedCss" ).text(oldStyleCss);

obtainComponentEle: function (domEle,className) {

var tempObj = domEle;

while (!$(tempObj).parent().hasClass(className)) {

tempObj = $(tempObj).parent().get(0);

return $(tempObj).parent().get(0);

* 存储的是要编辑的对象

editObj : null ,

* 表示的是否是多列的

isMultiseriate : false ,

* 1 、点击编辑按钮的时候执行的操作

* domEle : 代表的是编辑按钮

* selectedElementInfo : 表示的是被选中的元素

* childPathOfSelectedElement : 表示的是放置内容的位置

* isMultiseriate : 表示的是是否多列

* obj : 表示的是被点击的个元素

* 如果是单列的:

* 比如点击 "text" 组件 " 编辑 " 按钮的时候传递进入的参数是: (this,selectedElementInfo,'',false,'')

* 如果实在配置文件中点击弹出的,传递的参数是: ('',selectedElementInfo,' . xxx . xxx ',false,''), 其中 ' . xxx . xxx ' 是你要改变的元素

* 如果是多列的:

* ('',selectedElementInfo,'',true,editObj)

tplEditSelectedContent: function (domEle,selectedElementInfo,childPathOfSelectedElement,isMultiseriate,editObj) {

// 存储的是点击的对象

CKEDITORHandler.editObj = editObj;

// 存储是否是多列的情况

CKEDITORHandler.isMultiseriate = isMultiseriate;

// 如果是多列的

if (CKEDITORHandler.isMultiseriate) {

// 获得要编辑的元素的内容:

var textContent = $(CKEDITORHandler.editObj).html();

} else {

// 获得 domEle 这个编辑按钮的组件

var componentEle = null ;

if (CKEDITORHandler.isNotBlank(domEle)) {

componentEle = CKEDITORHandler.obtainComponentEle(domEle, "tpl-monitored-class" );

} else {

var id = selectedElementInfo.get( "id" );

componentEle = $( "#" + id);

// 将当前元素的 id 存储到隐藏域中

$( ".tpl-edit-popup-window #componentId" ).val($(componentEle).attr( "id" ));

// 存储要设置的元素的值

if (!CKEDITORHandler.isNotBlank($.trim(childPathOfSelectedElement))) {

childPathOfSelectedElement = " .tpl-component-2015-12-30-text-content" ;

// 将要编辑的后代的值存到隐藏域中

$( ".tpl-edit-popup-window #childPathOfSelectedElement" ).val(childPathOfSelectedElement);

// 获得当前要编辑的元素的 id

var componentId = $(componentEle).attr( "id" );

// 获得要编辑的元素的内容:

var textContent = $( "#" + componentId + " " + childPathOfSelectedElement).html();

// 获得文本组件中的内容

CKEDITORHandler.init(textContent);

$( '.theme-popover-mask' ).fadeIn(10);

$( '.theme-popover' ).slideDown(20);

* 点击取消的时候执行的动作

* @return

tplEditCancel: function () {

$( '.theme-popover-mask' ).fadeOut(100);

$( '.theme-popover' ).slideUp(200);

* 点击 " 确定的时候执行的动作 "

* @return

tplEditOk: function () {

// 获得编辑器中的内容

var editorContent = CKEDITOR.instances.tplContentEditor.getData();

var id = selectedElementInfo.get( "id" );

* 判断是否是多列的

if (CKEDITORHandler.isMultiseriate) {

$(CKEDITORHandler.editObj).empty();

$(CKEDITORHandler.editObj).append(editorContent);

} else {

//1 、首先判断编辑器内容中第一个子标签的内容是否是 <pre>, 若是,则在后面不在添加 <pre>

//$(" <div></div> ").append(editorContent).first().prop("tagName");

//$(" <div></div> ").append(editorContent).first().prop("nodeName");

// 获得要修改的组件的 id

var componentId = $( ".tpl-edit-popup-window #componentId" ).val();

// 获得组件中要放置内容的元素

var childPathOfSelectedElement = $( ".tpl-edit-popup-window #childPathOfSelectedElement" ).val();

$( "#" + componentId + " " + childPathOfSelectedElement).empty();

$( "#" + componentId + " " + childPathOfSelectedElement).append(editorContent);

if ($( "#" + id + " .picturegroup #topMarquee_1 li" ).length>0){

var currCount = $( "#" + id + " .picturegroup #topMarquee_1 li" ).length;

var baseHeight = 0;

var i=0;

for (;i<currCount;i++){

baseHeight += $( "#" + id + " .picturegroup #topMarquee_1 li" ).eq(i).outerHeight( true );

var dyHeight = baseHeight + 'px' ;

var divHeight = baseHeight * 2 + 'px' ;

$( "#" + id + " .picturegroup .picture-holder" ).css( "height" , dyHeight);

$( "#" + id + " .picturegroup div" ).css( "height" , divHeight);

/*if($("#" + id + " . picturegroup # erwm ").length>0){

this.removeCss(id," . picturegroup ","height");

this.removeCss(id," . picturegroup # erwm ","height");

var height = parseFloat($("#picHeight"). val ());

var spanHeight = $("#" + id + " . picturegroup # erwm .bottomContent").height();

console.log(spanHeight);

$("#" + id + " . picturegroup "). css ("height","'+(height+spanHeight)+'+' px '");

$("#" + id + " . picturegroup # erwm "). css ("height","'+(height+spanHeight)+'+' px '");

$( '.theme-popover-mask' ).fadeOut(100);

$( '.theme-popover' ).slideUp(200);

// 恢复默认值

CKEDITORHandler.isMultiseriate = false ;

CKEDITORHandler.editObj = null ;

})(jQuery);

* 1 、页面加载完成后执行的动作

$( function (){

$( '.theme-poptit .close' ).click( function (){

$( '.theme-popover-mask' ).fadeOut(100);

$( '.theme-popover' ).slideUp(200);

关于图片上传的后台操作,使用的框架是 Spring+SpringMVC+MyBatis

package XXX.controller.upload;

import org.apache.log4j.Logger;

@Controller

@RequestMapping(value = "/import", method = { RequestMethod.GET,RequestMethod.POST })

public class ImportController extends BaseController{

/** 用于打印日志 */

private static final Logger logger = Logger

.getLogger(SpecialController.class);

* 此方法用于 CKEditor 的本地上传图片的功能

* @param param

* @param imageFile

* @return

@RequestMapping(value = "/ckeditorUploadFile", produces = "text/json")

public void ckeditorUploadFile(

@RequestParam("upload") MultipartFile upload,

HttpServletRequest request,

HttpServletResponse response,

@RequestParam("CKEditorFuncNum")String CKEditorFuncNum)

throws IllegalStateException,IOException {

PrintWriter out = response.getWriter();

response.setCharacterEncoding("utf-8");

// 判断扩展文件名是否正确

String uploadContentType = upload.getContentType();

if(uploadContentType.equals("image/pjpeg") || uploadContentType.equals("image/jpeg")) {

} else if(uploadContentType.equals("image/png") || uploadContentType.equals("image/x-png")) {

} else if(uploadContentType.equals("image/gif")) {

} else if(uploadContentType.equals("image/bmp")) {

} else {

out.println("<script type=\"text/javascript\">");

out.println("window.parent.CKEDITOR.tools.callFunction(" + CKEditorFuncNum + ",''," + "' 文件格式不正确(必须为 .jpg/.gif/.bmp/.png 文件) ');");

out.println("</script>");

return;

if (!upload.isEmpty()) {

try {

// 如果上传的图片大于 10M, 返回提示

if (upload.getSize() > 10 * 1024 * 1024) {

out.println("<script type=\"text/javascript\">");

out.println("window.parent.CKEDITOR.tools.callFunction(" + CKEditorFuncNum + ",''," + "' 文件大小不得大于 600k');");

out.println("</script>");

return;

Calendar calendar = Calendar.getInstance();// 获取当前时间

// 时间路径,解压文件,以年月日创建文件夹

String dataPath ="/"+calendar.get(Calendar.YEAR)+"/"

+ (calendar.get(Calendar.MONTH)+1)+"/" + calendar.get(Calendar.DATE)+"/";

// 原文件名

String srcName = upload.getOriginalFilename();

// 获取上传文件后缀

String suffix = srcName.substring(srcName.lastIndexOf(".") + 1,

srcName.length()).toLowerCase();

// 随机生成 32 id, 用于解压文件目录

String uuid = UUIDGenerator.generate();

// 新的文件名,随机的 uuid;

String picName = uuid +"."+suffix;

// 图片存储的实际路径

String urlPrefix = ExtendedServerConfig.getInstance().getStringProperty("VISITE_PREFIX_URL");

// 大图缩略图生成路径

String thumbnailPath =ExtendedServerConfig.getInstance()

.getStringProperty("THUMBNAIL_PATH")+ ExtendedServerConfig.getInstance()

.getStringProperty("SAVE_BIG_THUMBNAIL")+dataPath;

// 生成缩略图保存数据库路径

String savePath =ExtendedServerConfig.getInstance()

.getStringProperty("SAVE_BIG_THUMBNAIL")+dataPath+picName;

// 文件夹不存在,则创建

File destfile = new File(thumbnailPath);

if(!destfile.exists()){

destfile.mkdirs();

// 写文件

InputStream fi = upload.getInputStream();

// 上传文件写入到配置文件夹下

FileUtils.writeFile(fi, thumbnailPath+picName);

File file = new File(thumbnailPath+picName);

if(file.exists()) {

out.println("<script type=\"text/javascript\">");

out.println("window.parent.CKEDITOR.tools.callFunction(" + CKEditorFuncNum + ",'" + urlPrefix + savePath + "','')");

out.println("</script>");

return;

} catch (Exception e) {

e.printStackTrace();

return;

Mybatis配置之别名(typeAliases)优化、设置(settings)优化、映射器(mappers)优化以及生命周期和作用域的学习和理解
Mybatis配置之别名(typeAliases)优化、设置(settings)优化、映射器(mappers)优化以及生命周期和作用域的学习和理解
软件工程高效学 | 实战案例:用海龟编辑器实现人脸识别
软件工程是计算机领域的一门专业基础课,它对于培养开发者的软件素质、提高开发者的软件开发能力与软件项目管理能力具有重要意义。本篇介绍了用海龟编辑器实现人脸识别。
上古神兵,先天至宝,Win11平台安装和配置NeoVim0.8.2编辑器搭建Python3开发环境(2023最新攻略)
毫无疑问,我们生活在编辑器的最好年代,Vim是仅在Vi之下的神级编辑器,而脱胎于Vim的NeoVim则是这个时代最好的编辑器,没有之一。异步支持、更好的内存管理、更快的渲染速度、更多的编辑命令,是大神Thiago de Arruda对开发者们最好的技术馈赠。