Background spell check in TinyMCE

TinyMCE has spellchecker plugin which checks your text when you click button. You can read how to setup it here.

However what we want is to have background spell checking when we type text. Just like in regular word processor. The idea is simple – trigger spell check each time we type something. There’s a problem if we’ll trigger it after each letter – spell check uses Ajax request to server script, it may be very slow. We’ll solve it by triggering spell checking within 3-seconds delay after user has stopped typing.

Here’s the code:

tinyMCE.init({
        //...
	//regular initialization here
	//...
	plugins : "spellchecker", 
	theme_advanced_buttons1 : "spellchecker",
	spellchecker_languages : "English=en", 
	setup: mceSpellCheckRuntimeHandler
  });

And setup function:

mceSpellCheckRuntimeHandler = function(ed) {
  ed.addCommand('mceSpellCheckRuntime', function() {
    t = ed.plugins.spellchecker;
    if (t.mceSpellCheckRuntimeTimer) {
      window.clearTimeout(t.mceSpellCheckRuntimeTimer);
    }
    t.mceSpellCheckRuntimeTimer = window.setTimeout(function() {
      t._done();
      t._sendRPC('checkWords', [t.selectedLang, t._getWords()], function(r) {
        if (r.length > 0) {
          t.active = 1;
          t._markWords(r);
          ed.nodeChanged();
        }
      });
     }, 3000); //3 seconds
  });
  ed.onKeyUp.add(function(ed, e) {
    ed.execCommand('mceSpellCheckRuntime');
  });
};

The code is not ideal, but it works. Feel free to improve it for your needs.
Update. There may be an issue with focus. For example when cursor leaves tinymce it may return back to the editor. Ask me if you have this problem.

Tags: , ,

AddThis Social Bookmark Button

10 Responses to “Background spell check in TinyMCE”

  1. Tao Says:

    Hi,

    Thanks for your code. It’s a quite clever idea. The only concern I have is the performance. As TinyMCE spell checker send the whole contents back to server for checking. If the content is quite big such as 500k, it means you send 500k back to the server every 3 second.

  2. admin Says:

    You are right, it will send whole content back to the server. However, it doesn’t happen every 3 seconds. When you type text it automatically clears queued request and schedules it again in 3 seconds. It means if you type text with regular speed, your content will be send to server only several times. In ideal situation – only once at the end.

  3. Tao Says:

    I see, it will schedules the request again when you’re typing. But it still not ideal if I type a few words then stay for a while for thinking then type again. If the content is quite big, it will waste a lot of CPU time our the server to check the same words again and again. It’s quite interesting to see how Google doc implement this, it only send the new typing words to the server, not the whole content so that it can reduce the transfer bandwidth and the server resource. Of course, I know this is not how TinyMCE spellchecker works but it would be good enhancement.

  4. Glenatron Says:

    You could use the “isDirty()” method to check whether the content of the box has changed, rather than sending it back regardless.

  5. Andrey Chorniy Says:

    Hi,
    That’s great idea, simple but yet powerful implementation.
    I’m going to try slightly different approach here – instead of wait user to stop typing (or make delay larger than 3 seconds) – execute spellcheck requests in background and send only “changed” (or “added”) portions of text periodically. That will allow to highlight errors even if user keep typing and minimize the traffic/server-side loading.
    Not sure if spellcheck/TinyMCE API is enough for that, but it worth trying.

    Actually, that question was asked here (http://achorniy.wordpress.com/2009/08/11/tinymce-spellchecker-in-java) and your post perfectly answer the original question

  6. Alex Says:

    This solution worked for me, however the cursor would move once the spell check kicked in. To resolve this I changed

    if (r.length > 0) {
    t.active = 1;
    t._markWords(r);
    ed.nodeChanged();
    }

    to

    if (r.length > 0) {
    ed.focus();
    var bookMark = ed.selection.getBookmark();
    t.active = 1;
    t._markWords(r);
    ed.nodeChanged();
    ed.selection.moveToBookmark(bookMark);
    }

  7. akhilesh Says:

    where to add set up function code??

  8. akhilesh Says:

    setup: mceSpellCheckRuntimeHandler
    in this line there is no comma or semi colon. i have to add like this only or change

  9. alex Says:

    akhilesh,

    Add setup function code before calling init. No comma or semicolon in last line of init call.

  10. Jim Says:

    Alex, Thanks for your example. It was extremely helpful.

Leave a Reply