使用Jquery检测CKEditor中的onChange事件

41
我正在使用CKEditor和jQuery,并希望在用户更改字段的值时将标志切换为true。其中一个字段是CKEditor实例。
所有具有“wysiwyg”类的文本区域都会转换为CKEditors,但是某种方式下$('.wysiwyg').change()事件无法被检测到。我进行了一些搜索,但关键字组合似乎只能带来无关的结果(我的搜索技巧很烂)。
感谢任何帮助 :)
编辑:
for (var i in CKEDITOR.instances) {
        CKEDITOR.instances[i].on('click', function() {alert('test 1 2 3')});
    }
我尝试了上面的代码,但它不起作用。它没有给我错误信息,这意味着它找到了CKEditor对象,但出于某些原因监听器没有附加到它上面?
此外,如果我用alert(CKEDITOR.instances[i].name);替换事件附加,它将弹出我的文本区域的名称,所以我知道我没有尝试将点击事件附加到什么东西 :)

2
这现在是核心的一部分(版本4.2+)。请参阅http://docs.ckeditor.com/#%21/api/CKEDITOR.editor-event-change。 - nfplee
14个回答

55

它与CKEditor 4兼容,尽管在内联模式下存在一些错误。如果你花时间修复它们(我不使用这样的配置),那么我会为所有人发布新版本。这就是开源的美丽之处。 - AlfonsoML
3
现在的 CKEditor(版本为4.2及以上)已经内置了“on change”功能。有关更多信息,请访问http://docs.ckeditor.com/#%21/api/CKEDITOR.editor-event-change。 - nfplee
@nfplee 是的,它是内置的;但是它缺少基本的更改,比如拖放或在源代码模式下工作时完成的任何操作。我没有在文档中看到任何关于这些缺失更改的提及(并且正如我的插件所示,修复这个问题非常简单)。 - AlfonsoML
@AlfonsoML 谢谢,我没有注意到。这对我来说不是很大的问题,但希望他们在以后的版本中能够解决它。 - nfplee
后续版本?我大约两年前报告了拖放问题(没有生成撤消),并提供了一个补丁,但仍未修复。此外,这个插件一直可用,但他们在实现功能时忽略了它,所以我猜他们不关心这些用例,现在你必须使用半开发的功能,而不能享受只执行一个任务的自定义插件的好处。 - AlfonsoML
显示剩余6条评论

14

我还没有成功使用onchange,但是onblur似乎可以工作,这可能足够满足你的需求

CKEDITOR.instances['name'].on('blur', function() {alert(1);});

即使您没有更改文本,仍会收到警告消息。 - tree em
2
就像我之前所说的,这取决于你的需求。如果你需要使用渲染文本来刷新某些内容,那么它会很好地工作。 - Alexei Tenitski

14

现在有一个改变事件:http://docs.ckeditor.com/#!/api/CKEDITOR.editor-event-change

以下内容适用于我正在使用的版本4.4.3。您需要处理源和HTML更改时的情况。

// Initialize the rich text editor.
var bodyEditor = CKEDITOR.replace('emailTemplate_Body',
{
    readOnly: false
});

// Handle when the Source changes.
bodyEditor.on('mode', function () {
    if (this.mode == 'source') {
        var editable = bodyEditor.editable();
        editable.attachListener(editable, 'input', function () {
            alert('source changed');
        });
    }
});

// Handle when the HTML changes.
bodyEditor.on('change', function () {
    alert('change fired');
});

