基于Ckeditor的表单设计器的开发

众所周知,表单、工作流是企业业务系统的核心,而一个通用的表单设计器能为开发节省很多的编码工作。

接下来,我将用几篇文章,介绍如何用CKeditor定制简单的表单设计器。


一、安装CKEditor


 从 CKEditor 网站:http://ckeditor.com/download 下载最新版本的 CKEditor 。

 将下载的文档解压到你的 website 根目录下的 ckeditor 目录中。

你可以将文档放在你的 website 的任意路径中。ckeditor 目录是缺省目录。


二、加载CKEditor


CKEditor 是 JavaScript 应用程序。要加载它,需要在页面中包含一个简单的文件引用。
如果已在站点根目录下的 ckeditor 目录中安装了 CKEditor , 你需要将下面的代码片段插入到
页面的<head>部分:
<head>
...
<script src="/ckeditor/ckeditor.js"></script>

</head>
当上述文件加载后,就可以使用 CKEditor JavaScript API。

三、生成编辑框


CKEditor 的工作就像页面中的文本域元素。编辑器提供了用户界面,可以容易在编写、格式化,并可与富文本一起处理,但是可以用<textarea>元素完成同样的事情(尽管不是那么容易) ,需要用户在其中输入 HTML 代码。

实际上,CKEditor 使用文本域将其数据传给服务器。对于终端用来来说,文本域是不可见的。

为了生成编辑器的实例,必须首先将<textarea>元素加入到 HTML 页面的源代码中。

<textarea name="editor1"></textarea>


插入文本域后,就可以使用 CKEditor JavaScript API 将 HTML 元素替换为编辑器的实例。
调用简单的 CKEDITOR.replace 方法:

<script>
CKEDITOR.replace( 'editor1' );
</script>


全部代码:

[java]   view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <%@ page language="java" contentType="text/html; charset=UTF-8"  
  2.     pageEncoding="UTF-8"%>  
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
  4. <html>  
  5. <head>  
  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
  7. <title>Insert title here</title>  
  8.   
  9. <%@ include file="/page/common/common.jsp"%>  
  10. <script src="${contextPath}/ckeditor_standard/ckeditor/ckeditor.js"></script>  
  11.   
  12. </head>  
  13. <body>  
  14.     <form method="post" action="${contextPath}/editor/test1">  
  15.         <p>  
  16.             My Editor:<br>  
  17.             <textarea name="editor1"><p>Initial value.</p></textarea>  
  18.             <script>  
  19.                 CKEDITOR.replace('editor1');  
  20.             </script>  
  21.         </p>  
  22.         <p>  
  23.             <input type="submit">  
  24.         </p>  
  25.     </form>  
  26. </body>  
  27. </html>  

效果


可以把上面的界面集成到自己的项目中。


CKEditor的安装,加载和集成都已经说完了,下篇将介绍如果扩展自己的插件。

一、配置CKEditor


CKEditor 具有丰富的一组配置选项,可以定制其外观、功能和行为。主配置文件名字为config.js。此文件可以在 CKEditor 安装文件夹的根目录中找到。

可用的配置选项在 API 文档中可以找到所有可用的配置选项。参考 CKEDITOR.config 对象的定义。


API文档:http://docs.ckeditor.com/#


给大家看看我的config配置:

 

