FCLEditor相关内容

主题:再谈FCKeditor添加自定义工具栏的问题
http://www.javaeye.com/topic/150487

以前在弄FCKeditor的时候写了一篇如何添加自定义工具栏的文章,请参看:http://j2ee.blog.sohu.com/36813753.html。不过那时候虽然写了具体的操作方法,不过写的比较杂乱,呵呵,什么都写了,所以可能来实践的时候会看的比较辛苦:-)同时也无意中发现了网上很多人也确实在找这样的东东,所以今天有时间就重新整理了一份如何添加自定义工具栏在FCKeditor编辑器中详细步骤。

话不多说了,首先做准备工作,下载相应的文件,呵呵。目前FCKeditor已经升级到2.5了,下载连接如下:
1.FCKeditor下载主页面:http://www.fckeditor.net/download
2.FCKeditor V2.5的下载页面:http://sourceforge.net/project/downloading.php?group_id=75348&filename=FCKeditor_2.5.1.zip
3.另外的,如java和.net的上传等工具包就根据自己的情况下载了。

我们今天来做一个非常简单的工具按钮,就是点击这个按钮后会弹出一个对话框,只有一个输入框,我们输入的任何内容都会被插入到编辑器中去。这个工具按钮我们就叫做:MyToolBar吧,呵~~~

一、修改fckconfig.js文件(位于FCKeditor_2.5.zip压缩包解压后的fckeditor目录下)
1.我们找到FCKConfig.ToolbarSets["Default"]这一行,在最后即'About'后添加一个工具按钮MyToolBar,名称为MyToolBar;
2.找到FCKConfig.DefaultLanguage,修改语言为:zh-cn;
3.找到FCKConfig.AutoDetectLanguage,设置为false,即关闭语言的自动检测功能;

二、修改zh-cn.js文件(位于editor\lang目录下)
1.在最后加入:MyToolBar : "我的自定义工具栏"
2.注意它前面的一个最后要加多一个逗号;

三、修改源码
1.打开文件fckregexlib.js(位于editor\_source\internals);
2.找到NamedCommands这一行,在最后加入:MyToolBar
3.然后再打开同目录下的fckcommands.js文件;
4.找到FCKCommands.GetCommand函数,在其中加入:

case 'MyToolBar' : oCommand = new FCKDialogCommand( 'MyToolBar', FCKLang.MyToolBar , 'dialog/MyToolBar.html', 450, 400 ) ; break ;

5.然后再打开同目录下的fcktoolbaritems.js文件;
6.找到FCKToolbarItems.GetItem函数,在其中加入:

case 'MyToolBar' : oItem = new FCKToolbarButton( 'MyToolBar' , FCKLang.MyToolBar, null, null, null, true, 72 ) ; break ;
这里72是表示skins目录下各个皮肤目录中fck_strip.gif图片文件中的图片索引,我们这里用和命令ShowBlocks一样的图标(一个问号图片)。

四、建立模式对话框文件
1.打开目录editor\dialog,在其下建立文件:MyToolBar.html
2.内容如下:

01 <html>...</html><html xmlns="http://www.w3.org/1999/xhtml">
02 <head>...</head><head>
03 <title></title>
04 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
05 <meta content="noindex, nofollow" name="robots" />
06 <script src="common/fck_dialog_common.js" type="text/javascript"></script>
07 <script type="text/javascript">
08
09 var oEditor = window.parent.InnerDialogLoaded() ;
10
11 window.onload = function()
12 ...{
13 window.parent.SetOkButton( true ) ;
14 window.parent.SetAutoSize( true ) ;
15 }
16
17 function Ok()
18 ...{
19 var oActiveEl = oEditor.FCK.EditorDocument.createElement( 'SPAN' ) ;
20 oActiveEl.innerHTML = GetE('txtName').value ;
21 oEditor.FCKUndo.SaveUndoStep() ;
22 oActiveEl = oEditor.FCK.InsertElement( oActiveEl ) ;
23
24 return true ;
25 }
26 </script>
27 </head>
28 <body>...</body><body style="overflow: hidden">
29 <table width="100%" style="height: 100%">
30 <tr>
31 <td align="center">
32 <table cellspacing="0" cellpadding="0" border="0">
33 <tr><td>请输入文字:<input id="txtName" type="text"/></td></tr>
34 </table>
35 </td>
36 </tr>
37 </table>
38 </body>
39 </html>


五、打包修改后的源代码
官方网站下载页面给出的那个压缩程序(.net写的)有问题,在运行的时候总是报错:Unhandled Exception: System.NullReferenceException: Object reference not set。然后在fckeditor论坛上找相关的帖子时发现另外一个地方可以下载,呵呵,一样是官方的,不过是php编译后的可执行程序。在windows下可以直接运行,非常方便。大家可以到这里下载:http://dev.fckeditor.net/browser/FCKpackager/trunk/fckpackager.exe。注意这个是下载页面,然后在页面在最下方点那个“downloading”下载即可!注意下下来的文件就是一个可执行程序fckpackager.exe。
1.copy这个程序(fckpackager.exe)到fckeditor目录下。
2.打开一个DOS窗口,定位到当前目录;
3.运行fckpackager命令即可。
4.命令运行后,DOS窗口会列出一长串的JS清单,然后最后会显示:
Number of files processed: 84
Original size............: 568,563 bytes
Output file size.........: 240,124 bytes (42.23% of original)

