3 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
4 <title>The source code</title>
5 <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
6 <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
8 <body onload="prettyPrint();">
9 <pre class="prettyprint lang-js">/*!
10 * Ext JS Library 3.3.1
11 * Copyright(c) 2006-2010 Sencha Inc.
12 * licensing@sencha.com
13 * http://www.sencha.com/license
15 <div id="cls-Ext.data.GroupingStore"></div>/**
16 * @class Ext.data.GroupingStore
17 * @extends Ext.data.Store
18 * A specialized store implementation that provides for grouping records by one of the available fields. This
19 * is usually used in conjunction with an {@link Ext.grid.GroupingView} to provide the data model for
20 * a grouped GridPanel.
22 * Internally, GroupingStore is simply a normal Store with multi sorting enabled from the start. The grouping field
23 * and direction are always injected as the first sorter pair. GroupingView picks up on the configured groupField and
24 * builds grid rows appropriately.
27 * Creates a new GroupingStore.
28 * @param {Object} config A config object containing the objects needed for the Store to access data,
29 * and read the data into Records.
30 * @xtype groupingstore
32 Ext.data.GroupingStore = Ext.extend(Ext.data.Store, {
35 constructor: function(config) {
36 config = config || {};
38 //We do some preprocessing here to massage the grouping + sorting options into a single
39 //multi sort array. If grouping and sorting options are both presented to the constructor,
40 //the sorters array consists of the grouping sorter object followed by the sorting sorter object
41 //see Ext.data.Store's sorting functions for details about how multi sorting works
42 this.hasMultiSort = true;
43 this.multiSortInfo = this.multiSortInfo || {sorters: []};
45 var sorters = this.multiSortInfo.sorters,
46 groupField = config.groupField || this.groupField,
47 sortInfo = config.sortInfo || this.sortInfo,
48 groupDir = config.groupDir || this.groupDir;
50 //add the grouping sorter object first
58 //add the sorting sorter object if it is present
60 sorters.push(sortInfo);
63 Ext.data.GroupingStore.superclass.constructor.call(this, config);
66 <div id="event-Ext.data.GroupingStore-groupchange"></div>/**
68 * Fired whenever a call to store.groupBy successfully changes the grouping on the store
69 * @param {Ext.data.GroupingStore} store The grouping store
70 * @param {String} groupField The field that the store is now grouped by
75 this.applyGroupField();
78 <div id="cfg-Ext.data.GroupingStore-groupField"></div>/**
79 * @cfg {String} groupField
80 * The field name by which to sort the store's data (defaults to '').
82 <div id="cfg-Ext.data.GroupingStore-remoteGroup"></div>/**
83 * @cfg {Boolean} remoteGroup
84 * True if the grouping should apply on the server side, false if it is local only (defaults to false). If the
85 * grouping is local, it can be applied immediately to the data. If it is remote, then it will simply act as a
86 * helper, automatically sending the grouping field name as the 'groupBy' param with each XHR call.
89 <div id="cfg-Ext.data.GroupingStore-groupOnSort"></div>/**
90 * @cfg {Boolean} groupOnSort
91 * True to sort the data on the grouping field when a grouping operation occurs, false to sort based on the
92 * existing sort info (defaults to false).
96 <div id="cfg-Ext.data.GroupingStore-groupDir"></div>/**
97 * @cfg {String} groupDir
98 * The direction to sort the groups. Defaults to <tt>'ASC'</tt>.
102 <div id="method-Ext.data.GroupingStore-clearGrouping"></div>/**
103 * Clears any existing grouping and refreshes the data using the default sort.
105 clearGrouping : function(){
106 this.groupField = false;
108 if(this.remoteGroup){
110 delete this.baseParams.groupBy;
111 delete this.baseParams.groupDir;
113 var lo = this.lastOptions;
115 delete lo.params.groupBy;
116 delete lo.params.groupDir;
122 this.fireEvent('datachanged', this);
126 <div id="method-Ext.data.GroupingStore-groupBy"></div>/**
127 * Groups the data by the specified field.
128 * @param {String} field The field name by which to sort the store's data
129 * @param {Boolean} forceRegroup (optional) True to force the group to be refreshed even if the field passed
130 * in is the same as the current grouping field, false to skip grouping on the same field (defaults to false)
132 groupBy : function(field, forceRegroup, direction) {
133 direction = direction ? (String(direction).toUpperCase() == 'DESC' ? 'DESC' : 'ASC') : this.groupDir;
135 if (this.groupField == field && this.groupDir == direction && !forceRegroup) {
136 return; // already grouped by this field
139 //check the contents of the first sorter. If the field matches the CURRENT groupField (before it is set to the new one),
140 //remove the sorter as it is actually the grouper. The new grouper is added back in by this.sort
141 var sorters = this.multiSortInfo.sorters;
142 if (sorters.length > 0 && sorters[0].field == this.groupField) {
146 this.groupField = field;
147 this.groupDir = direction;
148 this.applyGroupField();
150 var fireGroupEvent = function() {
151 this.fireEvent('groupchange', this, this.getGroupState());
154 if (this.groupOnSort) {
155 this.sort(field, direction);
156 fireGroupEvent.call(this);
160 if (this.remoteGroup) {
161 this.on('load', fireGroupEvent, this, {single: true});
165 fireGroupEvent.call(this);
169 //GroupingStore always uses multisorting so we intercept calls to sort here to make sure that our grouping sorter object
170 //is always injected first.
171 sort : function(fieldName, dir) {
172 if (this.remoteSort) {
173 return Ext.data.GroupingStore.superclass.sort.call(this, fieldName, dir);
178 //cater for any existing valid arguments to this.sort, massage them into an array of sorter objects
179 if (Ext.isArray(arguments[0])) {
180 sorters = arguments[0];
181 } else if (fieldName == undefined) {
182 //we preserve the existing sortInfo here because this.sort is called after
183 //clearGrouping and there may be existing sorting
184 sorters = this.sortInfo ? [this.sortInfo] : [];
186 //TODO: this is lifted straight from Ext.data.Store's singleSort function. It should instead be
187 //refactored into a common method if possible
188 var field = this.fields.get(fieldName);
189 if (!field) return false;
191 var name = field.name,
192 sortInfo = this.sortInfo || null,
193 sortToggle = this.sortToggle ? this.sortToggle[name] : null;
196 if (sortInfo && sortInfo.field == name) { // toggle sort dir
197 dir = (this.sortToggle[name] || 'ASC').toggle('ASC', 'DESC');
203 this.sortToggle[name] = dir;
204 this.sortInfo = {field: name, direction: dir};
206 sorters = [this.sortInfo];
209 //add the grouping sorter object as the first multisort sorter
210 if (this.groupField) {
211 sorters.unshift({direction: this.groupDir, field: this.groupField});
214 return this.multiSort.call(this, sorters, dir);
219 * Saves the current grouping field and direction to this.baseParams and this.lastOptions.params
220 * if we're using remote grouping. Does not actually perform any grouping - just stores values
222 applyGroupField: function(){
223 if (this.remoteGroup) {
224 if(!this.baseParams){
225 this.baseParams = {};
228 Ext.apply(this.baseParams, {
229 groupBy : this.groupField,
230 groupDir: this.groupDir
233 var lo = this.lastOptions;
234 if (lo && lo.params) {
235 lo.params.groupDir = this.groupDir;
237 //this is deleted because of a bug reported at http://www.extjs.com/forum/showthread.php?t=82907
238 delete lo.params.groupBy;
245 * TODO: This function is apparently never invoked anywhere in the framework. It has no documentation
246 * and should be considered for deletion
248 applyGrouping : function(alwaysFireChange){
249 if(this.groupField !== false){
250 this.groupBy(this.groupField, true, this.groupDir);
253 if(alwaysFireChange === true){
254 this.fireEvent('datachanged', this);
262 * Returns the grouping field that should be used. If groupOnSort is used this will be sortInfo's field,
263 * otherwise it will be this.groupField
264 * @return {String} The group field
266 getGroupState : function(){
267 return this.groupOnSort && this.groupField !== false ?
268 (this.sortInfo ? this.sortInfo.field : undefined) : this.groupField;
271 Ext.reg('groupingstore', Ext.data.GroupingStore);