[javascript]   view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. CKEDITOR.editorConfig = function( config ) {  
  2.       
  3.     //定义工具栏显示按钮  
  4.     config.toolbar_ths =  
  5.          [  
  6.              { name: 'document', items: ['Source''-''DocProps''Print''-''Templates'] },  
  7.              { name: 'clipboard', items: ['Cut''Copy''Paste''PasteText''PasteFromWord''-''Undo''Redo'] },  
  8.              { name: 'editing', items: ['Find''Replace''-''SelectAll''-''SpellChecker''Scayt'] },  
  9.              { name: 'links', items: ['Link''Unlink''Anchor'] },  
  10.             '/',  
  11.              { name: 'basicstyles', items: ['Bold''Italic''Underline''Strike''Subscript''Superscript''-''RemoveFormat'] },  
  12.              { name: 'paragraph', items: ['NumberedList''BulletedList''-''Outdent''Indent''-''Blockquote''-''JustifyLeft''JustifyCenter''JustifyRight''JustifyBlock''-''BidiLtr''BidiRtl'] },  
  13.                
  14.              { name: 'insert', items: ['Image''Flash''HorizontalRule''Smiley''SpecialChar''PageBreak''Iframe'] },  
  15.              '/',  
  16.              { name: 'styles', items: ['Styles''Format''Font''FontSize'] },  
  17.              { name: 'colors', items: ['TextColor''BGColor'] },  
  18.              { name: 'tools', items: ['Maximize''ShowBlocks'] },  
  19.              //自定义插件在工具栏上的位置  
  20.              { name: 'extent', items: ['Table','-','ths_form','-','ths_div','-','ths_label','-','ths_textfield','-','ths_select','-','ths_radio','-','ths_checkbox','-','ths_hiddenfield','-','ths_textarea','-','ths_button''-','Preview']}  
  21.          ];  
  22.       
  23.         //使用哪个工具栏  
  24.         config.toolbar = 'ths';  
  25.           
  26.         //加载自定义插件  
  27.         config.extraPlugins += (config.extraPlugins ? ',ths_textfield,ths_select,ths_radio,ths_checkbox,ths_hiddenfield,ths_textarea,ths_button,ths_div,ths_label,ths_form' : 'ths_textfield,ths_select,ths_radio,ths_checkbox,ths_hiddenfield,ths_textarea,ths_button,ths_div,ths_label,ths_form');  
  28.           
  29.         //移除不需要的插件  
  30.         config.removePlugins = 'forms,elementspath';  
  31.           
  32.         //移除不需要的工具栏按钮  
  33.         config.removeButtons = 'CreateDiv';  
  34.           
  35.         //去掉回车添加p标签,使用br  
  36.         config.enterMode = CKEDITOR.ENTER_BR ;    
  37.         config.shiftEnterMode =CKEDITOR.ENTER_BR;   
  38.         //config.startupMode = 'source';  (默认进入源代码编辑)  
  39.         //取消内容过滤  
  40.         config.allowedContent = true;  
  41.         //工具栏是否可以被收缩  
  42.         config.toolbarCanCollapse = true;  
  43.   
  44.         config.contentsCss = ['../assets/css/bootstrap.min.css'];  
  45.           
  46.         //工具栏的位置  
  47.         config.toolbarLocation = 'top';//可选:bottom  
  48.   
  49.         //工具栏默认是否展开  
  50.         config.toolbarStartupExpanded = true;  
  51.           
  52.         config.pasteFromWordRemoveStyles = false;  
  53.   
  54.           
  55. };  


这个配置,基本上囊括了CKEditor的最常用配置,注意注释部分


config中每一项的意思,请参照http://docs.ckeditor.com/#!/api/CKEDITOR.config


注意到config中,我们加入了自己的插件

 

[javascript]   view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. ths_textfield,ths_select,ths_radio,ths_checkbox,ths_hiddenfield,ths_textarea,ths_button,ths_div,ths_label,ths_form  

那么最终,我们的表单设计器是什么样子?

看看效果:



看到这,熟悉.NET的同学,有没有想起VS中的可视化页面设计器?其实要实现的表单设计器,就是运行在浏览器中类似vs这种设计器的Javascript富文本编辑器。


下节终于可以介绍重头戏,自定义插件的开发了。

前面基本环境都做得差不多了,这篇我们来介绍自定义插件的开发。


我们以"文本框“为例,

先来看效果:



点击确定,即可插入一个文本框


实现方式:


1、在ckeditor目录下 plugins文件夹下,新建如下结构:



plugin.js


 

[javascript]   view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. CKEDITOR.plugins.add( 'ths_textfield', {  
  2.     icons: 'ths_textfield',  
  3.     init: function( editor ) {   //初始化  
  4.         var pluginName = 'ths_textfield'//控件名称  
  5.         editor.addCommand( pluginName, new CKEDITOR.dialogCommand( pluginName ) ); //给编辑器注册一个打开弹出窗命令  
  6.                  
  7.         editor.ui.addButton(pluginName, {  //在工具栏上增加一个按钮,绑定按钮事件  
  8.             label: '单行文本框',  
  9.             command: pluginName  
  10.         });  
  11.       
  12.         if ( editor.contextMenu ) {  //为文本框加右键属性菜单  
  13.             editor.addMenuGroup( 'textFieldGroup' );  
  14.              editor.addMenuItem( 'textFieldItem', {  
  15.                     label: '文本框属性',  
  16.                     command:pluginName,  
  17.                     group: 'textFieldGroup'  
  18.                 });  
  19.               //右键菜单的监听器,判断是否显示菜单         
  20.               editor.contextMenu.addListener( function( element ) {  
  21.                     if ( element && !element.isReadOnly() ) {  
  22.                         var name = element.getName();  
  23.                         if ( name == 'input' ) {  
  24.                             var type = element.getAttribute( 'type' ) || 'text';  
  25.                             if ( type=='text' ){  
  26.                                    return { textFieldItem: CKEDITOR.TRISTATE_OFF };  
  27.                             }  
  28.                         }  
  29.                     }  
  30.                 });  
  31.         }  
  32.                 //增加弹出窗  
  33.         CKEDITOR.dialog.add( pluginName, this.path + 'dialogs/'+pluginName+'.js' );  
  34.         //为文本框双击事件绑定一个事件,即显示弹出窗  
  35.         editor.on( 'doubleclick'function( evt ) {  
  36.             var element = evt.data.element;  
  37.               
  38.              if ( element.is( 'input' ) ) {  
  39.                     var type = element.getAttribute( 'type' ) || 'text';  
  40.                     if ( type=='text' ){  
  41.                         evt.data.dialog =pluginName;  
  42.                     }  
  43.             }  
  44.         })  
  45.           
  46.     }  
  47. });  

 


