41

I'm working with the CKEditor and jQuery and I'd like to toggle a flag to true whenever a user changes the value of a field. One of those fields is a CKEditor instance.

All the textareas that have the "wysiwyg" class get converted to CKEditors but somehow the $('.wysiwyg').change() event never gets detected. I did some googling but the keyword combination seems to bring up nothing but irrelevant results (my google-fu sucks).

Thanks for any help :)

Edit:

for (var i in CKEDITOR.instances) {
        CKEDITOR.instances[i].on('click', function() {alert('test 1 2 3')});
    }

I tried the code above and it doesn't work. It doesn't give me an error meaning that it finds the CKEditor objects but for some reason the listener isn't attached to it?

Also, if I replace the event attachment with just alert(CKEDITOR.instances[i].name); it'll alert the name of my textarea so I know I'm not trying to attach the click event to nothing :)

Gazillion
  • 4,822
  • 11
  • 42
  • 59
  • 2
    This is now part of the core (version 4.2+). See http://docs.ckeditor.com/#%21/api/CKEDITOR.editor-event-change. – nfplee Aug 14 '13 at 13:24

14 Answers14

55

You can get a plugin (and an explanation about what things are detected as changes) in this post: http://alfonsoml.blogspot.com/2011/03/onchange-event-for-ckeditor.html so you can do things like

for (var i in CKEDITOR.instances) {
        CKEDITOR.instances[i].on('change', function() {alert('test 1 2 3')});
    }
AlfonsoML
  • 12,634
  • 2
  • 46
  • 53
  • I have already copied plugin into my directory and set proper path on my html page. I have only one instance of CKEDITO on my page. I have written this lines CKEDITOR.instances.text_area1.on('change', function() {alert('test 1 2 3')});. But it doesn't fires alert. May I missing something ? – krunal shah Apr 28 '11 at 12:13
  • Have you added the plugin to your configuration? (eg: config.extraPlugins = 'onchange';). Do you get any errors? have you verified if the plugin has really been loaded (with Network tab in firebug, Fiddler, etc..., or just adding an alert(1) inside of it)? – AlfonsoML Apr 28 '11 at 16:48
  • I up voted this answer since it was posted after I accept the right answer (which the description said wasn't really a good solution). If krunal or someone else confirms that this works I will change the correct to this one :) – Gazillion Jul 25 '11 at 17:46
  • No, it works. Maybe something is blocking your access to blogspot? – AlfonsoML Oct 24 '12 at 12:32
  • This plugin is not maintained anymore and, worse, is [not compatible with CKEditor4](http://alfonsoml.blogspot.fr/2012/12/no-more-releases-for-onchange-plugin.html). – vaab Feb 21 '13 at 10:57
  • It's compatible with CKEditor 4, although it has some bugs with inline mode. If you spend the time fixing them (I don't use such configuration) then I'll release the new version for everybody. That's the beauty of Open Source. – AlfonsoML Feb 21 '13 at 17:27
  • 3
    On change functionality is now built into CKEditor (version 4.2+). See http://docs.ckeditor.com/#%21/api/CKEDITOR.editor-event-change for more information. – nfplee Aug 14 '13 at 13:25
  • @nfplee yes, it's built in; but it's missing basic changes like drag&drop or anything done while working in source mode. I don't see any mention in the doc about such changes that they are missing (and as shown in my plugin it's trivial to fix that) – AlfonsoML Aug 14 '13 at 13:54
  • @AlfonsoML thanks, I hadn't noticed that. It's not that big a problem for me but hopefully they'll address it in a later release. – nfplee Aug 15 '13 at 08:56
  • A later release? I reported the drag&drop issue (no undo is generated) about two years ago with a patch and it still hasn't been fixed. Also this plugin has been available all the time but they have ignored it while implementing their functionality so I guess that they don't care about these use cases and now you have to live with a half-developed feature instead of enjoying a custom plugin that did just one task correctly – AlfonsoML Aug 15 '13 at 09:54
  • URL for API docs for ckeditor4 is now: https://ckeditor.com/docs/ckeditor4/latest/api/CKEDITOR_editor.html#event-change – phils Mar 05 '21 at 06:08
