【ExtJs】Ext.form.CKEditor:整合CKEditor的组件



    CKEditor是一个出色的所见即所得的富文本编辑器,相比ExtJs原生的htmleditor要强大很多,于是把CKEditor集成到ExtJs中便是一个很好的选择。

    从ExtJs官方论坛找到了整合的实例,不过其中的问题不少,比如组件setValue、isDiry等方法无法得到正确的结果。经过改造,修正了以上问题,并将CKFinder做了整合,同时增加了对CKEditor工具栏选择配置的支持。

    修改后的Ext.form.CKEditor组件源码如下:



    /****************************************************
    * CKEditor Extension
    * by Maple Nan 2010.7.21
    * http://witmax.cn/extjs-ckeditor.html
    *****************************************************/
    Ext.form.CKEditor = function(config){
      this.config = config;
      Ext.form.CKEditor.superclass.constructor.call(this, config);
    };
    Ext.form.CKEditor.CKEDITOR_CONFIG = "/ckeditor/config.js";
    Ext.form.CKEditor.CKEDITOR_TOOLBAR = "Default";
    Ext.extend(Ext.form.CKEditor, Ext.form.TextArea,  {
      onRender : function(ct, position){
        if(!this.el){
          this.defaultAutoCreate = {
            tag: "textarea",
            autocomplete: "off"
          };
        }
        Ext.form.TextArea.superclass.onRender.call(this, ct, position);
        var config = {
          customConfig: Ext.form.CKEditor.CKEDITOR_CONFIG
          //,toolbar: Ext.form.CKEditor.CKEDITOR_TOOLBAR  // 如需要默认工具条设置,请去掉行前注释
        };
        Ext.apply(config, this.config.CKConfig);
        var editor = CKEDITOR.replace(this.id, config);
        CKFinder.setupCKEditor( editor, './ckfinder/' ) ;
      },
    
      onDestroy: function(){
        if (CKEDITOR.instances[this.id]) {
          delete CKEDITOR.instances[this.id];
        }
      },
    
      setValue : function(value){
        Ext.form.TextArea.superclass.setValue.apply(this,[value]);
        CKEDITOR.instances[this.id].setData( value );
      },
    
      getValue : function(){
        CKEDITOR.instances[this.id].updateElement();
        var value=CKEDITOR.instances[this.id].getData();
        Ext.form.TextArea.superclass.setValue.apply(this,[value]);
        return Ext.form.TextArea.superclass.getValue.apply(this);
      },
    
      getRawValue : function(){
        CKEDITOR.instances[this.id].updateElement();
        return Ext.form.TextArea.superclass.getRawValue(this);
      },
    
      isDirty : function() {
        if(this.disabled) {
          return false;
        }
        var value = String(this.getValue()).replace(/\s/g,'');
        value = (value == "<br />" || value == "<br/>" ? "" : value);
        this.originalValue = this.originalValue || "";
        this.originalValue = this.originalValue.replace(/\s/g,'');
        return String(value) !== String(this.originalValue) ? String(value) !== "<p>"+String(this.originalValue)+"</p>" : false;
      }
    });
    Ext.reg('ckeditor', Ext.form.CKEditor);

    由于Ext.form.CKEditor组件的特殊性,需要重写Ext.form.BasicForm组件的一些方法,对Ext.form.CKEditor组件提供特殊的支持,Ext.form.BasicForm组件重写部分源码如下:

    // Add methods to the BasicForm that clears the isDirty flag to return "false" again.
    Ext.override(Ext.form.BasicForm,{
      /**
       * clear the value of all items in BasicForm and set originalValue to ''
       * @param {Object} o
       */
      clearValues: function(o){
        o = o || this;
        o.items.each(function(f){
          if(f.items){
            this.clearValues(f);
          } else if(f.setValue){
            f.setValue('');
            // ckeditor needs being treated specially, or an error will appear in IE
            if (f.getXType() == "ckeditor"){
              f.originalValue = '';
            }
            else if (f.getValue){
              f.originalValue = f.getValue();
            }
          }
        }, this);
        this.clearInvalid();
      }
    
      /**
       * clear isDirty flag of all items of BasicForm
       * @param {Object} o
       *
       * reference: http://www.extjs.com/forum/showthread.php?t=40568
       */
      ,clearDirty : function(o){
        o = o || this;
        o.items.each(function(f){
          if(f.items){
            this.clearDirty(f);
          } else if(typeof(f.originalValue) != "undefined" && f.getValue){  // Ext.isEmpty(f.originalValue) &&
            f.originalValue = f.getValue();
          }
        }, this);
      }
    
      ,setValues : function(values){
        if(Ext.isArray(values)){ // array of objects
          for(var i = 0, len = values.length; i < len; i++){
            var v = values[i];
            var f = this.findField(v.id);
            if(f){
              f.setValue(v.value);
              // ckeditor is special
              if (f.getXType() == "ckeditor"){
                f.originalValue = v.value;
              }
              // checkboxgroup.originalValue won't be set, or it may cause a bug when reset
              else if(this.trackResetOnLoad && typeof(f.originalValue) != "undefined" && f.getValue){
                f.originalValue = f.getValue();
              }
            }
          }
        }else{ // object hash
          var field, id;
          for(id in values){
            if(typeof values[id] != 'function' && (field = this.findField(id))){
              field.setValue(values[id]);
              if (this.trackResetOnLoad){
                if (field.getXType() == "ckeditor"){
                  field.originalValue = values[id];
                }
                else if(typeof(field.originalValue) != "undefined" && field.getValue){
                  field.originalValue = field.getValue();
                }
              }
            }
          }
        }
        return this;
      }
    
      ,findField : function(id){
        var field = this.items.get(id);
        if(!field){
          this.items.each(function(f){
            if(f.isXType('radiogroup')||f.isXType('checkboxgroup')){
              if (f.isXType('radiogroup'))
                f.unitedValue = true;
              f.items.each(function(c){
                if(c.isFormField && (c.dataIndex == id || c.id == id || c.getName() == id)){
                  field = f.unitedValue ? f : c;
                  if (typeof(f.trackResetOnLoad) == "undefined")
                    f.trackResetOnLoad = this.trackResetOnLoad;
                  return false;
                }
              }, this);
            }
            if(f.isFormField && (f.dataIndex == id || f.id == id || f.getName() == id)){
              field = f;
              return false;
            }
          }, this);
        }
        return field || null;
      }
    });
    

    组件使用方法:

    {
      xtype: 'ckeditor',
      fieldLabel: 'Editor',
      name: 'htmlcode',
      CKConfig: {
        /* Enter your CKEditor config paramaters here or define a custom CKEditor config file. */
        customConfig : '/ckeditor/config.js',
        toolbar: 'Other',
        height : 200,
        width: 250
      }
    }

    说明:以上customConfig为CKEditor组件配置文件的绝对路径(使用相对路径好像有问题,会无效,暂不清楚原因),不设定时默认为/ckeditor/config.js,默认值设定可以通过对Ext.form.CKEditor.CKEDITOR_CONFIG重新赋值来完成,也可修改Ext.form.CKEditor组件源码的对应部分;toolbar为采用的CKEditor配置文件中工具栏配置的名词,对于CKEditor工具栏如何配置可参考FckEditor(CKEditor)配置,不设定时默认为Default,此项默认值可以通过重新赋值Ext.form.CKEditor.CKEDITOR_TOOLBAR来设定或修改Ext.form.CKEditor组件源码的对应部分;width、height对应为组件显示的宽和高。

    完整实例源码下载[download id="40" format="3"],其中ckeditor、ckfinder及extjs都需位于站点根目录下,具体路径也可自行修改实例源码。



    本博客所有文章如无特别注明均为原创。
    复制或转载请以超链接形式注明转自枫芸志,原文地址《【ExtJs】Ext.form.CKEditor:整合CKEditor的组件
    标签:
    分享:

