1. #1
    Sencha User
    Join Date
    Apr 2013
    Posts
    10
    Vote Rating
    2
    hakimio is on a distinguished road

      1  

    Default [Ext 4] Simple Textfield character counter

    [Ext 4] Simple Textfield character counter


    This simple plugin displays remaining character count (maxLength has to be set) next to a textfield.
    It's pretty rough in current state and one of the reasons I am posting it is to get some feedback.

    Current version has few drawbacks:
    • Character count is not updated when textfield value is set by loading a record to a form (updateCounter has to be manually called)
    • It doesn't automatically reduce input width to accommodate the counter width. The right textfield width has to be manually set. Fixed by geopalam.
    • Only compatible with ExtJS 4. Doesn't work correctly with 5.
    I know that I could use (X)Templates to add the counter to the field (afterSubTpl?) but I am not sure how to efficiently update it when textfield value changes. Suggestions how the plugin could be improved are highly appreciated.

    PHP Code:
    Ext.define('Ext.ux.plugins.CounterTextField', {
        
    extend'Ext.util.Observable',
        
    alias'plugin.counter',

        
    constructor: function (config)
        {
            
    Ext.apply(thisconfig || {});
            
    this.callParent(arguments);
        },

        
    init: function (field)
        {
            
    field.on({
                
    scopefield,
                
    keyupthis.updateCounter,
                
    focusthis.updateCounter
            
    });
            if (!
    field.rendered)
                
    field.on('afterrender'this.handleAfterRenderfield);
            else
                
    this.handleAfterRender(field);
        },

        
    handleAfterRender: function(field)
        {
            
    field.counterEl field.bodyEl.createChild({
                
    tag'span',
                
    style'padding-left:5px;top:4px;position:absolute;',
                
    htmlfield.maxLength
            
    });
            
    setTimeout(function() {field.inputEl.setStyle({display:'inline',width:'90%'});}, 200);
            
    field.enableKeyEvents true;
        },

        
    updateCounter: function(textField)
        {
            
    textField.counterEl.update('' +
                 (
    textField.maxLength textField.getValue().length));
        }
    }); 
    Here is a usage example: https://fiddle.sencha.com/#fiddle/82v

    Edit: applied fix (or a simple hack) by geopalam for one of the issues listed above.

  2. #2
    Sencha - Support Team
    Join Date
    Feb 2013
    Location
    California
    Posts
    3,386
    Vote Rating
    62
    Gary Schlosberg is a jewel in the rough Gary Schlosberg is a jewel in the rough Gary Schlosberg is a jewel in the rough

      0  

    Default


    Looks handy! Thanks for sharing with the community.
    Get on the Fast Track with Sencha Training http://sencha.com/training

    Are you a Sencha products veteran who has wondered what it might be like to work at Sencha? If so, please reach out to our recruiting manager: sheryl@sencha.com

  3. #3
    Sencha Premium Member
    Join Date
    Aug 2012
    Posts
    4
    Vote Rating
    1
    geopalam is on a distinguished road

      1  

    Question


    Hi

    I have been, for my own amusement, trying to rewrite part of this so it will work in both extjs 4.2 and 5.0 at the same time.

    Code is:

    Code:
    Ext.define('Ext.ux.plugins.CounterTextField', {
                extend: 'Ext.util.Observable',
                alias: 'plugin.counter',
    
                constructor: function (config)
                {
                    Ext.apply(this, config || {});
    
                    this.callParent(arguments);
                },
    
                init: function (field)
                {
                    field.on({
                        scope: field,
                        keyup: this.updateCounter,
                        focus: this.updateCounter
                    });
                    if (!field.rendered) {
                        field.on('afterrender', this.handleAfterRender, field, {single:true});
                    } else {
                        this.handleAfterRender(field);
                    }
                },
    
                handleAfterRender: function(field)
                {
                    field.counterEl = Ext.DomHelper.insertAfter(
                            field.inputEl,
                            {
                                tag: 'span',
                                style: 'width:10%;padding-left:4px',
                                html: field.maxLength
                            },
                            true);
    
                    field.enableKeyEvents = true;
    
                    setInterval(function(){
                        field.inputEl.setStyle({'display':'inline','width':'90%'},1);
                    });
                },
    
                updateCounter: function(textField)
                {
                    textField.counterEl.update('' +
                            (textField.maxLength - textField.getValue().length));
                }
            });
    
            Ext.application({
                name : 'Character Counter',
    
                launch : function() {
                    Ext.create('Ext.form.Panel', {
                        title: 'Character Counter',
                        bodyPadding: 5,
                        width: 400,
    
                        layout: 'vbox',
    
                        defaults: {
                            xtype: 'textfield',
                            width: 350,
                            labelWidth: 70
                        },
    
                        items: [{
                            fieldLabel: 'First Name',
                            maxLength: 45,
                            grow: false,
                            plugins: ['counter']
                        },{
                            fieldLabel: 'Last Name',
                            maxLength: 50,
                            plugins: ['counter']
                        }, {
                            fieldLabel: 'Address',
                            width: 380
                        }],
    
                        renderTo: Ext.getBody()
                    });
                }
            });
    Would it be better to not use an Observable here and instead use a custom field container with a hbox layout?

    And the layout only seems to work when I add this in:

    Code:
     setInterval(function(){
                        field.inputEl.setStyle({'display':'inline','width':'90%'},1);
                    });
    Why is that?

  4. #4
    Sencha User
    Join Date
    Apr 2013
    Posts
    10
    Vote Rating
    2
    hakimio is on a distinguished road

      1  

    Default


    I think instead of setInterval() you meant to use "setTimeout()" or "Ext.util.DelayedTask()".
    You can use a combination of textfield and displayfield in hbox layout as an altrernative, but even it's easy to implement it can be a bit "heavy" solution.
    I guess the best solution might be to create custom textfield by extending "Ext.form.textfield" and set some custom template(s) like it was done with IconCombo.

  5. #5
    Sencha Premium Member
    Join Date
    Aug 2012
    Posts
    4
    Vote Rating
    1
    geopalam is on a distinguished road

      0  

    Default


    Quote Originally Posted by hakimio View Post
    I think instead of setInterval() you meant to use "setTimeout()" or "Ext.util.DelayedTask()".
    You can use a combination of textfield and displayfield in hbox layout as an altrernative, but even it's easy to implement it can be a bit "heavy" solution.
    I guess the best solution might be to create custom textfield by extending "Ext.form.textfield" and set some custom template(s) like it was done with IconCombo.
    Yes you are absolutely correct, should be setTimeout or Delayed Task. Thanks for pointing out that IconCombo will check that out.