Deprecated: Assigning the return value of new by reference is deprecated in /homepages/32/d230485870/htdocs/jessmann/blog/wp-settings.php on line 520

Deprecated: Assigning the return value of new by reference is deprecated in /homepages/32/d230485870/htdocs/jessmann/blog/wp-settings.php on line 535

Deprecated: Assigning the return value of new by reference is deprecated in /homepages/32/d230485870/htdocs/jessmann/blog/wp-settings.php on line 542

Deprecated: Assigning the return value of new by reference is deprecated in /homepages/32/d230485870/htdocs/jessmann/blog/wp-settings.php on line 578

Deprecated: Function set_magic_quotes_runtime() is deprecated in /homepages/32/d230485870/htdocs/jessmann/blog/wp-settings.php on line 18

Strict Standards: Declaration of Walker_Page::start_lvl() should be compatible with Walker::start_lvl(&$output) in /homepages/32/d230485870/htdocs/jessmann/blog/wp-includes/classes.php on line 1199

Strict Standards: Declaration of Walker_Page::end_lvl() should be compatible with Walker::end_lvl(&$output) in /homepages/32/d230485870/htdocs/jessmann/blog/wp-includes/classes.php on line 1199

Strict Standards: Declaration of Walker_Page::start_el() should be compatible with Walker::start_el(&$output) in /homepages/32/d230485870/htdocs/jessmann/blog/wp-includes/classes.php on line 1199

Strict Standards: Declaration of Walker_Page::end_el() should be compatible with Walker::end_el(&$output) in /homepages/32/d230485870/htdocs/jessmann/blog/wp-includes/classes.php on line 1199

Strict Standards: Declaration of Walker_PageDropdown::start_el() should be compatible with Walker::start_el(&$output) in /homepages/32/d230485870/htdocs/jessmann/blog/wp-includes/classes.php on line 1244

Strict Standards: Declaration of Walker_Category::start_lvl() should be compatible with Walker::start_lvl(&$output) in /homepages/32/d230485870/htdocs/jessmann/blog/wp-includes/classes.php on line 1391

Strict Standards: Declaration of Walker_Category::end_lvl() should be compatible with Walker::end_lvl(&$output) in /homepages/32/d230485870/htdocs/jessmann/blog/wp-includes/classes.php on line 1391

Strict Standards: Declaration of Walker_Category::start_el() should be compatible with Walker::start_el(&$output) in /homepages/32/d230485870/htdocs/jessmann/blog/wp-includes/classes.php on line 1391

Strict Standards: Declaration of Walker_Category::end_el() should be compatible with Walker::end_el(&$output) in /homepages/32/d230485870/htdocs/jessmann/blog/wp-includes/classes.php on line 1391

Strict Standards: Declaration of Walker_CategoryDropdown::start_el() should be compatible with Walker::start_el(&$output) in /homepages/32/d230485870/htdocs/jessmann/blog/wp-includes/classes.php on line 1442

Strict Standards: Redefining already defined constructor for class wpdb in /homepages/32/d230485870/htdocs/jessmann/blog/wp-includes/wp-db.php on line 306

Strict Standards: Redefining already defined constructor for class WP_Object_Cache in /homepages/32/d230485870/htdocs/jessmann/blog/wp-includes/cache.php on line 431

Strict Standards: Declaration of Walker_Comment::start_lvl() should be compatible with Walker::start_lvl(&$output) in /homepages/32/d230485870/htdocs/jessmann/blog/wp-includes/comment-template.php on line 1266

Strict Standards: Declaration of Walker_Comment::end_lvl() should be compatible with Walker::end_lvl(&$output) in /homepages/32/d230485870/htdocs/jessmann/blog/wp-includes/comment-template.php on line 1266

Strict Standards: Declaration of Walker_Comment::start_el() should be compatible with Walker::start_el(&$output) in /homepages/32/d230485870/htdocs/jessmann/blog/wp-includes/comment-template.php on line 1266

Strict Standards: Declaration of Walker_Comment::end_el() should be compatible with Walker::end_el(&$output) in /homepages/32/d230485870/htdocs/jessmann/blog/wp-includes/comment-template.php on line 1266

