Hybrid View

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

      1  

    Arrow [3.0] ComboGrid (a combobox variant)

    [3.0] ComboGrid (a combobox variant)


    Hello, this is just me again with another eXtension. This component is a simply solution for a combobox which using grid (or any grid-class component) instead of standard selection list (dataview or descendants) to display the attached store`s records. With a grid the number of usability would muliplies than original implementation. All of this possible by some simple overrides based on the original code and with some new features to better fit to component`s goal:
    • You can easily define your columns in that config option but component has its own default to working properly.
    • You can define a callback function in the component`s scope to generate the standard XTemplate for display cell - this able you to use config option values or properties in template. This is just if you using the standard (built-in) columns.
    • You have a fully preconfigured view for grid but you able to override all of the settings one by one, eighter the xtype so you can use any grid descendant component which have registered xtype!
    .
    Warning! I`m only used this on FF3, but I hope that will not causing problems on other browsers.

    Updates:
    • [2009 May, 23] Many bugfixes applied that are goals that this component will able to use with editorgrid in the dropped box layout.
    • [2009 Jun, 29] Some bugfixes applied.
    .
    Tips
    :
    • If you use ComboGrid with EditorGridPanel it is highly recommended to set lazyInit to true.
    .
    Here is the code:
    Code:
    /**
     * Ext.sm.Form.ComboGrid - 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!
     */
    
    /**
     * @namespace Ext.sm.Form
     */
    Ext.namespace('Ext.sm.Form');
    
    /**
     * @component
     * @class Ext.sm.Form.ComboGrid
     * @extends Ext.form.ComboBox
     * <p>This is a specialized combobox which uses grid component to dropdown
     * instead of DataView. This one is to power-up the combobox usability for example
     * with EditorGridPanel or multiple columns instead of template hacking, or with
     * enabling column headers to use ordering, etc.</p>
     * <code><pre>
    var win = new Ext.Window({
    	title : 'Test',
    	items : [{
    		xtype : 'form',
    		autoHeight : true,
    		ctCls: 'testForm',
    		items : [{
    			xtype: 'combogrid',
    			store : [['1', 'One'], ['2', 'Two'], ['3', 'Three'], ['4', 'Four']],
    			columns: [
    				{id: 'value', hidden: true, sortable: false},
    				{
    					id: 'text',
    					dataIndex: 'text',
    					sortable: true,
    					tpl: '<tpl for="."><div class="x-combo-list-item">{text}</div></tpl>',
    					editor: new Ext.form.TextField({
    						allowBlank: false
    					})
    				}
    			],
    			name: 'cgtest',
    			hiddenName: 'cgtest',
    			fieldLabel: 'ComboGrid',
    			typeAhead : true,
    			forceSelection : true,
    			triggerAction : "all",
    			selectOnFocus :true,
    			mode: 'local',
    			selectEvent: 'dblclick',
    			pageSize: 4,
    			view: {
    				xtype: 'editorgrid',
    				clicksToEdit: 1
    			}
    		}],
    		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();
    </pre></code>
     */
    Ext.sm.Form.ComboGrid = Ext.extend(Ext.form.ComboBox, {
    	/**
    	 * @cfg {Array} columns <p>An array of {@link Ext.grid.Column columns} to auto
    	 * create a {@link Ext.grid.ColumnModel}. The ColumnModel may be explicitly
    	 * created via the <tt>{@link Ext.grid.GridPanel#colModel}</tt> configuration
    	 * property in {@link #view}.</p>
    	 * <b>Note:</b> A default column specification generated by ComboGrid. you
    	 * must be careful if you override this setting. In the view config, you`re
    	 * able to override the view`s xtype - for example to 'editorgrid' - therefore
    	 * you can specify editor controls in here for columns.
    	 */
    
    	/**
    	 * @cfg {String} selectEvent <p>This specifies that what kind of event will
    	 * cause item selection. Default is 'click'.</p>
    	 * <b>Tipp:</b> If you override the {@link #view} (grid) xtype to 'editorgrid'
    	 * change this setting to 'dblclick' then specify {@link Ext.grid.EditorGridPanel#clicksToEdit clicksToEdit}
    	 * for view to 1. This is a workaround for usability conflicts.
    	 */
    	selectEvent: 'click',
    
    	/**
    	 * @cfg {String/Ext.XTemplate} tpl
    	 * <b>Note:</b> This setting mapped to the view by default to its
    	 * {@link Ext.grid.TemplateColumn TemplateColumn} - so if you override the
    	 * grid`s column settings, this option will unhandled!
    	 * <p>The template string, or {@link Ext.XTemplate} instance to use to
    	 * display each item in the dropdown list. The dropdown list is displayed in
    	 * a DataView. See {@link #view}.</p>
    	 * <p>The default template string is:</p><pre><code>
    	   '&lt;tpl for=".">&lt;div class="x-combo-list-item">{' + this.displayField + '}&lt;/div>&lt;/tpl>'
    	 * </code></pre>
    	 * <p>Override the default value to create custom UI layouts for items in
    	 * the list. For example:</p><pre><code>
    	   '&lt;tpl for=".">&lt;div ext:qtip="{state}. {nick}" class="x-combo-list-item">{state}&lt;/div>&lt;/tpl>'
    	 * </code></pre>
    	 * <p>The template <b>must</b> contain one or more substitution parameters
    	 * using field names from the Combo's</b> {@link #store Store}. In the
    	 * example above an <pre>ext:qtip</pre> attribute is added to display other
    	 * fields from the Store.</p>
    	 * <p>To preserve the default visual look of list items, add the CSS class
    	 * name <pre>x-combo-list-item</pre> to the template's container element.</p>
    	 * <p>Also see {@link #itemSelector} for additional details.</p>
    	 */
    
    	/**
    	 * @cfg {String} valueTitle This option specifies the display title of
    	 * grid`s column header. Header being hidden if this setting is empty. You
    	 * can fully override this options working in the {@link #view} option.
    	 * Default is empty.
    	 */
    	valueTitle: '',
    
    	/**
    	 * @cfg {Component/Config} view This redefined config option now specifies
    	 * a {@link Ext.grid.GridPanel Grid} component (or any GridPanel descendant)
         * based on xtype.
    	 */
    	view: null,
    
    	/**
    	 * @cfg {Function} defaultTpl
    	 * Now you can specify a callback function to generate the {@link #tpl}
    	 * option`s default value. No parameters passed but scope is 'this'. You must
    	 * return a valid XTemplate string or an XTemplate definitoin string.
    	 */
    	defaultTpl: function()
    	{
    		return '<tpl for="."><div class="x-combo-list-item">{' + this.displayField + '}</div></tpl>';
    	},
    
    	// private - overrided
    	initComponent: function()
    	{
    		this.lazyInit = false
    		this.inEditMode = false;
    		Ext.sm.Form.ComboGrid.superclass.initComponent.call(this);
    	},
    
    	// private - this will generate default config for view
    	defaultView: function()
    	{
    		var cols = [
    			{id: this.valueField, dataIndex: this.valueField, hidden: true, sortable: false},
    			{id: this.displayField, dataIndex: this.displayField, sortable: true, header: this.valueTitle, tpl: this.tpl}
    		];
    		
    		return {
    			xtype: 'grid',
    			applyTo: this.innerList,
    			store: this.store,
    			cm: new Ext.grid.ColumnModel({
    				columns: (Ext.isEmpty(this.columns)? cols : this.columns),
    				defaults: {
    					hideable: false,
    					menuDisabled: true
    				},
    				xtype: 'templatecolumn'
    			}),
    			viewConfig: {
    				forceFit: true,
    				headersDisabled: Ext.isEmpty(this.valueTitle),
    				emptyText: this.listEmptyText,
    				scrollOffset: 0
    			},
    			sm: new Ext.grid.RowSelectionModel({moveEditorOnEnter: false}),
    			frame: false,
    			height: (this.minHeight + 5),
    			autoHeight: true
    		};
    	},
    
    	// private - overrided
    	bindStore : function(store, initial)
    	{
    		if (this.store && !initial)
    		{
    			this.store.un('beforeload', this.onBeforeLoad, this);
    			this.store.un('load', this.onLoad, this);
    			this.store.un('loadexception', this.collapse, this);
    			if (this.store !== store && this.store.autoDestroy)
    			{
    				this.store.destroy();
    			}
    
    			if (!store)
    			{
    				this.store = null;
    			}
    		}
    		if (store)
    		{
    			if (!initial)
    			{
    				this.lastQuery = null;
    				if (this.pageTb)
    				{
    					this.pageTb.bindStore(store);
    				}
    			}
    
    			this.store = Ext.StoreMgr.lookup(store);
    			this.store.on('beforeload', this.onBeforeLoad, this);
    			this.store.on('load', this.onLoad, this);
    			this.store.on('loadexception', this.collapse, this);
    
    			if (this.view)
    			{
    				this.view.view.refresh();
    			}
    		}
    	},
    
    	// private - overrided to create a grid instead of a DataView
    	initList: function()
    	{
    		var cls = 'x-combo-list';
    
    		if (!this.list)
    		{
    			// Begin of copy-paste
    			this.list = new Ext.Layer({
    				parentEl: this.getListParent(),
    				shadow: this.shadow,
    				cls: [cls, this.listClass].join(' '),
    				constrain:false
    			});
    
    			var lw = this.listWidth || Math.max(this.wrap.getWidth(), this.minListWidth);
    			this.list.setSize(lw, 0);
    			this.list.swallowEvent('mousewheel');
    			this.assetHeight = 0;
    			if(this.syncFont !== false){
    				this.list.setStyle('font-size', this.el.getStyle('font-size'));
    			}
    			if(this.title){
    				this.header = this.list.createChild({cls:cls+'-hd', html: this.title});
    				this.assetHeight += this.header.getHeight();
    			}
    
    			this.innerList = this.list.createChild({cls:cls+'-inner'});
    			this.mon(this.innerList, 'mouseover', this.onViewOver, this);
    			this.mon(this.innerList, 'mouseout', this.onViewOut, this); // this one is mine :)
    			this.mon(this.innerList, 'mousemove', this.onViewMove, this);
    			this.innerList.setWidth(lw - this.list.getFrameWidth('lr'));
    
    			if(this.pageSize){
    				this.footer = this.list.createChild({cls:cls+'-ft'});
    				this.pageTb = new Ext.PagingToolbar({
    					store: this.store,
    					pageSize: this.pageSize,
    					renderTo:this.footer
    				});
    				this.assetHeight += this.footer.getHeight();
    			}
    			// End of copy-paste
    
    			if (Ext.isEmpty(this.tpl)) this.tpl = this.defaultTpl.call(this);
    			if (Ext.isEmpty(this.view)) this.view = {};
    			if (!(this.view instanceof Ext.Component))
    			{
    				this.view = Ext.applyIf(this.view, this.defaultView());
    				this.view = Ext.ComponentMgr.create(this.view);
    			}
    			if (this.view instanceof Ext.grid.EditorGridPanel)
    			{
    				this.view.on('beforeedit', this.onViewBeforeEdit, this);
    			}
    
    			// Begin of copy-paste
    			this.mon(this.view, this.selectEvent, this.onViewClick, this);
    			this.view.on('keydown', this.onViewKeyDown, this); // this one is mine :)
    
    			this.bindStore(this.store, true);
    
    			if(this.resizable){
    				this.resizer = new Ext.Resizable(this.list,  {
    				   pinned:true, handles:'se'
    				});
    				this.mon(this.resizer, 'resize', function(r, w, h){
    					this.maxHeight = h-this.handleHeight-this.list.getFrameWidth('tb')-this.assetHeight;
    					this.listWidth = w;
    					this.innerList.setWidth(w - this.list.getFrameWidth('lr'));
    					this.restrictHeight();
    				}, this);
    
    				this[this.pageSize?'footer':'innerList'].setStyle('margin-bottom', this.handleHeight+'px');
    			}
    			// End of copy-paste
    		}
    	},
    
        // private - overrided
        onLoad : function(){
    		if (this.view && this.view.view)
    		{
    			this.innerList.update('');
    			this.view.view.refresh();
    			this.view.body.appendTo(this.innerList);
    		}
    		Ext.sm.Form.ComboGrid.superclass.onLoad.call(this);
        },
    
    	// private - overrided, updated
    	onViewOver : function(e, t)
    	{
    		if(this.inKeyMode || this.inEditMode) // prevent key nav and mouse over conflicts
    		{
    			return;
    		}
    		var v = this.view.getView();
    		var index = v.findRowIndex(t);
    		var row = v.findRow(t);
    		var r, rs;
    		var cls = 'x-grid3-cell-selected';
    
    		if (index !== false)
    		{
    			rs = this.view.getEl().query('.'+cls);
    			Ext.each(rs, function(i){Ext.get(i).removeClass(cls);});
    			r = Ext.get(row);
    			if (!r.hasClass(cls)) {
    				r.addClass(cls);
    		        this.selectedIndex = index;
    			}
    		}
    	},
    
    	// private - new handler
    	onViewOut: function()
    	{
    		if (!this.inEditMode)
    		{
    			var v = this.view.getView();
    			var cls = 'x-grid3-cell-selected';
    			var rs;
    
    			rs = this.view.getEl().query('.'+cls);
    			Ext.each(rs, function(i){Ext.get(i).removeClass(cls);});
    			this.select(this.selectedIndex, false, this.hasFocus);
    		}
    	},
    
    	// private
    	onViewClick : function(doFocus)
    	{
    		var r = this.store.getAt(this.selectedIndex);
    
    		if (r)
    		{
    			this.onSelect(r, this.selectedIndex);
    		}
    		if (doFocus !== false)
    		{
    			this.el.focus();
    		}
    	},
    
    	// private - if view got focus, emulates original navigation.
    	onViewKeyDown: function(e)
    	{
    		switch (e.getKey())
    		{
    			case e.ENTER:
    			{
    				this.keyNav['enter'].call(this, e);
    				break;
    			}
    			case e.ESC:
    			{
    				this.keyNav['esc'].call(this, e);
    				break;
    			}
    			case e.TAB:
    			{
    				this.keyNav['tab'].call(this, e);
    				break;
    			}
    		}
    		e.stopEvent();
    		return false;
    	},
    
        /**
         * Select an item in the dropdown list by its numeric index in the list.
    	 * This function does NOT cause the select event to fire. The store must be
    	 * loaded and the list expanded for this function to work, otherwise use
    	 * setValue.
         * @param {Number} index The zero-based index of the list item to select
         * @param {Boolean} scrollIntoView False to prevent the dropdown list from
    	 * autoscrolling to display the selected item if it is not currently in view
    	 * (defaults to true)
    	 * @param {Boolean} focus Optional. If true, focus sets on textfield after
    	 * select.
         */
        select : function(index, scrollIntoView, focus)
    	{
    		var sm = this.view.getSelectionModel();
    		
            this.selectedIndex = index;
    
    		if (sm instanceof Ext.grid.RowSelectionModel)
    		{
    			sm.selectRow(Ext.isArray(index)? index[0] : index);
    		}
    		else if (sm instanceof Ext.grid.CellSelectionModel)
    		{
    			sm.select(
    				Ext.isArray(index)? index[0] : index
    			,
    				Ext.isArray(index)? index[1] : 1
    			);
    		}
    
            if (scrollIntoView !== false)
    		{
                var el = this.view.getView().getRow(index);
                if (el)
    			{
                    this.innerList.scrollChildIntoView(el, false);
                }
            }
    
    		if (focus !== undefined && focus === true) this.focus();
        },
    
    	onViewBeforeEdit: function(o)
    	{
    		var ce = o.grid.getColumnModel().getCellEditor(o.column, o.row);
    
    		ce.un('hide', this.onViewAfterEdit, this);
    		ce.on('hide', this.onViewAfterEdit, this);
    		this.inEditMode = true;
    	},
    
    	onViewAfterEdit: function()
    	{
    		this.inEditMode = false;
    	}
    });
    
    Ext.reg('combogrid', Ext.sm.Form.ComboGrid);

  2. #2
    Sencha User
    Join Date
    Apr 2009
    Posts
    87
    Vote Rating
    1
    mabra is on a distinguished road

      0  

    Default ComboGrid:Sounds eciting, but I cannot make it running

    ComboGrid:Sounds eciting, but I cannot make it running


    Hi !

    I am not able to make it running, got always errors and the form does not appear ... Could you please provide a html page too? Additionally:What does the PHP file sends [structure]? I am too new to ext - especially to that depth of javascript knowledge, to find the problem. I am using ext 3.0 rc2 and tried that part of code from your introductionary material on top of the combogrid class.

    Thanks a lot.

    br--mabra

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

      0  

    Default


    Hi and thanks for trying out and respond, I`m busy at work very hard but as soon as possible I planed to starting a demosite with all my components and other Ext related stuffs. I`m try to update the above source now because I made some modifications on that code, so please retry again and if do not worked anyway please be patient a little to my demosite startup day (this is within 1 week, I`m hope so that).
    This component tested at RC1.1 with FF3, I does not tryed out RC2 deeply enough so I don`t knowing how my component works with it.

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

      0  

    Default


    Now code is up to date. ComboGrid needs JSON result on load like a normal ComboBox, for example:
    Code:
    {"success":true,"data":{"cgtest":"1"}}
    Copy this raw JSON to cgtest.json and move to docroot, rename the cgtest.php in the example code to cgtest.json and retry. If not working there is a version conflict with RC2 maybe.

  5. #5
    Sencha User emredagli's Avatar
    Join Date
    Jun 2008
    Posts
    300
    Vote Rating
    2
    emredagli is on a distinguished road

      0  

    Default


    Has any body try it in IE8.0?
    Grid could not be shown in IE8.0.

    If anybody know solution please reply.

  6. #6
    Sencha User
    Join Date
    Mar 2011
    Posts
    1
    Vote Rating
    0
    pranama1 is on a distinguished road

      0  

    Default


    Great Control! But how do we fix this in IE8, I dont see the grid at all.. Any advice would be hugely beneficial..

  7. #7
    Ext JS Premium Member
    Join Date
    Oct 2009
    Posts
    4
    Vote Rating
    0
    innerbreath is on a distinguished road

      0  

    Default Fixed for IE?

    Fixed for IE?


    Hi,

    was anyone able to get this working in IE?

    Thanks!

Turkiyenin en sevilen filmlerinin yer aldigi xnxx internet sitemiz olan ve porn sex tarzi bir site olan mobil porno izle sitemiz gercekten dillere destan bir durumda herkesin sevdigi bir site olarak tarihe gececege benziyor. Sitenin en belirgin ozelliklerinden birisi de Turkiyede gercekten kaliteli ve muntazam, duzenli porno izle siteleri olmamasidir. Bu yuzden iste. Ayrica en net goruntu kalitesine sahip adresinde yayinlanmaktadir. Mesela diğer sitelerimizden bahsedecek olursak, en iyi hd porno video arşivine sahip bir siteyiz. "The Best anal porn videos and slut anus, big asses movies set..." hd porno faketaxi