首页 > 网页设计 > 【ExtJs】Ext.form.CKEditor:整合CKEditor的组件

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

2010年8月21日 发表评论 阅读评论

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对应为组件显示的宽和高。

完整实例源码下载ExtJs CKEditor插件,其中ckeditor、ckfinder及extjs都需位于站点根目录下,具体路径也可自行修改实例源码。


枫芸志原创文章,转载请注明来源并保留原文链接

本文链接:http://witmax.cn/ext-form-ckeditor.html


分类: 网页设计 标签: , , 6,019次阅读
  1. 2010年8月23日16:03 | #1

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

    [回复]

    晴枫 回复:

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

    [回复]

  2. 你好
    2010年9月24日16:50 | #2

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

    [回复]

    晴枫 回复:

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

    [回复]

  3. ray
    2010年10月21日10:11 | #3

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

    把onDestroy改成

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

    就好了

    [回复]

  4. 赵伟雄
    2011年7月30日18:26 | #4

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

    期待大侠的解答

    [回复]

    晴枫 回复:

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

    [回复]

  5. rar
    2011年8月1日10:50 | #5

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

    [回复]

    晴枫 回复:

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

    [回复]

  6. IT信任
    2011年8月5日14:53 | #6

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

    [回复]

    晴枫 回复:

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

    [回复]

  7. 测试我的
    2011年8月14日21:11 | #7

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

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

    [回复]

    晴枫 回复:

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

    [回复]

  8. 测试我的
    2011年8月14日21:22 | #8

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

    [回复]

    晴枫 回复:

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

    [回复]

  9. 测试我的
    2011年8月14日21:26 | #9

    新问题:在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数据前让组件渲染好

    [回复]

  10. 测试我的
    2011年8月15日12:08 | #10

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

    [回复]

  11. 测试我的
    2011年8月15日12:45 | #11

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

    [回复]

  12. 测试我的
    2011年8月15日12:47 | #12

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

    [回复]

  13. 测试我的
    2011年8月15日15:13 | #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组件的问题,在渲染的时候要处理一下。

    [回复]

  14. 测试我的
    2011年8月15日15:18 | #14

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

    [回复]

  1. 本文目前尚无任何 trackbacks 和 pingbacks.
订阅评论
  欢迎参与讨论,请在这里发表您的看法、交流您的观点。

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