The generation of 2 files has been completed in 3.3316287994 seconds.
这样就表示文件已经压缩成功了!

六、查看运行效果
打开目录_samples\html下的sample01.html文件,我们就可以在页面上的最后一个工具栏发现我们刚添加的这个按钮命令了。

七、添加上下文菜单
我们在使用FCKeditor来添加一个单行输入框的时候,添加成功后会发现在编辑区域我们通过在该input员素上点右键就可以很方便的来编辑我们刚才输入的内容。这就是fckeditor中的contextmenu了,我们也可以非常方便的为我们自定义的工具栏来添加上下文菜单。
1.打开源文件夹中internals目录下的fck_contextmenu.js文件;
2.找到函数FCK_ContextMenu_GetListener,在最后加入一指定的CASE代码,具体的视自己的情况而写;
3.修改fckconfig.js在FCKConfig.ContextMenu的最后加入一菜单名称,注意要和你的第二步中的case的条件名称一样;
4.另外在zh-cn.js中添加一个上下文菜单的中文名称,然后在第二步中的代码中的menu.AddItem处使用该名称,通常的命名规范就是你的工具按钮的命令名称后加一个Prop;

通过这几步后就可以很方便的添加一个上下文菜单了,我前面的一篇文章也提到了这个,可以参考一下。至此,我们对fckeditor进行自定义工具栏的添加就算完成了。可以试一试哦,如果大家觉得好的话也顶一下和鼓励下咯~

另外,附件里已经是按照上面说的添加成功的的编辑器,大家可以试一试!

比较不错的修改FCKEditor的修改方法
http://blog.csdn.net/cnming/archive/2008/03/12/2172886.aspx
比较不错的修改FCKEditor的修改方法
 
由于项目需要,近期仔细研究了FCKEditor。发现一下bug,以及缺少的一些东西。
一、防止连续文本导致出现滚动条
        FCKEditor编辑器使用Iframe来处理编辑器内容,可惜不支持文本换行,假如你连续输入一段英文或数字等,将会出现滚动条,这时我们需要给其增加word-wrap样式为break-word;
添加方式有很多,我选择最便捷的修改方式:具体做法是修改fckeditor.html文件,给<iframe id="eEditorArea" 增加事件 onload="window.frames['eEditorArea'].document.body.style.wordWrap='break-word'"
二、增加Media以及Realplay按钮
      此项工作相对庞大,要修改很多js文件,以及一些图片和样式文件。
      a.准备图片:FCKeditor\editor\css\images下面,添加fck_medialogo.gif和fck_realplaylogo.gif,大小随意,作为背景居中显示的。
FCKeditor\editor\skins\default\toolbar\增加media.gif和realplay.gif,其他皮肤类推。
      b.修改css:给FCKeditor\editor\css\fck_internal.css增加
 
 
.FCK__Media
{
 border: darkgray 1px solid;
 background-position: center center;
 background-image: url(images/fck_medialogo.gif);
 background-repeat: no-repeat;
 width: 80px ;
 height: 80px ;
}
 
.FCK__Realplay
{
 border: darkgray 1px solid;
 background-position: center center;
 background-image: url(images/fck_realplaylogo.JPG);
 background-repeat: no-repeat;
 width: 80px ;
 height: 80px ;
}
c。修改js,主要以realplay做示例
FCKeditor\editor\js\fckeditorcode_ie_1.js,在FCKDocumentProcessors.addItem(FCKFlashProcessor);后面增加
// Realplay begin
var FCKRealplayProcessor=new Object();
FCKRealplayProcessor.ProcessDocument=function(A){
    var B=A.getElementsByTagName('EMBED');
    var C;
    var i=B.length-1;
 
while (i>=0&&(C=B[i--])){
if (C.src.endsWith('.rm',true) || C.src.endsWith('.ram',true) || C.src.endsWith('.ra',true))
{var D=FCKDocumentProcessors_CreateFakeImage('FCK__Realplay',C.cloneNode(true));
D.setAttribute('_fckRealplay','true',0);
FCKRealplayProcessor.RefreshView(D,C);
C.parentNode.insertBefore(D,C);
C.parentNode.removeChild(C);
};
};
};
 