Strict Standards: Redefining already defined constructor for class WP_Dependencies in /homepages/32/d230485870/htdocs/jessmann/blog/wp-includes/class.wp-dependencies.php on line 31

Strict Standards: Redefining already defined constructor for class WP_Http in /homepages/32/d230485870/htdocs/jessmann/blog/wp-includes/http.php on line 61

Strict Standards: call_user_func_array() expects parameter 1 to be a valid callback, non-static method GoogleSitemapGenerator::Enable() should not be called statically in /homepages/32/d230485870/htdocs/jessmann/blog/wp-includes/plugin.php on line 339
Jess Mann » 2009 » April -

Archive for April, 2009

TinyMCE wordcount with jQuery

Posted in Javascript, Programming on April 4th, 2009 by admin – 15 Comments

I was recently working on a custom content management system for a client, and I finished everything up well before our deadline. So, as I usually do, I started work on a few small additions to the software just to round off some of the functionality. One area I felt could use some improvement was the wysiwyg editor in the backend. Now, don’t get me wrong… I’ve used TinyMCE in the past, and in comparison to many other popular options such as fkceditor and wymeditor, I’ve been extraordinarily happy with it. However, the user interface looks rather plain, and there are some other simple widgets I felt could be tacked on.

One thing I was interested in adding was a “word count” area right below the editor. Looking around in the plugin repository and on google, I didn’t see any real viable solutions to this. Most involved clicking a button to check the word count, which to me, seemed a bit too clunky. I wanted something simple, where the wordcount was prominantly visible (but unobtrusive) at the bottom of the editor, and was automatically updated *every new word*.

Here’s a basic rundown of what I did (code is to follow):

First, the tricky part: We needed to add an area for the wordcount below the editor automatically. This way, when TinyMCE is instantiated for every textarea, the wordcount will drop in neatly without any extra markup. So, let’s create a function to do just that:

function addWordCount() {
$(’span.mceEditor’).after(’<div id=”‘ + tinyMCE.activeEditor.id + ‘_wordcount” class=”wordcount”>0  words, 0 characters</div>’);
return true;
}

This function simply searches for every tinyMCE instance, and appends a div (with a specific id) after the editor. Now, we’re going to call this function in TinyMCE’s “setup” function, so every time a new TinyMCE instance is created, we drop in a new “wordcount” div right below it.

Next, we need to figure out how to count the words. To do this, we need to get the editor’s contents, replace all the html so it doesn’t muddle our results, trim out any extra space, and then count the number of words (assuming a word is any alphanumeric string between spaces). This looks something like:

var text = ed.getContent().replace(/(<([^>]+)>)/g,”").replace(/\s+/g,” “);
text = $.trim(text);
var words = text.split(’ ‘).length;
var letters = text.length;

Lastly, now that we have the wordcount and have created the wordcount section, we’re going to tack on some code to change the contents of this “wordcount” div on every keystroke. We do this by adding on “onKeyUp” event listener, which retrieves the current editor contents, counts the words, and replaces the wordcount numbers. Our added code looks like this:

ed.onKeyUp.add(function(ed, e) {
$(’#’ + tinyMCE.activeEditor.id + ‘_wordcount’).html(”<span>” + words + “</span> words, <span>” + letters + “</span> characters”);
});

That’s it! Now, just for one last improvement, let’s combine all the code so that the wordcount doesn’t appear until the user has typed at least one letter (just to make things easier on the eyes), then we’re done! Here’s the final code for “setup”:

setup: function(ed) {
var text = “”;
var wordcount = false;
ed.onKeyUp.add(function(ed, e) {
if (!wordcount) {
wordcount = addWordCount();
}
text = ed.getContent().replace(/(<([^>]+)>)/g,”").replace(/\s+/g,” “);
text = $.trim(text);
$(’#’ + tinyMCE.activeEditor.id + ‘_wordcount’).html(”<span>” + text.split(’ ‘).length + “</span> words, <span>” + text.length + “</span> characters”);
});
}