#TinyMCE: Add Character Count

TinyMCE has a built in word counter but it does not have a way to count characters.  We have a requirement that limits the users to 5000 characters per textarea field.  This count is purely to keep the users from writing a book each time they enter data.  We only need to count the actual characters that the user sees, all html and hidden characters are ignored.

To do this I created a character count plugin.  It ended up pretty straight forward in the end.  I tried many different ways of pulling and counting the visible characters but many of them were pretty inaccurate.  This version is the closest I could get to the Microsoft Word character counts.

Factoids:

  • I started the plugin with a generic base similar to the existing TinyMCE word count plugin.
  • I layered on this Stack Overflow answer to decode the raw HTML in a way that gave me the most accurate character count.
  • I used this Stack Overflow answer to hide the the path in the status bar of the editor.
  • I also added a generic “Over 5000 characters” validation message that I turn on and off based on the validation done in the “on change” event.
  • The last piece was to validate the character count in the “on submit” event.
  • Thanks to the commenters who found some problems with this code!

TinyMCE Initialization



<pre>
    $('textarea.tinymce').tinymce({
      script_url: '/scripts/tinymce/4.0.25/tinymce.min.js',
      theme: "modern",
      plugins: "charactercount",
      toolbar: "bold italic | link | bullist numlist ",
      menubar: false,
      statusbar: true,
      setup: function (editor) {
        editor.on('change', function(e) {
          var count = this.plugins["charactercount"].getCount();
          if (count > 5000)
            $('#invalidContentHtml').show();
          else
            $('#invalidContentHtml').hide();
        });
      },
      init_instance_callback: function (editor) {
        $('.mce-tinymce').show('fast');
        $(editor.getContainer()).find(".mce-path").css("display", "none");
      }
    });
</pre>

Character Count Plugin:

tinymce.PluginManager.add('charactercount', function (editor) {
  var self = this;

  function update() {
    editor.theme.panel.find('#charactercount').text(['Characters: {0}', self.getCount()]);
  }

  editor.on('init', function () {
    var statusbar = editor.theme.panel && editor.theme.panel.find('#statusbar')[0];

    if (statusbar) {
      window.setTimeout(function () {
        statusbar.insert({
          type: 'label',
          name: 'charactercount',
          text: ['Characters: {0}', self.getCount()],
          classes: 'charactercount',
          disabled: editor.settings.readonly
        }, 0);

        editor.on('setcontent beforeaddundo', update);

        editor.on('keyup', function (e) {
            update();
        });
      }, 0);
    }
  });

  self.getCount = function () {
    var tx = editor.getContent({ format: 'raw' });
    var decoded = decodeHtml(tx);
    var decodedStripped = decoded.replace(/(<([^>]+)>)/ig, "").trim();
    var tc = decodedStripped.length;
    return tc;
  };

  function decodeHtml(html) {
    var txt = document.createElement("textarea");
    txt.innerHTML = html;
    return txt.value;
  }
});

On Submit Code:

var charcnt = tinyMCE.editors["{TextAreaId}"].plugins["charactercount"].getCount() <= 5000;

CSS Tweaks:

/* Optional: Adjust the positioning of the character count text. */
label.mce-charactercount {
margin: 2px 0 2px 2px;
padding: 8px;
}

/* Optional: Remove the html path code from the status bar. */
.mce-path {
    display: none !important;
}

** Updated on 10/28/15: Minor changes based on comments

8 thoughts on “#TinyMCE: Add Character Count

  1. Thanks, Amy … this is great. I ended up adding the following to my stylesheet to make it line up with the “p > strong” path stuff at the bottom:

    label.mce-charactercount {
    margin: 2px 0 2px 2px;
    padding: 8px;
    }

    Liked by 1 person

    • I finally made it work. There are several important typos in your code, plugin and function call are not unified:

      1) fmgcharactercount -> rename to charactercount
      2) customcharactercount -> rename to charactercount
      3) plugin code should be placed inside charactercount dir, with filename plugin.min.js
      4) “>” should be replaced with plain non-encoded version “>”

      Upon loading, it is displayed Characters: 23, I think this is because of bogus content inserted by default, but it gets corrected upon typing. The algorithm for counting seems to be have room for improvements, because counter tends to jump down, then up, then down while typing fast random characters in combination with break enter/return (line breaks).

      Thanks!

      Like

    • Thanks for pointing these out. When I get a chance I will be sure to update it. I got the code working locally and never went back to update this.

      We have been using a version of this on our production system for quite a while now.

      Thanks for identifying the mistakes!

      Like

  2. I really appreciate this code. It appears to be one of the only ways to update the statusbar with the character count. i modified it a bit for my purposes, but thanks (and thanks to those who threw in the comments with formatting and other issues — it helped!). I now have a character counter that shows what I need. Couldn’t get much help from the support forum for TinyMCE.

    Like

  3. BTW, Amy — there’s an error in the:
    var statusbar …

    statement, the ampersands were converted to the HTML entities …

    Like

Leave a comment