代码不过多解释,请看注释
不喜欢讲代码,大家结合文档看注释


ths_textfield.js

 

[javascript]   view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. CKEDITOR.dialog.add( 'ths_textfield'function( editor ) {  
  2.       
  3.     return {  
  4.         title: '单行文本框属性',  
  5.         minWidth: 400,  
  6.         minHeight: 200,  
  7.         //弹出窗上显示的内容  
  8.         contents: [  
  9.             {  
  10.                 id: 'tab-basic',  
  11.                 label: '基本属性',  
  12.                 elements:[ {  
  13.                     type: 'hbox',  
  14.                     widths: [ '50%''50%' ],  
  15.                     children:  
  16.                     [  
  17.                          ths_editor_field(editor),              
  18.                              ths_editor_value(editor)  
  19.                      ]  
  20.                 },  
  21.                 {  
  22.                         type: 'hbox',  
  23.                         widths: [ '50%''50%' ],  
  24.                         children:  
  25.                         [ths_editor_relative_width(editor) ,  
  26.                          ths_editor_style(editor)  
  27.                         ]  
  28.                  }  
  29.                 ]  
  30.             },  
  31.   
  32.             {  
  33.                 id: 'tab-validate',  
  34.                 label: '数据校验',  
  35.                 elements: [  
  36.                     {  
  37.                         type: 'checkbox',  
  38.                         id: 'required',  
  39.                         label: '必填',  
  40.                         setup: function( element ) {  
  41.                             if(element.getAttribute( "required" )){  
  42.                                 this.setValue(true);  
  43.                             }  
  44.                         },  
  45.                         commit: function ( element ) {  
  46.                             var required = this.getValue();  
  47.                             if ( required )  
  48.                                 element.setAttribute( 'required''true' );  
  49.                             else if ( !this.insertMode )  
  50.                                 element.removeAttribute( 'required' );  
  51.                         }  
  52.                     }  
  53.                 ]  
  54.             },  
  55.             {  
  56.                 id: 'tab-event',  
  57.                 label: '事件',  
  58.                 elements: [  
  59.                                 ths_editor_onblur(editor),  
  60.                             ths_editor_onfocus(editor),  
  61.                             ths_editor_onclick(editor),  
  62.                             ths_editor_onchange(editor)  
  63.                 ]  
  64.             }  
  65.         ],  
  66.         //弹出窗显示事件  
  67.         onShow: function() {  
  68.   
  69.             var selection = editor.getSelection();  
  70.             var element = selection.getStartElement();  
  71.             if ( !element || element.getName() != 'input' || element.getAttribute( 'type' )!='text'  ) {  
  72.                 this.insertMode = true;  
  73.             }else{  
  74.                 this.insertMode = false;  
  75.             }  
  76.   
  77.             this.element = element;  
  78.             if ( !this.insertMode ){  
  79.                 this.setupContent( this.element );  
  80.             }  
  81.                   
  82.         },  
  83.         //弹出窗确定按钮事件  
  84.         onOk: function() {  
  85.             submitElement(this,editor,'text');  
  86.         }  
  87.     };  
  88. });  


补充js函数

这是针对所有表单组件的js

 

