在CKEditor的instanceReady上调用时,setReadOnly会导致错误

ele*_*y19 8 javascript jquery gwt ckeditor backbone.js

我试图在实例完全加载后将我的CKEditor实例设置为"readOnly",但是我收到了一个Javascript错误:Cannot call method 'setReadOnly' of null.当我深入研究它时,错误来自ckeditor.js中的这一行,在editor.setReadOnly方法中:this.editable().setReadOnly(a);这意味着编辑器存在,但editable方法/属性(在CKEditor实例上)却没有.

下面是我的代码,我会稍微解释一下.我的应用程序是GWT和Backbone的组合.CKEditor本身是由Backbone代码创建的,但父元素是在GWT中,所以我在那里发起了setEnabled动作.

private native void setEnabledOnLoad(boolean enabled, String id) /*-{
  CKEDITOR.on("instanceReady", function(evt) {
    if(evt.editor.name === id) {
      Namespace.trigger(Namespace.Events.SET_ENABLED, enabled);
    }
  });
}-*/;

setEnabled: function(enabled) {
  this.editor.setReadOnly(!enabled);
  if(enabled){
    this.editor.focusManager.focus();
  } else {
    this.editor.focusManager.blur();
  }
}
Run Code Online (Sandbox Code Playgroud)

Backbone类具有Namespace.Events.SET_ENABLED该触发器的侦听器setEnabled.

我应该听听另一个CKEditor事件吗?似乎没有instanceReady事件editable.我错过了什么?

EDIT
this.editor是在Backbone类render函数中创建的,如下所示:

this.editor = CKEDITOR.replace(this.$(this.id)[0], config);
Run Code Online (Sandbox Code Playgroud)

instanceReady在创建之后不立即添加侦听器的原因是因为setEnabledOnLoad在实例完全初始化之前在GWT中调用了该函数.这是将代码放在两个地方的结果.GWT已经说"好了,创建了实例",但是当GWT进入下一行代码并希望将其设置为启用/禁用时,Backbone还没有完成.

Sti*_*lig 9

两年后,但这是我的解决方案.也许别人会觉得它很有用.如上所述,事件在完全设置editable()函数之前被触发,因此一种解决方案是在将其设置为只读之前等待它完成.这可能是一种丑陋的方式,但它确实有效.

        //Delayed execution - ckeditor must be properly initialized before setting readonly
        var retryCount = 0;
        var delayedSetReadOnly = function () {
            if (CKEDITOR.instances['bodyEditor'].editable() == undefined && retryCount++ < 10) {
                setTimeout(delayedSetReadOnly, retryCount * 100); //Wait a while longer each iteration
            } else {
                CKEDITOR.instances['bodyEditor'].setReadOnly();
            }
        };
        setTimeout(delayedSetReadOnly, 50);
Run Code Online (Sandbox Code Playgroud)


nos*_*tio 5

您可以尝试以instanceReady这种方式订阅活动:

CKEDITOR.instances.editor.on("instanceReady", onInstanceReadyHandler) 
Run Code Online (Sandbox Code Playgroud)

但是,editor实例必须已经在那时创建(CKEDITOR.instances在调试器中检查).

我对editable和之间的区别感到有点困惑editor.你能在哪里显示你的代码片段this.editorthis.editable获得分配?

[编辑]我想我知道发生了什么.CKEDITOR是一个全局对象,您可以将其视为包含所有CKEDITOR实例的类.试图处理事件CKEDITOR.on是不对的,你需要在特定的实例上做(如上所示).我假设,"编辑器"是您要附加CKEDITOR实例的父元素的ID (如果我错了,请纠正我).我不熟悉Backbone,但通常用替换完成:

var editorInstance = CKEDITOR.replace("editor", { on: { 
    instanceReady: function(ev) { alert("editor is ready!"); }}});
Run Code Online (Sandbox Code Playgroud)

这里我们将一个新的CKEDITOR实例附加到editor父元素并同时订阅该instanceReady事件.返回的对象editorInstance应提供您可能需要的所有API,包括setReadOnly.您还可以CKEDITOR使用父元素ID 通过全局对象访问它,即CKEDITOR.instances.editor.另一方面,editable编辑器上可用的服务对象.我想不出你可能需要直接使用它的任何特定情况.