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