how to limit a field with javascript-prototype and display the counter

2011-04-10

For job purposes I had to learn a lot of JavaScript, including AJAX related stuffs. Like every lazy (but intelligent) developer, I looked around for frameworks that could help me doing my work. I knew that prototype existed, but I never looked at it because of lack of interest. Well it’s great, it’s really great! Nowadays everybody should use frameworks, as their abstraction permits a rapid development without worrying about things like platform compatibility, in our case browsers. Prototype also has a very nice and clean syntax that overtakes functions not compatible with every browser.

In this post I’m going to report a very nice function I implemented for limiting Form input fields, like textarea and input of type text. You have to call it via onkeyup and onkeydown events. The function accepts 3 parameters: field, limit and counterDesired. The first is the field object, you should use the keyword this for a value. The second parameter is a limit value, the number of characters that the field should contain at maximum. The third parameter is optional, false as default. It permits to add a visual counter after the field, like the one you see on YouTube, for example. You can either tell to the function to add the counter for you (put inside a __ block) or to put it inside another block you’ve already defined. In the second case, the block must have an id of the form ‘fieldID_counter’

This is the compact version, see below for some examples and the expanded, explained version:

<script type="text/javascript">
// < ![CDATA[ 
function limit_text(field, limit, counterDesired) {
    if (counterDesired == null)
        counterDesired = false;
    var length = $F(field).length;
    if (length &gt; limit) 
        $(field).value = $(field).value.substring(0, limit);
    if (counterDesired) {
        if ($($(field).id + '_counter')) {
            $($(field).id + '_counter').update($F(field).length + " / " + limit);
        } else {
            var counterText = new Element('span', {'id': $(field).id + '_counter'});
            counterText.update($F(field).length + " / " + limit);
            $(field).insert({'after': counterText});
        }
    }
}
// ]]>
</script>

This is the longer version for those who want a better understanding:

<script type="text/javascript">
    // <![CDATA[
    function limit_text(field, limit, counterDesired) {
        if (counterDesired == null) {
            // if we omit "counterDesired" parameter
            counterDesired = false;
        }

        // get field length
        var length = $F(field).length;

        if (length &gt; limit) {
            // if it's greater than the limit
            // we truncate its content at the limit
            var newFieldContent = $(field).value.substring(0, limit);
            $(field).value = newFieldContent;
        }

        if (counterDesired) {
            length = $F(field).length;
            // if we desire a counter displayed
            if ($($(field).id + '_counter')) {
                // this is if user wants a customized counter
                $($(field).id + '_counter').update(length + " / " + limit);
                // called "[ID_OF_FIELD]_counter"
            } else {
                // default behavior, create a span for the counter
                var counterText = new Element('span', {
                    'id': $(field).id + '_counter'
                });
                counterText.update((length) + " / " + limit);
                // displays  " current length / limit "
                $(field).insert({
                    'after': counterText
                    // we want the counter after the field
                });
            }
        }

    }
    // ]]>
</script>

Because of Prototypejs, I’m sure this works with every browser, at least those supported by prototype, and I don’t have to worry about compatibility issues! I hope this may help you, and comment this post if you have suggestions or thoughts.


I do not use a commenting system anymore, but I would be glad to read your comments and feedback. Feel free to contact me.