FCKRealplayProcessor.RefreshView=function(A,B){
    if (B.width>0) A.style.width=FCKTools.ConvertHtmlSizeToStyle(B.width);
    if (B.height>0) A.style.height=FCKTools.ConvertHtmlSizeToStyle(B.height);
};
FCKDocumentProcessors.addItem(FCKRealplayProcessor);
// Realplay end
var FCKMediaProcessor=new Object();
FCKMediaProcessor.ProcessDocument=function(A)
{
    var B=A.getElementsByTagName('EMBED');
    var C;
    var i=B.length-1;
    while (i>=0&&(C=B[i--]))
    {
        if (C.src.endsWith('.avi',true) || C.src.endsWith('.mpg',true) || C.src.endsWith('.mpeg',true))
        {
            var D=FCKDocumentProcessors_CreateFakeImage('FCK__Media',C.cloneNode(true));
            D.setAttribute('_fckmedia','true',0);FCKMediaProcessor.RefreshView(D,C);
            C.parentNode.insertBefore(D,C);C.parentNode.removeChild(C);
        };
    };
};
FCKMediaProcessor.RefreshView=function(A,B)
{
    if (B.width>0) A.style.width=FCKTools.ConvertHtmlSizeToStyle(B.width);
    if (B.height>0) A.style.height=FCKTools.ConvertHtmlSizeToStyle(B.height);
};
FCKDocumentProcessors.addItem(FCKMediaProcessor);
然后修改FCK.GetRealElement方法为下面代码,该方法为处理编辑器中width和height的调整
FCK.GetRealElement=function(A){
var e=FCKTempBin.Elements[A.getAttribute('_fckrealelement')];
 
if (A.getAttribute('_fckflash')|| A.getAttribute('_fckrealplay') || A.getAttribute('_fckmedia')){
    if (A.style.width.length>0) e.width=FCKTools.ConvertStyleSizeToHtml(A.style.width);
    if (A.style.height.length>0) e.height=FCKTools.ConvertStyleSizeToHtml(A.style.height);
};
return e;};
----------
FCKeditor\editor\js\fckeditorcode_ie_2.js
FCKCommands.GetCommand方法增加
case 'Media':B=new FCKDialogCommand('Media',FCKLang.DlgMediaTitle,'dialog/fck_Media.html',450,400);
break;
case 'Realplay':B=new FCKDialogCommand('Realplay',FCKLang.DlgMediaTitle,'dialog/fck_Realplay.html',450,400);
break;
FCKToolbarItems.GetItem方法增加
case 'Media':B=new FCKToolbarButton('Media',FCKLang.InsertMediaLbl,FCKLang.InsertMedia);
break;
case 'Realplay':B=new FCKToolbarButton('Realplay',FCKLang.InsertRealplayLbl,FCKLang.InsertRealplay);
break;
FCKContextMenu._GetGroup方法增加
case 'Media':return new FCKContextMenuGroup(true,this,'Media',FCKLang.MediaProperties,true);
case 'Realplay':return new FCKContextMenuGroup(true,this,'Realplay',FCKLang.RealplayProperties,true);   // truly
FCKContextMenu.RefreshState方法增加
if (this.Groups['Media'])   this.Groups['Media'].SetVisible(B=='IMG'&&A.getAttribute('_fckmedia'));
if (this.Groups['Realplay']) this.Groups['Realplay'].SetVisible(B=='IMG'&&A.getAttribute('_fckrealplay'));
 
然后要增加'dialog/fck_Media.html'和'dialog/fck_Realplay.html'页面,具体我懒得再写了,自己到我的源码下载里看,我是在2。1的基础上改的,2.2要做一些调整!
fckconfig.js也有较多调整,但是这个文件非常简单,自己去看我的源码吧。
然后就是lang目录中对常量的定义,搜索一下就很容易得到,没什么可讲。
在然后就可以了,:)。
 
三、添加删除按钮列,类似sina的blog中的编辑控件
四、修改上传路径
        默认是根目录/UserFiles,有多种方式进行修改,先看一下它的源码:
protected string UserFilesPath
{
 get
 {
 if ( sUserFilesPath == null )
 {
   // Try to get from the "Application".
   sUserFilesPath = (string)Application["FCKeditor:UserFilesPath"] ;
 
   // Try to get from the "Session".
   if ( sUserFilesPath == null || sUserFilesPath.Length == 0 )
   {
    sUserFilesPath = (string)Session["FCKeditor:UserFilesPath"] ;
    // Try to get from the Web.config file.
    if ( sUserFilesPath == null || sUserFilesPath.Length == 0 )
    {
     sUserFilesPath = System.Configuration.ConfigurationSettings.AppSettings["FCKeditor:UserFilesPath"] ;
     // Otherwise use the default value.
     if ( sUserFilesPath == null || sUserFilesPath.Length == 0 )
      sUserFilesPath = DEFAULT_USER_FILES_PATH ;
 
     // Try to get from the URL.
     if ( sUserFilesPath == null || sUserFilesPath.Length == 0 )
     {
      sUserFilesPath = Request.QueryString["ServerPath"] ;
     }
    }
   }
 
   // Check that the user path ends with slash ("/")
   if ( ! sUserFilesPath.EndsWith("/") )
    sUserFilesPath += "/" ;
 }
 return sUserFilesPath ;
 }
}
由此,可以在Global里或者程序任意位置(加载fckeditor前可以运行到的位置)设置Application["FCKeditor:UserFilesPath"] ,或者Session,或者Webconfig,或者action中的请求参数等。

FCKeditor添加自定义按钮 
http://blog.csdn.net/cnming/archive/2008/03/12/2172811.aspx
最近项目需要对已有的FCKeditor添加新的功能,以前的做法只是在外壳处再次封装,这次看样子要进行全面改造了。

需要修改的文件:
  1. fckconfig.js
  2. zh-cn.js
  3. fckeditorcode_gecko.js || fckeditorcode_ie.js(这里针对gecko的浏览器,ie的相同)