[javascript]   view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. function submitElement(dialog,editor,type){  
  2.       if ( dialog.insertMode ){  //如果是新建状态  
  3.           
  4.         var div=editor.document.createElement( 'div' );  
  5.         var label;  
  6.         var element;  
  7.                 //为不同的元素赋值  
  8.             switch ( type ) {  
  9.                 case 'select':  
  10.                     element = editor.document.createElement( 'select' );  
  11.                     if(dialog.getValueOf( 'tab-basic''dictionary')){element.setAttribute( 'dictionary', dialog.getValueOf( 'tab-basic''dictionary') )};           
  12.                     break;  
  13.                 case 'textarea':  
  14.                     element = editor.document.createElement( 'textarea' );  
  15.                     if(dialog.getValueOf( 'tab-basic''value')){element.setAttribute( 'value', dialog.getValueOf( 'tab-basic''value') )};              
  16.                     break;  
  17.                 case 'text':  
  18.                     element = editor.document.createElement( 'input' );  
  19.                     element.setAttribute( 'type', type );  
  20.                     //if(dialog.getValueOf( 'tab-basic', 'size')!='default'){element.addClass( dialog.getValueOf( 'tab-basic', 'size') )};  
  21.                     if(dialog.getValueOf( 'tab-basic''value')){element.setAttribute( 'value', dialog.getValueOf( 'tab-basic''value') )};              
  22.                     break;  
  23.                 case 'checkbox':  
  24.                     label=editor.document.createElement( 'label' );  
  25.                     label.addClass( 'checkbox-inline' );  
  26.                     element = editor.document.createElement( 'input' );  
  27.                     element.setAttribute( 'type', type );  
  28.                     if(dialog.getValueOf( 'tab-basic''dictionary')){element.setAttribute( 'dictionary', dialog.getValueOf( 'tab-basic''dictionary') )};           
  29.                     break;  
  30.                 case 'radio':  
  31.                     label=editor.document.createElement( 'label' );  
  32.                     label.addClass( 'radio-inline' );  
  33.                     element = editor.document.createElement( 'input' );  
  34.                     element.setAttribute( 'type', type );  
  35.                     if(dialog.getValueOf( 'tab-basic''dictionary')){element.setAttribute( 'dictionary', dialog.getValueOf( 'tab-basic''dictionary') )};           
  36.                     break;  
  37.                 case 'hidden':  
  38.                     element = editor.document.createElement( 'input' );  
  39.                     element.setAttribute( 'type', type );  
  40.                     element.setAttribute( 'name', dialog.getValueOf( 'tab-basic''name' ) );  
  41.                     if(dialog.getValueOf( 'tab-basic''value')){element.setAttribute( 'value', dialog.getValueOf( 'tab-basic''value') )};              
  42.                     editor.insertElement( element );  
  43.                     return;  
  44.             }  
  45.           
  46.             element.addClass( 'form-control' );  
  47.             element.setAttribute( 'name', dialog.getValueOf( 'tab-basic''name' ) );  
  48.             if(dialog.getValueOf( 'tab-basic''style' )){  
  49.                 element.setAttribute( 'style', element.getAttribute('style') ? element.getAttribute('style')+dialog.getValueOf( 'tab-basic''style' ):dialog.getValueOf( 'tab-basic''style' ) )  
  50.             };  
  51.               
  52.             if(dialog.getValueOf( 'tab-basic''width' )) {div.addClass(dialog.getValueOf( 'tab-basic''width'))};  
  53.               
  54.             if(dialog.getValueOf( 'tab-event''onclick')){element.setAttribute( 'onclick', dialog.getValueOf( 'tab-event''onclick') )};  
  55.             if(dialog.getValueOf( 'tab-event''onfocus')){element.setAttribute( 'onfocus', dialog.getValueOf( 'tab-event''onfocus') )};  
  56.             if(dialog.getValueOf( 'tab-event''onblur')){element.setAttribute( 'onblur', dialog.getValueOf( 'tab-event''onblur') )} ;  
  57.             if(dialog.getValueOf( 'tab-event''onchange')){element.setAttribute( 'onchange', dialog.getValueOf( 'tab-event''onchange') )} ;  
  58.             if(dialog.getValueOf( 'tab-validate''required' )){element.setAttribute( 'required', dialog.getValueOf( 'tab-validate''required' ) )};  
  59.               
  60.             if(label){  
  61.                 label.append(element);  
  62.                 div.append(label);  
  63.             }else{  
  64.                 div.append(element);  
  65.             }  
  66.               
  67.             editor.insertElement( div );  
  68.           
  69.       }else{  
  70.           dialog.commitContent( dialog.element );  
  71.       }  
  72.       
  73. }  


弹出窗中,显示文本域的示例:

 

[javascript]   view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. function ths_editor_size(editor){  
  2.     var editor_size={  
  3.            type : 'select',  
  4.         id: 'size',  
  5.         label: '大小:',  
  6.         style: 'width:190px',  
  7.         'default' : 'default',  
  8.         items :  
  9.                 [  
  10.                     [ '大''input-lg' ],  
  11.                     [ '默认''default' ],  
  12.                     [ '小''input-sm' ]  
  13.                 ],  
  14.         setup: function( element ) {  //弹出窗初始化时会调用  
  15.              
  16.            var classStr=element.getAttribute( "class" ) ? element.getAttribute( "class" ) : 'default';  
  17.              
  18.            if(classStr.indexOf('input')>=0){  
  19.                classStr=classStr.substring(classStr.indexOf('input'),classStr.indexOf('input')+8);  
  20.                this.setValue(classStr);  
  21.            }else{  
  22.                return;  
  23.            }  
  24.              
  25.         },  
  26.         commit: function( element ) {  //提交时会调用  
  27.              var classStr = this.getValue();  
  28.                
  29.              if(element.hasClass('input-lg')) element.removeClass('input-lg');  
  30.              if(element.hasClass('input-sm')) element.removeClass('input-sm');  
  31.                
  32.               if ( classStr && classStr!='default'){  
  33.                  element.addClass(classStr);  
  34.               }  
  35.         }  
  36.        }  
  37.     return editor_size;  
  38. }  



 

不想贴代码,感觉代码真的很无力,但想说明白一件事,似乎代码来得更直接些,上面代码均为核心代码。


随后会把代码开源,请留意


如果你英文比较好,推荐看如下两篇文章:

http://docs.ckeditor.com/#!/guide/plugin_sdk_sample_1

http://docs.ckeditor.com/#!/guide/plugin_sdk_sample_2