14

There is now a change event: http://docs.ckeditor.com/#!/api/CKEDITOR.editor-event-change

The following is working for me using version 4.4.3. You need to handle when the Source and HTML changes.

// 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');
});
Garry English
  • 5,070
  • 1
  • 36
  • 23
  • I see where this source code comes from at CKEditor regarding listening for changes while in Source mode. But it does not work for me. Does this work for anyone else? – nuander Oct 27 '14 at 22:41
  • @nuander about 1.5 years late... but yes... this works for me in the latest CKEditor 4. The `bodyEditor.on('change'...` part is the only part that you really need. – degenerate Feb 08 '16 at 16:25
14

I haven't managed to get onchange working however onblur seem to work which may be sufficient for your needs

CKEDITOR.instances['name'].on('blur', function() {alert(1);});
Alexei Tenitski
  • 9,030
  • 6
  • 41
  • 50
11

I got it!

First I had the editors on my web created as textareas with the class ckeditor, and I let the ckeditor.js make them richTextEditors. Then I tried distinct solutions from the other answers, but couldn't make them work.
Then I changed the class name (to CKeditor), so I have to initialize the editors in my code. I tried this and it works:

<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!');});
});

So when a editor loses the focus it checks if it's dirty, and if it is then it fires the changed function (the alert in this example).

Later I've tried again with the onchanges plugin, in this way:

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

Now it works with the plugin too (thanks @Alfonso). But I think that the plugin makes the changes event fire too much, I prefer the first solution where changes are only evaluated on blur.

Hope this helps! and thanks to all for your help.

Peto
  • 2,680
  • 1
  • 18
  • 13
9

The CKEditor has function a 'checkDirty()'. The simplest way to check if the CKEditor value has been changed is to add this piece of JS in your Code.

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

Note: emailBody - is the id of your textarea field

Praveen Kumar Purushothaman
  • 164,888
  • 24
  • 203
  • 252
Ryan Wright
  • 91
  • 1
  • 4
  • If you will use `checkDirty` method, perhaps do you will need also to use the `resetDirty` - to clear the "dirty" status flag. – marciowb Sep 18 '15 at 20:11
7

Best I can do, basically gives you an indication as to if the content of the editor has changed from the original state.

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

editor.on("instanceReady", function(){                    
     this.document.on("keyup", function(){
     console.log(editor.checkDirty());
   });
});
Simon
  • 1,849
  • 3
  • 22
  • 29
  • This one didn't work but the variation below (http://stackoverflow.com/a/15206334/913223) did. – Daniel Sokolowski Jun 13 '16 at 20:52
  • Thanks Simon, Worked for me, @josh I think you should be enumerate All ck Editor elements (for example by using each) and attach event to them. – QMaster Aug 07 '16 at 14:35
  • this.document.on("keyup"... will capture all keyup functions on the entire window. If you have more than one ckeditor you wouldn't know which one is being edited. – Josh Woodcock Aug 08 '16 at 17:22
  • The keyup function doesn't work on the ckeditor element because the actual editor is in an iframe in a different element. – Josh Woodcock Aug 08 '16 at 17:37
3

I haven't come up with a solution but the following link talks more about the events available witht he CKEditor:

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

This is not the perfect solution I was looking for but I'm using the following to flag that my content has been modified:

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

This doesn't actually mean the content has been modified but that the user has focused or blurred from the editor (which is better than nothing).

Gazillion
  • 4,822
  • 11
  • 42
  • 59
  • 1
    Haha, Alfonso answered this question directly with top scores but the accepted answer is from his blog, I find that just so funny. – Joel Peltonen Oct 21 '13 at 11:52
  • Mind you I don't go back and check my old questions very often (you can see I originally answered with my solution in '11. I just looked now at Alfonso's answer and see that he's been upvoted to the top with a few comments claiming it works so I changed the correct answer. – Gazillion Jan 23 '14 at 20:38
  • Oh yeah you don't get automatic updates from them. That I think might be a big improvement for SO that would help a lot with maintaining asked questions. I wasn't trying to be a jerk, I just found it funny :) – Joel Peltonen Jan 24 '14 at 07:04
