Upgrade to ExtJS 3.3.1 - Released 11/30/2010
[extjs.git] / examples / grid / multiple-sorting.js
1 /*!
2  * Ext JS Library 3.3.1
3  * Copyright(c) 2006-2010 Sencha Inc.
4  * licensing@sencha.com
5  * http://www.sencha.com/license
6  */
7 Ext.onReady(function() {
8     // create the data store
9     var store = new Ext.data.ArrayStore({
10         fields: [
11            {name: 'rating', type: 'int'},
12            {name: 'salary', type: 'float'},
13            {name: 'name'}
14         ]
15     });
16
17     // manually load local fake data
18     store.loadData(createFakeData(25));
19     
20     var reorderer = new Ext.ux.ToolbarReorderer();
21     var droppable = new Ext.ux.ToolbarDroppable({
22         /**
23          * Creates the new toolbar item from the drop event
24          */
25         createItem: function(data) {
26             var column = this.getColumnFromDragDrop(data);
27             
28             return createSorterButton({
29                 text    : column.header,
30                 sortData: {
31                     field: column.dataIndex,
32                     direction: "ASC"
33                 }
34             });
35         },
36
37         /**
38          * Custom canDrop implementation which returns true if a column can be added to the toolbar
39          * @param {Object} data Arbitrary data from the drag source
40          * @return {Boolean} True if the drop is allowed
41          */
42         canDrop: function(dragSource, event, data) {
43             var sorters = getSorters(),
44                 column  = this.getColumnFromDragDrop(data);
45
46             for (var i=0; i < sorters.length; i++) {
47                 if (sorters[i].field == column.dataIndex) return false;
48             }
49
50             return true;
51         },
52         
53         afterLayout: doSort,
54
55         /**
56          * Helper function used to find the column that was dragged
57          * @param {Object} data Arbitrary data from
58          */
59         getColumnFromDragDrop: function(data) {
60             var index    = data.header.cellIndex,
61                 colModel = grid.colModel,
62                 column   = colModel.getColumnById(colModel.getColumnId(index));
63
64             return column;
65         }
66     });
67     
68     //create the toolbar with the 2 plugins
69     var tbar = new Ext.Toolbar({
70         items  : ['Sorting order:', '-'],
71         plugins: [reorderer, droppable],
72         listeners: {
73             scope    : this,
74             reordered: function(button) {
75                 changeSortDirection(button, false);
76             }
77         }
78     });
79     
80     // create the Grid
81     var grid = new Ext.grid.GridPanel({
82         tbar : tbar,
83         store: store,
84         
85         columns: [
86             {header: 'Name',   width: 160, sortable: false, dataIndex: 'name',   id:'company'},
87             {header: 'Rating', width: 125, sortable: false, dataIndex: 'rating'},
88             {header: 'Salary', width: 125, sortable: false, dataIndex: 'salary', renderer: 'usMoney'}
89         ],
90         autoExpandColumn: 'company',
91         stripeRows: true,
92         
93         height: 350,
94         width : 600,
95         title : 'Array Grid',
96         
97         listeners: {
98             scope: this,
99             
100             //here we tell the toolbar's droppable plugin that it can accept items from the columns' dragdrop group
101             render: function() {
102                 var dragProxy = grid.getView().columnDrag,
103                     ddGroup   = dragProxy.ddGroup;
104                 
105                 droppable.addDDGroup(ddGroup);
106             }
107         }
108     });
109     
110     tbar.add(createSorterButton({
111         text: 'Rating',
112         sortData: {
113             field: 'rating',
114             direction: 'DESC'
115         }
116     }));
117     
118     tbar.add(createSorterButton({
119         text: 'Salary',
120         sortData: {
121             field: 'salary',
122             direction: 'ASC'
123         }
124     }));
125     
126     // render the grid to the specified div in the page
127     grid.render('grid-example');
128     doSort();
129     
130     //The following functions are used to get the sorting data from the toolbar and apply it to the store
131     
132     /**
133      * Tells the store to sort itself according to our sort data
134      */
135     function doSort() {
136         store.sort(getSorters(), "ASC");
137     };
138     
139     /**
140      * Callback handler used when a sorter button is clicked or reordered
141      * @param {Ext.Button} button The button that was clicked
142      * @param {Boolean} changeDirection True to change direction (default). Set to false for reorder
143      * operations as we wish to preserve ordering there
144      */
145     function changeSortDirection(button, changeDirection) {
146         var sortData = button.sortData,
147             iconCls  = button.iconCls;
148         
149         if (sortData != undefined) {
150             if (changeDirection !== false) {
151                 button.sortData.direction = button.sortData.direction.toggle("ASC", "DESC");
152                 button.setIconClass(iconCls.toggle("sort-asc", "sort-desc"));
153             }
154             
155             store.clearFilter();
156             doSort();
157         }
158     };
159     
160     /**
161      * Returns an array of sortData from the sorter buttons
162      * @return {Array} Ordered sort data from each of the sorter buttons
163      */
164     function getSorters() {
165         var sorters = [];
166         
167         Ext.each(tbar.findByType('button'), function(button) {
168             sorters.push(button.sortData);
169         }, this);
170         
171         return sorters;
172     }
173     
174     /**
175      * Convenience function for creating Toolbar Buttons that are tied to sorters
176      * @param {Object} config Optional config object
177      * @return {Ext.Button} The new Button object
178      */
179     function createSorterButton(config) {
180         config = config || {};
181               
182         Ext.applyIf(config, {
183             listeners: {
184                 click: function(button, e) {
185                     changeSortDirection(button, true);                    
186                 }
187             },
188             iconCls: 'sort-' + config.sortData.direction.toLowerCase(),
189             reorderable: true
190         });
191         
192         return new Ext.Button(config);
193     };
194     
195     /**
196      * Returns an array of fake data
197      * @param {Number} count The number of fake rows to create data for
198      * @return {Array} The fake record data, suitable for usage with an ArrayReader
199      */
200     function createFakeData(count) {
201         var firstNames   = ['Ed', 'Tommy', 'Aaron', 'Abe', 'Jamie', 'Adam', 'Dave', 'David', 'Jay'],
202             lastNames    = ['Spencer', 'Maintz', 'Conran', 'Elias', 'Avins', 'Mishcon', 'Kaneda', 'Davis', 'Robinson'],
203             ratings      = [1, 2, 3, 4, 5],
204             salaries     = [100, 400, 900, 1500, 1000000];
205
206         var data = [];
207         for (var i=0; i < (count || 25); i++) {
208             var ratingId    = Math.floor(Math.random() * ratings.length),
209                 salaryId    = Math.floor(Math.random() * salaries.length),
210                 firstNameId = Math.floor(Math.random() * firstNames.length),
211                 lastNameId  = Math.floor(Math.random() * lastNames.length),
212
213                 rating      = ratings[ratingId],
214                 salary      = salaries[salaryId],
215                 name        = String.format("{0} {1}", firstNames[firstNameId], lastNames[lastNameId]);
216
217             data.push([rating, salary, name]);
218         }
219         
220         return data;
221     }
222 });