/*!
* Ext JS Library 3.3.0
* Copyright(c) 2006-2010 Ext JS, Inc.
* licensing@extjs.com
* http://www.extjs.com/license
*/
Ext.ns('Ext.ux.tree');
/**
* @class Ext.ux.tree.TreeGridSorter
* @extends Ext.tree.TreeSorter
* Provides sorting of nodes in a {@link Ext.ux.tree.TreeGrid}. The TreeGridSorter automatically monitors events on the
* associated TreeGrid that might affect the tree's sort order (beforechildrenrendered, append, insert and textchange).
* Example usage:
*
new Ext.ux.tree.TreeGridSorter(myTreeGrid, {
folderSort: true,
dir: "desc",
sortType: function(node) {
// sort by a custom, typed attribute:
return parseInt(node.id, 10);
}
});
* @constructor
* @param {TreeGrid} tree
* @param {Object} config
*/
Ext.ux.tree.TreeGridSorter = Ext.extend(Ext.tree.TreeSorter, {
/**
* @cfg {Array} sortClasses The CSS classes applied to a header when it is sorted. (defaults to ['sort-asc', 'sort-desc'])
*/
sortClasses : ['sort-asc', 'sort-desc'],
/**
* @cfg {String} sortAscText The text displayed in the 'Sort Ascending' menu item (defaults to 'Sort Ascending')
*/
sortAscText : 'Sort Ascending',
/**
* @cfg {String} sortDescText The text displayed in the 'Sort Descending' menu item (defaults to 'Sort Descending')
*/
sortDescText : 'Sort Descending',
constructor : function(tree, config) {
if(!Ext.isObject(config)) {
config = {
property: tree.columns[0].dataIndex || 'text',
folderSort: true
}
}
Ext.ux.tree.TreeGridSorter.superclass.constructor.apply(this, arguments);
this.tree = tree;
tree.on('headerclick', this.onHeaderClick, this);
tree.ddAppendOnly = true;
var me = this;
this.defaultSortFn = function(n1, n2){
var desc = me.dir && me.dir.toLowerCase() == 'desc',
prop = me.property || 'text',
sortType = me.sortType,
caseSensitive = me.caseSensitive === true,
leafAttr = me.leafAttr || 'leaf',
attr1 = n1.attributes,
attr2 = n2.attributes;
if(me.folderSort){
if(attr1[leafAttr] && !attr2[leafAttr]){
return 1;
}
if(!attr1[leafAttr] && attr2[leafAttr]){
return -1;
}
}
var prop1 = attr1[prop],
prop2 = attr2[prop],
v1 = sortType ? sortType(prop1) : (caseSensitive ? prop1 : prop1.toUpperCase());
v2 = sortType ? sortType(prop2) : (caseSensitive ? prop2 : prop2.toUpperCase());
if(v1 < v2){
return desc ? +1 : -1;
}else if(v1 > v2){
return desc ? -1 : +1;
}else{
return 0;
}
};
tree.on('afterrender', this.onAfterTreeRender, this, {single: true});
tree.on('headermenuclick', this.onHeaderMenuClick, this);
},
onAfterTreeRender : function() {
if(this.tree.hmenu){
this.tree.hmenu.insert(0,
{itemId:'asc', text: this.sortAscText, cls: 'xg-hmenu-sort-asc'},
{itemId:'desc', text: this.sortDescText, cls: 'xg-hmenu-sort-desc'}
);
}
this.updateSortIcon(0, 'asc');
},
onHeaderMenuClick : function(c, id, index) {
if(id === 'asc' || id === 'desc') {
this.onHeaderClick(c, null, index);
return false;
}
},
onHeaderClick : function(c, el, i) {
if(c && !this.tree.headersDisabled){
var me = this;
me.property = c.dataIndex;
me.dir = c.dir = (c.dir === 'desc' ? 'asc' : 'desc');
me.sortType = c.sortType;
me.caseSensitive === Ext.isBoolean(c.caseSensitive) ? c.caseSensitive : this.caseSensitive;
me.sortFn = c.sortFn || this.defaultSortFn;
this.tree.root.cascade(function(n) {
if(!n.isLeaf()) {
me.updateSort(me.tree, n);
}
});
this.updateSortIcon(i, c.dir);
}
},
// private
updateSortIcon : function(col, dir){
var sc = this.sortClasses,
hds = this.tree.innerHd.select('td').removeClass(sc);
hds.item(col).addClass(sc[dir == 'desc' ? 1 : 0]);
}
});