Disclaimer: This is not design pattern oriented, or remotely as elegantly written as the code we frequently see in these forums. Just a quick experiment.

I wanted a counter for my TextAreas, all of which correspond to database table columns with fixed sizes (e.g. Notes -> 100 chars). The EXTJS textarea comes with a maxlength property, but I don't think it comes with a live counter for depicting the current character count. So as a small experiment, I decided to make a function.

Target Markup:
Code:
<textarea class="maxlength100 someClass anotherClass" style="width: 400px; height:200px; border:1px solid #00CCFF;">34</textarea>
Not sure if it was a good design decision, but that's how I decided to pick my target items. Any textarea which has a valid maxlengthXXXX css class would be a candidate for processing. I simply place an input next to the textarea with the DomHelper, initialize it, and finally bind the textarea's keyup event to update it when the user types.

Here's the code for the function:
Code:
function textAreaAutoLimit()
{
    var dh = Ext.DomHelper;
    var collection = Ext.DomQuery.select('textarea');
    
    /* we'll loop through the collection working only on
     * items which have a valid maxlength css class with
     * them. Rest will be ignored.
     */
    Ext.each(collection, function(item, index) {
        /* does the active item have a valid maxlength css class?
         * If not, skip the current item
         */
        var max = arrayFindPartial(item.className.split(' '), 'maxlength') == null ? 
                    false : arrayFindPartial(item.className.split(' '), 'maxlength');
        if(!max) {
            return; //we return from the closure, not the textAreaAutoLimit() function
        }
        
        /* if the current item does not have an id, generate
         * one, or use the existing id if available. No check
         * is done to see if the dom contains any other elements
         * with the same id (common mistake).
         */
        item.id = (item.id == null || item.id.trim() == '') ? ('tfAutoLimit' + index+1) : (item.id);
        
        /* the input field which will be the display counter for the current item */
        var spec = {
            id: 'count' + item.id,
            tag: 'input',
            style: {
                'background-color': '#fff !important',
                'border':             'none !important',
                'padding':            '4px',
                'font':                '11px/11px Tahoma'
            },
            readOnly: true,
            cls: 'genCounter',
            tabIndex: -1
        };
        dh.insertAfter(
            Ext.DomQuery.select('#' + item.id)[0],
            spec
        );
        
        /* init the value (since the item can load prepopulated with some value) */
        document.getElementById('count' + item.id).value = max - item.value.length + ' characters left';
        
        /* event binding */
        Ext.get(item).on('keyup', function(e) {
            if((max - item.value.length) >= 0) {
                document.getElementById('count' + item.id).value = max - item.value.length + ' characters left';
            }
            if(item.value.length > max) {
                item.value = item.value.substring(0, max);
            }
        });
    });
}

function arrayFindPartial(array, str) {
    for(var i = 0; i < array.length; i++) {
        return array[i].indexOf('maxlength') == 0 ? array[i].replace(/[^\d]/g, '') : null;
    }
}
Some thoughts & questions:

- I don't know how to 'wrap' existing items with markup using the DomHelper. Otherwise instead of adding the counter input after the textarea, I would have packaged all that inside multiple divs with good styles (floats, alignments et al.).

- The EXT equivalent of doc.getElById is? (I know dojo has dojo.byId). I thought it was Ext.get(id), but that doesn't return the html element, it returns an EXT element I think.

- That arrayFindPartial function can be a bloody performance mess. I wanted pick my target items like this:
Code:
<textarea maxlength="1000" class="someClass" style="width: 400px; height:200px; border:1px solid #00CCFF;">34</textarea>
Then I'd easily filter these items and their maxlengths with a simple xpath expression, but unfortunately, I'm working with Spring Tags, and maxlength is not recognized as a valid property. I'd expect the Tiles/Spring JSP interpretors to just shut up when they encounter that property, but they don't. It leads to a JSP error.....how silly. That makes me think, on many other frameworks/platforms (which don't have such silly limitations), the target picking can be very efficient.

Needless to say, this is a very substandard job compared to most of the code I see here, but it was an emergency hack done in a few minutes. I'm working to improve it. Do share your thoughts in the meantime.

-