文章内不再提供示例,需要查看者请从SVN下载,地址:
http://exttools.googlecode.com/svn/trunk/
效果图:

示例js:
http://exttools.googlecode.com/svn/trunk/
效果图:

- /**?
- ?*?扩展了Panel类,其布局设为accordion,所在区域为west;该组件初始化后会根据配置的url和root向后台发?
- ?*?起请求并解析返回的json串,根据parentcode为空的结点生成TreePanel,子节点通过parentcode属性添加为?
- ?*?对应结点的子节点,注意此处每个节点的code必须小于父节点并接大于下方的其它结点;?
- ?*??
- ?*?1.1更新:?
- ?*?1.不再需要leaf属性,程序内部判断;?
- ?*?2.store用完后即销毁,不再可用;?
- ?*?3.修改了结点点击的触发事件,仅注册一次以减少内存占用,该方法传递给监听函数一个Ext.tree.TreeNode对象,?
- ?*?可通过node.attributes属性获取结点属性;?
- ?*?4.添加了一个findNodeById方法,该方法通过id字符串返回对应Ext.tree.TreeNode对象;?
- ?*??
- ?*?@author?chemzqm@gmail.com?
- ?*?@version?1.1?
- ?*?@since?2010-5-9?
- ?*?
- ?*/??
- Ext.namespace("QM.ui");??
- ??
- QM.ui.AccordinTreePanel?=?Ext.extend(Ext.Panel,?{??
- ????/**?
- ?????*?@cfg(url)?发送请求的地址?
- ?????*/??
- ????/**?
- ?????*?@cfg(root)?json数组的根字符串?
- ?????*/??
- ????margins:?'5?0?5?5',??
- ????split:?true,??
- ????width:?210,??
- ????initComponent:?function(){??
- ????????Ext.apply(this,?{??
- ????????????layout:?'accordion',??
- ????????????region:?'west'??
- ????????})??
- ????????QM.ui.AccordinTreePanel.superclass.initComponent.call(this);??
- ????????this.addEvents(????????/**?
- ?????????*?@event?itemclick??树结点被点击时触发??参数:node?当前结点对象,record?当前结点对应record对象?
- ?????????*/??
- ????????'click',????????/**?
- ?????????*?@event?afterload?菜单项加载完毕后触发?
- ?????????*/??
- ????????'afterload');??
- ????????if?(!this.store)?{??
- ????????????this.store?=?new?Ext.data.JsonStore({??
- ????????????????url:?this.url,??
- ????????????????root:?this.root,??
- ????????????????fields:?['code',?'name',?'parentcode',?'iconCls',?'href']??
- ????????????});??
- ????????}??
- ????????this.store.load({??
- ????????????callback:?this.loadTrees,??
- ????????????scope:?this??
- ????????});??
- ????},??
- ????loadTrees:?function(records,?o,?s){??
- ????????var?pnodes,trees?=?[],tree;??
- ????????this.store.sort('code');??
- ????????for?(var?i?=?0;?i?<?records.length;?i++)?{??
- ????????????var?record?=?records[i];??
- ????????????if?(!record.get('parentcode'))?{??
- ????????????????tree?=?this.creatTreeConfig(record);??
- ????????????????trees.push(tree);??
- ????????????????pnodes?=?[];??
- ????????????????pnodes.push(tree.root);??
- ????????????}??
- ????????????else?{??
- ????????????????var?next_record?=?records[i?+?1];??
- ????????????????var?isLeaf?=?!next_record?||?next_record.get('parentcode')?!=?record.get('code');??
- ????????????????this.addTreeNode(pnodes,?record,?isLeaf);??
- ????????????}??
- ????????}??
- ????????Ext.each(trees,function(tree){??
- ????????????this.add(tree);??
- ????????},this);??
- ????????this.fireEvent('afterload',?this);??
- ????????this.mon(this.el,?'click',?this.onClick,?this);??
- ????????this.doLayout();??
- ????????this.store.destroy();??
- ????},??
- ????findNodeById:function(id){??
- ????????var?node,trees?=?this.findByType('treepanel',true);??
- ????????Ext.each(trees,function(tree){??
- ????????????node?=?tree.getNodeById(id);??
- ????????????return?!node;//找到的话返回false??
- ????????});??
- ????????return?node;??
- ????},??
- ????onClick:?function(e,?t,?o){??
- ????????if(Ext.fly(t).hasClass('x-tree-ec-icon')){//点击伸展按钮时无视??
- ????????????return;??
- ????????}??
- ????????var?el,id,node;?????
- ????????if?(el?=?e.getTarget('.x-tree-node-el',?3,true))?{??
- ????????????e.stopEvent();??
- ????????????id?=?el.getAttributeNS('ext','tree-node-id');??
- ????????????node?=?this.findNodeById(id);??
- ????????????this.fireEvent('click',node);??
- ????????}??
- ????},??
- ????creatTreeConfig:?function(record){??
- ????????var?config?=?{??
- ????????????xtype:?'treepanel',??
- ????????????autoScroll:?true,??
- ????????????rootVisible:?false,??
- ????????????title:?record.get('name'),??
- ????????????iconCls:?record.get('iconCls'),??
- ????????????root:?{??
- ????????????????nodeType:?'async',??
- ????????????????expanded:?true,??
- ????????????????id:?record.get('code'),??
- ????????????????children:?[]??
- ????????????}??
- ????????};??
- ????????return?config;??
- ????},??
- ????addTreeNode:?function(pnodes,?record,?isLeaf){??
- ????????var?len?=?pnodes.length;??
- ????????for?(var?i?=?len?-?1;?i?>=?0;?i--)?{??
- ????????????if?(pnodes[i].id?!=?record.get('parentcode'))?{??
- ????????????????pnodes.pop();??
- ????????????}??
- ????????????else?{??
- ????????????????var?parent?=?pnodes[i].children;??
- ????????????????var?node?=?{??
- ????????????????????text:?record.get('name'),??
- ????????????????????id:?record.get('code'),??
- ????????????????????iconCls:?record.get('iconCls'),??
- ????????????????????href:?record.get('href'),??
- ????????????????????leaf:?isLeaf??
- ????????????????};??
- ????????????????if?(!isLeaf)?{??
- ????????????????????node.children?=?[];??
- ????????????????????pnodes.push(node);??
- ????????????????}??
- ????????????????parent.push(node);??
- ????????????????return;??
- ????????????}??
- ????????}??
- ????}??
- });??
- ??
- Ext.reg('accTree',?QM.ui.AccordinTreePanel);??
/** * 扩展了Panel类,其布局设为accordion,所在区域为west;该组件初始化后会根据配置的url和root向后台发 * 起请求并解析返回的json串,根据parentcode为空的结点生成TreePanel,子节点通过parentcode属性添加为 * 对应结点的子节点,注意此处每个节点的code必须小于父节点并接大于下方的其它结点; * * 1.1更新: * 1.不再需要leaf属性,程序内部判断; * 2.store用完后即销毁,不再可用; * 3.修改了结点点击的触发事件,仅注册一次以减少内存占用,该方法传递给监听函数一个Ext.tree.TreeNode对象, * 可通过node.attributes属性获取结点属性; * 4.添加了一个findNodeById方法,该方法通过id字符串返回对应Ext.tree.TreeNode对象; * * @author chemzqm@gmail.com * @version 1.1 * @since 2010-5-9 * */ Ext.namespace("QM.ui"); QM.ui.AccordinTreePanel = Ext.extend(Ext.Panel, { /** * @cfg(url) 发送请求的地址 */ /** * @cfg(root) json数组的根字符串 */ margins: '5 0 5 5', split: true, width: 210, initComponent: function(){ Ext.apply(this, { layout: 'accordion', region: 'west' }) QM.ui.AccordinTreePanel.superclass.initComponent.call(this); this.addEvents( /** * @event itemclick 树结点被点击时触发 参数:node 当前结点对象,record 当前结点对应record对象 */ 'click', /** * @event afterload 菜单项加载完毕后触发 */ 'afterload'); if (!this.store) { this.store = new Ext.data.JsonStore({ url: this.url, root: this.root, fields: ['code', 'name', 'parentcode', 'iconCls', 'href'] }); } this.store.load({ callback: this.loadTrees, scope: this }); }, loadTrees: function(records, o, s){ var pnodes,trees = [],tree; this.store.sort('code'); for (var i = 0; i < records.length; i++) { var record = records[i]; if (!record.get('parentcode')) { tree = this.creatTreeConfig(record); trees.push(tree); pnodes = []; pnodes.push(tree.root); } else { var next_record = records[i + 1]; var isLeaf = !next_record || next_record.get('parentcode') != record.get('code'); this.addTreeNode(pnodes, record, isLeaf); } } Ext.each(trees,function(tree){ this.add(tree); },this); this.fireEvent('afterload', this); this.mon(this.el, 'click', this.onClick, this); this.doLayout(); this.store.destroy(); }, findNodeById:function(id){ var node,trees = this.findByType('treepanel',true); Ext.each(trees,function(tree){ node = tree.getNodeById(id); return !node;//找到的话返回false }); return node; }, onClick: function(e, t, o){ if(Ext.fly(t).hasClass('x-tree-ec-icon')){//点击伸展按钮时无视 return; } var el,id,node; if (el = e.getTarget('.x-tree-node-el', 3,true)) { e.stopEvent(); id = el.getAttributeNS('ext','tree-node-id'); node = this.findNodeById(id); this.fireEvent('click',node); } }, creatTreeConfig: function(record){ var config = { xtype: 'treepanel', autoScroll: true, rootVisible: false, title: record.get('name'), iconCls: record.get('iconCls'), root: { nodeType: 'async', expanded: true, id: record.get('code'), children: [] } }; return config; }, addTreeNode: function(pnodes, record, isLeaf){ var len = pnodes.length; for (var i = len - 1; i >= 0; i--) { if (pnodes[i].id != record.get('parentcode')) { pnodes.pop(); } else { var parent = pnodes[i].children; var node = { text: record.get('name'), id: record.get('code'), iconCls: record.get('iconCls'), href: record.get('href'), leaf: isLeaf }; if (!isLeaf) { node.children = []; pnodes.push(node); } parent.push(node); return; } } } }); Ext.reg('accTree', QM.ui.AccordinTreePanel);
示例js:
- new?Ext.Viewport({??
- ????????????????????layout:?'border',??
- ????????????????????items:?[{??
- ????????????????????????xtype:?'accTree',??
- ????????????????????????title?:?'菜单',??
- ????????????????????????root?:?'menus',//必须要配??
- ????????????????????????url:?'menu.json',//必须要配??
- ????????????????????????listeners:{??
- ????????????????????????????'click':function(node){??
- ????????????????????????????????alert(node.attributes.href);??
- ????????????????????????????}??
- ????????????????????????}??
- ????????????????????},?{??
- ????????????????????????region:?'center',??
- ????????????????????????html:?'center'??
- ????????????????????}]??
- ????????????????});??
- ????????????});??