X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/ee06f37b0f6f6d94cd05a6ffae556660f7c4a2bc..c930e9176a5a85509c5b0230e2bff5c22a591432:/src/widgets/grid/ColumnModel.js diff --git a/src/widgets/grid/ColumnModel.js b/src/widgets/grid/ColumnModel.js new file mode 100644 index 00000000..09126668 --- /dev/null +++ b/src/widgets/grid/ColumnModel.js @@ -0,0 +1,592 @@ +/*! + * Ext JS Library 3.0.0 + * Copyright(c) 2006-2009 Ext JS, LLC + * licensing@extjs.com + * http://www.extjs.com/license + */ +/** + * @class Ext.grid.ColumnModel + * @extends Ext.util.Observable + *
After the data has been read into the client side cache ({@link Ext.data.Store Store}), + * the ColumnModel is used to configure how and what parts of that data will be displayed in the + * vertical slices (columns) of the grid. The Ext.grid.ColumnModel Class is the default implementation + * of a ColumnModel used by implentations of {@link Ext.grid.GridPanel GridPanel}.
+ *Data is mapped into the store's records and then indexed into the ColumnModel using the + * {@link Ext.grid.Column#dataIndex dataIndex}:
+ *
+{data source} == mapping ==> {data store} == {@link Ext.grid.Column#dataIndex dataIndex} ==> {ColumnModel}
+ *
+ * Each {@link Ext.grid.Column Column} in the grid's ColumnModel is configured with a + * {@link Ext.grid.Column#dataIndex dataIndex} to specify how the data within + * each record in the store is indexed into the ColumnModel.
+ *There are two ways to initialize the ColumnModel class:
+ *Initialization Method 1: an Array
+
+ var colModel = new Ext.grid.ColumnModel([
+ { header: "Ticker", width: 60, sortable: true},
+ { header: "Company Name", width: 150, sortable: true, id: 'company'},
+ { header: "Market Cap.", width: 100, sortable: true},
+ { header: "$ Sales", width: 100, sortable: true, renderer: money},
+ { header: "Employees", width: 100, sortable: true, resizable: false}
+ ]);
+
+ * The ColumnModel may be initialized with an Array of {@link Ext.grid.Column} column configuration + * objects to define the initial layout / display of the columns in the Grid. The order of each + * {@link Ext.grid.Column} column configuration object within the specified Array defines the initial + * order of the column display. A Column's display may be initially hidden using the + * {@link Ext.grid.Column#hidden hidden} config property (and then shown using the column + * header menu). Field's that are not included in the ColumnModel will not be displayable at all.
+ *How each column in the grid correlates (maps) to the {@link Ext.data.Record} field in the + * {@link Ext.data.Store Store} the column draws its data from is configured through the + * {@link Ext.grid.Column#dataIndex dataIndex}. If the + * {@link Ext.grid.Column#dataIndex dataIndex} is not explicitly defined (as shown in the + * example above) it will use the column configuration's index in the Array as the index.
+ *See {@link Ext.grid.Column} for additional configuration options for each column.
+ *Initialization Method 2: an Object
+ *In order to use configuration options from Ext.grid.ColumnModel, an Object may be used to + * initialize the ColumnModel. The column configuration Array will be specified in the {@link #columns} + * config property. The {@link #defaults} config property can be used to apply defaults + * for all columns, e.g.:
+ var colModel = new Ext.grid.ColumnModel({
+ columns: [
+ { header: "Ticker", width: 60, menuDisabled: false},
+ { header: "Company Name", width: 150, id: 'company'},
+ { header: "Market Cap."},
+ { header: "$ Sales", renderer: money},
+ { header: "Employees", resizable: false}
+ ],
+ defaults: {
+ sortable: true,
+ menuDisabled: true,
+ width: 100
+ },
+ listeners: {
+ {@link #hiddenchange}: function(cm, colIndex, hidden) {
+ saveConfig(colIndex, hidden);
+ }
+ }
+});
+
+ * In both examples above, the ability to apply a CSS class to all cells in a column (including the + * header) is demonstrated through the use of the {@link Ext.grid.Column#id id} config + * option. This column could be styled by including the following css:
+ //add this css *after* the core css is loaded
+.x-grid3-td-company {
+ color: red; // entire column will have red font
+}
+// modify the header row only, adding an icon to the column header
+.x-grid3-hd-company {
+ background: transparent
+ url(../../resources/images/icons/silk/building.png)
+ no-repeat 3px 3px ! important;
+ padding-left:20px;
+}
+
+ * Note that the "Company Name" column could be specified as the
+ * {@link Ext.grid.GridPanel}.{@link Ext.grid.GridPanel#autoExpandColumn autoExpandColumn}.
+ * @constructor
+ * @param {Mixed} config Specify either an Array of {@link Ext.grid.Column} configuration objects or specify
+ * a configuration Object (see introductory section discussion utilizing Initialization Method 2 above).
+ */
+Ext.grid.ColumnModel = function(config){
+ /**
+ * An Array of {@link Ext.grid.Column Column definition} objects representing the configuration
+ * of this ColumnModel. See {@link Ext.grid.Column} for the configuration properties that may
+ * be specified.
+ * @property config
+ * @type Array
+ */
+ if(config.columns){
+ Ext.apply(this, config);
+ this.setConfig(config.columns, true);
+ }else{
+ this.setConfig(config, true);
+ }
+ this.addEvents(
+ /**
+ * @event widthchange
+ * Fires when the width of a column is programmaticially changed using
+ * {@link #setColumnWidth}
.
+ * Note internal resizing suppresses the event from firing. See also
+ * {@link Ext.grid.GridPanel}.{@link #columnresize}
.
+ * @param {ColumnModel} this
+ * @param {Number} columnIndex The column index
+ * @param {Number} newWidth The new width
+ */
+ "widthchange",
+ /**
+ * @event headerchange
+ * Fires when the text of a header changes.
+ * @param {ColumnModel} this
+ * @param {Number} columnIndex The column index
+ * @param {String} newText The new header text
+ */
+ "headerchange",
+ /**
+ * @event hiddenchange
+ * Fires when a column is hidden or "unhidden".
+ * @param {ColumnModel} this
+ * @param {Number} columnIndex The column index
+ * @param {Boolean} hidden true if hidden, false otherwise
+ */
+ "hiddenchange",
+ /**
+ * @event columnmoved
+ * Fires when a column is moved.
+ * @param {ColumnModel} this
+ * @param {Number} oldIndex
+ * @param {Number} newIndex
+ */
+ "columnmoved",
+ /**
+ * @event configchange
+ * Fires when the configuration is changed
+ * @param {ColumnModel} this
+ */
+ "configchange"
+ );
+ Ext.grid.ColumnModel.superclass.constructor.call(this);
+};
+Ext.extend(Ext.grid.ColumnModel, Ext.util.Observable, {
+ /**
+ * @cfg {Number} defaultWidth (optional) The width of columns which have no {@link #width}
+ * specified (defaults to 100). This property shall preferably be configured through the
+ * {@link #defaults} config property.
+ */
+ defaultWidth: 100,
+ /**
+ * @cfg {Boolean} defaultSortable (optional) Default sortable of columns which have no
+ * sortable specified (defaults to false). This property shall preferably be configured
+ * through the {@link #defaults} config property.
+ */
+ defaultSortable: false,
+ /**
+ * @cfg {Array} columns An Array of object literals. The config options defined by
+ * {@link Ext.grid.Column} are the options which may appear in the object literal for each
+ * individual column definition.
+ */
+ /**
+ * @cfg {Object} defaults Object literal which will be used to apply {@link Ext.grid.Column}
+ * configuration options to all {@link #columns}. Configuration options specified with
+ * individual {@link Ext.grid.Column column} configs will supersede these {@link #defaults}.
+ */
+
+ /**
+ * Returns the id of the column at the specified index.
+ * @param {Number} index The column index
+ * @return {String} the id
+ */
+ getColumnId : function(index){
+ return this.config[index].id;
+ },
+
+ getColumnAt : function(index){
+ return this.config[index];
+ },
+
+ /**
+ * Reconfigures this column model according to the passed Array of column definition objects. + * For a description of the individual properties of a column definition object, see the + * Config Options.
+ *Causes the {@link #configchange} event to be fired. A {@link Ext.grid.GridPanel GridPanel} + * using this ColumnModel will listen for this event and refresh its UI automatically.
+ * @param {Array} config Array of Column definition objects. + * @param {Boolean} initial Specify true to bypass cleanup which deletes the totalWidth + * and destroys existing editors. + */ + setConfig : function(config, initial){ + var i, c, len; + if(!initial){ // cleanup + delete this.totalWidth; + for(i = 0, len = this.config.length; i < len; i++){ + c = this.config[i]; + if(c.editor){ + c.editor.destroy(); + } + } + } + + // backward compatibility + this.defaults = Ext.apply({ + width: this.defaultWidth, + sortable: this.defaultSortable + }, this.defaults); + + this.config = config; + this.lookup = {}; + // if no id, create one + for(i = 0, len = config.length; i < len; i++){ + c = Ext.applyIf(config[i], this.defaults); + if(!c.isColumn){ + var cls = Ext.grid.Column.types[c.xtype || 'gridcolumn']; + c = new cls(c); + config[i] = c; + } + this.lookup[c.id] = c; + } + if(!initial){ + this.fireEvent('configchange', this); + } + }, + + /** + * Returns the column for a specified id. + * @param {String} id The column id + * @return {Object} the column + */ + getColumnById : function(id){ + return this.lookup[id]; + }, + + /** + * Returns the index for a specified column id. + * @param {String} id The column id + * @return {Number} the index, or -1 if not found + */ + getIndexById : function(id){ + for(var i = 0, len = this.config.length; i < len; i++){ + if(this.config[i].id == id){ + return i; + } + } + return -1; + }, + + /** + * Moves a column from one position to another. + * @param {Number} oldIndex The index of the column to move. + * @param {Number} newIndex The position at which to reinsert the coolumn. + */ + moveColumn : function(oldIndex, newIndex){ + var c = this.config[oldIndex]; + this.config.splice(oldIndex, 1); + this.config.splice(newIndex, 0, c); + this.dataMap = null; + this.fireEvent("columnmoved", this, oldIndex, newIndex); + }, + + /** + * Returns the number of columns. + * @param {Boolean} visibleOnly Optional. Pass as true to only include visible columns. + * @return {Number} + */ + getColumnCount : function(visibleOnly){ + if(visibleOnly === true){ + var c = 0; + for(var i = 0, len = this.config.length; i < len; i++){ + if(!this.isHidden(i)){ + c++; + } + } + return c; + } + return this.config.length; + }, + + /** + * Returns the column configs that return true by the passed function that is called + * with (columnConfig, index) +
+// returns an array of column config objects for all hidden columns
+var columns = grid.getColumnModel().getColumnsBy(function(c){
+ return c.hidden;
+});
+
+ * @param {Function} fn
+ * @param {Object} scope (optional)
+ * @return {Array} result
+ */
+ getColumnsBy : function(fn, scope){
+ var r = [];
+ for(var i = 0, len = this.config.length; i < len; i++){
+ var c = this.config[i];
+ if(fn.call(scope||this, c, i) === true){
+ r[r.length] = c;
+ }
+ }
+ return r;
+ },
+
+ /**
+ * Returns true if the specified column is sortable.
+ * @param {Number} col The column index
+ * @return {Boolean}
+ */
+ isSortable : function(col){
+ return this.config[col].sortable;
+ },
+
+ /**
+ * Returns true if the specified column menu is disabled.
+ * @param {Number} col The column index
+ * @return {Boolean}
+ */
+ isMenuDisabled : function(col){
+ return !!this.config[col].menuDisabled;
+ },
+
+ /**
+ * Returns the rendering (formatting) function defined for the column.
+ * @param {Number} col The column index.
+ * @return {Function} The function used to render the cell. See {@link #setRenderer}.
+ */
+ getRenderer : function(col){
+ if(!this.config[col].renderer){
+ return Ext.grid.ColumnModel.defaultRenderer;
+ }
+ return this.config[col].renderer;
+ },
+
+ /**
+ * Sets the rendering (formatting) function for a column. See {@link Ext.util.Format} for some
+ * default formatting functions.
+ * @param {Number} col The column index
+ * @param {Function} fn The function to use to process the cell's raw data
+ * to return HTML markup for the grid view. The render function is called with
+ * the following parameters:The data value for the cell.
An object in which you may set the following attributes:
A CSS class name to add to the cell's TD element.
An HTML attribute definition string to apply to the data container element within the table cell + * (e.g. 'style="color:red;"').
The {@link Ext.data.Record} from which the data was extracted.
Row index
Column index
The {@link Ext.data.Store} object from which the Record was extracted.
{@link #widthchange}
+ * event. Defaults to false.
+ */
+ setColumnWidth : function(col, width, suppressEvent){
+ this.config[col].width = width;
+ this.totalWidth = null;
+ if(!suppressEvent){
+ this.fireEvent("widthchange", this, col, width);
+ }
+ },
+
+ /**
+ * Returns the total width of all columns.
+ * @param {Boolean} includeHidden True to include hidden column widths
+ * @return {Number}
+ */
+ getTotalWidth : function(includeHidden){
+ if(!this.totalWidth){
+ this.totalWidth = 0;
+ for(var i = 0, len = this.config.length; i < len; i++){
+ if(includeHidden || !this.isHidden(i)){
+ this.totalWidth += this.getColumnWidth(i);
+ }
+ }
+ }
+ return this.totalWidth;
+ },
+
+ /**
+ * Returns the header for the specified column.
+ * @param {Number} col The column index
+ * @return {String}
+ */
+ getColumnHeader : function(col){
+ return this.config[col].header;
+ },
+
+ /**
+ * Sets the header for a column.
+ * @param {Number} col The column index
+ * @param {String} header The new header
+ */
+ setColumnHeader : function(col, header){
+ this.config[col].header = header;
+ this.fireEvent("headerchange", this, col, header);
+ },
+
+ /**
+ * Returns the tooltip for the specified column.
+ * @param {Number} col The column index
+ * @return {String}
+ */
+ getColumnTooltip : function(col){
+ return this.config[col].tooltip;
+ },
+ /**
+ * Sets the tooltip for a column.
+ * @param {Number} col The column index
+ * @param {String} tooltip The new tooltip
+ */
+ setColumnTooltip : function(col, tooltip){
+ this.config[col].tooltip = tooltip;
+ },
+
+ /**
+ * Returns the dataIndex for the specified column.
+
+// Get field name for the column
+var fieldName = grid.getColumnModel().getDataIndex(columnIndex);
+
+ * @param {Number} col The column index
+ * @return {String} The column's dataIndex
+ */
+ getDataIndex : function(col){
+ return this.config[col].dataIndex;
+ },
+
+ /**
+ * Sets the dataIndex for a column.
+ * @param {Number} col The column index
+ * @param {String} dataIndex The new dataIndex
+ */
+ setDataIndex : function(col, dataIndex){
+ this.config[col].dataIndex = dataIndex;
+ },
+
+ /**
+ * Finds the index of the first matching column for the given dataIndex.
+ * @param {String} col The dataIndex to find
+ * @return {Number} The column index, or -1 if no match was found
+ */
+ findColumnIndex : function(dataIndex){
+ var c = this.config;
+ for(var i = 0, len = c.length; i < len; i++){
+ if(c[i].dataIndex == dataIndex){
+ return i;
+ }
+ }
+ return -1;
+ },
+
+ /**
+ * Returns true if the cell is editable.
+
+var store = new Ext.data.Store({...});
+var colModel = new Ext.grid.ColumnModel({
+ columns: [...],
+ isCellEditable: function(col, row) {
+ var record = store.getAt(row);
+ if (record.get('readonly')) { // replace with your condition
+ return false;
+ }
+ return Ext.grid.ColumnModel.prototype.isCellEditable.call(this, col, row);
+ }
+});
+var grid = new Ext.grid.GridPanel({
+ store: store,
+ colModel: colModel,
+ ...
+});
+
+ * @param {Number} colIndex The column index
+ * @param {Number} rowIndex The row index
+ * @return {Boolean}
+ */
+ isCellEditable : function(colIndex, rowIndex){
+ return (this.config[colIndex].editable || (typeof this.config[colIndex].editable == "undefined" && this.config[colIndex].editor)) ? true : false;
+ },
+
+ /**
+ * Returns the editor defined for the cell/column.
+ * @param {Number} colIndex The column index
+ * @param {Number} rowIndex The row index
+ * @return {Ext.Editor} The {@link Ext.Editor Editor} that was created to wrap
+ * the {@link Ext.form.Field Field} used to edit the cell.
+ */
+ getCellEditor : function(colIndex, rowIndex){
+ return this.config[colIndex].getCellEditor(rowIndex);
+ },
+
+ /**
+ * Sets if a column is editable.
+ * @param {Number} col The column index
+ * @param {Boolean} editable True if the column is editable
+ */
+ setEditable : function(col, editable){
+ this.config[col].editable = editable;
+ },
+
+
+ /**
+ * Returns true if the column is hidden.
+ * @param {Number} colIndex The column index
+ * @return {Boolean}
+ */
+ isHidden : function(colIndex){
+ return this.config[colIndex].hidden;
+ },
+
+
+ /**
+ * Returns true if the column width cannot be changed
+ */
+ isFixed : function(colIndex){
+ return this.config[colIndex].fixed;
+ },
+
+ /**
+ * Returns true if the column can be resized
+ * @return {Boolean}
+ */
+ isResizable : function(colIndex){
+ return colIndex >= 0 && this.config[colIndex].resizable !== false && this.config[colIndex].fixed !== true;
+ },
+ /**
+ * Sets if a column is hidden.
+
+myGrid.getColumnModel().setHidden(0, true); // hide column 0 (0 = the first column).
+
+ * @param {Number} colIndex The column index
+ * @param {Boolean} hidden True if the column is hidden
+ */
+ setHidden : function(colIndex, hidden){
+ var c = this.config[colIndex];
+ if(c.hidden !== hidden){
+ c.hidden = hidden;
+ this.totalWidth = null;
+ this.fireEvent("hiddenchange", this, colIndex, hidden);
+ }
+ },
+
+ /**
+ * Sets the editor for a column and destroys the prior editor.
+ * @param {Number} col The column index
+ * @param {Object} editor The editor object
+ */
+ setEditor : function(col, editor){
+ Ext.destroy(this.config[col].editor);
+ this.config[col].editor = editor;
+ },
+
+ /**
+ * Destroys this column model by purging any event listeners, and removing any editors.
+ */
+ destroy : function(){
+ for(var i = 0, c = this.config, len = c.length; i < len; i++){
+ Ext.destroy(c[i].editor);
+ }
+ this.purgeListeners();
+ }
+});
+
+// private
+Ext.grid.ColumnModel.defaultRenderer = function(value){
+ if(typeof value == "string" && value.length < 1){
+ return " ";
+ }
+ return value;
+};
\ No newline at end of file