1. #1
    Sencha User
    Join Date
    May 2008
    Posts
    73
    Vote Rating
    1
    prometheus is on a distinguished road

      0  

    Arrow Multiselect 'CheckboxSelect' control

    Multiselect 'CheckboxSelect' control


    Sorry for double post (this post originaly created on Ext 2 subforum, but control based on Ext 3 - I think that should works on ver 2 but never tested), it's my mistake - that topic being unmonitored in the future.

    Hi, this is a composite control using a combobox for selecting items and checkboxes for displaying and unselecting preivously selected items. This is great for users because their selections are visible but not reserve a lot of space (like a list) and very easy to use (not need any knowledge to handle). Component handled like any other form fields and able to load initial values from remote server in a practical way using a simple array.
    Why this component created? Because most of my useres have a lot of problem with Ctrl-click selection and default auto multiselection. Another reason that I don`t like to see list controls in a complex layout. My goal is a practial, intuitive and easily oversightable solution.

    Warning! This component isn`t a well-tested, it`s under developed and seems it`s works. I`m only tested on FF3. Code documentation is actual but has some formal bug which will be fixed if I have enough time to it, sorry.

    Usability tips:
    • Select tags - a very visible implementation, user could type one of the available tags, tag added if return pressed, checkbox with tag appears.
    • Any case where there are so many items available, list seems like unlimited, and we do not want to force the user to "scroll and scroll and select one or some" - this control should be a very useful solution because user colud select items very easily and will alvays see what he/she choosed.
    • etc.
    .
    Changelog after first revision shared:

    [2009 May, 16]
    • config setting 'checkboxArrayName' becomes 'name' to better fit to the fields standard.
    • added 'hiddenName' config which if specified, control creates a hidden field with that name to store the field`s raw value to able to submit that to server-side.
    • added more of standard field config settings: cls, fieldClass, focusClass, invalidClass, invalidText, msgFx, msgTarget, readOnly (not implemented yet), tabIndex, validateOnBlur, validationEvent, value.
    • added standard field methods: clearInvalid, getName, getRawValue, getValue, isDirty, isValid, markInvalid, reset, setValue, setRawValue, validate.
    • updated example code (you can see that highlighted at end of this post).
    • bugfix deleted two IE-killer commas.
    • example code extracted to here from code
    • bugfix added an extra checking to setRawValue() method
    • feature added mode=local to default combo config for usability reasons
    [2009 May, 23]
    • comboConfig now supports user specified xtype for specifing any ComboBox-derived control in there (for example my ComboGrid solution )
    .
    Actual code base:
    PHP Code:
    /**
     * Ext.sm.Form.CheckboxSelect - ExtJS Library for sYs-mini SDK
     * 
     * For any licensing informations ask licensing@extjs.com or visit
     * http://extjs.com/license
     * 
     * @author Csaba Dobai (prometheus) <fejlesztes@php-sparcle.hu>
     * @copyright All rights reserved by author, based on ExtJS 3.0 licensing!
     */

    Ext.namespace('Ext.sm.Form');

    /**
     * @class Ext.sm.Form.CheckboxSelect
     * @extends Ext.Panel
     * <p><b>Represent a composite control to realize special multiselection.</b></p>
     * <p>This control displays an Ext.form.ComboBox, and a panel below the combobox.
     * If you select an item from the combobox, a checked checkbox appears within the
     * panel. User can uncheck a checkbox, then checkbox disappears (going to remove).</p>
     * <p>You can configure fully the ComboBox as usual within the {@link #comboConfig}.
     * Checkboxes are displayed in columns, next to each other. On default the control
     * has three columns for that, but you can override this by set the {@link #checkboxColumns}
     * configuration setting. Checkbox values parsed as array of values. For example you
     * have a ComboBox with items ['first'='One', 'second'='Two'] (value=text) and {@link name}
     * has the value 'numbers' - now if you select all items, you have two checkboxes on
     * the form, the parsed result is similar: <i>...numbersItem[]=first&numbersItem[]=second</i>.</p>
     * <p>The code below illustrates how the component works:</p><pre><code>
    var win = new Ext.Window({
        title : 'Test',
        items : [{
            xtype : 'form',
            autoHeight : true,
            ctCls: 'testForm',
            items : [{
                xtype : 'checkboxselect',
                name : 'numbers',
                hiddenName: 'numbersRaw',
                fieldLabel : 'Test',
                comboConfig : {
                    store : [['1', 'One'], ['2', 'Two'], ['3', 'Three'], ['4', 'Four']]
                }
            }],
            buttons: [{
                text: 'Save',
                handler: function()
                {
                    var fp = this.findParentByType('form');

                    if(fp.getForm().isValid()){
                        Ext.Msg.alert('Submitted Values', 'The following values could get by the server: <br />'+
                            fp.getForm().getValues(true));
                    }
                }
            }]
        }],
        listeners: {
            afterrender: function(self)
            {
                self.find('ctCls', 'testForm')[0].load({
                    url: '/cstest.php'
                });
            }
        }
    });

    win.show();
    </code></pre></p>
     */
    Ext.sm.Form.CheckboxSelect Ext.extend(Ext.Panel, {
        
    /**
         * @cfg {String} cls A custom CSS class to apply to the field's underlying
         * element (defaults to ""). Mapped to ComboBox.
         */

        /**
         * @cfg {String} fieldClass The default CSS class for the field (defaults
         * to "x-form-field"). Mapped to ComboBox.
         */

        /**
         * @cfg {String} focusClass The CSS class to use when the field receives
         * focus (defaults to "x-form-focus"). Mapped to ComboBox.
         */

        /**
         * @cfg {String} invalidClass The CSS class to use when marking a field
         * invalid (defaults to "x-form-invalid").
         */
        
    invalidClass'x-form-invalid',

        
    /**
         * @cfg {String} invalidText The error text to use when marking a field
         * invalid and no message is provided (defaults to "The value in this field
         * is invalid"). Mapped to ComboBox.
         */

        /**
         * @cfg {String} msgFx <b>Experimental</b> The effect used when displaying a
         * validation message under the field (defaults to 'normal').
         */
        
    msgFx'normal',

        
    /**
         * @cfg {String} msgTarget The location where error text should display.
         * Should be one of the following values (defaults to 'qtip'):
         * <pre>
    Value         Description
    -----------   ----------------------------------------------------------------------
    qtip          Display a quick tip when the user hovers over the field
    title         Display a default browser title attribute popup
    under         Add a block div beneath the field containing the error text
    side          Add an error icon to the right of the field with a popup on hover
    [element id]  Add the error text directly to the innerHTML of the specified element
    </pre>
         */
        
    msgTarget 'qtip',

        
    /**
         * @cfg {String} name Name of Ext.form.Checkbox components. A
         * default 'unnamed' set, but you must change this if you want a normal result
         * on the server-side, or use this field by form load.
         */
        
    name'unnamed',

        
    /**
         * @cfg {Boolean} readOnly True to mark the field as readOnly in HTML
         * (defaults to false) -- Note: this only sets the element's readOnly DOM
         * attribute. <b>This is mapped to all subfields!</b>
         */
        
    readOnly false,

        
    /**
         * @cfg {Number} tabIndex The tabIndex for this field. Note this only
         * applies to fields that are rendered, not those which are built via
         * applyTo (defaults to undefined). Mapped to ComboBox.
         */

        /**
         * @cfg {Boolean} validateOnBlur Whether the field should validate when
         * it loses focus (defaults to true). Mapped to ComboBox.
         */

        /**
         * @cfg {String/Boolean} validationEvent The event that should initiate
         * field validation. Set to false to disable automatic validation (defaults
         * to "keyup"). Mapped to ComboBox.
         */

        /**
         * @cfg {Mixed} value A value to initialize this field with (defaults to
         * undefined). Mapped to ComboBox.
         */

        // private - indicates that this is a form field for BasicForm.
        
    isFormFieldtrue,

        
    // private
        
    originalValue null,

        
    // private
        
    comboConfigDefault : {
            
    xtype'combo',
            
    typeAhead true,
            
    forceSelection true,
            
    triggerAction "all",
            
    selectOnFocus :true,
            
    mode'local'
        
    },
        
        
    // private
        
    cbpanelConfigDefault : {
            
    xtype "panel",
            
    border false,
            
    layout 'column'
        
    },
        
        
    // private
        
    cbpanelColConfig : {
            
    defaultType 'checkbox',
            
    layout 'form',
            
    border false,
            
    defaults : {
                
    hideLabel true,
                
    anchor '100%'
            
    }
        },
        
        
    // private
        
    combo null,
        
        
    // private
        
    checkboxPanel null,

        
    // private
        
    privateValueField null,

        
    /**
         * @cfg {String} hiddenName
         * This is the name of used hidden field for storing raw value for correctly
         * submitting this field. If this has an empty (null, undefined, etc) value,
         * hidden field will not created. Default is undefined.
         */
        
        /**
         * @cfg {Object} comboConfig
         * This is the config of component`s ComboBox, here you can set the fieldLabel and
         * store etc on it. Default settings are: typeAhead=true, forceSelection=true.
         */
        
    comboConfig : {},
        
        
    /**
         * @cfg {Integer} checkboxColumns
         * Number of columns in checkbox display panel. Default is 3.
         */
        
    checkboxColumns 3,
        
    /**
         * @cfg {String/Object} layout
         * Layout is fixed to 'form', because this panel is going to a FormPanel
         * component now.
         */
        
        // private
        
    lastColIdx 0,
        
        
    // private
        
    initComponent : function()
        {
            var 
    comboConfig = (this.comboConfig == undefined ? {} : this.comboConfig);
            var 
    colCfg;
            var 
    columns = [];
            
            
    Ext.sm.Form.CheckboxSelect.superclass.initComponent.call(this);
            
    this.border false;
            
            
    // combo
            
    this.mapToCombo();
            
    comboConfig Ext.applyIf(comboConfigthis.comboConfigDefault);
            
    this.combo = new Ext.ComponentMgr.create(comboConfig);
            
            
    // checkbox panel
            
    for (var i=0i<this.checkboxColumnsi++)
            {
                
    colCfg Ext.apply({}, this.cbpanelColConfig);
                
    columns.push(colCfg);
            }
            
    Ext.apply(this.cbpanelConfigDefault, {
                
    layoutConfig : {columns this.checkboxColumns},
                
    items columns
            
    });
            
    this.checkboxPanel = new Ext.Panel(this.cbpanelConfigDefault);
            
            
    // listener
            
    this.combo.on('select', function(selfrecordindex){this.onComboSelect(selfrecordindex)}.createDelegate(this));

            
    // add to me
            
    this.add(this.combo);
            
    this.add(this.checkboxPanel);
        },

        
    // private
        
    onComboSelect : function(selfrecordindex)
        {
            var 
    vf this.combo.valueField;
            var 
    df this.combo.displayField;
            
            
    this.addCheckbox(record.data[df], record.data[vf]);

            return 
    true;
        },

        
    // private
        
    addCheckbox : function(textvalue)
        {
            var 
    cb;
            var 
    p;

            if (
    this.checkboxPanel.find('value'value).length == 0)
            {
                
    this.getColumnNext();
                
    cb = new Ext.form.Checkbox({
                    
    boxLabel text,
                    
    name this.name '[]',
                    
    valuevalue,
                    
    inputValue value,
                    
    checked true
                
    });
                
    cb.on('check', function(selfchecked){this.onCheckboxCheck(selfchecked)}.createDelegate(this));
                
    p.add(cb);
                
    p.bubble(function(){this.render(); return true;});
            }
        },
        
        
    // private
        
    onCheckboxCheck : function(selfchecked)
        {
            if (!
    checked)
            {
                
    this.removeCheckbox(self);
            }
        },
        
        
    /**
         * Removes the passed checkbox from the panel and reorders the other.
         * @param {Component} cb The checkbox to remove.
         */
        
    removeCheckbox : function(cb)
        {
            var 
    cbColList = [];
            var 
    cbConfigList = [];
            var 
    p;
            var 
    i0;
            var 
    maxLength 0;
            var 
    cbi;
            
            
    // Clone all checkbox components in order, except the removed one.
            
    for (var i=0i<this.checkboxColumnsi++)
            {
                
    cbColList.push(this.checkboxPanel.get(i).findByType('checkbox'));
            }
            for (var 
    i=0i<cbColList.lengthi++)
            {
                if (
    maxLength cbColList[i].lengthmaxLength cbColList[i].length;
            }
            for (var 
    i=0i<maxLengthi++)
            {
                for (var 
    j=0j<this.checkboxColumnsj++)
                {
                    
    cbi this.checkboxPanel.get(j).get(i);
                    if (
    cbi !== undefined && cbi.getId() != cb.getId())
                    {
                        
    cbConfigList.push(cbi.cloneConfig());
                    }
                }
            }
            
            
    // Remove checkboxes from all columns.
            
    this.removeAllCheckboxes();

            
    // recreate all checkboxes
            
    this.lastColIdx 0;
            for (var 
    i=0i<cbConfigList.lengthi++)
            {
                
    this.getColumnNext();
                
    cbConfigList[i].on('check', function(selfchecked){this.onCheckboxCheck(selfchecked)}.createDelegate(this));
                
    p.add(cbConfigList[i]);
                
    p.bubble(function(){this.render(); return true;});
            }
        },

        
    // private
        
    removeAllCheckboxes: function()
        {
            for (var 
    i=0i<this.checkboxColumnsi++)
            {
                
    this.checkboxPanel.get(i).removeAll();
            }
        },
        
        
    // private
        
    getColumnNext : function()
        {
            var 
    key this.lastColIdx;
            
            
    this.lastColIdx++;
            if (
    this.lastColIdx >= this.checkboxColumnsthis.lastColIdx 0;
            
            return 
    this.checkboxPanel.get(key);
        },
        
        
    /**
         * Returns selected items` values in array.
         * @return {Array}
         */
        
    getSelectedValues : function()
        {
            var 
    result = [];
            var 
    chs;
            
            
    chs this.checkboxPanel.findByType('checkbox');
            for (var 
    i=0i<chs.lengthi++)
            {
                
    result.push(chs[i].inputValue);
            }
            
            return 
    result;
        },

        
    //***
        // Now implementing necessary Ext.form.Field methods.
        //
        
        /**
         * Clear any invalid styles/messages for this field. Mapped to ComboBox.
         */
        
    clearInvalid : function()
        {
            
    this.combo.clearInvalid();
        },

        
    /**
         * Returns the name attribute of the field if available.
         * @return {String} name The field {@link Ext.form.Field#name name} or {@link Ext.form.ComboBox#hiddenName hiddenName}
         */
        
    getName : function()
        {
            return (
    Ext.isEmpty(this.name)? null this.name);
        },

        
    /**
         * Returns the raw data value which may or may not be a valid, defined value.
         * To return a normalized value see {@link #getValue}. This value on this field
         * is a dynamic set of values like 'value[]=1&value[]=2&value[]=3'.
         * @return {String} value The field value
         */
        
    getRawValue : function()
        {
            var 
    this.getSelectedValues();
            var 
    ra = [];
            var 
    result;

            if (
    this.rendered)
            {
                for (var 
    i=0i<v.lengthi++)
                {
                    
    ra.push(this.name '[]=' v[i]);
                }
            }

            
    result = (ra.length == 0'' ra.join('&'));

            return 
    result;
        },

        
    /**
         * Returns the normalized data value (undefined or emptyText will be returned
         * as ''). To return the raw value see {@link #getRawValue}.
         * @return {String} value The field value
         */
        
    getValue : function()
        {
            return 
    this.getRawValue();
        },

        
    /**
         * <p>Returns true if the value of this Field has been changed from its original value,
         * and is not disabled.</p>
         * <p>Note that if the owning {@link Ext.form.BasicForm form} was configured with
         * {@link Ext.form.BasicForm}.{@link Ext.form.BasicForm#trackResetOnLoad trackResetOnLoad}
         * then the <i>original value</i> is updated when the values are loaded by
         * {@link Ext.form.BasicForm}.{@link Ext.form.BasicForm#setValues setValues}.</p>
         * @return {Boolean} True if this field has been changed from its original value (and
         * is not disabled), false otherwise.
         */
        
    isDirty : function()
        {
            if (
    this.disabled)
            {
                return 
    false;
            }

            return 
    String(this.getValue()) !== String(this.originalValue);
        },

        
    /**
         * Returns whether or not the field value is currently valid. Mapped to ComboBox.
         * @param {Boolean} preventMark True to disable marking the field invalid
         * @return {Boolean} True if the value is valid, else false
         */
        
    isValid : function(preventMark)
        {
            return 
    this.combo.isValid(preventMark);
        },

        
    /**
         * Mark this field as invalid, using {@link #msgTarget} to determine how to
         * display the error and applying {@link #invalidClass} to the field's element.
         * @param {String} msg (optional) The validation message (defaults to {@link #invalidText})
         */
        
    markInvalid : function(msg)
        {
            var 
    mtt;

            if (!
    this.rendered || this.preventMark// not rendered
            
    {
                return;
            }

            
    msg msg || this.invalidText;
            
    mt this.getMessageHandler();
            if (
    mt)
            {
                
    mt.mark(thismsg);
            }
            else if (
    this.msgTarget)
            {
                
    this.el.addClass(this.invalidClass);
                
    Ext.getDom(this.msgTarget);
                if (
    t)
                {
                    
    t.innerHTML msg;
                    
    t.style.display this.msgDisplay;
                }
            }

            
    // TODO: events implementation.
            //this.fireEvent('invalid', this, msg);
        
    },

        
    /**
         * Resets the current field value to the originally loaded value and clears
         * any validation messages.
         * See {@link Ext.form.BasicForm}.{@link Ext.form.BasicForm#trackResetOnLoad trackResetOnLoad}
         */
        
    reset : function()
        {
            
    this.clearInvalid();
            
    this.combo.reset();
            
    this.removeAllCheckboxes();
            
    this.setValue(this.originalValue);
        },

        
    /**
         * Sets a data value into the field and validates it. To set the value directly
         * without validation see {@link #setRawValue}. Applied values are type of
         * String and Array.
         * @param {String/Array} value The value to set
         * @return {Ext.form.Field} this
         */
        
    setValue : function(value)
        {
            
    this.value '';

            if (!
    Ext.isEmpty(value))
            {
                
    this.value this.valueIfArray(value);
            }

            if (
    this.rendered)
            {
                
    this.setRawValue(this.value);
                
    this.validate();
            }

            return 
    this;
        },

        
    /**
         * Sets the values by creating all checkboxes that are existed by combo`s
         * store, bypassing validation. To set the value with validation see {@link #setValue}.
         * @param {String/Array} value The value to set
         * @return {String} value The field value that is set
         */
        
    setRawValue : function(value)
        {
            var 
    va = [];
            var 
    vivdr;
            var 
    vf this.combo.valueField;
            var 
    df this.combo.displayField;
            var 
    result;

            if (!
    Ext.isEmpty(value))
            {
                
    va this.valueIfArray(value).split('&');
            }

            if (
    this.combo.store && this.combo.store.getCount() == 0this.combo.store.load();

            for (var 
    i=0i<va.lengthi++)
            {
                
    vi va[i].split('=');
                
    = (vi.length == 1'' vi[1]); // if has no value for this item.
                
    dr this.combo.findRecord(vfv);

                
    this.addCheckbox(dr.data[df], v);
            }

            
    result this.getValue();

            if (!
    Ext.isEmpty(this.hiddenName))
            {
                if (
    Ext.isEmpty(this.privateValueField))
                {
                    
    this.privateValueField = new Ext.form.Hidden({
                        
    namethis.hiddenName,
                        
    valueresult,
                        
    inputValueresult
                    
    });
                    
    this.add(this.privateValueField);
                }
                else
                {
                    
    this.privateValueField.setValue(result);
                }
            }

            return 
    result;
        },

        
    /**
         * Validates the field value. Mapped to ComboBox.
         * @return {Boolean} True if the value is valid, else false
         */
        
    validate : function()
        {
            return 
    this.combo.validate();
        },

        
    // private
        
    afterRender : function()
        {
            
    Ext.sm.Form.CheckboxSelect.superclass.afterRender.call(this);
            
    // TODO: This is the place for initEvents() if needed.
            //this.initEvents();
            
    this.initValue();
        },

        
    // private
        
    initValue : function()
        {
            if (
    this.value !== undefined)
            {
                
    this.setValue(this.value);
            }
            else
            {
                
    this.setValue(this.getValue());
            }
            
    // reference to original value for reset
            
    this.originalValue this.getValue();
        },

        
    // private
        
    getMessageHandler : function()
        {
            return 
    Ext.form.MessageTargets[this.msgTarget];
        },

        
    // private
        
    valueIfArray : function(value)
        {
            var 
    result value;
            var 
    ri;
            var 
    ra = [];

            if (
    Ext.isArray(value) && !Ext.isEmpty(value[0]))
            {
                for (var 
    i=0i<value.lengthi++)
                {
                    
    ri this.name '[]=' value[i];
                    
    ra.push(ri);
                }
                
    result ra.join('&');
            }

            return 
    result;
        },

        
    // private
        
    mapToCombo : function()
        {
            var 
    toMap = [
                
    'cls',
                
    'fieldClass',
                
    'focusClass',
                
    'invalidText',
                
    'tabIndex',
                
    'validateOnBlur',
                
    'validationEvent',
            ];

            for (var 
    i=0i<toMap.lengthi++)
            {
                if (
    this[toMap[i]] !== undefinedthis.comboConfigDefault[toMap[i]] = this[toMap[i]];
            }
        }
    });

    Ext.reg('checkboxselect'Ext.sm.Form.CheckboxSelect); 
    Example that demonstrated the magic of using:
    PHP Code:
    var win = new Ext.Window({
        
    title 'Test',
        
    items : [{
            
    xtype 'form',
            
    autoHeight true,
            
    ctCls'testForm',
            
    items : [{
                
    xtype 'checkboxselect',
                
    name 'numbers',
                
    hiddenName'numbersRaw',
                
    fieldLabel 'Test',
                
    comboConfig : {
                    
    store : [['1''One'], ['2''Two'], ['3''Three'], ['4''Four']]
                }
            }],
            
    buttons: [{
                
    text'Save',
                
    handler: function()
                {
                    var 
    fp this.findParentByType('form');

                    if(
    fp.getForm().isValid()){
                        
    Ext.Msg.alert('Submitted Values''The following values could get by the server: <br />'+
                            
    fp.getForm().getValues(true));
                    }
                }
            }]
        }],
        
    listeners: {
            
    afterrender: function(self)
            {
                
    self.find('ctCls''testForm')[0].load({
                    
    url'/cstest.json'
                
    });
            }
        }
    });

    win.show(); 
    Content of cstest.json is:
    Code:
    {"success":true,"data":{"numbers":[1,3]}}
    Any bugreports, replies or comments are welcomed!


    Regards,
    Attached Images

film izle

hd film izle

film sitesi

takipci kazanma sitesi

takipci kazanma sitesi

güzel olan herşey

takipci alma sitesi

komik eğlenceli videolar