Ckeditor 更新文本区域

42

我正在尝试让ckeditor正常工作。显然它不使用textarea,因此在提交表单时,表单不会提交编辑器中的文本。由于我使用了多态关联等功能,我无法创建一个onsubmit函数来获取textarea的值(当表单被提交时)。

所以我找到了这个问题:使用jQuery从CKEditor的iframe中获取内容

其中有一些非常好的答案。那里发布的答案会使textarea保持最新状态。这非常好,正是我需要的!不幸的是,我无法让它工作。 有人知道为什么(例如)这不起作用吗?

我有一个textarea(rails,但它只是转换为普通的textarea):
<%= f.text_area :body,:id =>'ckeditor',:rows =>3%>

和以下js:

if(CKEDITOR.instances.ckeditor ) {
  CKEDITOR.remove(CKEDITOR.instances.ckeditor);
}
CKEDITOR.replace( 'ckeditor',
{
skin : 'kama',
toolbar :[['Styles', 'Format', '-', 'Bold', 'Italic', '-', 'NumberedList', 'BulletedList', 'Link']]});


CKEDITOR.instances["ckeditor"].on("instanceReady", function()
{
//set keyup event
this.document.on("keyup", CK_jQ);

//and paste event
this.document.on("paste", CK_jQ);
}

function CK_jQ()
{
 CKEDITOR.instances.ckeditor.updateElement(); 
}

我在firebug中看到以下的“错误”
缺少参数列表后的 ) [在此处中断错误] function CK_jQ()\n


好的,当然上面的代码中有一个错误。少了一个括号:P (但仍然不起作用) - heldopslippers
请将标题更改为Ckeditor 4更新文本区域 - Rafal
11个回答

122

提交之前要做:

for(var instanceName in CKEDITOR.instances)
    CKEDITOR.instances[instanceName].updateElement();

