Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / docs / source / Sortable.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5   <title>The source code</title>
6   <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
7   <script type="text/javascript" src="../prettify/prettify.js"></script>
8   <style type="text/css">
9     .highlight { display: block; background-color: #ddd; }
10   </style>
11   <script type="text/javascript">
12     function highlight() {
13       document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
14     }
15   </script>
16 </head>
17 <body onload="prettyPrint(); highlight();">
18   <pre class="prettyprint lang-js"><span id='Ext-util-Sortable'>/**
19 </span> * @class Ext.util.Sortable
20
21 A mixin which allows a data component to be sorted. This is used by e.g. {@link Ext.data.Store} and {@link Ext.data.TreeStore}.
22
23 **NOTE**: This mixin is mainly for internal library use and most users should not need to use it directly. It
24 is more likely you will want to use one of the component classes that import this mixin, such as
25 {@link Ext.data.Store} or {@link Ext.data.TreeStore}.
26  * @markdown
27  * @docauthor Tommy Maintz &lt;tommy@sencha.com&gt;
28  */
29 Ext.define(&quot;Ext.util.Sortable&quot;, {
30 <span id='Ext-util-Sortable-property-isSortable'>    /**
31 </span>     * @property isSortable
32      * @type Boolean
33      * Flag denoting that this object is sortable. Always true.
34      */
35     isSortable: true,
36     
37 <span id='Ext-util-Sortable-property-defaultSortDirection'>    /**
38 </span>     * The default sort direction to use if one is not specified (defaults to &quot;ASC&quot;)
39      * @property defaultSortDirection
40      * @type String
41      */
42     defaultSortDirection: &quot;ASC&quot;,
43     
44     requires: [
45         'Ext.util.Sorter'
46     ],
47
48 <span id='Ext-util-Sortable-property-'>    /**
49 </span>     * The property in each item that contains the data to sort.
50      * @type String
51      */    
52     
53 <span id='Ext-util-Sortable-method-initSortable'>    /**
54 </span>     * Performs initialization of this mixin. Component classes using this mixin should call this method
55      * during their own initialization.
56      */
57     initSortable: function() {
58         var me = this,
59             sorters = me.sorters;
60         
61 <span id='Ext-util-Sortable-property-sorters'>        /**
62 </span>         * The collection of {@link Ext.util.Sorter Sorters} currently applied to this Store
63          * @property sorters
64          * @type Ext.util.MixedCollection
65          */
66         me.sorters = Ext.create('Ext.util.AbstractMixedCollection', false, function(item) {
67             return item.id || item.property;
68         });
69         
70         if (sorters) {
71             me.sorters.addAll(me.decodeSorters(sorters));
72         }
73     },
74
75 <span id='Ext-util-Sortable-method-sort'>    /**
76 </span>     * &lt;p&gt;Sorts the data in the Store by one or more of its properties. Example usage:&lt;/p&gt;
77 &lt;pre&gt;&lt;code&gt;
78 //sort by a single field
79 myStore.sort('myField', 'DESC');
80
81 //sorting by multiple fields
82 myStore.sort([
83     {
84         property : 'age',
85         direction: 'ASC'
86     },
87     {
88         property : 'name',
89         direction: 'DESC'
90     }
91 ]);
92 &lt;/code&gt;&lt;/pre&gt;
93      * &lt;p&gt;Internally, Store converts the passed arguments into an array of {@link Ext.util.Sorter} instances, and delegates the actual
94      * sorting to its internal {@link Ext.util.MixedCollection}.&lt;/p&gt;
95      * &lt;p&gt;When passing a single string argument to sort, Store maintains a ASC/DESC toggler per field, so this code:&lt;/p&gt;
96 &lt;pre&gt;&lt;code&gt;
97 store.sort('myField');
98 store.sort('myField');
99      &lt;/code&gt;&lt;/pre&gt;
100      * &lt;p&gt;Is equivalent to this code, because Store handles the toggling automatically:&lt;/p&gt;
101 &lt;pre&gt;&lt;code&gt;
102 store.sort('myField', 'ASC');
103 store.sort('myField', 'DESC');
104 &lt;/code&gt;&lt;/pre&gt;
105      * @param {String|Array} sorters Either a string name of one of the fields in this Store's configured {@link Ext.data.Model Model},
106      * or an Array of sorter configurations.
107      * @param {String} direction The overall direction to sort the data by. Defaults to &quot;ASC&quot;.
108      */
109     sort: function(sorters, direction, where, doSort) {
110         var me = this,
111             sorter, sorterFn,
112             newSorters;
113         
114         if (Ext.isArray(sorters)) {
115             doSort = where;
116             where = direction;
117             newSorters = sorters;
118         }
119         else if (Ext.isObject(sorters)) {
120             doSort = where;
121             where = direction;
122             newSorters = [sorters];
123         }
124         else if (Ext.isString(sorters)) {
125             sorter = me.sorters.get(sorters);
126
127             if (!sorter) {
128                 sorter = {
129                     property : sorters,
130                     direction: direction
131                 };
132                 newSorters = [sorter];
133             }
134             else if (direction === undefined) {
135                 sorter.toggle();
136             }
137             else {
138                 sorter.setDirection(direction);
139             }
140         }
141         
142         if (newSorters &amp;&amp; newSorters.length) {
143             newSorters = me.decodeSorters(newSorters);
144             if (Ext.isString(where)) {
145                 if (where === 'prepend') {
146                     sorters = me.sorters.clone().items;
147                     
148                     me.sorters.clear();
149                     me.sorters.addAll(newSorters);
150                     me.sorters.addAll(sorters);
151                 }
152                 else {
153                     me.sorters.addAll(newSorters);
154                 }
155             }
156             else {
157                 me.sorters.clear();
158                 me.sorters.addAll(newSorters);
159             }
160             
161             if (doSort !== false) {
162                 me.onBeforeSort(newSorters);
163             }
164         }
165         
166         if (doSort !== false) {
167             sorters = me.sorters.items;
168             if (sorters.length) {
169                 //construct an amalgamated sorter function which combines all of the Sorters passed
170                 sorterFn = function(r1, r2) {
171                     var result = sorters[0].sort(r1, r2),
172                         length = sorters.length,
173                         i;
174
175                         //if we have more than one sorter, OR any additional sorter functions together
176                         for (i = 1; i &lt; length; i++) {
177                             result = result || sorters[i].sort.call(this, r1, r2);
178                         }
179
180                     return result;
181                 };
182
183                 me.doSort(sorterFn);                
184             }
185         }
186         
187         return sorters;
188     },
189     
190     onBeforeSort: Ext.emptyFn,
191         
192 <span id='Ext-util-Sortable-method-decodeSorters'>    /**
193 </span>     * @private
194      * Normalizes an array of sorter objects, ensuring that they are all Ext.util.Sorter instances
195      * @param {Array} sorters The sorters array
196      * @return {Array} Array of Ext.util.Sorter objects
197      */
198     decodeSorters: function(sorters) {
199         if (!Ext.isArray(sorters)) {
200             if (sorters === undefined) {
201                 sorters = [];
202             } else {
203                 sorters = [sorters];
204             }
205         }
206
207         var length = sorters.length,
208             Sorter = Ext.util.Sorter,
209             fields = this.model ? this.model.prototype.fields : null,
210             field,
211             config, i;
212
213         for (i = 0; i &lt; length; i++) {
214             config = sorters[i];
215
216             if (!(config instanceof Sorter)) {
217                 if (Ext.isString(config)) {
218                     config = {
219                         property: config
220                     };
221                 }
222                 
223                 Ext.applyIf(config, {
224                     root     : this.sortRoot,
225                     direction: &quot;ASC&quot;
226                 });
227
228                 //support for 3.x style sorters where a function can be defined as 'fn'
229                 if (config.fn) {
230                     config.sorterFn = config.fn;
231                 }
232
233                 //support a function to be passed as a sorter definition
234                 if (typeof config == 'function') {
235                     config = {
236                         sorterFn: config
237                     };
238                 }
239
240                 // ensure sortType gets pushed on if necessary
241                 if (fields &amp;&amp; !config.transform) {
242                     field = fields.get(config.property);
243                     config.transform = field ? field.sortType : undefined;
244                 }
245                 sorters[i] = Ext.create('Ext.util.Sorter', config);
246             }
247         }
248
249         return sorters;
250     },
251     
252     getSorters: function() {
253         return this.sorters.items;
254     }
255 });</pre>
256 </body>
257 </html>