已经有26 条评论抢在你前面了~

  1. 沙发
    xyc717 2012年9月20日 下午1:18

    这个问题怎么回事呢
    TypeError: CKEDITOR.instances[this.id] is undefined

    [回复]

    晴枫

    晴枫 回复:

    @xyc717, 请看一下上面的评论或许能帮你解决问题

    [回复]

  2. 板凳
    郁闷 2012年5月21日 下午12:19

    为什么我在用ie看效果的时候提示this.id不是对象或者对象为空

    [回复]

    晴枫

    晴枫 回复:

    @郁闷, 看看上面的讨论有没有能帮你解决问题

    [回复]

  3. 地板
    测试我的 2011年8月15日 下午3:18

    还有忘记提醒了:不能用FORM.LOAD这种方式加载赋值,因为它是自动赋值的,只能通过侦听事件的方式,用Ext.Ajax.request来加载服务器数据,然后逐一赋值.

    [回复]

  4. 4楼
    测试我的 2011年8月15日 下午3:13

    终于解决了,要在代码里,把每个TAB激活后,在赋值

    核心代码:
    Ext.getCmp(“EditBaseinfotab”).setActiveTab(‘EditBaseinfotab4’);
    Ext.getCmp(“wincomment”).setValue(fdata[“wincomment”]);

    ‘EditBaseinfotab4’ 就是包含有ckeditor的TAB的 id, 希望对各位有帮助,在非window里加载TABPANEL 中的CKEDITOR 要激活选项才会被渲染的,设置deferredRender: false, 也没有用的,默认只会激活第一个TAB, 但是在window的TABPANEL 只要加了设置deferredRender: false, 所有的TAB项都被激活渲染的,到目前我也不明白原因。可能是Ext.form.CKEditor组件的问题,在渲染的时候要处理一下。

    [回复]

  5. 5楼
    测试我的 2011年8月15日 下午12:47

    同过WINDOW加载的TABPANEL 中的CKEDITOR 居然没有问题,其他方式的不行

    [回复]

  6. 6楼
    测试我的 2011年8月15日 下午12:45

    在TABPANEL 中的CKEDITOR 要激活选项才会被渲染的,郁闷,设置看deferredRender: false, 也没有用

    [回复]

  7. 7楼
    测试我的 2011年8月15日 下午12:08

    我也考虑过这个问题,通过按钮手工加载也不行,我在试试

    [回复]

  8. 8楼
    测试我的 2011年8月14日 下午9:26

    新问题:在TABLPANEL的FROM中的编辑器,好像初始化有问题,也是加载数据的时候:

    ext.form.CKEDITOR.JS 行 38

    ‘CKEDITOR.instances[…]’ 为空或不是对象

    在代码: setValue : function(value){
    Ext.form.TextArea.superclass.setValue.apply(this,[value]);
    CKEDITOR.instances[this.id].setData( value );
    },
    就是这行CKEDITOR.instances[this.id].setData( value );
    出现问题

    [回复]

    晴枫

    晴枫 回复:

    @测试我的, 应该是这时候组件还没有被渲染导致的,建议在load数据前让组件渲染好

    [回复]

  9. 9楼
    测试我的 2011年8月14日 下午9:22

    这个问题解决了,居然ID不能有下划线命名

    [回复]

    晴枫

    晴枫 回复:

    @测试我的, 还有这样的问题 没碰到过

    [回复]

  10. 10楼
    测试我的 2011年8月14日 下午9:11

    如果加载数据,比如 myform.getForm().load({ ….

    会提示错误
    ckeditor.js ….. 16行
    ‘this.$.innerHTML’ 为空或不是对象

    [回复]

    晴枫

    晴枫 回复:

    @测试我的, 应该是这时候组件还没有被渲染导致的,建议在load数据前让组件渲染好

    [回复]

  11. 11楼
    IT信任 2011年8月5日 下午2:53

    我想问下 ,我用你说的把CKEditor集成到ExtJs中,但是我要给CKeditor添加附加组件的时候,(比如说行距),怎么样都没有反应,自定义插件也不行,是不是什么地方没有配置

    [回复]

    晴枫

    晴枫 回复:

    @IT信任, 有可能插件引入没有生效,看看插件引入的配置代码是不是被执行到了

    [回复]

  12. 12楼
    rar 2011年8月1日 上午10:50

    这个组件有个问题就是如果把这个组件放在window窗体中,第一次打开window窗体可以展示,如果关闭掉window窗口,然后重新打开,此时就无法打开window窗口了

    [回复]

    晴枫

    晴枫 回复:

    @rar, 你需要设置window的closeAction为hide,使得窗口关闭后控件不被销毁

    [回复]

  13. 13楼
    赵伟雄 2011年7月30日 下午6:26

    谢谢大侠的贡献!
    问个问题:
    在这个ckeditor中编辑文本之后,如何取得其文本呢?
    对应的,怎么让它初始时显示特定的文本呢?

    期待大侠的解答

    [回复]

    晴枫

    晴枫 回复:

    @赵伟雄, 用法和其他的控件一样,比如textfield

    [回复]

  14. 14楼
    ray 2010年10月21日 上午10:11

    很奇怪,关闭窗口时会出现container.getChild(…)的错误,

    把onDestroy改成

    var o = CKEDITOR.instances[this.id];
    if (o) o.destroy();

    就好了

    [回复]

  15. 15楼
    你好 2010年9月24日 下午4:50

    大侠我好,你好大害,我好崇拜你。
    另外问下怎么配置工具条。。
    我弄了好久没弄明白。可以给点配置工具栏上按钮的代码吗
    我的email :23444440@qq.com
    谢谢了啊。。

    [回复]

    晴枫

    晴枫 回复:

    @你好, 末尾增加一段说明,看是否对你有帮助

    [回复]

  16. 16楼
    老饕 2010年8月23日 下午4:03

    没用过~~一直用notepad++来着

    [回复]

    晴枫

    晴枫 回复:

    @老饕, notepad++是桌面应用程序 CKEditor是网页版的的富文本编辑器,不一样

    [回复]

无觅相关文章插件,快速提升流量