上篇,我们介绍了表单域的开发,那么针对一键初始化,保存,重置,清空,预览,这些操作如何做呢?


看看效果:



点击初始化,直接初始化一个完整的表单,当然初始化规则,需要你自己定义。




点击预览,即可弹出新窗口,预览设计好的表单。

其他操作不再一一截图。


这些效果,其实不难实现,参照Ckeditor提供的api,我们定义好自己的规则即可,完整代码如下:

 

[html]   view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <%@ page language="java" contentType="text/html; charset=UTF-8"  
  2.     pageEncoding="UTF-8"%>  
  3.     <%@ include file="/page/common/common.jsp"%>  
  4. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
  5. <html>  
  6. <head>  
  7. <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />  
  8. <meta charset="utf-8" />  
  9. <title>Insert title here</title>  
  10.   
  11.   
  12. <meta name="description" content="Static & Dynamic Tables" />  
  13. <meta name="viewport"  
  14.     content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />  
  15.   
  16. <!-- bootstrap & fontawesome -->  
  17. <link rel="stylesheet"  
  18.     href="${contextPath}/assets/css/bootstrap.min.css" />  
  19. <link rel="stylesheet"  
  20.     href="${contextPath}/assets/css/font-awesome.min.css" />  
  21.   
  22. <!-- page specific plugin styles -->  
  23.   
  24. <!-- text fonts -->  
  25. <link rel="stylesheet" href="${contextPath}/assets/css/ace-fonts.css" />  
  26.   
  27. <!-- ace styles -->  
  28. <link rel="stylesheet" href="${contextPath}/assets/css/ace.min.css"  
  29.     id="main-ace-style" />  
  30.   
  31. <!--[if lte IE 9]>  
  32.             <link rel="stylesheet" href="${contextPath}/assets/css/ace-part2.min.css" />  
  33.         <![endif]-->  
  34. <link rel="stylesheet"  
  35.     href="${contextPath}/assets/css/ace-skins.min.css" />  
  36. <link rel="stylesheet" href="${contextPath}/assets/css/ace-rtl.min.css" />  
  37.   
  38. <!--[if lte IE 9]>  
  39.           <link rel="stylesheet" href="${contextPath}/assets/css/ace-ie.min.css" />  
  40. <![endif]-->  
  41.   
  42. <link rel="stylesheet" href="${contextPath}/assets/css/ths.content.css" />  
  43. <link rel="stylesheet" type="text/css" href="${contextPath}/assets/css/easyui.css">  
  44.   
  45. <!-- ace settings handler -->  
  46. <script src="${contextPath}/assets/js/ace-extra.min.js"></script>  
  47.   
  48. <!-- HTML5shiv and Respond.js for IE8 to support HTML5 elements and media queries -->  
  49. <!--[if lte IE 8]>  
  50.         <script src="${contextPath}/assets/js/html5shiv.min.js"></script>  
  51.         <script src="${contextPath}/assets/js/respond.min.js"></script>  
  52. <![endif]-->  
  53.   
  54. <script src="${contextPath}/assets/js/jquery.min.js"></script>  
  55. <script src="${contextPath}/ckeditor/ckeditor.js"></script>  
  56. <script src="${contextPath}/ckeditor/ths_editor.js"></script>  
  57.   
  58. </head>  
  59. <body>  
  60.     <form id="editor_form" method="post" action="${contextPath}/editor/submit">  
  61.        
  62.      <input type="hidden" id="formid"   value="user_form" />  
  63.      <input type="hidden" id="listid"   value="user_list" />  
  64.      <input type="hidden" id="formurl"   value="${contextPath}/editor/formjson" />  
  65.      <input type="hidden" id="formjson"   value="" />  
  66.         <p>  
  67.             <textarea name="ths_editor"></textarea>  
  68.             <script>  
  69.             //初始化ckeditor  
  70.             var ths_editor=CKEDITOR.replace('ths_editor');  
  71.             //执行ckeditor插件  
  72.             function ths_exec_cmd(cmd){  
  73.                 CKEDITOR.instances['ths_editor'].execCommand(cmd);  
  74.             }  
  75.               
  76.             function ths_editor_init(flag){  
  77.                 if(flag=='table'){  
  78.                     var url="${contextPath}/editor/tableform"   
  79.                 }else{  
  80.                     var url="${contextPath}/editor/divform"   
  81.                 }  
  82.                   
  83.                 var param =  "formid=" + $('#formid').val()+ "&listid="  
  84.                         + $('#listid').val();  
  85.                  $.ajax({  
  86.                         type : 'post',  
  87.                         url :url,  
  88.                         data : param,  
  89.                         async : false,//这里必须是同步请求  
  90.                         success : function(response) {  
  91.                               CKEDITOR.instances['ths_editor'].insertHtml(response);  
  92.                         },  
  93.                         error:function (XMLHttpRequest, textStatus, errorThrown) {  
  94.                                alert(textStatus);  
  95.                         }  
  96.                 });  
  97.                   
  98.             }  
  99.               
  100.             function ths_editor_preview(){  
  101.                  var data = CKEDITOR.instances.ths_editor.getData();  
  102.                  $('#preview').html(data);  
  103.                  $('#preview').show()  
  104.             }  
  105.               
  106.             function ths_editor_reset(){  
  107.                 CKEDITOR.instances.ths_editor.setData( '', function() {  
  108.                     //this.checkDirty(); // true  
  109.                     ths_editor_init();  
  110.                 });  
  111.             }  
  112.               
  113.             function ths_editor_clear(){  
  114.                 CKEDITOR.instances.ths_editor.setData('');  
  115.                 $('#preview').html("");  
  116.                 $('#preview').hidden()  
  117.             }  
  118.               
  119.             function ths_editor_save(){  
  120.                  var param =  "formid=" + $('#formid').val()+ "&listid="  
  121.                     + $('#listid').val()+"&ths_editor="+CKEDITOR.instances.ths_editor.getData();  
  122.                    
  123.                  $.ajax({  
  124.                         type : 'post',  
  125.                         url : $('#editor_form').attr('action'),  
  126.                         data : param,  
  127.                         async : false,//这里必须是同步请求  
  128.                         success : function(response) {  
  129.                             alert(response);  
  130.                         },  
  131.                         error:function (XMLHttpRequest, textStatus, errorThrown) {  
  132.                                alert(textStatus);  
  133.                         }  
  134.                 });  
  135.                    
  136.             }  
  137.               
  138.             </script>  
  139.         </p>  
  140.         <p>  
  141.             <!--  <input type="submit">   -->  
  142.         </p>  
  143.     </form>  
  144.       
  145.     <input id="btn_inittable"  type="button"  value="初始化Table表单"  onclick="ths_editor_init('table')"></input>  
  146.     <input id="btn_initdiv"  type="button"  value="初始化Div表单"  onclick="ths_editor_init('div')"></input>  
  147.     <input id="btn_reset"  type="button"  value="重置"  onclick="ths_editor_reset()"></input>  
  148.     <input id="btn_clear"  type="button"  value="清空"  onclick="ths_editor_clear()"></input>  
  149.     <input id="btn_preview"  type="button"  value="预览"  onclick="ths_editor_preview()"></input>  
  150.     <input id="btn_save"  type="button"  value="保存"  onclick="ths_editor_save()"></input>  
  151.     <input id="btn_ths_textfield"  type="button"  value="单行文本框"  onclick="ths_exec_cmd('ths_textfield')"></input>  
  152.     <input id="btn_ths_textarea"  type="button"  value="多行文本框"  onclick="ths_exec_cmd('ths_textarea')"></input>  
  153.     <input id="btn_ths_select"  type="button"  value="下拉框"  onclick="ths_exec_cmd('ths_select')"></input>  
  154.     <input id="btn_ths_radio"  type="button"  value="单选框"  onclick="ths_exec_cmd('ths_radio')"></input>  
  155.     <input id="btn_ths_checkbox"  type="button"  value="复选框"  onclick="ths_exec_cmd('ths_checkbox')"></input>  
  156.     <input id="btn_ths_hiddenfield"  type="button"  value="隐藏域"  onclick="ths_exec_cmd('ths_hiddenfield')"></input>  
  157.       
  158.     <div  id="preview" style="padding:10px;margin-top:10px;display:none">  
  159.     </div>  
  160.       
  161. </body>  
  162. </html>  



 

