123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506 |
- /*
- * Ext JS Library 2.0 Copyright(c) 2006-2007, Ext JS, LLC. licensing@extjs.com
- *
- * http://extjs.com/license
- */
- /**
- * @class Ext.grid.GroupingView
- * @extends Ext.grid.GridView Adds the ability for single level grouping to the
- * grid.
- *
- * <pre><code>
- * var grid = new Ext.grid.GridPanel({
- * // A groupingStore is required for a GroupingView
- * store : new Ext.data.GroupingStore({
- * reader : reader,
- * data : xg.dummyData,
- * sortInfo : {
- * field : 'company',
- * direction : "ASC"
- * },
- * groupField : 'industry'
- * }),
- *
- * columns : [{
- * id : 'company',
- * header : "Company",
- * width : 60,
- * sortable : true,
- * dataIndex : 'company'
- * }, {
- * header : "Price",
- * width : 20,
- * sortable : true,
- * renderer : Ext.util.Format.usMoney,
- * dataIndex : 'price'
- * }, {
- * header : "Change",
- * width : 20,
- * sortable : true,
- * dataIndex : 'change',
- * renderer : Ext.util.Format.usMoney
- * }, {
- * header : "Industry",
- * width : 20,
- * sortable : true,
- * dataIndex : 'industry'
- * }, {
- * header : "Last Updated",
- * width : 20,
- * sortable : true,
- * renderer : Ext.util.Format.dateRenderer('m/d/Y'),
- * dataIndex : 'lastChange'
- * }],
- *
- * view : new Ext.grid.GroupingView({
- * forceFit : true,
- * // custom grouping text template to display the number of items per group
- * groupTextTpl : '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Items" : "Item"]})'
- * }),
- *
- * frame : true,
- * width : 700,
- * height : 450,
- * collapsible : true,
- * animCollapse : false,
- * title : 'Grouping Example',
- * iconCls : 'icon-grid',
- * renderTo : document.body
- * });
- * </code></pre>
- *
- * @constructor
- * @param {Object}
- * config
- */
- Ext.grid.GroupingView = Ext.extend(Ext.grid.GridView, {
- /**
- * @cfg {Boolean} hideGroupedColumn True to hide the column that is
- * currently grouped
- */
- hideGroupedColumn : false,
- /**
- * @cfg {Boolean} showGroupName True to display the name for each set of
- * grouped rows (defaults to false)
- */
- showGroupName : true,
- /**
- * @cfg {Boolean} startCollapsed True to start all groups collapsed
- */
- startCollapsed : false,
- /**
- * @cfg {Boolean} enableGrouping False to disable grouping functionality
- * (defaults to true)
- */
- enableGrouping : true,
- /**
- * @cfg {Boolean} enableGroupingMenu True to enable the grouping control in
- * the column menu
- */
- enableGroupingMenu : true,
- /**
- * @cfg {Boolean} enableNoGroups True to allow the user to turn off grouping
- */
- enableNoGroups : true,
- /**
- * @cfg {String} emptyGroupText The text to display when there is an empty
- * group value
- */
- emptyGroupText : '(None)',
- /**
- * @cfg {Boolean} ignoreAdd True to skip refreshing the view when new rows
- * are added (defaults to false)
- */
- ignoreAdd : false,
- /**
- * @cfg {String} groupTextTpl The template used to render the group text
- */
- groupTextTpl : '{text}',
- // private
- gidSeed : 1000,
- // private
- initTemplates : function() {
- Ext.grid.GroupingView.superclass.initTemplates.call(this);
- this.state = {};
- var sm = this.grid.getSelectionModel();
- sm.on(sm.selectRow ? 'beforerowselect' : 'beforecellselect',
- this.onBeforeRowSelect, this);
- if (!this.startGroup) {
- this.startGroup = new Ext.XTemplate(
- '<div id="{groupId}" class="x-grid-group {cls}">',
- '<div id="{groupId}-hd" class="x-grid-group-hd" style="{style}"><div>',
- this.groupTextTpl, '</div></div>',
- '<div id="{groupId}-bd" class="x-grid-group-body">');
- }
- this.startGroup.compile();
- this.endGroup = '</div></div>';
- },
- // private
- findGroup : function(el) {
- return Ext.fly(el).up('.x-grid-group', this.mainBody.dom);
- },
- // private
- getGroups : function() {
- return this.hasRows() ? this.mainBody.dom.childNodes : [];
- },
- // private
- onAdd : function() {
- if (this.enableGrouping && !this.ignoreAdd) {
- var ss = this.getScrollState();
- this.refresh();
- this.restoreScroll(ss);
- } else if (!this.enableGrouping) {
- Ext.grid.GroupingView.superclass.onAdd.apply(this, arguments);
- }
- },
- // private
- onRemove : function(ds, record, index, isUpdate) {
- Ext.grid.GroupingView.superclass.onRemove.apply(this, arguments);
- var g = document.getElementById(record._groupId);
- if (g && g.childNodes[1].childNodes.length < 1) {
- Ext.removeNode(g);
- }
- this.applyEmptyText();
- },
- // private
- refreshRow : function(record) {
- if (this.ds.getCount() == 1) {
- this.refresh();
- } else {
- this.isUpdating = true;
- Ext.grid.GroupingView.superclass.refreshRow.apply(this, arguments);
- this.isUpdating = false;
- }
- },
- // private
- beforeMenuShow : function() {
- var field = this.getGroupField();
- var g = this.hmenu.items.get('groupBy');
- if (g) {
- g.setDisabled(this.cm.config[this.hdCtxIndex].groupable === false);
- }
- var s = this.hmenu.items.get('showGroups');
- if (s) {
- s.setChecked(!!field);
- }
- },
- // private
- renderUI : function() {
- Ext.grid.GroupingView.superclass.renderUI.call(this);
- this.mainBody.on('mousedown', this.interceptMouse, this);
- if (this.enableGroupingMenu && this.hmenu) {
- this.hmenu.add('-', {
- id : 'groupBy',
- text : this.groupByText,
- handler : this.onGroupByClick,
- scope : this,
- iconCls : 'x-group-by-icon'
- });
- if (this.enableNoGroups) {
- this.hmenu.add({
- id : 'showGroups',
- text : this.showGroupsText,
- checked : true,
- checkHandler : this.onShowGroupsClick,
- scope : this
- });
- }
- this.hmenu.on('beforeshow', this.beforeMenuShow, this);
- }
- },
- // private
- onGroupByClick : function() {
- this.grid.store.groupBy(this.cm.getDataIndex(this.hdCtxIndex));
- },
- // private
- onShowGroupsClick : function(mi, checked) {
- if (checked) {
- this.onGroupByClick();
- } else {
- this.grid.store.clearGrouping();
- }
- },
- /**
- * Toggles the specified group if no value is passed, otherwise sets the
- * expanded state of the group to the value passed.
- *
- * @param {String}
- * groupId The groupId assigned to the group (see getGroupId)
- * @param {Boolean}
- * expanded (optional)
- */
- toggleGroup : function(group, expanded) {
- this.grid.stopEditing();
- group = Ext.getDom(group);
- var gel = Ext.fly(group);
- expanded = expanded !== undefined ? expanded : gel
- .hasClass('x-grid-group-collapsed');
- this.state[gel.dom.id] = expanded;
- gel[expanded ? 'removeClass' : 'addClass']('x-grid-group-collapsed');
- },
- /**
- * Toggles all groups if no value is passed, otherwise sets the expanded
- * state of all groups to the value passed.
- *
- * @param {Boolean}
- * expanded (optional)
- */
- toggleAllGroups : function(expanded) {
- var groups = this.getGroups();
- for (var i = 0, len = groups.length; i < len; i++) {
- this.toggleGroup(groups[i], expanded);
- }
- },
- /**
- * Expands all grouped rows.
- */
- expandAllGroups : function() {
- this.toggleAllGroups(true);
- },
- /**
- * Collapses all grouped rows.
- */
- collapseAllGroups : function() {
- this.toggleAllGroups(false);
- },
- // private
- interceptMouse : function(e) {
- var hd = e.getTarget('.x-grid-group-hd', this.mainBody);
- if (hd) {
- e.stopEvent();
- this.toggleGroup(hd.parentNode);
- }
- },
- // private
- getGroup : function(v, r, groupRenderer, rowIndex, colIndex, ds) {
- var g = groupRenderer
- ? groupRenderer(v, {}, r, rowIndex, colIndex, ds)
- : String(v);
- if (g === '') {
- g = this.cm.config[colIndex].emptyGroupText || this.emptyGroupText;
- }
- return g;
- },
- // private
- getGroupField : function() {
- return this.grid.store.getGroupState();
- },
- // private
- renderRows : function() {
- var groupField = this.getGroupField();
- var eg = !!groupField;
- // if they turned off grouping and the last grouped field is hidden
- if (this.hideGroupedColumn) {
- var colIndex = this.cm.findColumnIndex(groupField);
- if (!eg && this.lastGroupField !== undefined) {
- this.mainBody.update('');
- this.cm.setHidden(this.cm.findColumnIndex(this.lastGroupField),
- false);
- delete this.lastGroupField;
- } else if (eg && this.lastGroupField === undefined) {
- this.lastGroupField = groupField;
- this.cm.setHidden(colIndex, true);
- } else if (eg && this.lastGroupField !== undefined
- && groupField !== this.lastGroupField) {
- this.mainBody.update('');
- var oldIndex = this.cm.findColumnIndex(this.lastGroupField);
- this.cm.setHidden(oldIndex, false);
- this.lastGroupField = groupField;
- this.cm.setHidden(colIndex, true);
- }
- }
- return Ext.grid.GroupingView.superclass.renderRows.apply(this,
- arguments);
- },
- // private
- doRender : function(cs, rs, ds, startRow, colCount, stripe) {
- if (rs.length < 1) {
- return '';
- }
- var groupField = this.getGroupField();
- var colIndex = this.cm.findColumnIndex(groupField);
- this.enableGrouping = !!groupField;
- if (!this.enableGrouping || this.isUpdating) {
- return Ext.grid.GroupingView.superclass.doRender.apply(this,
- arguments);
- }
- var gstyle = 'width:' + this.getTotalWidth() + ';';
- var gidPrefix = this.grid.getGridEl().id;
- var cfg = this.cm.config[colIndex];
- var groupRenderer = cfg.groupRenderer || cfg.renderer;
- var cls = this.startCollapsed ? 'x-grid-group-collapsed' : '';
- var prefix = this.showGroupName
- ? (cfg.groupName || cfg.header) + ': '
- : '';
- var groups = [], curGroup, i, len, gid;
- for (i = 0, len = rs.length; i < len; i++) {
- var rowIndex = startRow + i;
- var r = rs[i], gvalue = r.data[groupField], g = this.getGroup(
- gvalue, r, groupRenderer, rowIndex, colIndex, ds);
- if (!curGroup || curGroup.group != g) {
- gid = gidPrefix + '-gp-' + groupField + '-' + g;
- var gcls = cls ? cls : (this.state[gid] === false
- ? 'x-grid-group-collapsed'
- : '');
- curGroup = {
- group : g,
- gvalue : gvalue,
- text : prefix + g,
- groupId : gid,
- startRow : rowIndex,
- rs : [r],
- cls : gcls,
- style : gstyle
- };
- groups.push(curGroup);
- } else {
- curGroup.rs.push(r);
- }
- r._groupId = gid;
- }
- var buf = [];
- for (i = 0, len = groups.length; i < len; i++) {
- var g = groups[i];
- this.doGroupStart(buf, g, cs, ds, colCount);
- buf[buf.length] = Ext.grid.GroupingView.superclass.doRender.call(
- this, cs, g.rs, ds, g.startRow, colCount, stripe);
- this.doGroupEnd(buf, g, cs, ds, colCount);
- }
- return buf.join('');
- },
- /**
- * Dynamically tries to determine the groupId of a specific value
- *
- * @param {String}
- * value
- * @return {String} The group id
- */
- getGroupId : function(value) {
- var gidPrefix = this.grid.getGridEl().id;
- var groupField = this.getGroupField();
- var colIndex = this.cm.findColumnIndex(groupField);
- var cfg = this.cm.config[colIndex];
- var groupRenderer = cfg.groupRenderer || cfg.renderer;
- var gtext = this.getGroup(value, {
- data : {}
- }, groupRenderer, 0, colIndex, this.ds);
- return gidPrefix + '-gp-' + groupField + '-' + value;
- },
- // private
- doGroupStart : function(buf, g, cs, ds, colCount) {
- buf[buf.length] = this.startGroup.apply(g);
- },
- // private
- doGroupEnd : function(buf, g, cs, ds, colCount) {
- buf[buf.length] = this.endGroup;
- },
- // private
- getRows : function() {
- if (!this.enableGrouping) {
- return Ext.grid.GroupingView.superclass.getRows.call(this);
- }
- var r = [];
- var g, gs = this.getGroups();
- for (var i = 0, len = gs.length; i < len; i++) {
- g = gs[i].childNodes[1].childNodes;
- for (var j = 0, jlen = g.length; j < jlen; j++) {
- r[r.length] = g[j];
- }
- }
- return r;
- },
- // private
- updateGroupWidths : function() {
- if (!this.enableGrouping || !this.hasRows()) {
- return;
- }
- var tw = Math.max(this.cm.getTotalWidth(), this.el.dom.offsetWidth
- - this.scrollOffset)
- + 'px';
- var gs = this.getGroups();
- for (var i = 0, len = gs.length; i < len; i++) {
- gs[i].firstChild.style.width = tw;
- }
- },
- // private
- onColumnWidthUpdated : function(col, w, tw) {
- this.updateGroupWidths();
- },
- // private
- onAllColumnWidthsUpdated : function(ws, tw) {
- this.updateGroupWidths();
- },
- // private
- onColumnHiddenUpdated : function(col, hidden, tw) {
- this.updateGroupWidths();
- },
- // private
- onLayout : function() {
- this.updateGroupWidths();
- },
- // private
- onBeforeRowSelect : function(sm, rowIndex) {
- if (!this.enableGrouping) {
- return;
- }
- var row = this.getRow(rowIndex);
- if (row && !row.offsetParent) {
- var g = this.findGroup(row);
- this.toggleGroup(g, true);
- }
- },
- /**
- * @cfg {String} groupByText Text displayed in the grid header menu for
- * grouping by a column (defaults to 'Group By This Field').
- */
- groupByText : 'Group By This Field',
- /**
- * @cfg {String} showGroupsText Text displayed in the grid header for
- * enabling/disabling grouping (defaults to 'Show in Groups').
- */
- showGroupsText : 'Show in Groups'
- });
- // private
- Ext.grid.GroupingView.GROUP_ID = 1000;
|