[76] | 1 | /*! |
---|
| 2 | * Ext JS Library 3.4.0 |
---|
| 3 | * Copyright(c) 2006-2011 Sencha Inc. |
---|
| 4 | * licensing@sencha.com |
---|
| 5 | * http://www.sencha.com/license |
---|
| 6 | */ |
---|
| 7 | /** |
---|
| 8 | * @class Ext.grid.GroupingView |
---|
| 9 | * @extends Ext.grid.GridView |
---|
| 10 | * Adds the ability for single level grouping to the grid. A {@link Ext.data.GroupingStore GroupingStore} |
---|
| 11 | * must be used to enable grouping. Some grouping characteristics may also be configured at the |
---|
| 12 | * {@link Ext.grid.Column Column level}<div class="mdetail-params"><ul> |
---|
| 13 | * <li><code>{@link Ext.grid.Column#emptyGroupText emptyGroupText}</code></li> |
---|
| 14 | * <li><code>{@link Ext.grid.Column#groupable groupable}</code></li> |
---|
| 15 | * <li><code>{@link Ext.grid.Column#groupName groupName}</code></li> |
---|
| 16 | * <li><code>{@link Ext.grid.Column#groupRender groupRender}</code></li> |
---|
| 17 | * </ul></div> |
---|
| 18 | * <p>Sample usage:</p> |
---|
| 19 | * <pre><code> |
---|
| 20 | var grid = new Ext.grid.GridPanel({ |
---|
| 21 | // A groupingStore is required for a GroupingView |
---|
| 22 | store: new {@link Ext.data.GroupingStore}({ |
---|
| 23 | autoDestroy: true, |
---|
| 24 | reader: reader, |
---|
| 25 | data: xg.dummyData, |
---|
| 26 | sortInfo: {field: 'company', direction: 'ASC'}, |
---|
| 27 | {@link Ext.data.GroupingStore#groupOnSort groupOnSort}: true, |
---|
| 28 | {@link Ext.data.GroupingStore#remoteGroup remoteGroup}: true, |
---|
| 29 | {@link Ext.data.GroupingStore#groupField groupField}: 'industry' |
---|
| 30 | }), |
---|
| 31 | colModel: new {@link Ext.grid.ColumnModel}({ |
---|
| 32 | columns:[ |
---|
| 33 | {id:'company',header: 'Company', width: 60, dataIndex: 'company'}, |
---|
| 34 | // {@link Ext.grid.Column#groupable groupable}, {@link Ext.grid.Column#groupName groupName}, {@link Ext.grid.Column#groupRender groupRender} are also configurable at column level |
---|
| 35 | {header: 'Price', renderer: Ext.util.Format.usMoney, dataIndex: 'price', {@link Ext.grid.Column#groupable groupable}: false}, |
---|
| 36 | {header: 'Change', dataIndex: 'change', renderer: Ext.util.Format.usMoney}, |
---|
| 37 | {header: 'Industry', dataIndex: 'industry'}, |
---|
| 38 | {header: 'Last Updated', renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'lastChange'} |
---|
| 39 | ], |
---|
| 40 | defaults: { |
---|
| 41 | sortable: true, |
---|
| 42 | menuDisabled: false, |
---|
| 43 | width: 20 |
---|
| 44 | } |
---|
| 45 | }), |
---|
| 46 | |
---|
| 47 | view: new Ext.grid.GroupingView({ |
---|
| 48 | {@link Ext.grid.GridView#forceFit forceFit}: true, |
---|
| 49 | // custom grouping text template to display the number of items per group |
---|
| 50 | {@link #groupTextTpl}: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Items" : "Item"]})' |
---|
| 51 | }), |
---|
| 52 | |
---|
| 53 | frame:true, |
---|
| 54 | width: 700, |
---|
| 55 | height: 450, |
---|
| 56 | collapsible: true, |
---|
| 57 | animCollapse: false, |
---|
| 58 | title: 'Grouping Example', |
---|
| 59 | iconCls: 'icon-grid', |
---|
| 60 | renderTo: document.body |
---|
| 61 | }); |
---|
| 62 | * </code></pre> |
---|
| 63 | * @constructor |
---|
| 64 | * @param {Object} config |
---|
| 65 | */ |
---|
| 66 | Ext.grid.GroupingView = Ext.extend(Ext.grid.GridView, { |
---|
| 67 | |
---|
| 68 | /** |
---|
| 69 | * @cfg {String} groupByText Text displayed in the grid header menu for grouping by a column |
---|
| 70 | * (defaults to 'Group By This Field'). |
---|
| 71 | */ |
---|
| 72 | groupByText : 'Group By This Field', |
---|
| 73 | /** |
---|
| 74 | * @cfg {String} showGroupsText Text displayed in the grid header for enabling/disabling grouping |
---|
| 75 | * (defaults to 'Show in Groups'). |
---|
| 76 | */ |
---|
| 77 | showGroupsText : 'Show in Groups', |
---|
| 78 | /** |
---|
| 79 | * @cfg {Boolean} hideGroupedColumn <tt>true</tt> to hide the column that is currently grouped (defaults to <tt>false</tt>) |
---|
| 80 | */ |
---|
| 81 | hideGroupedColumn : false, |
---|
| 82 | /** |
---|
| 83 | * @cfg {Boolean} showGroupName If <tt>true</tt> will display a prefix plus a ': ' before the group field value |
---|
| 84 | * in the group header line. The prefix will consist of the <tt><b>{@link Ext.grid.Column#groupName groupName}</b></tt> |
---|
| 85 | * (or the configured <tt><b>{@link Ext.grid.Column#header header}</b></tt> if not provided) configured in the |
---|
| 86 | * {@link Ext.grid.Column} for each set of grouped rows (defaults to <tt>true</tt>). |
---|
| 87 | */ |
---|
| 88 | showGroupName : true, |
---|
| 89 | /** |
---|
| 90 | * @cfg {Boolean} startCollapsed <tt>true</tt> to start all groups collapsed (defaults to <tt>false</tt>) |
---|
| 91 | */ |
---|
| 92 | startCollapsed : false, |
---|
| 93 | /** |
---|
| 94 | * @cfg {Boolean} enableGrouping <tt>false</tt> to disable grouping functionality (defaults to <tt>true</tt>) |
---|
| 95 | */ |
---|
| 96 | enableGrouping : true, |
---|
| 97 | /** |
---|
| 98 | * @cfg {Boolean} enableGroupingMenu <tt>true</tt> to enable the grouping control in the column menu (defaults to <tt>true</tt>) |
---|
| 99 | */ |
---|
| 100 | enableGroupingMenu : true, |
---|
| 101 | /** |
---|
| 102 | * @cfg {Boolean} enableNoGroups <tt>true</tt> to allow the user to turn off grouping (defaults to <tt>true</tt>) |
---|
| 103 | */ |
---|
| 104 | enableNoGroups : true, |
---|
| 105 | /** |
---|
| 106 | * @cfg {String} emptyGroupText The text to display when there is an empty group value (defaults to <tt>'(None)'</tt>). |
---|
| 107 | * May also be specified per column, see {@link Ext.grid.Column}.{@link Ext.grid.Column#emptyGroupText emptyGroupText}. |
---|
| 108 | */ |
---|
| 109 | emptyGroupText : '(None)', |
---|
| 110 | /** |
---|
| 111 | * @cfg {Boolean} ignoreAdd <tt>true</tt> to skip refreshing the view when new rows are added (defaults to <tt>false</tt>) |
---|
| 112 | */ |
---|
| 113 | ignoreAdd : false, |
---|
| 114 | /** |
---|
| 115 | * @cfg {String} groupTextTpl The template used to render the group header (defaults to <tt>'{text}'</tt>). |
---|
| 116 | * This is used to format an object which contains the following properties: |
---|
| 117 | * <div class="mdetail-params"><ul> |
---|
| 118 | * <li><b>group</b> : String<p class="sub-desc">The <i>rendered</i> value of the group field. |
---|
| 119 | * By default this is the unchanged value of the group field. If a <tt><b>{@link Ext.grid.Column#groupRenderer groupRenderer}</b></tt> |
---|
| 120 | * is specified, it is the result of a call to that function.</p></li> |
---|
| 121 | * <li><b>gvalue</b> : Object<p class="sub-desc">The <i>raw</i> value of the group field.</p></li> |
---|
| 122 | * <li><b>text</b> : String<p class="sub-desc">The configured header (as described in <tt>{@link #showGroupName})</tt> |
---|
| 123 | * if <tt>{@link #showGroupName}</tt> is <tt>true</tt>) plus the <i>rendered</i> group field value.</p></li> |
---|
| 124 | * <li><b>groupId</b> : String<p class="sub-desc">A unique, generated ID which is applied to the |
---|
| 125 | * View Element which contains the group.</p></li> |
---|
| 126 | * <li><b>startRow</b> : Number<p class="sub-desc">The row index of the Record which caused group change.</p></li> |
---|
| 127 | * <li><b>rs</b> : Array<p class="sub-desc">Contains a single element: The Record providing the data |
---|
| 128 | * for the row which caused group change.</p></li> |
---|
| 129 | * <li><b>cls</b> : String<p class="sub-desc">The generated class name string to apply to the group header Element.</p></li> |
---|
| 130 | * <li><b>style</b> : String<p class="sub-desc">The inline style rules to apply to the group header Element.</p></li> |
---|
| 131 | * </ul></div></p> |
---|
| 132 | * See {@link Ext.XTemplate} for information on how to format data using a template. Possible usage:<pre><code> |
---|
| 133 | var grid = new Ext.grid.GridPanel({ |
---|
| 134 | ... |
---|
| 135 | view: new Ext.grid.GroupingView({ |
---|
| 136 | groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Items" : "Item"]})' |
---|
| 137 | }), |
---|
| 138 | }); |
---|
| 139 | * </code></pre> |
---|
| 140 | */ |
---|
| 141 | groupTextTpl : '{text}', |
---|
| 142 | |
---|
| 143 | /** |
---|
| 144 | * @cfg {String} groupMode Indicates how to construct the group identifier. <tt>'value'</tt> constructs the id using |
---|
| 145 | * raw value, <tt>'display'</tt> constructs the id using the rendered value. Defaults to <tt>'value'</tt>. |
---|
| 146 | */ |
---|
| 147 | groupMode: 'value', |
---|
| 148 | |
---|
| 149 | /** |
---|
| 150 | * @cfg {Function} groupRenderer This property must be configured in the {@link Ext.grid.Column} for |
---|
| 151 | * each column. |
---|
| 152 | */ |
---|
| 153 | |
---|
| 154 | /** |
---|
| 155 | * @cfg {Boolean} cancelEditOnToggle True to cancel any editing when the group header is toggled. Defaults to <tt>true</tt>. |
---|
| 156 | */ |
---|
| 157 | cancelEditOnToggle: true, |
---|
| 158 | |
---|
| 159 | // private |
---|
| 160 | initTemplates : function(){ |
---|
| 161 | Ext.grid.GroupingView.superclass.initTemplates.call(this); |
---|
| 162 | this.state = {}; |
---|
| 163 | |
---|
| 164 | var sm = this.grid.getSelectionModel(); |
---|
| 165 | sm.on(sm.selectRow ? 'beforerowselect' : 'beforecellselect', |
---|
| 166 | this.onBeforeRowSelect, this); |
---|
| 167 | |
---|
| 168 | if(!this.startGroup){ |
---|
| 169 | this.startGroup = new Ext.XTemplate( |
---|
| 170 | '<div id="{groupId}" class="x-grid-group {cls}">', |
---|
| 171 | '<div id="{groupId}-hd" class="x-grid-group-hd" style="{style}"><div class="x-grid-group-title">', this.groupTextTpl ,'</div></div>', |
---|
| 172 | '<div id="{groupId}-bd" class="x-grid-group-body">' |
---|
| 173 | ); |
---|
| 174 | } |
---|
| 175 | this.startGroup.compile(); |
---|
| 176 | |
---|
| 177 | if (!this.endGroup) { |
---|
| 178 | this.endGroup = '</div></div>'; |
---|
| 179 | } |
---|
| 180 | }, |
---|
| 181 | |
---|
| 182 | // private |
---|
| 183 | findGroup : function(el){ |
---|
| 184 | return Ext.fly(el).up('.x-grid-group', this.mainBody.dom); |
---|
| 185 | }, |
---|
| 186 | |
---|
| 187 | // private |
---|
| 188 | getGroups : function(){ |
---|
| 189 | return this.hasRows() ? this.mainBody.dom.childNodes : []; |
---|
| 190 | }, |
---|
| 191 | |
---|
| 192 | // private |
---|
| 193 | onAdd : function(ds, records, index) { |
---|
| 194 | if (this.canGroup() && !this.ignoreAdd) { |
---|
| 195 | var ss = this.getScrollState(); |
---|
| 196 | this.fireEvent('beforerowsinserted', ds, index, index + (records.length-1)); |
---|
| 197 | this.refresh(); |
---|
| 198 | this.restoreScroll(ss); |
---|
| 199 | this.fireEvent('rowsinserted', ds, index, index + (records.length-1)); |
---|
| 200 | } else if (!this.canGroup()) { |
---|
| 201 | Ext.grid.GroupingView.superclass.onAdd.apply(this, arguments); |
---|
| 202 | } |
---|
| 203 | }, |
---|
| 204 | |
---|
| 205 | // private |
---|
| 206 | onRemove : function(ds, record, index, isUpdate){ |
---|
| 207 | Ext.grid.GroupingView.superclass.onRemove.apply(this, arguments); |
---|
| 208 | var g = document.getElementById(record._groupId); |
---|
| 209 | if(g && g.childNodes[1].childNodes.length < 1){ |
---|
| 210 | Ext.removeNode(g); |
---|
| 211 | } |
---|
| 212 | this.applyEmptyText(); |
---|
| 213 | }, |
---|
| 214 | |
---|
| 215 | // private |
---|
| 216 | refreshRow : function(record){ |
---|
| 217 | if(this.ds.getCount()==1){ |
---|
| 218 | this.refresh(); |
---|
| 219 | }else{ |
---|
| 220 | this.isUpdating = true; |
---|
| 221 | Ext.grid.GroupingView.superclass.refreshRow.apply(this, arguments); |
---|
| 222 | this.isUpdating = false; |
---|
| 223 | } |
---|
| 224 | }, |
---|
| 225 | |
---|
| 226 | // private |
---|
| 227 | beforeMenuShow : function(){ |
---|
| 228 | var item, items = this.hmenu.items, disabled = this.cm.config[this.hdCtxIndex].groupable === false; |
---|
| 229 | if((item = items.get('groupBy'))){ |
---|
| 230 | item.setDisabled(disabled); |
---|
| 231 | } |
---|
| 232 | if((item = items.get('showGroups'))){ |
---|
| 233 | item.setDisabled(disabled); |
---|
| 234 | item.setChecked(this.canGroup(), true); |
---|
| 235 | } |
---|
| 236 | }, |
---|
| 237 | |
---|
| 238 | // private |
---|
| 239 | renderUI : function(){ |
---|
| 240 | var markup = Ext.grid.GroupingView.superclass.renderUI.call(this); |
---|
| 241 | |
---|
| 242 | if(this.enableGroupingMenu && this.hmenu){ |
---|
| 243 | this.hmenu.add('-',{ |
---|
| 244 | itemId:'groupBy', |
---|
| 245 | text: this.groupByText, |
---|
| 246 | handler: this.onGroupByClick, |
---|
| 247 | scope: this, |
---|
| 248 | iconCls:'x-group-by-icon' |
---|
| 249 | }); |
---|
| 250 | if(this.enableNoGroups){ |
---|
| 251 | this.hmenu.add({ |
---|
| 252 | itemId:'showGroups', |
---|
| 253 | text: this.showGroupsText, |
---|
| 254 | checked: true, |
---|
| 255 | checkHandler: this.onShowGroupsClick, |
---|
| 256 | scope: this |
---|
| 257 | }); |
---|
| 258 | } |
---|
| 259 | this.hmenu.on('beforeshow', this.beforeMenuShow, this); |
---|
| 260 | } |
---|
| 261 | return markup; |
---|
| 262 | }, |
---|
| 263 | |
---|
| 264 | processEvent: function(name, e){ |
---|
| 265 | Ext.grid.GroupingView.superclass.processEvent.call(this, name, e); |
---|
| 266 | var hd = e.getTarget('.x-grid-group-hd', this.mainBody); |
---|
| 267 | if(hd){ |
---|
| 268 | // group value is at the end of the string |
---|
| 269 | var field = this.getGroupField(), |
---|
| 270 | prefix = this.getPrefix(field), |
---|
| 271 | groupValue = hd.id.substring(prefix.length), |
---|
| 272 | emptyRe = new RegExp('gp-' + Ext.escapeRe(field) + '--hd'); |
---|
| 273 | |
---|
| 274 | // remove trailing '-hd' |
---|
| 275 | groupValue = groupValue.substr(0, groupValue.length - 3); |
---|
| 276 | |
---|
| 277 | // also need to check for empty groups |
---|
| 278 | if(groupValue || emptyRe.test(hd.id)){ |
---|
| 279 | this.grid.fireEvent('group' + name, this.grid, field, groupValue, e); |
---|
| 280 | } |
---|
| 281 | if(name == 'mousedown' && e.button == 0){ |
---|
| 282 | this.toggleGroup(hd.parentNode); |
---|
| 283 | } |
---|
| 284 | } |
---|
| 285 | |
---|
| 286 | }, |
---|
| 287 | |
---|
| 288 | // private |
---|
| 289 | onGroupByClick : function(){ |
---|
| 290 | var grid = this.grid; |
---|
| 291 | this.enableGrouping = true; |
---|
| 292 | grid.store.groupBy(this.cm.getDataIndex(this.hdCtxIndex)); |
---|
| 293 | grid.fireEvent('groupchange', grid, grid.store.getGroupState()); |
---|
| 294 | this.beforeMenuShow(); // Make sure the checkboxes get properly set when changing groups |
---|
| 295 | this.refresh(); |
---|
| 296 | }, |
---|
| 297 | |
---|
| 298 | // private |
---|
| 299 | onShowGroupsClick : function(mi, checked){ |
---|
| 300 | this.enableGrouping = checked; |
---|
| 301 | if(checked){ |
---|
| 302 | this.onGroupByClick(); |
---|
| 303 | }else{ |
---|
| 304 | this.grid.store.clearGrouping(); |
---|
| 305 | this.grid.fireEvent('groupchange', this, null); |
---|
| 306 | } |
---|
| 307 | }, |
---|
| 308 | |
---|
| 309 | /** |
---|
| 310 | * Toggle the group that contains the specific row. |
---|
| 311 | * @param {Number} rowIndex The row inside the group |
---|
| 312 | * @param {Boolean} expanded (optional) |
---|
| 313 | */ |
---|
| 314 | toggleRowIndex : function(rowIndex, expanded){ |
---|
| 315 | if(!this.canGroup()){ |
---|
| 316 | return; |
---|
| 317 | } |
---|
| 318 | var row = this.getRow(rowIndex); |
---|
| 319 | if(row){ |
---|
| 320 | this.toggleGroup(this.findGroup(row), expanded); |
---|
| 321 | } |
---|
| 322 | }, |
---|
| 323 | |
---|
| 324 | /** |
---|
| 325 | * Toggles the specified group if no value is passed, otherwise sets the expanded state of the group to the value passed. |
---|
| 326 | * @param {String} groupId The groupId assigned to the group (see getGroupId) |
---|
| 327 | * @param {Boolean} expanded (optional) |
---|
| 328 | */ |
---|
| 329 | toggleGroup : function(group, expanded){ |
---|
| 330 | var gel = Ext.get(group), |
---|
| 331 | id = Ext.util.Format.htmlEncode(gel.id); |
---|
| 332 | |
---|
| 333 | expanded = Ext.isDefined(expanded) ? expanded : gel.hasClass('x-grid-group-collapsed'); |
---|
| 334 | if(this.state[id] !== expanded){ |
---|
| 335 | if (this.cancelEditOnToggle !== false) { |
---|
| 336 | this.grid.stopEditing(true); |
---|
| 337 | } |
---|
| 338 | this.state[id] = expanded; |
---|
| 339 | gel[expanded ? 'removeClass' : 'addClass']('x-grid-group-collapsed'); |
---|
| 340 | } |
---|
| 341 | }, |
---|
| 342 | |
---|
| 343 | /** |
---|
| 344 | * Toggles all groups if no value is passed, otherwise sets the expanded state of all groups to the value passed. |
---|
| 345 | * @param {Boolean} expanded (optional) |
---|
| 346 | */ |
---|
| 347 | toggleAllGroups : function(expanded){ |
---|
| 348 | var groups = this.getGroups(); |
---|
| 349 | for(var i = 0, len = groups.length; i < len; i++){ |
---|
| 350 | this.toggleGroup(groups[i], expanded); |
---|
| 351 | } |
---|
| 352 | }, |
---|
| 353 | |
---|
| 354 | /** |
---|
| 355 | * Expands all grouped rows. |
---|
| 356 | */ |
---|
| 357 | expandAllGroups : function(){ |
---|
| 358 | this.toggleAllGroups(true); |
---|
| 359 | }, |
---|
| 360 | |
---|
| 361 | /** |
---|
| 362 | * Collapses all grouped rows. |
---|
| 363 | */ |
---|
| 364 | collapseAllGroups : function(){ |
---|
| 365 | this.toggleAllGroups(false); |
---|
| 366 | }, |
---|
| 367 | |
---|
| 368 | // private |
---|
| 369 | getGroup : function(v, r, groupRenderer, rowIndex, colIndex, ds){ |
---|
| 370 | var column = this.cm.config[colIndex], |
---|
| 371 | g = groupRenderer ? groupRenderer.call(column.scope, v, {}, r, rowIndex, colIndex, ds) : String(v); |
---|
| 372 | if(g === '' || g === ' '){ |
---|
| 373 | g = column.emptyGroupText || this.emptyGroupText; |
---|
| 374 | } |
---|
| 375 | return g; |
---|
| 376 | }, |
---|
| 377 | |
---|
| 378 | // private |
---|
| 379 | getGroupField : function(){ |
---|
| 380 | return this.grid.store.getGroupState(); |
---|
| 381 | }, |
---|
| 382 | |
---|
| 383 | // private |
---|
| 384 | afterRender : function(){ |
---|
| 385 | if(!this.ds || !this.cm){ |
---|
| 386 | return; |
---|
| 387 | } |
---|
| 388 | Ext.grid.GroupingView.superclass.afterRender.call(this); |
---|
| 389 | if(this.grid.deferRowRender){ |
---|
| 390 | this.updateGroupWidths(); |
---|
| 391 | } |
---|
| 392 | }, |
---|
| 393 | |
---|
| 394 | afterRenderUI: function () { |
---|
| 395 | Ext.grid.GroupingView.superclass.afterRenderUI.call(this); |
---|
| 396 | |
---|
| 397 | if (this.enableGroupingMenu && this.hmenu) { |
---|
| 398 | this.hmenu.add('-',{ |
---|
| 399 | itemId:'groupBy', |
---|
| 400 | text: this.groupByText, |
---|
| 401 | handler: this.onGroupByClick, |
---|
| 402 | scope: this, |
---|
| 403 | iconCls:'x-group-by-icon' |
---|
| 404 | }); |
---|
| 405 | |
---|
| 406 | if (this.enableNoGroups) { |
---|
| 407 | this.hmenu.add({ |
---|
| 408 | itemId:'showGroups', |
---|
| 409 | text: this.showGroupsText, |
---|
| 410 | checked: true, |
---|
| 411 | checkHandler: this.onShowGroupsClick, |
---|
| 412 | scope: this |
---|
| 413 | }); |
---|
| 414 | } |
---|
| 415 | |
---|
| 416 | this.hmenu.on('beforeshow', this.beforeMenuShow, this); |
---|
| 417 | } |
---|
| 418 | }, |
---|
| 419 | |
---|
| 420 | // private |
---|
| 421 | renderRows : function(){ |
---|
| 422 | var groupField = this.getGroupField(); |
---|
| 423 | var eg = !!groupField; |
---|
| 424 | // if they turned off grouping and the last grouped field is hidden |
---|
| 425 | if(this.hideGroupedColumn) { |
---|
| 426 | var colIndex = this.cm.findColumnIndex(groupField), |
---|
| 427 | hasLastGroupField = Ext.isDefined(this.lastGroupField); |
---|
| 428 | if(!eg && hasLastGroupField){ |
---|
| 429 | this.mainBody.update(''); |
---|
| 430 | this.cm.setHidden(this.cm.findColumnIndex(this.lastGroupField), false); |
---|
| 431 | delete this.lastGroupField; |
---|
| 432 | }else if (eg && !hasLastGroupField){ |
---|
| 433 | this.lastGroupField = groupField; |
---|
| 434 | this.cm.setHidden(colIndex, true); |
---|
| 435 | }else if (eg && hasLastGroupField && groupField !== this.lastGroupField) { |
---|
| 436 | this.mainBody.update(''); |
---|
| 437 | var oldIndex = this.cm.findColumnIndex(this.lastGroupField); |
---|
| 438 | this.cm.setHidden(oldIndex, false); |
---|
| 439 | this.lastGroupField = groupField; |
---|
| 440 | this.cm.setHidden(colIndex, true); |
---|
| 441 | } |
---|
| 442 | } |
---|
| 443 | return Ext.grid.GroupingView.superclass.renderRows.apply( |
---|
| 444 | this, arguments); |
---|
| 445 | }, |
---|
| 446 | |
---|
| 447 | // private |
---|
| 448 | doRender : function(cs, rs, ds, startRow, colCount, stripe){ |
---|
| 449 | if(rs.length < 1){ |
---|
| 450 | return ''; |
---|
| 451 | } |
---|
| 452 | |
---|
| 453 | if(!this.canGroup() || this.isUpdating){ |
---|
| 454 | return Ext.grid.GroupingView.superclass.doRender.apply(this, arguments); |
---|
| 455 | } |
---|
| 456 | |
---|
| 457 | var groupField = this.getGroupField(), |
---|
| 458 | colIndex = this.cm.findColumnIndex(groupField), |
---|
| 459 | g, |
---|
| 460 | gstyle = 'width:' + this.getTotalWidth() + ';', |
---|
| 461 | cfg = this.cm.config[colIndex], |
---|
| 462 | groupRenderer = cfg.groupRenderer || cfg.renderer, |
---|
| 463 | prefix = this.showGroupName ? (cfg.groupName || cfg.header)+': ' : '', |
---|
| 464 | groups = [], |
---|
| 465 | curGroup, i, len, gid; |
---|
| 466 | |
---|
| 467 | for(i = 0, len = rs.length; i < len; i++){ |
---|
| 468 | var rowIndex = startRow + i, |
---|
| 469 | r = rs[i], |
---|
| 470 | gvalue = r.data[groupField]; |
---|
| 471 | |
---|
| 472 | g = this.getGroup(gvalue, r, groupRenderer, rowIndex, colIndex, ds); |
---|
| 473 | if(!curGroup || curGroup.group != g){ |
---|
| 474 | gid = this.constructId(gvalue, groupField, colIndex); |
---|
| 475 | // if state is defined use it, however state is in terms of expanded |
---|
| 476 | // so negate it, otherwise use the default. |
---|
| 477 | this.state[gid] = !(Ext.isDefined(this.state[gid]) ? !this.state[gid] : this.startCollapsed); |
---|
| 478 | curGroup = { |
---|
| 479 | group: g, |
---|
| 480 | gvalue: gvalue, |
---|
| 481 | text: prefix + g, |
---|
| 482 | groupId: gid, |
---|
| 483 | startRow: rowIndex, |
---|
| 484 | rs: [r], |
---|
| 485 | cls: this.state[gid] ? '' : 'x-grid-group-collapsed', |
---|
| 486 | style: gstyle |
---|
| 487 | }; |
---|
| 488 | groups.push(curGroup); |
---|
| 489 | }else{ |
---|
| 490 | curGroup.rs.push(r); |
---|
| 491 | } |
---|
| 492 | r._groupId = gid; |
---|
| 493 | } |
---|
| 494 | |
---|
| 495 | var buf = []; |
---|
| 496 | for(i = 0, len = groups.length; i < len; i++){ |
---|
| 497 | g = groups[i]; |
---|
| 498 | this.doGroupStart(buf, g, cs, ds, colCount); |
---|
| 499 | buf[buf.length] = Ext.grid.GroupingView.superclass.doRender.call( |
---|
| 500 | this, cs, g.rs, ds, g.startRow, colCount, stripe); |
---|
| 501 | |
---|
| 502 | this.doGroupEnd(buf, g, cs, ds, colCount); |
---|
| 503 | } |
---|
| 504 | return buf.join(''); |
---|
| 505 | }, |
---|
| 506 | |
---|
| 507 | /** |
---|
| 508 | * Dynamically tries to determine the groupId of a specific value |
---|
| 509 | * @param {String} value |
---|
| 510 | * @return {String} The group id |
---|
| 511 | */ |
---|
| 512 | getGroupId : function(value){ |
---|
| 513 | var field = this.getGroupField(); |
---|
| 514 | return this.constructId(value, field, this.cm.findColumnIndex(field)); |
---|
| 515 | }, |
---|
| 516 | |
---|
| 517 | // private |
---|
| 518 | constructId : function(value, field, idx){ |
---|
| 519 | var cfg = this.cm.config[idx], |
---|
| 520 | groupRenderer = cfg.groupRenderer || cfg.renderer, |
---|
| 521 | val = (this.groupMode == 'value') ? value : this.getGroup(value, {data:{}}, groupRenderer, 0, idx, this.ds); |
---|
| 522 | |
---|
| 523 | return this.getPrefix(field) + Ext.util.Format.htmlEncode(val); |
---|
| 524 | }, |
---|
| 525 | |
---|
| 526 | // private |
---|
| 527 | canGroup : function(){ |
---|
| 528 | return this.enableGrouping && !!this.getGroupField(); |
---|
| 529 | }, |
---|
| 530 | |
---|
| 531 | // private |
---|
| 532 | getPrefix: function(field){ |
---|
| 533 | return this.grid.getGridEl().id + '-gp-' + field + '-'; |
---|
| 534 | }, |
---|
| 535 | |
---|
| 536 | // private |
---|
| 537 | doGroupStart : function(buf, g, cs, ds, colCount){ |
---|
| 538 | buf[buf.length] = this.startGroup.apply(g); |
---|
| 539 | }, |
---|
| 540 | |
---|
| 541 | // private |
---|
| 542 | doGroupEnd : function(buf, g, cs, ds, colCount){ |
---|
| 543 | buf[buf.length] = this.endGroup; |
---|
| 544 | }, |
---|
| 545 | |
---|
| 546 | // private |
---|
| 547 | getRows : function(){ |
---|
| 548 | if(!this.canGroup()){ |
---|
| 549 | return Ext.grid.GroupingView.superclass.getRows.call(this); |
---|
| 550 | } |
---|
| 551 | var r = [], |
---|
| 552 | gs = this.getGroups(), |
---|
| 553 | g, |
---|
| 554 | i = 0, |
---|
| 555 | len = gs.length, |
---|
| 556 | j, |
---|
| 557 | jlen; |
---|
| 558 | for(; i < len; ++i){ |
---|
| 559 | g = gs[i].childNodes[1]; |
---|
| 560 | if(g){ |
---|
| 561 | g = g.childNodes; |
---|
| 562 | for(j = 0, jlen = g.length; j < jlen; ++j){ |
---|
| 563 | r[r.length] = g[j]; |
---|
| 564 | } |
---|
| 565 | } |
---|
| 566 | } |
---|
| 567 | return r; |
---|
| 568 | }, |
---|
| 569 | |
---|
| 570 | // private |
---|
| 571 | updateGroupWidths : function(){ |
---|
| 572 | if(!this.canGroup() || !this.hasRows()){ |
---|
| 573 | return; |
---|
| 574 | } |
---|
| 575 | var tw = Math.max(this.cm.getTotalWidth(), this.el.dom.offsetWidth-this.getScrollOffset()) +'px'; |
---|
| 576 | var gs = this.getGroups(); |
---|
| 577 | for(var i = 0, len = gs.length; i < len; i++){ |
---|
| 578 | gs[i].firstChild.style.width = tw; |
---|
| 579 | } |
---|
| 580 | }, |
---|
| 581 | |
---|
| 582 | // private |
---|
| 583 | onColumnWidthUpdated : function(col, w, tw){ |
---|
| 584 | Ext.grid.GroupingView.superclass.onColumnWidthUpdated.call(this, col, w, tw); |
---|
| 585 | this.updateGroupWidths(); |
---|
| 586 | }, |
---|
| 587 | |
---|
| 588 | // private |
---|
| 589 | onAllColumnWidthsUpdated : function(ws, tw){ |
---|
| 590 | Ext.grid.GroupingView.superclass.onAllColumnWidthsUpdated.call(this, ws, tw); |
---|
| 591 | this.updateGroupWidths(); |
---|
| 592 | }, |
---|
| 593 | |
---|
| 594 | // private |
---|
| 595 | onColumnHiddenUpdated : function(col, hidden, tw){ |
---|
| 596 | Ext.grid.GroupingView.superclass.onColumnHiddenUpdated.call(this, col, hidden, tw); |
---|
| 597 | this.updateGroupWidths(); |
---|
| 598 | }, |
---|
| 599 | |
---|
| 600 | // private |
---|
| 601 | onLayout : function(){ |
---|
| 602 | this.updateGroupWidths(); |
---|
| 603 | }, |
---|
| 604 | |
---|
| 605 | // private |
---|
| 606 | onBeforeRowSelect : function(sm, rowIndex){ |
---|
| 607 | this.toggleRowIndex(rowIndex, true); |
---|
| 608 | } |
---|
| 609 | }); |
---|
| 610 | // private |
---|
| 611 | Ext.grid.GroupingView.GROUP_ID = 1000; |
---|