这几篇文章更多地是介绍使用CKeditor来定制自己的表单设计器的一个思路,其中包括了CKeditor的初始化,配置,插件开发,扩展功能等。

不要拘泥于每一行代码,重要的是思路。


随后会把代码公开到CSDN CODE,不要急着跟我要代码哈。

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
宏天BPM X3软件平台是一个易于部署和使用的新一代业务流程管理平台,能够以最快的速度帮助您梳理、设计、执行、监控分析和优化业务流程,从业务和IT相结合的完美视角为用户组建长期而久远的卓越BPM流程管 理架构。通过实施BPM方案让您的企业在运营效率、透明度、控制力和敏捷性方面迅速受益。 BPMX3是基于J2EE开源、轻量级的企业业务开发平台,基于代码重用、组件重用、业务逻辑重用、组装重用,结合快速开发平台中的工具,将开发人员从重复的代码编写中解放出来,把更多的精力集中解决客户的业务逻辑处理上。 BPMX3是支持流程管理、监控、优化、再造的全套IT管理开发平台,并且集单点登录、企业单位门户、业务流程管理、开发、整合、业务分析及重构等多重职能于一身的软件开发工具和企业IT架构平台。 BPMX3是企业管理业务的创新关键,可以帮忙用户更科学、更有效管理企业业务的各个环节,企业通过BPMX3可以明显实现业务的高效运营。同时,由于其架构的开放性,采用业界开放性的技术及流程标准,使其能够成为企业SOA架构的流程基础平台及开发平台,越来越多的企业更偏向采用开源的平台来解决其内部的信息化平台的要求,BPMX3却允许更多的平台系统接入及自身扩展更多的功能,以满足更多的企业不同的个性化的需求,以达到最大满足最终的客户使用要求。 【图一】工作流引擎中心 1.BPMX3的特点 1.是一个开放式、轻量级的开发平台 2.BPMX3多层系统架构 3.基于模板代码生成 4.丰富的报表展示 5.跨数据库的数据访问支持 6.简易的前端使用 7.参照最新的BPMN2标准设计 8.满足中国特色流程需求 9.在线的可视化流程设计、可视化的流程监控 10.完全独立的流程引擎服务,可与其他系统无缝集成 11.基于流行的JAVA 流程引擎Activiti 5.8扩展 12.灵活的在线流程定义 13.灵活的嵌入式部署、独立部署 14.灵活的在线表单定义及版本管理(支持按内表及外部表及视图生成表单) 15.灵活的第三方表单集成 16.开放式的流程体系 17.灵活的组织结构支持 18.流程的导入与导出 19.子流程支持 20.流程任务逐步回退处理(任务追回及多驳回 ) 21.流程自由跳转 22.流程跳转业务规则设置 23.多级分发任务与任务汇总 24.会签(并行与串行)、补签及投票处理 25.流程版本变更管理 26.流程催办(基于MQ短信及邮件设置) 27.流程任务的工作日设置(用于统计流程任务执行效率) 28.任务监控管理 29.流程委办、转办 2.BPMX3多层架构 系统采用多层的系统架构进行功能开发,有利于代码功能责任分开,同时有利于不同开发人员的分工及合作,也有利于代码的单元测试。系统总体结构如下图所示: 【图二】BPMX3多层架构 •数据访问层Dao: 负责与数据库交互 •业务处理层Service: 负责系统的所有业务逻辑处理 •数据控制层Controller: 负责系统的页面数据准备及跳转处理 •视图层View :负责数据的展示处理 整合的开源技术 1.Spring Core 3.0.4 2.Spring MVC 3.0 3.Spring Security 3.0.5 4.Spring AOP 3.0.4 5.Apache Active MQ 5.5 6.MyBatis 3 7.CKEditor 3.6 8.JQuery 1.8 9.CXF 2.0 10.Alfresco Activiti 5.8 11.Compass + Lucene 12.JasperReport 4.5 13.JavaMail 14.Other: Log4j,Velocity,Sitemesh,Jfreechart,Jforum,Solr 15.Maven 2 3.BPMX3的组件构建方式 BPMX3同时也是基于组件构构建,整个系统的构建如下所示: 【图三】BPMX3组件构建 系统提供在线流程设计,在线表单设计,代码生成,结合BPMX3的基础组件,以实现复杂的流程业务应用。基础组件包括: Spring基础组件库,报表引擎,数据库访问模块,短信模块,后台定时任务调用组件,短信访问组件,搜索引擎组件,JMS消息组件,Activiti工作流组件,Cas统一用户认证组件,Spring安全认证组件。 4.BPMX3总体功能 1.多系统管理 BPMX3支持多个业务系统同时运行及切换处理,根据不同的用户授权允许用户进入不同的系统进行访问,而不同的业务系统的开发可以基于BPMX3平台上开发,也可以由其他开发框架开发再与BPMX3做整合。这种模式非常适合企业把BPMX3作为其内部的首先开发平台,以使后续的新应用系统都整合在一起进行管理及使用。 【图四】多系统管理 2.用户管理 BPMX3提供多种维度的用户人员管理,以支持各种类型的组织机构及人员的统一管理,目前可以支持内部组织、外部组织 、虚拟组织。而且还提供用户的属性自定义,允许对用户进行多种属性的扩展,以支持工作流中的任务节点的人员的复杂查找计算。 3.系统安全管理 系统的安全管理由Spring Security 3提供配置及管理,非常容易与第三方的用户或认证平台进行整合,如与CAS服务作统一认证,只需要加上新的配置模块即可实现,不影响系统现有的功能模块。大大满足了各种不同系统的安全管理认证的需要。 同时系统可以支持URL访问权限、数据权限、列权限及页面按钮权限的统一配置管理。系统的安全认证机制如下所示: 【图五】系统安全拦截原理 4.动态表单管理 BPMX3提供了基于数据库内部表、外部表、视图等来生成在线的流程表单的功能,其生成是基于模板,模板可由开发人员进行自定义,也可以采用BPMX3提供的默认模板。生成的表单后,系统管理员还可以对表单进行编辑管理以实现企业的业务要求,其中,还允许开发人员在表单上编写编写脚本,以实现更复杂的应用。 表单上支持系统中的大量组件,如角色选择,用户选择,角色选择,在线表单,套红在线Office表单,签章表单等。系统开发人员几乎不用作任何开发,可以设计出任何复杂的表单应用需求。 表单上支持系统中的大量组件,如角色选择,用户选择,角色选择,在线表单,套红在线Office表单,签章表单等。系统开发人员几乎不用作任何开发,可以设计出任何复杂的表单应用需求。 【图六】在线动态表单 5.流程管理 BPMX3提供了基于BPMN2标准的流程管理,包括流程版本变量,流程节点表单设置,表单的权限设置,流程任务通知,催办,代办,转化,并行会签、串行会签、补签,子流程,同步任务,多实例任务,人工任务、消息任务、邮件任务等,任务多级分发与汇总、任务追回、任务层层驳回,任务自由跳转等中国特色的流程需求。能满足企业复杂的流程应用需求。 BPMX3在流程管理上,不但能结合在线设计的复杂表单,还能结合本系统或其他系统其他模块的功能表单一起进行业务审批的工作。这大大方便了业务流程在所有的系统中进行流程开发的工作,简化了以往开发流程业务的代码固死的做法,把程序员或业务员真正从流程业务中解放出来。 【图七】在线流程管理 【图八】在线流程设计 6.报表管理 系统的报表管理是基于模板来进行设置管理的,目前支持FineReport及Jasper Report两种报表引擎,前者是商业报表,其功能非常强大,可以实现多样式数据呈现方式,支持HTML、PDF、EXCEL、Word、TXT、Flash样式呈,能完美解决中国式报表难题,无论数据库内原始数据是以何种样式的表结构存储,无论最终用户要求数据以何种表格样式显示,FineReport报表软件独创的多数据源关联查询、公式动态扩展计算等强大的功能,在无需改变表结构,无需改变用户的要求的基础上,完全按照用户的需求制作出报表模板。 【图九】报表管理 7.系统基础组件 系统的基础组件如用户模块一样,是系统的业务功能的基础,在其他业务模块中被大量使用。 ◦定时任务管理 通过配置以实现某时刻重复执行的系统任务,如配置每月最后一天进行库存清算任务,并且启动库存清算审批流程。 ◦系统日志管理 记录进入系统中的每个用户访问的每个功能 ◦数据源管理 可以设置多种数据源,为在线表单设计及展示提供数据来源 ◦资源管理 管理系统的所有资源,包括URL,业务方法等,提供给安全管理进行极限配置 ◦流水号管理 用于产生业务的一些处理流水单号 ◦数据字典管理 用于管理所有的业务中常用的数据字典的数据 ◦附件管理 管理系统中所有的上传附件。 ◦桌面管理 管理用户的桌面布局及常用的功能展示 ◦邮件、短信模板管理 用于配置系统的发送邮件、短信的模板 ◦工作日历管理 用于配置系统的工作流的待办事项的处理工作时间的计算处理 ◦动态脚本管理 用于为流程任务节点或事件中可被调用的逻辑计算代码 ◦短信收发管理 基于USB短信猫的短信模块或短信网关,以实现收发手机短信功能。 ◦外部邮件管理 支持POP3,IMap协议的邮件服务收发功能,允许用户设置多个外部邮箱。 ◦内部短消息收发管理 在系统中用户之间可以收发短消息,如工作流任务的通知也采用短消息进行实时提醒。
包括源代码、数据库文档、数据库创建SQL脚本。一套基于ASP.NET MVC+EF6+Bootstrap开发出来的框架源代码! 采用主流框架,容易上手,简单易学,学习成本低。可完全实现二次开发、基本满足80%项目需求。 可以帮助解决.NET项目70%的重复工作,让开发更多关注业务逻辑。既能快速提高开发效率,帮助公司节省人力成本,同时又不失灵活性。 支持SQLServer、MySQL、Oracle、SQLite、Access 等多数据库类型。模块化设计,层次结构清晰。内置一系列企业信息管理的基础功能。 操作权限控制精密细致,对所有管理链接都进行权限验证,可控制到导航菜单、功能按钮。 数据权限(精细化数据权限控制,控制到行级,列表级,表单字段级,实现不同人看不同数据,不同人对同一个页面操作不同字段 兼容目前最流行浏览(IE8+、Chrome、Firefox、360浏览) 1、前端技术 JS框架:Bootstrap、JQuery CSS框架:Bootstrap v3.3.4(稳定是后台,UI方面根据需求自己升级改造吧)。 客户端验证:jQuery Validation Plugin。 在线编辑ckeditor、simditor 上传文件:Uploadify 数据表格:jqGrid、Bootstrap Talbe 对话框:layer 页面布局:jquery.layout.js 图表插件:echarts、highcharts 2、后端技术 核心框架:ASP.NET MVC5、WEB API 持久层框架:EntityFramework 定时计划任务:Quartz.Net组件 安全支持:过滤、Sql注入、请求伪造 服务端验证:实体模型验证、自己封装Validator 缓存框架:微软自带Cache、Redis 日志管理:Log4net、登录日志、操作日志 工具类:NPOI、Newtonsoft.Json、验证码

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值