/*!
 * Ext JS Library 3.3.1
 * Copyright(c) 2006-2010 Sencha Inc.
 * licensing@sencha.com
 * http://www.sencha.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]); } });