但是OP已经一直调用updateElement,但对于OP来说仍然无效,这可能就是为什么这不是答案的原因。 - Joel Peltonen
@Nenotlep:被接受的答案基本上是相同的,但它是对我的答案的变通,因为CKEDITOR已经通过updateElement提供了它。 - xtds
@sldev:我同意你的解决方案更好,我想指出他在他的解决方案中已经调用了updateElement(),尽管不像你的那么合乎逻辑,在提交之前放置它 :) - Joel Peltonen
1
运行得很好。令我困惑的是,为什么CKEditor的默认保存操作不是这样工作的。 - András Szepesházi
不要忘记 if (CKEDITOR.instances.hasOwnProperty(instanceName)) { - zanderwar

55

你解决了吗?

我正在使用带有jQuery表单提交处理程序的CKEditor版本3.6.1。提交时,文本区域为空,这对我来说是不正确的。然而,有一个简单的解决方法,假设你所有的CKEditor文本区域都有css类 ckeditor 。

$('textarea.ckeditor').each(function () {
   var $textarea = $(this);
   $textarea.val(CKEDITOR.instances[$textarea.attr('name')].getData());
});

在执行提交处理(如表单验证)之前,请先执行上述操作。


@TJ- 我是Jquery的新手,不知道它是如何工作的?你能否写一行代码来弹出ckeditor的值?我正在尝试使用:alert($textarea.val(CKEDITOR.instances[$textarea.attr('name')].getData()));。谢谢... - Bajrang
@J.J. 在你警告之前,将你的文本区域的jQuery对象分配给$textarea。var $textarea = $('textarea.mytextarea'); 然后在应用ckeditor之后使用 alert(CKEDITOR.instances[$textarea.attr('name')].getData()) - T. Junghans
我不得不使用以下代码: $('textarea.ckeditor').each(function () { var $textarea = $(this); $textarea.val(CKEDITOR.instances[$textarea.attr('id')].getData()); });实例的名称是由字段ID而不是名称命名的。但正如Ben Amada上面提到的,似乎有一个更受支持的解决方案: for ( instance in CKEDITOR.instances ) CKEDITOR.instances[instance].updateElement(); - Mark
如果有人需要为FCKeditor执行此操作,则情况是不同的:$(this).val(FCKeditorAPI.Instances[this.id].GetData()); - user1850421
如果您想在将HTML放入文本区域之前对其进行编码,这将非常有用。 - JDandChips
显示剩余5条评论

10

将所有以上答案结合成一个。

创建一个新的custom.js文件并添加以下内容:

CKEDITOR.on('instanceReady', function(){
  $.each( CKEDITOR.instances, function(instance) {

    CKEDITOR.instances[instance].on("instanceReady", function() {
      this.document.on("keyup", CK_jQ);
      this.document.on("paste", CK_jQ);
      this.document.on("keypress", CK_jQ);
      this.document.on("blur", CK_jQ);
      this.document.on("change", CK_jQ);
    });
  });

});

function CK_jQ() {
  for ( var instance in CKEDITOR.instances ) { CKEDITOR.instances[instance].updateElement(); }
}

您不必担心


10

感谢 @JohnDel 提供的信息,我使用 onchange 来使其在每次更改时更新。

CKEDITOR.on('instanceReady', function(){
   $.each( CKEDITOR.instances, function(instance) {
    CKEDITOR.instances[instance].on("change", function(e) {
        for ( instance in CKEDITOR.instances )
        CKEDITOR.instances[instance].updateElement();
    });
   });
});

1
我希望CKEDITOR默认情况下可以这样做,我真的看不出有任何理由不这样做? - t.mikael.d
1
instanceReady 会为每个编辑器实例触发。因此,如果您有多个实例,则会将 onChange 事件绑定多次,从而执行大量不必要的工作。您应该使用 提供给 instanceReady 回调函数的事件参数 并使用其 editor 属性,该属性是刚刚调用其 instanceReady 事件的编辑器实例,而不是使用 $.each(...) - flu
这个也适用于多个文本区域,通过ajax加载并使用CKEDITOR.replace('item', language)。 - AllThisOnAnACER

6

添加JavaScript函数以进行更新操作

function CKupdate() {
  for (instance in CKEDITOR.instances)
    CKEDITOR.instances[instance].updateElement();
}

它工作了。很棒。


2

只需添加

CKEDITOR.instances.textAreaClientId.on('blur', function(){CKEDITOR.instances. textAreaClientId.updateElement();});

其中textAreaClientId是您的实例名称。

祝好!


1
CKEDITOR.instances["ckeditor"].on("instanceReady", function()
{
//set keyup event
this.document.on("keyup", CK_jQ);

//and paste event
this.document.on("paste", CK_jQ);
})

1

我只是将其增加到T.J.的响应中,然后它对我起作用了:

$("form").on("submit", function(e){
    $('textarea.ckeditor').each(function () {
       var $textarea = $(this);
       $textarea.val(CKEDITOR.instances[$textarea.attr('name')].getData());
    });
});

0

加载时:

$(function () {
  setTimeout(function () {
    function CK_jQ(instance) {
      return function () {
        CKEDITOR.instances[instance].updateElement();
      };
    }

    $.each(CKEDITOR.instances, function (instance) {
      CKEDITOR.instances[instance].on("keyup", CK_jQ(instance));
      CKEDITOR.instances[instance].on("paste", CK_jQ(instance));
      CKEDITOR.instances[instance].on("keypress", CK_jQ(instance));
      CKEDITOR.instances[instance].on("blur", CK_jQ(instance));
      CKEDITOR.instances[instance].on("change", CK_jQ(instance));
    });
  }, 0 /* 0 => To run after all */);
});

0

最新版本的CKEditor有一些API更改,因此这里提供CKEditor 5的答案:

let ckeditor;

// Create a CKEditor, and store its handle someplace that you may
// access later. In this example, we'll use the `ckeditor` variable:
ClassicEditor
  .create(document.querySelector("textarea"), {})
  .then(editor => { ckeditor = editor; });

// When your form submits, use the `updateSourceElement` method
// on the editor's handle:
document.querySelector("form").addEventListener("submit", function() {
  ckeditor.updateSourceElement();
});

据我所知,当您提交表单时,CKEditor会自动执行此操作,因此这个特定的示例实际上不应该做任何事情。但是,当您需要更新包含它的表单而无需提交表单的文本区域的内容时,它非常有用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接