我看到这段源代码来自于CKEditor,用于在源代码模式下监听变化。但是对我来说它不起作用。这对其他人有效吗? - nuander
@nuander 大约晚了1.5年...但是...这对我在最新的CKEditor 4中有效。bodyEditor.on('change'... 部分是你真正需要的唯一部分。 - degenerate

11

我懂了!

一开始我在我的网页上使用 class 为 ckeditor 的 textarea 创建编辑器,并让 ckeditor.js 将它们转换成富文本编辑器。后来我尝试了其他答案中提供的不同解决方案,但都无法使它们正常工作。
然后我将 class 名称更改为 CKeditor,并在我的代码中初始化编辑器。我尝试了这个方法,它可以正常工作:

<script type="text/javascript" src="/ckeditor/ckeditor.js"></script>
<script type="text/javascript" src="/ckeditor/adapters/jquery.js"></script>

$('.CKeditor').ckeditor(function(){
     this.on('blur', function({if(this.checkDirty())alert('text changed!');});
});

编辑器失去焦点时会检查它是否被修改过,如果有修改则会触发changed函数(例如此示例中的警告框)。

后来我尝试了使用onchanges插件,代码如下:

$('.CKeditor').ckeditor();
for (var i in CKEDITOR.instances) {
    CKEDITOR.instances[i].on('change', function() {alert('text changed!');});
}

现在它也适用于插件了(感谢@Alfonso)。但我认为插件会触发太多的更改事件,我更喜欢第一种解决方案,只在失去焦点时评估更改。

希望这有所帮助!感谢大家的帮助。


9

CKEditor有一个函数'checkDirty()'。检查CKEditor的值是否已更改的最简单方法是在您的代码中添加此JS片段。

CKEDITOR.instances['emailBody'].on('blur', function(e) {
    if (e.editor.checkDirty()) {
        var emailValChanged=true; // The action that you would like to call onChange
    }
});

注意:emailBody是您的文本框字段的ID。

如果您将使用 checkDirty 方法,可能还需要使用 resetDirty - 清除“脏”状态标志。 - marciowb

7

最好的方法,基本上可以告诉您编辑器的内容是否已从原始状态更改。

var editor = $('#ckeditor').ckeditorGet();

editor.on("instanceReady", function(){                    
     this.document.on("keyup", function(){
     console.log(editor.checkDirty());
   });
});

这个没用,但是下面的变体(https://dev59.com/xW435IYBdhLWcg3w50j4#15206334)可以。 - Daniel Sokolowski
谢谢Simon,这对我有用。@josh,我认为你应该枚举所有的CKEditor元素(例如使用each)并将事件附加到它们上。 - QMaster
this.document.on("keyup"... 将捕获整个窗口上的所有键盘弹起事件。如果您有多个 ckeditor,则无法确定正在编辑哪一个。 - Josh Woodcock
keyup函数在ckeditor元素上不起作用,因为实际的编辑器在不同元素中的一个iframe中。 - Josh Woodcock

3

我还没有想出解决方案,但以下链接讨论了CKEditor可用的事件:

http://alfonsoml.blogspot.com/2009/09/ckeditor-events.html

这不是我寻找的完美解决方案,但我正在使用以下方法标记我的内容已被修改:

CKEDITOR.on('currentInstance', function(){modified = true;});

这并不意味着内容已经被修改,而是表示用户已经聚焦或失焦于编辑器(这比没有好)。


1
哈哈,Alfonso 直接回答了这个问题并获得了最高分,但被采纳的答案来自他的博客,我觉得这太有趣了。 - Joel Peltonen
请注意,我不经常回顾我的旧问题(你可以看到我最初在'11年用我的解决方案回答了这个问题)。我刚刚看了一下Alfonso的答案,发现他已经得到了一些评论的支持,所以我更改了正确答案。 - Gazillion
哦,是的,你不会从它们那里获得自动更新。我认为这可能是对 SO 的一个重大改进,可以帮助更好地维护提出的问题。我并不是想成为个讨厌鬼,我只是觉得很有趣 :) - Joel Peltonen

2

要更改事件,请下载插件onchange http://ckeditor.com/addon/onchange 并执行以下操作:

var options_cke = {
    toolbar: [
        { name: 'basicstyles', items: ['Bold', 'Italic', 'Underline', 'Image', 'TextColor'] },
        { name: 'paragraph', items: ['JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock', 'BGColor'] },
        { name: 'font', items: ['Font', 'Styles']}
    ],
    on: {
        change: function(ev) {
            //ev.editor.focus();
            console.log(ev);
        }
    }
};
var editor = $('yourCkeEditorID').ckeditor(options_cke);

2
editor = CKEDITOR.appendTo('container', {resize_enabled: false}); 
editor.on('key', function () { setTimeout(setHtmlData,10); });

etc


1
从我在CKEditor文档网站上看到的,CKEditor带有内置的事件处理。这意味着您应该使用它来监听onChange事件,而不是使用JQuery。这主要是因为像CKEditors这样的编辑器创建其“花哨”的UI时,您最终会监听到错误的元素进行更改。我相信如果您可以获取CKEditor JavaScript对象的引用,您应该能够编写类似于以下内容的代码:
ckRefObj.on('onChange', function() { /* do your stuff here */ });

希望这能有所帮助。


谢谢ZeSimon。根据您的回答,我已经接近了一点,但是我仍然无法将事件附加到它上面。我编辑了上面的问题以展示我尝试过的内容。 - Gazillion
相同的结果。我尝试了各种组合以及来自这个类似问题的解决方案http://stackoverflow.com/questions/4354774/jquery-events-on-ckeditor,但仍然不起作用。 - Gazillion
3
很抱歉如果我不能再提供更多帮助...顺便需要注意的最后一件事是,根据链接的帖子,CKEditor使用一个iframe来加载实际的用户界面。这意味着你将无法响应事件,因为它们附加到当前文档的DOM上,而CKEditor加载在另一个文档中的iframe中,因此你的绑定不起作用,因为它们引用的实际上是一个不会改变的元素。但是,你仍然可以通过JavaScript检索当前的CKEditor实例并将事件处理程序附加到它上面。我现在要去睡觉了,所以不能再提供帮助了,很抱歉。 - Simon H
1
使用CKEditor4.4.5,在阅读文档(docs.ckeditor.com/#!/api/CKEDITOR.event)之后,以下代码适用于我:CKEDITOR.instances.frase1.on('change', function(){ console.info('changed') }). 这里的frase1是我的P元素ID。 - eleuteron

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