1. #1
    Sencha User
    Join Date
    Jun 2010
    Posts
    18
    Vote Rating
    0
    alexwebb2 is on a distinguished road

      0  

    Default Ext.ux.CustomPicker, Ext.ux.CustomPickerField, Ext.ux.TimePickerField

    Ext.ux.CustomPicker, Ext.ux.CustomPickerField, Ext.ux.TimePickerField




    In order to get around the issues with Ext.form.Select components on Android in v1.0, I've created Ext.ux.CustomPicker and its field wrapper, Ext.ux.CustomPickerField. As an example of how it's used, I've created Ext.ux.TimePickerField.

    The CustomPickerField accepts slotConfigs and slotOrder, which it passes to the CustomPicker to generate the slots (lists). The slotConfigs object consists of named slot configurations, which each have title (displays with useTitles), from, to, step, align, flex, and renderer.

    Here is the code for the Ext.ux.CustomPicker and Ext.ux.CustomPickerField components:
    PHP Code:
    Ext.ux.CustomPicker Ext.extend(Ext.Picker, {
        
    slotConfigs: {
            
    'slot_a': {
                
    title:        '1-10',
                
    from:        1,
                
    to:        10,
                
    step:        1,
                
    align:        'center',
                
    flex:        2,
                
    renderer:    function(value) {return value;}
            },
            
    'slot_b': {
                
    title:        '1-100',
                
    from:        1,
                
    to:        100,
                
    step:        1,
                
    align:        'center',
                
    flex:        2,
                
    renderer:    function(value) {return value;}
            },
            
    'slot_c': {
                
    title:        '0-99(.1)',
                
    from:        1,
                
    to:        10,
                
    step:        .1,
                
    align:        'center',
                
    flex:        2,
                
    renderer:    function(value) {return (value 1) * 10;}
            }
        },
        
    slotOrder: [
            
    'slot_a',
            
    'slot_b',
            
    'slot_c'
        
    ],

        
    initComponent: function()
        {
            var 
    tmpi;

            for (var 
    slotName in this.slotConfigs)
            {
                if (
    this.slotConfigs.hasOwnProperty(slotName))
                {
                    if (
    this.slotConfigs[slotName].from && this.slotConfigs[slotName].to && this.slotConfigs[slotName].step)
                    {
                        
    // Swap from and to if slotName
                        
    if (this.slotConfigs[slotName].from this.slotConfigs[slotName].to)
                        {
                            
    tmp this.slotConfigs[slotName].from;
                            
    this.slotConfigs[slotName].from this.slotConfigs[slotName].to;
                            
    this.slotConfigs[slotName].from tmp;
                        }

                        for (
    this.slotConfigs[slotName].from<= this.slotConfigs[slotName].to+= this.slotConfigs[slotName].step)
                        {
                            if (!
    this.slotConfigs[slotName].values)
                            {
                                
    this.slotConfigs[slotName].values = [];
                            }

                            
    this.slotConfigs[slotName].values.push(i);
                        }
                    }
                }
            }

            
    this.slots = [];

            for (
    0this.slotOrder.lengthi++)
            {
                var 
    slotName this.slotOrder[i];

                if (
    this.slotConfigs[slotName])
                {
                    var 
    data = [];

                    for (var 
    0this.slotConfigs[slotName].values.lengthj++)
                    {
                        
    data.push({
                            
    text:    this.slotConfigs[slotName].renderer(this.slotConfigs[slotName].values[j]),
                            
    value:    this.slotConfigs[slotName].values[j]
                        });
                    }

                    
    this.slots.push({
                        
    name:    slotName,
                        
    align:    this.slotConfigs[slotName].align,
                        
    data:    data,
                        
    title:    this.useTitles this.slotConfigs[slotName].title false,
                        
    flex:    this.slotConfigs[slotName].flex
                    
    });
                }
            }

            
    Ext.ux.CustomPicker.superclass.initComponent.call(this);
        },

        
    initEvents: function()
        {
            
    Ext.ux.CustomPicker.superclass.initEvents.call(this);
        },

        
    afterRender: function()
        {
            
    Ext.ux.CustomPicker.superclass.afterRender.apply(thisarguments);

            
    this.setValue(this.value);
        },

        
    onSlotPick: function(slotvalue)
        {
            
    Ext.ux.CustomPicker.superclass.onSlotPick.apply(thisarguments);
        },

        
    onMaskTap: function(slotvalue)
        {
            
    Ext.ux.CustomPicker.superclass.onMaskTap.apply(thisarguments);
        },

        
    getValue: function()
        {
            var 
    value Ext.ux.CustomPicker.superclass.getValue.call(this);
            var 
    returnValue = {};

            for (var 
    slotName in value)
            {
                if (
    value.hasOwnProperty(slotName))
                {
                    
    returnValue[slotName] = value[slotName];
                }
            }

            return 
    returnValue;
        },

        
    getTextValues: function()
        {
            var 
    value Ext.ux.CustomPicker.superclass.getValue.call(this);
            var 
    returnValue = {};

            for (var 
    slotName in value)
            {
                if (
    value.hasOwnProperty(slotName))
                {
                    
    returnValue[slotName] = this.slotConfigs[slotName].renderer(value[slotName]);
                }
            }

            return 
    returnValue;
        },

        
    setValue: function(valueanimated)
        {
            
    this.value value;

            return 
    Ext.ux.CustomPicker.superclass.setValue.call(thisthis.valueanimated);
        }
    });

    Ext.ux.CustomPickerField Ext.extend(Ext.form.Field, {
        
    ui'select',
        
    pickernull,
        
    destroyPickerOnHidefalse,

        
    initComponent: function()
        {
            
    this.addEvents('select');

            
    this.tabIndex = -1;
            
    this.useMask true;

            
    Ext.form.Text.superclass.initComponent.apply(thisarguments);
        },

        
    getCustomPicker: function()
        {
            if (!
    this.customPicker)
            {
                if (
    this.picker instanceof Ext.ux.CustomPicker)
                {
                    
    this.customPicker this.picker;
                }
                else
                {
                    
    this.customPicker = new Ext.ux.CustomPicker(Ext.apply(this.picker || {}));
                }

                
    this.customPicker.setValue(this.value || null);

                
    this.customPicker.on({
                    
    scope:    this,
                    
    change:    this.onPickerChange,
                    
    hide:    this.onPickerHide
                
    });
            }

            return 
    this.customPicker;
        },

        
    onMaskTap: function()
        {
            
    this.getCustomPicker().show();
        },

        
    onPickerChange: function(pickervalue)
        {
            
    this.setValue(value);
            
    this.fireEvent('select'thisthis.getValue());
        },

        
    onPickerHide: function()
        {
            if (
    this.destroyPickerOnHide && this.customPicker)
            {
                
    this.customPicker.destroy();
            }
        },

        
    setValue: function(valueanimated)
        {
            
    this.value value;

            if (
    this.getCustomPicker())
            {
                
    this.getCustomPicker().setValue(valueanimated);
            }

            if (
    this.rendered)
            {
                
    this.fieldEl.dom.value this.getDisplayValue();
            }

            return 
    this;
        },

        
    getValue: function()
        {
            return 
    this.getCustomPicker() ? this.getCustomPicker().getValue() : this.value;
        },

        
    getDisplayValue: function()
        {
            return 
    this.renderer this.renderer(this.getTextValues()) : null;
        },

        
    getTextValues: function()
        {
            return 
    this.getCustomPicker() ? this.getCustomPicker().getTextValues() : null;
        },

        
    onDestroy: function()
        {
            if (
    this.customPicker)
            {
                
    this.customPicker.destroy();
            }

            
    Ext.form.customPicker.superclass.onDestroy.call(this);
        }
    }); 
    The CustomPickerField is not intended to be used on its own, but extended and given a getDisplayValue() function to convert the list of text values in this.value (indexed by slot name) into a displayed string. As an example, here is the code for Ext.ux.TimePickerField (though if you're specifically looking for a TimePicker, you may want to check out blessan's DateTimePicker as an alternative):
    PHP Code:
    Ext.ux.TimePickerField Ext.extend(Ext.ux.CustomPickerField, {
        
    slotConfigs: {
            
    'hour': {
                
    title:        'Hour',
                
    from:        1,
                
    to:        12,
                
    step:        1,
                
    align:        'right',
                
    flex:        4,
                
    renderer:    function(value) {
                    return 
    value;
                }
            },
            
    'minute': {
                
    title:        'Minute',
                
    from:        1,
                
    to:        60,
                
    step:        5,
                
    align:        'left',
                
    flex:        2,
                
    renderer:    function(value) {
                    
    value value 1;

                    return 
    value >= 10 value '' '0' value;
                }
            },
            
    'am_pm': {
                
    title:        'AM/PM',
                
    from:        1,
                
    to:        2,
                
    step:        1,
                
    align:        'left',
                
    flex:        4,
                
    renderer:    function(value) {
                    return 
    value == 'AM' 'PM';
                }
            }
        },
        
    slotOrder: [
            
    'hour',
            
    'minute',
            
    'am_pm'
        
    ],

        
    initComponent: function()
        {
            
    this.picker = new Ext.ux.CustomPicker({slotConfigsthis.slotConfigsslotOrderthis.slotOrder});

            
    Ext.ux.TimePickerField.superclass.initComponent.call(this);
        },

        
    onPickerChange: function(pickervalue)
        {
            
    this.setValue(value);
            
    this.fireEvent('select'thisthis.getValue());
        },

        
    afterRender: function()
        {
            
    Ext.ux.TimePickerField.superclass.afterRender.apply(thisarguments);

            
    this.setValue(this.value);
        },

        
    onSlotPick: function(slotvalue)
        {
            
    Ext.ux.TimePickerField.superclass.onSlotPick.apply(thisarguments);
        },

        
    getValue: function()
        {
            return 
    Ext.ux.TimePickerField.superclass.getValue.call(this);
        },

        
    getTextValues: function()
        {
            return 
    Ext.ux.TimePickerField.superclass.getTextValues.call(this);
        },

        
    getDisplayValue: function()
        {
            var 
    values this.getTextValues.call(this);
            var 
    value;

            if (
    values && values.hour && values.minute && values.am_pm)
            {
                
    value values.hour ':' values.minute ' ' values.am_pm;
            }

            return 
    value value null;
        },

        
    setValue: function(valueanimated)
        {
            
    this.value value;

            
    Ext.ux.TimePickerField.superclass.setValue.call(thisthis.valueanimated);

            if (
    this.rendered)
            {
                
    this.fieldEl.dom.value this.getDisplayValue();
            }
        }
    }); 
    Finally, an example of how to instantiate the field and provide a default value ("2:30 AM"):
    PHP Code:
    this.startTimePickerField = new Ext.ux.TimePickerField({
        
    label:    'Start Time',
        
    value:    {
            
    hour:    2,
            
    minute:    31,
            
    am_pm:    1
        
    }
    }); 
    As this was a one-night hack, it's got a LOT of room for improvement. If you end up making any fixes/changes/improvements to it, please leave a post!
    Last edited by alexwebb2; 19 Nov 2010 at 8:08 AM. Reason: Added ref to blessan's DateTimePicker

  2. #2
    Sencha User blessan's Avatar
    Join Date
    May 2010
    Posts
    316
    Vote Rating
    1
    blessan is on a distinguished road

      0  

    Default


    Looks good. It would be great if you could attach a zip file with the extension and a test file so the we can download and check right away.

Similar Threads

  1. Replies: 1
    Last Post: 4 Oct 2010, 11:41 AM
  2. Replies: 4
    Last Post: 12 Mar 2010, 5:02 PM
  3. Replies: 1
    Last Post: 17 Aug 2008, 2:31 PM
  4. Replies: 0
    Last Post: 2 Aug 2007, 5:12 PM
  5. Replies: 9
    Last Post: 7 Jun 2007, 12:16 AM

Thread Participants: 1