Step 1:在Toolbar中添加功能按钮

        fckconfig.js:FCKConfig.ToolbarSets[“Basic”] 中添加按钮名称
      
  1. FCKConfig.ToolbarSets["Basic"] = [  
  2.     ['Bold','Italic','-','About', 'Test']  
  3. ] ; 

Step 2:为按钮添加中文名称

    zh-cn.js:为你的按钮起个名字

  1. DlgAboutInfo        : "要获得更多信息请访问 ",  
  2. Test                : "测试"

Step 3:在Toolbar中显示该按钮

      fckeditorcode_gecko.js:(这个JS的代码经过压缩,可以使用工具格式化再进行修改)

      查找:

  1. case 'NewPage':B=new FCKToolbarButton('NewPage',FCKLang.NewPage,null,null,true,null,4);break;  

       在break后插入你的代码
      
  1. case 'Test':B=new FCKToolbarButton('Test',FCKLang.Test,null,null,true,null,50);break; 

 
        这样就可以在Toolbar中显示你的按钮了

Step 4:定义按钮功能原型
   
    ckeditorcode_gecko.js:

    查找:

  1. var FCKNewPageCommand=function(){this.Name='NewPage';};  
  2. FCKNewPageCommand.prototype.Execute=function(){FCKUndo.SaveUndoStep();FCK.SetHTML('');FCKUndo.Typing=true;};  
  3. FCKNewPageCommand.prototype.GetState=function(){return FCK_TRISTATE_OFF;};  

   
    定义功能原型:(这里直接复NewPage的实现代码,可修改成自已的)

  1. var FCKTestCommand=function(){this.Name='NewPage';};  
  2. FCKTestCommand.prototype.Execute=function(){function(){FCKUndo.SaveUndoStep();FCK.SetHTML('');FCKUndo.Typing=true;};
  3. FCKNewPageCommand.prototype.GetState=function(){return FCK_TRISTATE_OFF;}; 
   
    将上面代码搜入到查找内容之后。

Step 5:按钮功能实例化:

    ckeditorcode_gecko.js:
   
    查找:

  1. case 'NewPage':B=new FCKNewPageCommand();break;  

    功能实例化:

  1. case 'Test':B=new FCKTestCommand();break;

    将上面代码搜入到查找内容之后。


OK,这样就可以在为FCKeditor加上自定义的按钮了。


FCKeditor的几点重要改进和使用心得,值得分享
http://www.blogjava.net/itstarting/archive/2007/03/11/103142.html

以前公司购买过eWebEditor,功能应该还是不错的,但即便到了现在,也还仅是一个IE only的版本,无法满足现在差异化的需求。故前段时间下了最新的FCKeditor2.3.3版本下来(当然了,连带java的integration),demo来看看,发现有几个地方非常不爽:
1、上载的文件,只能放在URL可及的地方(如默认只能放到嵌入应用路径的/UserFiles/下);
2、没有明确的上载视频的按钮;
3、图片、FLASH、附件上载等,步骤多,复杂度高(想想,用户不都是高手)。

怎么办呢,改!

一、第一个就是增加一个FileLocatorServlet,思路很简单:通过这个服务来定位文件,而不是之间产生链接,既是安全的考虑,也是应用集群的一个重要考虑点。而且原来的几个servlet的配置罗嗦且重叠,难以让人产生美感。所谓代码胜千言,通过下面的web.xml大家应该可以看出修理的要点:

  1 <? xml version="1.0" encoding="ISO-8859-1" ?>
  2
  3 <! DOCTYPE web-app
  4   PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
  5   "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd" >
  6
  7 < web-app >
  8    < display-name > FCKeditor Test Application </ display-name >   
  9      < context-param >
 10          <!--  setting the FCKecitor context based parameters  -->
 11          <!--  baseDir means the root of the uploaded file/image/flash stored 
 12              the prefix of 'file:/' means strore in a file system root that cannot get from webapp url
 13          -->
 14          < param-name > baseDir </ param-name >
 15          < param-value > file:/C:/Temp/FCKeditorUpload/ </ param-value >
 16      </ context-param >  
 17
 18      < context-param >
 19          <!--  
 20              if the baseDir prefix by 'file:/',please set it.
 21          -->
 22          < param-name > fileLocator </ param-name >
 23          < param-value > /editor/filemanager/browser/default/service/jsp/filelocator </ param-value >
 24      </ context-param >  
 25
 26      < context-param >
 27          <!--  
 28              debug setting,true means verbose output to the console.
 29          -->
 30          < param-name > debug </ param-name >
 31          < param-value > true </ param-value >
 32      </ context-param >  
 33
 34      < context-param >
 35          <!--  
 36              enabled setting,true means upload enabled.
 37          -->
 38          < param-name > enabled </ param-name >
 39          < param-value > true </ param-value >
 40      </ context-param >  
 41
 42      < context-param >
 43          <!--  
 44              encoding,the response encoding of the file/image/flash,default is UTF-8
 45          -->
 46          < param-name > encoding </ param-name >
 47          < param-value > UTF-8 </ param-value >
 48      </ context-param >  
 49
 50      < context-param >
 51          <!--  
 52              contentTypeMapping,a map for the response ContentType
 53          -->
 54          < param-name > contentTypeMapping </ param-name >
 55          < param-value > doc=application/vnd.ms-word
 56         |xls=application/vnd.ms-excel
 57         |jpg=image/jpeg
 58         |gif=image/gif
 59         |swf=application/x-shockwave-flash
 60         |avi=video/x-msvideo
 61          </ param-value >
 62      </ context-param >  
 63
 64      < context-param >
 65          <!--  
 66              allowedExtensionsFile,the logic is 'Not allowed means deny.'
 67          -->
 68          < param-name > allowedExtensionsFile </ param-name >
 69          < param-value > doc|xls|pdf|avi </ param-value >
 70      </ context-param >  
 71
 72      < context-param >
 73          <!--  
 74              allowedExtensionsImage,the logic is 'Not allowed means deny.'
 75          -->
 76          < param-name > allowedExtensionsImage </ param-name >
 77          < param-value > jpg|gif|png </ param-value >
 78      </ context-param >  
 79
 80      < context-param >
 81          <!--  
 82              allowedExtensionsFlash,the logic is 'Not allowed means deny.'
 83          -->
 84          < param-name > allowedExtensionsFlash </ param-name >
 85          < param-value > swf|fla </ param-value >
 86      </ context-param >
 87
 88      < servlet >
 89          < servlet-name > Connector </ servlet-name >
 90          < servlet-class > com.fredck.FCKeditor.connector.ConnectorServlet </ servlet-class >
 91          < load-on-startup > 1 </ load-on-startup >
 92      </ servlet >
 93     
 94      < servlet >
 95          < servlet-name > FileLocator </ servlet-name >
 96          < servlet-class > com.fredck.FCKeditor.service.FileLocatorServlet </ servlet-class >
 97          < load-on-startup > 1 </ load-on-startup >
 98      </ servlet >
 99
100      < servlet >
101          < servlet-name > SimpleUploader </ servlet-name >
102          < servlet-class > com.fredck.FCKeditor.uploader.SimpleUploaderServlet </ servlet-class >
103          < load-on-startup > 1 </ load-on-startup >
104      </ servlet >
105
106    < servlet-mapping >
107      < servlet-name > Connector </ servlet-name >
108      < url-pattern > /editor/filemanager/browser/default/connectors/jsp/connector </ url-pattern >
109    </ servlet-mapping >
110   
111    < servlet-mapping >
112      < servlet-name > SimpleUploader </ servlet-name >
113      < url-pattern > /editor/filemanager/upload/simpleuploader </ url-pattern >
114    </ servlet-mapping >   
115   
116    < servlet-mapping >
117      < servlet-name > FileLocator </ servlet-name >
118      < url-pattern > /editor/filemanager/browser/default/service/jsp/filelocator </ url-pattern >
119    </ servlet-mapping >   
120
121 </ web-app >

连带FCKeditorConfigurations.java一并修理,配置统一且singleton。关键代码为:

 1
 2      /**
 3      * Make the configuration sigleton
 4      *  @param  sc
 5      *  @return  the static configuration map
 6       */

 7      public   static  Map getContextConfigurationsInstance(ServletContext sc) {
 8          if (contextConfigurations == null ) {
 9             initContextConfigurations(sc);
10         }

11          return  contextConfigurations;
12     }

13     
14      /**
15      * Init all the FCKeditor configuration.
16      * add by zhengxq
17      *  @param  sc
18       */

19      private   static   void  initContextConfigurations(ServletContext sc) {
20          if  (debug)
21             System.out.println( " \r\n---- FCKeditorConfigurations for java initialization started ---- " );
22         
23         String baseDir  =  sc.getInitParameter( " baseDir " );
24         String fileLocator  =  sc.getInitParameter( " fileLocator " );
25         String debugStr  =  sc.getInitParameter( " debug " );
26         String enabledStr  =  sc.getInitParameter( " enabled " );        
27         String encoding  =  sc.getInitParameter( " encoding " );
28         String contentTypeMapping  =  sc.getInitParameter( " contentTypeMapping " );
29         String AllowedExtensionsFile  =  sc.getInitParameter( " allowedExtensionsFile " );
30         String AllowedExtensionsImage  =  sc.getInitParameter( " allowedExtensionsImage " );
31         String AllowedExtensionsFlash  =  sc.getInitParameter( " allowedExtensionsFlash " );
32         
33         debug  =  ( new  Boolean(debugStr)).booleanValue();
34         encoding  =  (encoding == null   ||  encoding.length() == 0 ) ? " UTF-8 " :encoding;
35         
36          if (baseDir == null   ||  baseDir.length() == 0 ) baseDir  =  defaultBaseDir;
37         String realBaseDir  =  defaultBaseDir;
38          if  (baseDir.startsWith(fileSystemUriPrefix))  {
39             realBaseDir  =  baseDir.substring(fileSystemUriPrefix.length());            
40         }
  else   {
41             realBaseDir  =  sc.getRealPath(baseDir);
42             fileLocator  =   null ; // no use and should set null
43         }

44         File baseFile = new  File(realBaseDir);
45          if ( ! baseFile.exists()) {
46             baseFile.mkdir();
47         }

48         contextConfigurations  =   new  HashMap();
49         contextConfigurations.put( " baseDir " ,baseDir);
50         contextConfigurations.put( " realBaseDir " ,realBaseDir);
51         contextConfigurations.put( " fileLocator " ,fileLocator);
52         contextConfigurations.put( " debug " ,debugStr);
53         contextConfigurations.put( " enabled " ,enabledStr);
54         contextConfigurations.put( " encoding " ,encoding);
55         contextConfigurations.put( " contentTypeMapping " ,contentTypeMappingToMap(contentTypeMapping));
56         contextConfigurations.put( " allowedExtensionsFile " ,stringToArrayList(AllowedExtensionsFile));
57         contextConfigurations.put( " allowedExtensionsImage " ,stringToArrayList(AllowedExtensionsImage));
58         contextConfigurations.put( " allowedExtensionsFlash " ,stringToArrayList(AllowedExtensionsFlash));
59         
60          if  (debug)
61             System.out.println( " \r\n---- FCKeditorConfigurations for java initialization end ---- " );
62         
63     }


FileLocatorServlet.java也很简单,无非就是文件的物理定位和文件流的输出:

 1 String type  =  request.getParameter( " Type " );
 2         String fileName  =  request.getParameter( " FileName " );
 3
 4         String realFilePath  =  config.get( " realBaseDir " +  type  +   " / "   +  fileName;
 5         File file  =   new  File(realFilePath);
 6          if  (file.exists())  {
 7             response.setHeader( " Content-Transfer-Encoding " " base64 " );
 8             response.setHeader( " Cache-Control " " no-store " );
 9             response.setHeader( " Pragma " " no-cache " );
10             response.setDateHeader( " Expires " 0 );
11             response.setContentType(getContentTypeByFileExt(fileName.substring(fileName.lastIndexOf( " . " ))));
12             
13             ServletOutputStream out  =  response.getOutputStream();            
14             InputStream in  =   new  FileInputStream(file);
15             BufferedInputStream bis  =   new  BufferedInputStream(in);
16             BufferedOutputStream bos  =   new  BufferedOutputStream(out);
17              byte [] buff  =   new   byte [ 2048 ];
18              int  bytesRead;
19              while  ( - 1   !=  (bytesRead  =  bis.read(buff,  0 , buff.length)))  {
20                 bos.write(buff,  0 , bytesRead);
21             }

22              if  (bis  !=   null {
23                 bis.close();
24             }

25              if  (bos  !=   null {
26                 bos.close();
27             }

28         }
  else   {
29              throw   new  FileNotFoundException(fileName);
30         }

上述改动已经提交给了FCKeditor,如果大家真的有兴趣,可以去找里面我所提交的patch。

二、至于上述的2、3问题,同样,动手即可解决,在此略过。

过程中倒是碰到几个有意思的问题,成了花絮,其实也是使用FCKeditor的一些心得,写写可能还有点意思:
1、如何取得FCKeditor的值?
答案:这是我们常常干的事情:取得这个值并赋值给某个hidden,再合法性检查+submit等。怎么取得呢?这样:

1      var  oEditor  =  FCKeditorAPI.GetInstance('editor') ;
2      // Get the editor contents in XHTML.
3      // alert( oEditor.GetXHTML(true) ) ;    // "true" means you want it formatted.
4     document.all( " tip.c_content " ).value = oEditor.GetXHTML( true );

2、如何使得FCKeditor接收tab键?
答案:我们希望界面元素按照外面的安排进行tab切换,但FCKeditor怎么能做到呢?也有办法:

1 function  focusIframeOnTab(caller, tabTargetId, callEvent) {
2                  //  If keypress TAB and not SHIFT+TAB 
3                  if (callEvent.keyCode  ==   9   &&   ! callEvent.shiftKey)
4                     document.getElementById(tabTargetId).contentWindow.focus();
5             }

光光有个函数顶个什么用,还要这样:在之前的那个界面元素中加上下面的事件,如使用struts的tag的化,这样就可以了:

< html:text  property ="tip.c_title"  style ="width:450px"  tabindex ="1"  onkeydown ="focusIframeOnTab(this, 'editor___Frame',event);if(!document.all) return false;" />

这点是google了半天最终在FCKeditor的FAQ中找到的,看来以后用开源的软件第一件事情就是看FAQ,错不了!

3、如何希望在FCKeditor加载完毕后做点什么事情?
答案:也很简单,编写自己的FCKeditor_OnComplete函数,如:

function  FCKeditor_OnComplete( editorInstance )  {
                window.status 
=  editorInstance.Description ;
            }


4、如果在图片、FLASH等界面中上载了东西后,希望能告诉自己的表单,怎么做?
答案:这个花了我不少看代码和调试时间!其实这里的关键就是如何获取嵌入FCKeditor的那个window,这样就可以了,在对应的js文件(如editor\dialog\fck_image\fck_image.js)中的ok方法的最后加入:


    
// edit by zhengxq
     try {        
        
var  obj  =  window.dialogArguments.Editor.parent.document;
        obj.getElementById(
" tip.c_tip_has_pic " ).value  =   " 1 " ;
    }
catch (e) {}     

关键就是:window.dialogArguments.Editor.parent.document,这个能够找到对应窗口的引用,有了这个,还不会控制吗?!

利用Js获取和修改FCKeditor的值

http://moredocs.com/articleview/2008-5-31/article_view_256.htm

利用Javascript取和设FCKeditor值也是非常容易的,如下:

// 获取编辑器中HTML内容
function getEditorHTMLContents(EditorName) {
    var oEditor = FCKeditorAPI.GetInstance(EditorName);
    return(oEditor.GetXHTML(true));
}

// 获取编辑器中文字内容
function getEditorTextContents(EditorName) {
    var oEditor = FCKeditorAPI.GetInstance(EditorName);
    return(oEditor.EditorDocument.body.innerText);
}

// 设置编辑器中内容
function SetEditorContents(EditorName, ContentStr) {
    var oEditor = FCKeditorAPI.GetInstance(EditorName) ;
    oEditor.SetHTML(ContentStr) ;
}

FCKeditorAPI是FCKeditor加载后注册的一个全局对象,利用它我们就可以完成对编辑器的各种操作。

在当前页获得 FCK 编辑器实例:
var Editor = FCKeditorAPI.GetInstance('InstanceName');

从 FCK 编辑器的弹出窗口中获得 FCK 编辑器实例:
var Editor = window.parent.InnerDialogLoaded().FCK;

从框架页面的子框架中获得其它子框架的 FCK 编辑器实例:
var Editor = window.FrameName.FCKeditorAPI.GetInstance('InstanceName');

从页面弹出窗口中获得父窗口的 FCK 编辑器实例:
var Editor = opener.FCKeditorAPI.GetInstance('InstanceName');

获得 FCK 编辑器的内容:
oEditor.GetXHTML(formatted); // formatted 为:true|false,表示是否按HTML格式取出
也可用:
oEditor.GetXHTML();

设置 FCK 编辑器的内容:
oEditor.SetHTML("content", false); // 第二个参数为:true|false,是否以所见即所得方式设置其内容。此方法常用于"设置初始值"或"表单重置"哦作。

插入内容到 FCK 编辑器:
oEditor.InsertHtml("html"); // "html"为HTML文本

检查 FCK 编辑器内容是否发生变化:
oEditor.IsDirty();

在 FCK 编辑器之外调用 FCK 编辑器工具条命令:
命令列表如下:
DocProps, Templates, Link, Unlink, Anchor, BulletedList, NumberedList, About, Find, Replace, Image, Flash, SpecialChar, Smiley, Table, TableProp, TableCellProp, UniversalKey, Style, FontName, FontSize, FontFormat, Source, Preview, Save, NewPage, PageBreak, TextColor, BGColor, PasteText, PasteWord, TableInsertRow, TableDeleteRows, TableInsertColumn, TableDeleteColumns, TableInsertCell, TableDeleteCells, TableMergeCells, TableSplitCell, TableDelete, Form, Checkbox, Radio, TextField, Textarea, HiddenField, Button, Select, ImageButton, SpellCheck, FitWindow, Undo, Redo

使用方法如下:
oEditor.Commands.GetCommand('FitWindow').Execute();

= FCKConfig.BasePath + 'plugins/' 
// FCKConfig.Plugins.Add( 'placeholder', 'en,it' ) ;


去掉//后,就相当于把placeholder这个插件功能加上了,fckeditor的插件文件都在/editor/plugins/文件夹下分类按文件夹放置的,对于fckeditor2.0来说,里面有两个文件夹,也就是有两个官方插件,placeholder这个文件夹就是我们刚才加上去的,主要用于多参数或单参数自定义标签的匹配,这个在制作编辑模板时非常管用,要想看具体实例的话,大家可以去下载acms这个系统查看学习,另一个文件夹tablecommands就是编辑器里的表格编辑用到的了。当然,如果你想制作自己其它用途的插件,那就只要按照fckeidtor插件的制作规则制作完放置在/editor/plugins/下就行,然后再在fckeidtor.js里再添加FCKConfig.Plugins.Add('Plugin Name',',lang,lang');就可以了。

第二部分 ,如何让编辑器一打开的时候,编辑工具条不出现,等点“展开工具栏”时才出现?Easy,FCKeditor本身提供了这个功能啦,打开fckconfig.js,找到

FCKConfig.ToolbarStartExpanded = true ;
改成
FCKConfig.ToolbarStartExpanded = false ;
就可以啦!

第三部分,使用自己的表情图标,同样打开fckcofnig.js到最底部那一段


FCKConfig.SmileyPath = FCKConfig.BasePath + 'images/smiley/msn/' ;
FCKConfig.SmileyImages = ['regular_smile.gif','sad_smile.gif','wink_smile.gif'] ;
FCKConfig.SmileyColumns = 8 ;
FCKConfig.SmileyWindowWidth    = 320 ;
FCKConfig.SmileyWindowHeight = 240 ;

上面这段已经是我修改过的了,为了我发表此文的版面不会被撑得太开,我把FCKConfig.SmileyImages那一行改得只有三个表情图了。

第一行,当然是表情图标路径的设置,第二行是相关表情图标文件名的一个List,第三行是指弹出的表情添加窗口最每行的表情数,下面两个参数是弹出的模态窗口的宽和高喽。

第四部分,文件上传管理部分

此部分可能是大家最为关心的,上一篇文章简单的讲了如何修改来上传文件以及使用fckeidtor2.0才提供的快速上传功能。再我们继续再深层次的讲解上传功能

FCKConfig.LinkBrowser = true ;
FCKConfig.ImageBrowser = true ;
FCKConfig.FlashBrowser = true ;在fckconfig.js找到这三句,这三句不是连着的哦,只是我把他们集中到这儿来了,设置为true的意思就是允许使用fckeditor来浏览服务器端的文件图像以及flash等,这个功能是你插入图片时弹出的窗口上那个“浏览服务器”按钮可以体现出来,如果你的编辑器只用来自己用或是只在后台管理用,这个功能无疑很好用,因为他让你很直观地对服务器的文件进行上传操作。但是如果你的系统要面向前台用户或是像blog这样的系统要用的话,这个安全隐患可就大了哦。于是我们把其一律设置为false;如下

FCKConfig.LinkBrowser = false ;
FCKConfig.ImageBrowser = false ;
FCKConfig.FlashBrowser = false ;

这样一来,我们就只有快速上传可用了啊,好!接下来就来修改,同样以asp为范例进行,进入/editor/filemanager/upload/asp/打开config.asp,修改
ConfigUserFilesPath = "/UserFiles/"这个设置是上传文件的总目录,我这里就不动了,你想改自己改了

好,再打开此目录下的upload.asp文件,找到下面这一段


Dim resourceType
If ( Request.QueryString("Type") <> "" ) Then
resourceType = Request.QueryString("Type")
Else
resourceType = "File"
End If
然后再在其后面添加


ConfigUserFilesPath = ConfigUserFilesPath & resourceType &"/"& Year(Date()) &"/"& Month(Date()) &"/"
这样的话,上传的文件就进入“/userfiles/文件类型(如image或file或flash)/年/月/”这样的文件夹下了,这个设置对单用户来用已经足够了,如果你想给多用户系统用,那就这样来改


ConfigUserFilesPath = ConfigUserFilesPath & Session("username") & resourceType &"/"& Year(Date()) &"/"& Month(Date()) &"/"
这样上传的文件就进入“/userfiles/用户目录/文件类型/年/月/”下了,当然如果你不想这么安排也可以修改成别的,比如说用户目录再深一层等,这里的Session("username")请根据自己的需要进行修改或换掉。

上传的目录设置完了,但是上传程序还不会自己创建这些文件夹,如果不存在的话,上传不会成功的,那么我们就得根据上面的上传路径的要求进行递归来生成目录了。

找到这一段


Dim sServerDir
sServerDir = Server.MapPath( ConfigUserFilesPath )
If ( Right( sServerDir, 1 ) <> "\" ) Then
    sServerDir = sServerDir & "\"
End If

把它下面的这两行


Dim oFSO
Set oFSO = Server.CreateObject( "Scripting.FileSystemObject" )
用下面这一段代码来替换


dim arrPath,strTmpPath,intRow
strTmpPath = ""
arrPath = Split(sServerDir, "\")
Dim oFSO
Set oFSO = Server.CreateObject( "Scripting.FileSystemObject" )
for intRow = 0 to Ubound(arrPath)
    strTmpPath = strTmpPath & arrPath(intRow) & "\"
    if oFSO.folderExists(strTmpPath)=false then
     oFSO.CreateFolder(strTmpPath)
    end if
next
用这段代码就可以生成你想要的文件夹了,在上传的时候自动生成。

好了,上传文件的修改到现在可以暂时告一段落了,但是,对于中文用户还存在这么个问题,就是fckeditor的文件上传默认是不改名的,同时还不支持中文文件名,这样一来是上传的文件会变成“.jpg”这样的无法读的文件,再就是会有重名文件,当然重名这点倒没什么,因为fckeditor会自动改名,会在文件名后加(1)这样来进行标识。但是,我们通常的习惯是让程序自动生成不重复的文件名

在刚才那一段代码的下面紧接着就是
' Get the uploaded file name.
sFileName = oUploader.File( "NewFile" ).Name
看清楚了,这个就是文件名啦,我们来把它改掉,当然得有个生成文件名的函数才行,改成下面这样

'//取得一个不重复的序号
Public Function GetNewID()
dim ranNum
dim dtNow
randomize
dtNow=Now()
ranNum=int(90000*rnd)+10000
GetNewID=year(dtNow) & right("0" & month(dtNow),2) & right("0" & day(dtNow),2) & right("0" & hour(dtNow),2) & right("0" & minute(dtNow),2) & right("0" & second(dtNow),2) & ranNum
End Function

' Get the uploaded file name.
sFileName = GetNewID() &"."& split(oUploader.File( "NewFile" ).Name,".")(1)

这样一来,上传的文件就自动改名生成如20050802122536365.jpg这样的文件名了,是由年月日时分秒以及三位随机数组成的文件名了



posted @ 2008-06-11 16:12  winnerlan  阅读(522)  评论(0编辑  收藏  举报