Upgrade to ExtJS 3.1.1 - Released 02/08/2010
[extjs.git] / src / data / GroupingStore.js
1 /*!
2  * Ext JS Library 3.1.1
3  * Copyright(c) 2006-2010 Ext JS, LLC
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7 /**\r
8  * @class Ext.data.GroupingStore\r
9  * @extends Ext.data.Store\r
10  * A specialized store implementation that provides for grouping records by one of the available fields. This\r
11  * is usually used in conjunction with an {@link Ext.grid.GroupingView} to proved the data model for\r
12  * a grouped GridPanel.\r
13  * @constructor\r
14  * Creates a new GroupingStore.\r
15  * @param {Object} config A config object containing the objects needed for the Store to access data,\r
16  * and read the data into Records.\r
17  * @xtype groupingstore\r
18  */\r
19 Ext.data.GroupingStore = Ext.extend(Ext.data.Store, {\r
20 \r
21     //inherit docs\r
22     constructor: function(config){\r
23         Ext.data.GroupingStore.superclass.constructor.call(this, config);\r
24         this.applyGroupField();\r
25     },\r
26 \r
27     /**\r
28      * @cfg {String} groupField\r
29      * The field name by which to sort the store's data (defaults to '').\r
30      */\r
31     /**\r
32      * @cfg {Boolean} remoteGroup\r
33      * True if the grouping should apply on the server side, false if it is local only (defaults to false).  If the\r
34      * grouping is local, it can be applied immediately to the data.  If it is remote, then it will simply act as a\r
35      * helper, automatically sending the grouping field name as the 'groupBy' param with each XHR call.\r
36      */\r
37     remoteGroup : false,\r
38     /**\r
39      * @cfg {Boolean} groupOnSort\r
40      * True to sort the data on the grouping field when a grouping operation occurs, false to sort based on the\r
41      * existing sort info (defaults to false).\r
42      */\r
43     groupOnSort:false,\r
44 \r
45     groupDir : 'ASC',\r
46 \r
47     /**\r
48      * Clears any existing grouping and refreshes the data using the default sort.\r
49      */\r
50     clearGrouping : function(){\r
51         this.groupField = false;\r
52 \r
53         if(this.remoteGroup){\r
54             if(this.baseParams){\r
55                 delete this.baseParams.groupBy;\r
56                 delete this.baseParams.groupDir;\r
57             }\r
58             var lo = this.lastOptions;\r
59             if(lo && lo.params){\r
60                 delete lo.params.groupBy;\r
61                 delete lo.params.groupDir;\r
62             }\r
63 \r
64             this.reload();\r
65         }else{\r
66             this.applySort();\r
67             this.fireEvent('datachanged', this);\r
68         }\r
69     },\r
70 \r
71     /**\r
72      * Groups the data by the specified field.\r
73      * @param {String} field The field name by which to sort the store's data\r
74      * @param {Boolean} forceRegroup (optional) True to force the group to be refreshed even if the field passed\r
75      * in is the same as the current grouping field, false to skip grouping on the same field (defaults to false)\r
76      */\r
77     groupBy : function(field, forceRegroup, direction){\r
78         direction = direction ? (String(direction).toUpperCase() == 'DESC' ? 'DESC' : 'ASC') : this.groupDir;\r
79         if(this.groupField == field && this.groupDir == direction && !forceRegroup){\r
80             return; // already grouped by this field\r
81         }\r
82         this.groupField = field;\r
83         this.groupDir = direction;\r
84         this.applyGroupField();\r
85         if(this.groupOnSort){\r
86             this.sort(field, direction);\r
87             return;\r
88         }\r
89         if(this.remoteGroup){\r
90             this.reload();\r
91         }else{\r
92             var si = this.sortInfo || {};\r
93             if(forceRegroup || si.field != field || si.direction != direction){\r
94                 this.applySort();\r
95             }else{\r
96                 this.sortData(field, direction);\r
97             }\r
98             this.fireEvent('datachanged', this);\r
99         }\r
100     },\r
101 \r
102     // private\r
103     applyGroupField: function(){\r
104         if(this.remoteGroup){\r
105             if(!this.baseParams){\r
106                 this.baseParams = {};\r
107             }\r
108             Ext.apply(this.baseParams, {\r
109                 groupBy : this.groupField,\r
110                 groupDir : this.groupDir\r
111             });\r
112 \r
113             var lo = this.lastOptions;\r
114             if(lo && lo.params){\r
115                 Ext.apply(lo.params, {\r
116                     groupBy : this.groupField,\r
117                     groupDir : this.groupDir\r
118                 });\r
119             }\r
120         }\r
121     },\r
122 \r
123     // private\r
124     applySort : function(){\r
125         Ext.data.GroupingStore.superclass.applySort.call(this);\r
126         if(!this.groupOnSort && !this.remoteGroup){\r
127             var gs = this.getGroupState();\r
128             if(gs && (gs != this.sortInfo.field || this.groupDir != this.sortInfo.direction)){\r
129                 this.sortData(this.groupField, this.groupDir);\r
130             }\r
131         }\r
132     },\r
133 \r
134     // private\r
135     applyGrouping : function(alwaysFireChange){\r
136         if(this.groupField !== false){\r
137             this.groupBy(this.groupField, true, this.groupDir);\r
138             return true;\r
139         }else{\r
140             if(alwaysFireChange === true){\r
141                 this.fireEvent('datachanged', this);\r
142             }\r
143             return false;\r
144         }\r
145     },\r
146 \r
147     // private\r
148     getGroupState : function(){\r
149         return this.groupOnSort && this.groupField !== false ?\r
150                (this.sortInfo ? this.sortInfo.field : undefined) : this.groupField;\r
151     }\r
152 });\r
153 Ext.reg('groupingstore', Ext.data.GroupingStore);