2
editor = CKEDITOR.appendTo('container', {resize_enabled: false}); 
editor.on('key', function () { setTimeout(setHtmlData,10); });

etc

Anoop
  • 23,044
  • 10
  • 62
  • 76
user1005462
  • 158
  • 2
  • 7
2

For event change download the plugin onchange http://ckeditor.com/addon/onchange and do this


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);
Flegoff
  • 21
  • 3
1

from what I can see on the CKEditor documentation site CKEditor comes with built event handling. This means that you should use that instead of JQuery to listen to the onChange event. This is also mainly because when editors like CKEditors create their "fancy" uis you will end up listening to the wrong element for a change. I believe if you can get the reference of the CKEditor javascript object you should be able to write something like this:

ckRefObj.on('onChange', function() { /* do your stuff here */ });

I hope this helps.

Simon H
  • 1,735
  • 12
  • 14
  • Thanks ZeSimon. Following your answer I was able to get a little bit closer but I still can't seem to attach events to it. I edited my question above to show what I tried. – Gazillion Feb 28 '11 at 15:39
  • Same result. I tried various combination plus the solution from this question (which is similar) http://stackoverflow.com/questions/4354774/jquery-events-on-ckeditor but still it doesn't work. – Gazillion Feb 28 '11 at 15:54
  • 3
    Hey sorry if I can't be anymore help ... anyway one last thing to note is that according to the linked post CKEditor uses an iframe to lod the actual UI. This means that you will not be able to respond to events because they are attached to the DOM of the current document, CKEditor is loaded in another document in an iframe hence you binds not working as they are referencing an element that does not actually change. You will however be able to retrieve the current instance of the CKEditor via javascript and attach an event handler to it. I am going to bed now so I can't help anymore sorry. – Simon H Feb 28 '11 at 15:58
  • 1
    Using CKEditor4.4.5, after reading the docs (docs.ckeditor.com/#!/api/CKEDITOR.event), this worked for me : CKEDITOR.instances.frase1.on( 'change', function(){ console.info('changed') } ). Where frase1 is my P element ID – eleuteron Nov 14 '14 at 08:26
0

This code will alert user on clicking any sidebar link

$("#side-menu a").click(function(e){
  if(checkUnsaved()){
    if (confirm("You have unsaved changes.Do you want to save?")) {
      e.preventDefault();          
    }
    // or ur custom alert
  }
});

function checkUnsaved() {
    if(CKEDITOR)
        return CKEDITOR.instances['edit-body'].checkDirty(); // edit-body is the name of textarea in my case.
    else
        return false;
}
Serjas
  • 2,184
  • 4
  • 21
  • 35
0

I apparently cant simply add a comment because I'm new to the site, but Garry's answer is correct and I've independently verified it so I wanted to add this.

CKEDITOR.instances[xxx].on('change', function() {alert('value changed!!')});

This works for CKEditor 4+, and captures all change events, including undo and redo, rendering Alfonso's js work unnecessary for new users.

Stan Lin
  • 928
  • 7
  • 6
0
$(document).ready(function () {        
    CKEDITOR.on('instanceReady', function (evt) {                    
        evt.editor.on('blur', function () {
            compare_ckeditor('txtLongDesc');
        });                    
    });
});

Don't know about the 'change' event but 'blur' event works perfectly for me when I am using CKeditor version 3.6

Himalaya Garg
  • 1,525
  • 18
  • 23
-1

For later Googlers, I noticed that if you create CKEditor using this

$("#mytextarea").ckeditor();

it works but on form submit doesn't update mytextarea value so it sends old value

but

if you do like this

CKEDITOR.replace('mytextarea');

on form submit it sends new value

Ergec
  • 11,608
  • 7
  • 52
  • 62