Count Words using tinymce in the front-end

i am using a front built in (article directory plugin) tinymce with wp_editor.
what ever i tried i cant get the word counter to work automatically..

i can count the words fine in the HTML tab using a jquery word counter but not
in the wysisyg tab since its an iframe…

Read More

i got some new white hairs dealing with this issue and would really appreciate
your input / help or even a gr8 reference to a solution.

Here is the code i currently have (relevant part of the page) including
the jquery counter which i would rather not use and would rather use wordpress
or to be precise tinymce build in plugin / ability to count words as if inside the dashboard.

<script type="text/javascript">
$(document).ready(function() {
    $("[class^='count[']").each(function() {
        var elClass = $(this).attr('class');
        var minwords = 0;
        var maxWords = 0;
        var countControl = elClass.substring((elClass.indexOf('['))+1, elClass.lastIndexOf(']')).split(',');

        if(countControl.length > 1) {
            minwords = countControl[0];
            maxWords = countControl[1];
        } else {
            maxWords = countControl[0];
        }   

        $(this).after('<div class="wordcount"><strong>0</strong> Words</div>');
        if(minwords > 0) {
            $(this).siblings('.wordcount').addClass('errorwords');
        }   

        $(this).bind('keyup click blur focus change paste', function() {
            var numWords = jQuery.trim($(this).val()).split(' ').length;
            if($(this).val() === '') {
                numWords = 0;
            }   
            $(this).siblings('.wordcount').children('strong').text(numWords);

            if(numWords < minwords || (numWords > maxWords && maxWords != 0)) {
                $(this).siblings('.wordcount').addClass('errorwords');
            } else {
                $(this).siblings('.wordcount').removeClass('errorwords');   
            }
        });
    });
});

</script>
<?php
        wp_print_scripts('quicktags');
        require_once(ABSPATH . '/wp-admin/includes/post.php');
        function richedit() { return true; }
        add_filter('user_can_richedit', 'richedit');
            //wp_tiny_mce( false, array( 'height' => '370' ) );
        if ($options['default_editor'] == 'html') {
            add_filter( 'wp_default_editor', create_function('', 'return "html";') );
        } else {
            add_filter( 'wp_default_editor', create_function('', 'return "tinymce";') );
        }
        wp_editor($_POST['post'], 'minword' , array('textarea_name' => 'minword', 'editor_class' => 'count[50,0]'));
    } else {
        echo '<style type="text/css">#quicktags {display:none}</style>';
        wp_editor($_POST['post'], 'minword' , array('textarea_name' => 'minword', 'editor_class' => 'count[50,0]'));
    }
?>

.

REVISED TO BETTER EXPLAIN @bueltge AND OTHER’S MY PROBLEM…
i have uploaded a temp version online so i can show you the problem.

The website is in hebrew so you need to login
with the demo user / pass combination which is: temp / temp

Url: HERE

Then Click the last button meaning the first from the left…
there you would see the editor. trying to write it would results
with the chars counter not changing but if you click the HTML tab you
would see the chars counter is working..

So.. How can i get the counter to count when in wysisyg mode?

this example uses the code buelge suggested which a minor change
to the id – here is the revised top two lines which i have changed

var comment_input = $( '#articleSubmit textarea' );
var submit_button = $( '#articleSubmit #submit' );

Related posts

Leave a Reply

3 comments

  1. A while later i decided to try it again… (needed it for a project)
    this time i went for clean jquery and i got it to work!

    here it is:
    the working & easy to use way to count words while
    they are being written inside a wp_editor both in the
    html editor and visual editor.

    <script type="text/javascript">
    i=0;
    $(document).ready(function(){
        // visual mode
        // the iframe id
        $("#description_ifr").ready(function () {
            setInterval(function(){
                var tinymceval = $('#description_ifr').contents().find('body').text();
                var wordscount = tinymceval.split(" ");
                        // you should crete a div with the 
                        // the id = #wordcount to show count
                $("#wordcount").text(wordscount.length);
            }, 5000)
        });
    
        // html mode
    // #description is the id of the text area
        $("#description").keypress(function(){
            $("#wordcount").text(i+=1);
        });
    }); 
    </script>
    

    Thanks for eveyone’s help 😉

  2. Have to do this as answer because of the char limit for comments ( irony 🙂 ):

    you can try to, instead of selecting the textarea by a class or what, use the tinymce object to get the content. in your case it’s tinyMCE.editors.minword.getContent.
    This will return the lenght of the content..not sure, but it shouldn’t matter if it’s in visual or html mode…but even if it matters, to target the visual mode use (repeating myself) tinymce.editors.minword.getContent .
    to check in which mode the editor is you can use something like:

    // get the container
    container = $('.wp-editor-wrap');
    
    // check for current state
    if ( $(container) ).hasClass('html-active') ) 
        { ..html mode stuff.. }
    else 
        { visual mode stuff }
    

    where html mode stuff / visual mode stuff just means to switch the selector for your keyup function.

    EDIT: To confirm that .getContent doesn’t care about the current state see this thread as well: How to get the input of a TinyMCE editor when using on the front-end?

    So. Just use tinyMCE.editors.##editor_id##.getContent to get the length of the current editor in use.

    EDIT:

    Without testing, no guarantee that there is no mistake

    <script type="text/javascript">
    $(document).ready(function() {
        $("[class^='count[']").each(function() {
            var elClass = $(this).attr('class');
            // new line, editor id
        var elId = $(this).attr('id');
            var minwords = 0;
            var maxWords = 0;
            var countControl = elClass.substring((elClass.indexOf('['))+1, elClass.lastIndexOf(']')).split(',');
    
            if(countControl.length > 1) {
                minwords = countControl[0];
                maxWords = countControl[1];
            } else {
                maxWords = countControl[0];
            }   
    
            $(this).after('<div class="wordcount"><strong>0</strong> Words</div>');
            if(minwords > 0) {
                $(this).siblings('.wordcount').addClass('errorwords');
            }   
    
            $(this).bind('keyup click blur focus change paste', function() {
    
                // new line, reference element ID
            var content = get_tinymce_content(elId);
                // changed line
                var numWords = jQuery.trim(content).split(' ').length;
                if($(this).val() === '') {
                    numWords = 0;
                }   
                $(this).siblings('.wordcount').children('strong').text(numWords);
    
                if(numWords < minwords || (numWords > maxWords && maxWords != 0)) {
                    $(this).siblings('.wordcount').addClass('errorwords');
                } else {
                    $(this).siblings('.wordcount').removeClass('errorwords');   
                }
            });
        });
    });
    
    
    function get_tinymce_content(elId){
        if (jQuery("#"+elId+"-wrap").hasClass("tmce-active")){
            return tinyMCE.editors.elId.getContent();
        }else{
            return jQuery('#'+elId).val();
        }
    }
    </script>