Upgrade to ExtJS 3.1.0 - Released 12/16/2009
[extjs.git] / examples / ux / treegrid / TreeGridSorter.js
1 /*!
2  * Ext JS Library 3.1.0
3  * Copyright(c) 2006-2009 Ext JS, LLC
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7 Ext.ns('Ext.ux.tree');
8
9 /**
10  * @class Ext.ux.tree.TreeGridSorter
11  * @extends Ext.tree.TreeSorter
12  */
13 Ext.ux.tree.TreeGridSorter = Ext.extend(Ext.tree.TreeSorter, {
14     /**
15      * @cfg {Array} sortClasses The CSS classes applied to a header when it is sorted. (defaults to <tt>['sort-asc', 'sort-desc']</tt>)
16      */
17     sortClasses : ['sort-asc', 'sort-desc'],
18     /**
19      * @cfg {String} sortAscText The text displayed in the 'Sort Ascending' menu item (defaults to <tt>'Sort Ascending'</tt>)
20      */
21     sortAscText : 'Sort Ascending',
22     /**
23      * @cfg {String} sortDescText The text displayed in the 'Sort Descending' menu item (defaults to <tt>'Sort Descending'</tt>)
24      */
25     sortDescText : 'Sort Descending',
26
27     constructor : function(tree, config) {
28         if(!Ext.isObject(config)) {
29             config = {
30                 property: tree.columns[0].dataIndex || 'text',
31                 folderSort: true
32             }
33         }
34
35         Ext.ux.tree.TreeGridSorter.superclass.constructor.apply(this, arguments);
36
37         this.tree = tree;
38         tree.on('headerclick', this.onHeaderClick, this);
39         tree.ddAppendOnly = true;
40
41         me = this;
42         this.defaultSortFn = function(n1, n2){
43
44             var dsc = me.dir && me.dir.toLowerCase() == 'desc';
45             var p = me.property || 'text';
46             var sortType = me.sortType;
47             var fs = me.folderSort;
48             var cs = me.caseSensitive === true;
49             var leafAttr = me.leafAttr || 'leaf';
50
51             if(fs){
52                 if(n1.attributes[leafAttr] && !n2.attributes[leafAttr]){
53                     return 1;
54                 }
55                 if(!n1.attributes[leafAttr] && n2.attributes[leafAttr]){
56                     return -1;
57                 }
58             }
59                 var v1 = sortType ? sortType(n1.attributes[p]) : (cs ? n1.attributes[p] : n1.attributes[p].toUpperCase());
60                 var v2 = sortType ? sortType(n2.attributes[p]) : (cs ? n2.attributes[p] : n2.attributes[p].toUpperCase());
61                 if(v1 < v2){
62                         return dsc ? +1 : -1;
63                 }else if(v1 > v2){
64                         return dsc ? -1 : +1;
65             }else{
66                 return 0;
67             }
68         };
69
70         tree.on('afterrender', this.onAfterTreeRender, this, {single: true});
71         tree.on('headermenuclick', this.onHeaderMenuClick, this);
72     },
73
74     onAfterTreeRender : function() {
75         var hmenu = this.tree.hmenu;
76         hmenu.insert(0,
77             {itemId:'asc', text: this.sortAscText, cls: 'xg-hmenu-sort-asc'},
78             {itemId:'desc', text: this.sortDescText, cls: 'xg-hmenu-sort-desc'}
79         );
80         this.updateSortIcon(0, 'asc');
81     },
82
83     onHeaderMenuClick : function(c, id, index) {
84         if(id === 'asc' || id === 'desc') {
85             this.onHeaderClick(c, null, index);
86             return false;
87         }
88     },
89
90     onHeaderClick : function(c, el, i) {
91         if(c && !this.tree.headersDisabled){
92             var me = this;
93
94             me.property = c.dataIndex;
95             me.dir = c.dir = (c.dir === 'desc' ? 'asc' : 'desc');
96             me.sortType = c.sortType;
97             me.caseSensitive === Ext.isBoolean(c.caseSensitive) ? c.caseSensitive : this.caseSensitive;
98             me.sortFn = c.sortFn || this.defaultSortFn;
99
100             this.tree.root.cascade(function(n) {
101                 if(!n.isLeaf()) {
102                     me.updateSort(me.tree, n);
103                 }
104             });
105
106             this.updateSortIcon(i, c.dir);
107         }
108     },
109
110     // private
111     updateSortIcon : function(col, dir){
112         var sc = this.sortClasses;
113         var hds = this.tree.innerHd.select('td').removeClass(sc);
114         hds.item(col).addClass(sc[dir == 'desc' ? 1 : 0]);
115     }
116 });