checkBoxColunmTree.html

    可以选择节点的多列的树,也可以说是可以分组选择的grid。既是tree也是grid。

    column-tree.css这个文件在ext2.2版本中的ext-2.2/examples/tree这个目录下会找到这个文件的。

    1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    2. <html>
    3. <head>
    4. <title>checkBoxColunmTree.html</title>
    5. <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    6. <meta http-equiv="description" content="this is my page">
    7. <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    8. <link rel="stylesheet" type="text/css" href="ext/resources/css/ext-all.css" />
    9. <link rel="stylesheet" type="text/css" href="ext/resources/css/column-tree.css" />
    10. <script type="text/javascript" src="ext/adapter/ext/ext-base.js"></script>
    11. <script type="text/javascript" src="ext/ext-all.js"></script>
    12. <script type="text/javascript" src="ext/ColumnTree.js"></script>
    13. <script type="text/javascript">
    14. Ext.onReady(function () {
    15. Ext.BLANK_IMAGE_URL = 'ext/resources/images/default/s.gif';
    16. var tree = new Ext.tree.ColumnTree({
    17. width:568,
    18. height:300,
    19. border: false,
    20. lines: false,
    21. animate: false,
    22. rootVisible: false,
    23. autoScroll:true,
    24. checkModel:'cascade',//级联多选,如果不需要checkbox,该属性去掉
    25. onlyLeafCheckable: false,//所有结点可选,如果不需要checkbox,该属性去掉
    26. loader: new Ext.tree.TreeLoader({
    27. dataUrl: '../TreeDataServlet',//'column-data.json',
    28. uiProviders:{
    29. 'col': Ext.ux.ColumnTreeCheckNodeUI//如果不需要checkbox,则需要使用Ext.tree.ColumnTreeNodeUI
    30. }
    31. }),
    32. columns:[
    33. { header:'商品名称', width:170, dataIndex:'commodityName'},
    34. { header:'编号', width:70, dataIndex:'id'},
    35. { header:'代理/公司', width:180, dataIndex:'proxyName' },
    36. { header:'价格', width:70, dataIndex:'price'}
    37. ],
    38. root: new Ext.tree.AsyncTreeNode({
    39. text: '代理/公司'
    40. }),
    41. tbar:['公司名称:',{xtype:'textfield',id:'proxyName'},'商品名称:',{xtype:'textfield',id:'commodityName'},{text:'查询'}]
    42. });
    43. var win = new Ext.Window({
    44. title: 'Example column tree',
    45. width:582,
    46. height:388,
    47. border :true,
    48. resizable : false,
    49. items: tree,
    50. buttonAlign:'center',
    51. buttons:[{text:'确定'},{text:'关闭'}]
    52. });
    53. win.show();
    54. });
    55. </script>
    56. </head>
    57. <body>
    58. </body>
    59. </html>

    后台java代码

    TreeDataServlet.java

    1. package com.hoo.servlet;
    2. import java.io.IOException;
    3. import java.io.PrintWriter;
    4. import javax.servlet.ServletException;
    5. import javax.servlet.http.HttpServlet;
    6. import javax.servlet.http.HttpServletRequest;
    7. import javax.servlet.http.HttpServletResponse;
    8. public class TreeDataServlet extends HttpServlet {
    9. public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    10. this.doPost(request, response);
    11. }
    12. public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    13. response.setContentType("text/text");
    14. response.setCharacterEncoding("UTF-8");
    15. PrintWriter out = response.getWriter();
    16. StringBuffer resultStr = new StringBuffer();
    17. resultStr.append("[{");
    18. resultStr.append("id: ' 10000',");
    19. resultStr.append("commodityName: '微软鼠标',");
    20. resultStr.append("uiProvider: 'col',");
    21. //得到group 值
    22. resultStr.append("children: [{");
    23. resultStr.append("id: ' 100000',");
    24. resultStr.append("proxyName: '微软代理商-中国代理 联强 ',");
    25. resultStr.append("commodityName: 'IO 1.0',");
    26. resultStr.append("price: '198.00',");
    27. resultStr.append("leaf:true,");
    28. resultStr.append("uiProvider: 'col'},");
    29. resultStr.append("{id: ' 100000',");
    30. resultStr.append("proxyName: '微软代理商-中国代理 联强 ',");
    31. resultStr.append("commodityName: 'IE 3.0',");
    32. resultStr.append("price: '298.00',");
    33. resultStr.append("leaf:true,");
    34. resultStr.append("uiProvider: 'col'},");
    35. resultStr.append("{id: ' 100000',");
    36. resultStr.append("proxyName: '微软代理商-中国代理 联强 ',");
    37. resultStr.append("commodityName: 'IO 2.0',");
    38. resultStr.append("price: '200.00',");
    39. resultStr.append("leaf:true,");
    40. resultStr.append("uiProvider: 'col'");
    41. resultStr.append("}]},{");
    42. resultStr.append("id: ' 20000',");
    43. resultStr.append("commodityName: '罗技鼠标',");
    44. resultStr.append("uiProvider: 'col',");
    45. //得到group 值
    46. resultStr.append("children: [{");
    47. resultStr.append("id: ' 100001',");
    48. resultStr.append("proxyName: '罗技',");
    49. resultStr.append("commodityName: 'max 500',");
    50. resultStr.append("price: '298.00',");
    51. resultStr.append("leaf:true,");
    52. resultStr.append("uiProvider: 'col'},");
    53. resultStr.append("{id: ' 100000',");
    54. resultStr.append("proxyName: '罗技',");
    55. resultStr.append("commodityName: 'max 518',");
    56. resultStr.append("price: '298.00',");
    57. resultStr.append("leaf:true,");
    58. resultStr.append("uiProvider: 'col'},");
    59. resultStr.append("{id: ' 100000',");
    60. resultStr.append("proxyName: '罗技',");
    61. resultStr.append("commodityName: 'max 520',");
    62. resultStr.append("price: '245.00',");
    63. resultStr.append("leaf:true,");
    64. resultStr.append("uiProvider: 'col'");
    65. resultStr.append("}]");
    66. resultStr.append("}]");
    67. out.print(resultStr.toString());
    68. out.flush();
    69. out.close();
    70. }
    71. }

    ext/ColumnTree.js

    这个是扩展Ext.tree.ColumnTree的组件,只是添加了一个Ext.ux.ColumnTreeCheckNodeUI组件。有了这个组件我们才可以选择节点,所以这个是必须的;

    1. /*
    2. * Ext JS Library 2.0
    3. * Copyright(c) 2006-2007, Ext JS, LLC.
    4. * licensing@extjs.com
    5. *
    6. * http://extjs.com/license
    7. */
    8. Ext.tree.ColumnTree = Ext.extend(Ext.tree.TreePanel, {
    9. //lines:false,
    10. borderWidth: Ext.isBorderBox ? 0 : 2, // the combined left/right border for each cell
    11. cls:'x-column-tree',
    12. scrollOffset : 18,
    13. onRender : function(){
    14. Ext.tree.ColumnTree.superclass.onRender.apply(this, arguments);
    15. this.headers = this.body.createChild(
    16. {cls:'x-tree-headers '},this.body.dom);
    17. var cols = this.columns, c;
    18. var totalWidth = 0;
    19. for(var i = 0, len = cols.length; i < len; i++){
    20. c = cols[i];
    21. totalWidth += c.width;
    22. this.headers.createChild({
    23. cls:'x-tree-hd ' + (c.cls?c.cls+'-hd':''),
    24. cn: {
    25. cls:'x-tree-hd-text',
    26. html: c.header
    27. },
    28. style:'width:'+(c.width-this.borderWidth)+'px;'
    29. });
    30. }
    31. this.headers.createChild({
    32. cls:'x-tree-hd ',
    33. cn: {
    34. html: ''
    35. },
    36. style:'width:'+this.scrollOffset+'px;'
    37. });
    38. totalWidth += this.scrollOffset;
    39. this.headers.createChild({cls:'x-clear'});
    40. // prevent floats from wrapping when clipped
    41. this.headers.setWidth(totalWidth);
    42. totalWidth -= this.scrollOffset;
    43. this.innerCt.setWidth(totalWidth);
    44. }
    45. });
    46. Ext.tree.ColumnTreeNodeUI = Ext.extend(Ext.tree.TreeNodeUI, {
    47. focus: Ext.emptyFn, // prevent odd scrolling behavior
    48. renderElements : function(n, a, targetNode, bulkRender){
    49. this.indentMarkup = n.parentNode ? n.parentNode.ui.getChildIndent() : '';
    50. var t = n.getOwnerTree();
    51. var cols = t.columns;
    52. var bw = t.borderWidth;
    53. var c = cols[0];
    54. var cb = typeof a.checked == 'boolean';
    55. if(typeof this.checkModel != 'undefined'){
    56. cb = (!this.onlyLeafCheckable || n.isLeaf());
    57. }
    58. var href = a.href ? a.href : Ext.isGecko ? "" : "#";
    59. var buf = ['<li class="x-tree-node"><div ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf x-unselectable ', a.cls,'" unselectable="on">',
    60. '<div class="x-tree-col" style="width:',c.width-bw,'px;">',
    61. '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
    62. '<img src="', this.emptyIcon, '" class="x-tree-ec-icon x-tree-elbow">',
    63. '<img src="', a.icon || this.emptyIcon, '" class="x-tree-node-icon',(a.icon ? " x-tree-node-inline-icon" : ""),(a.iconCls ? " "+a.iconCls : ""),'" unselectable="on">',
    64. cb ? ('<input class="x-tree-node-cb" type="checkbox" ' + (a.checked ? 'checked="checked" />' : '/>')) : '',
    65. '<a hidefocus="on" class="x-tree-node-anchor" href="',href,'" tabIndex="1" ',
    66. a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '>',
    67. '<span unselectable="on">', n.text || (a[c.dataIndex]?(c.renderer ? c.renderer(a[c.dataIndex], n, a) : a[c.dataIndex]):''),"&nbsp;</span></a>",
    68. "</div>"];
    69. for(var i = 1, len = cols.length; i < len; i++){
    70. c = cols[i];
    71. buf.push('<div class="x-tree-col ',(c.cls?c.cls:''),'" style="width:',c.width-bw,'px;">',
    72. '<div class="x-tree-col-text">',(a[c.dataIndex]?(c.renderer ? c.renderer(a[c.dataIndex], n, a) : a[c.dataIndex]):''),"&nbsp;</div>",
    73. "</div>");
    74. }
    75. buf.push('<div class="x-clear"></div>',
    76. '</div>',
    77. '<ul class="x-tree-node-ct" style="display:none;"></ul>',
    78. "</li>");
    79. if(bulkRender !== true && n.nextSibling && n.nextSibling.ui.getEl()){
    80. this.wrap = Ext.DomHelper.insertHtml("beforeBegin",n.nextSibling.ui.getEl(), buf.join(""));
    81. }else{
    82. this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf.join(""));
    83. }
    84. this.elNode = this.wrap.childNodes[0];
    85. this.ctNode = this.wrap.childNodes[1];
    86. var cs = this.elNode.firstChild.childNodes;
    87. this.indentNode = cs[0];
    88. this.ecNode = cs[1];
    89. this.iconNode = cs[2];
    90. var index = 3;
    91. if(cb){
    92. this.checkbox = cs[3];
    93. index++;
    94. }
    95. this.anchor = cs[index];
    96. this.textNode = cs[index].firstChild;
    97. }
    98. });
    99. //这个组件是扩展的,加入这个组件即可
    100. Ext.ux.ColumnTreeCheckNodeUI = function() {
    101. //多选: 'multiple'(默认)
    102. //单选: 'single'
    103. //级联多选: 'cascade'(同时选父和子);'parentCascade'(选父);'childCascade'(选子)
    104. this.checkModel = 'multiple';
    105. //only leaf can checked
    106. this.onlyLeafCheckable = false;
    107. Ext.ux.ColumnTreeCheckNodeUI.superclass.constructor.apply(this, arguments);
    108. };
    109. Ext.extend(Ext.ux.ColumnTreeCheckNodeUI, Ext.tree.ColumnTreeNodeUI, {
    110. renderElements : function(n, a, targetNode, bulkRender){
    111. var t = n.getOwnerTree();
    112. this.checkModel = t.checkModel || this.checkModel;
    113. this.onlyLeafCheckable = t.onlyLeafCheckable || false;
    114. Ext.ux.ColumnTreeCheckNodeUI.superclass.renderElements.apply(this, arguments);
    115. var cb = (!this.onlyLeafCheckable || n.isLeaf());
    116. if(cb){
    117. Ext.fly(this.checkbox).on('click', this.check.createDelegate(this,[null]));
    118. }
    119. },
    120. // private
    121. check : function(checked){
    122. var n = this.node;
    123. var tree = n.getOwnerTree();
    124. this.checkModel = tree.checkModel || this.checkModel;
    125. if( checked === null ) {
    126. checked = this.checkbox.checked;
    127. } else {
    128. this.checkbox.checked = checked;
    129. }
    130. n.attributes.checked = checked;
    131. tree.fireEvent('check', n, checked);
    132. if(!this.onlyLeafCheckable){
    133. if(this.checkModel == 'cascade' || this.checkModel == 'parentCascade'){
    134. var parentNode = n.parentNode;
    135. if(parentNode !== null) {
    136. this.parentCheck(parentNode,checked);
    137. }
    138. }
    139. if(this.checkModel == 'cascade' || this.checkModel == 'childCascade'){
    140. if( !n.expanded && !n.childrenRendered ) {
    141. n.expand(false,false,this.childCheck);
    142. }else {
    143. this.childCheck(n);
    144. }
    145. }
    146. } else if(this.checkModel == 'single'){
    147. var checkedNodes = tree.getChecked();
    148. for(var i=0;i<checkedNodes.length;i++){
    149. var node = checkedNodes[i];
    150. if(node.id != n.id){
    151. node.getUI().checkbox.checked = false;
    152. node.attributes.checked = false;
    153. tree.fireEvent('check', node, false);
    154. }
    155. }
    156. }
    157. },
    158. // private
    159. childCheck : function(node){
    160. var a = node.attributes;
    161. if(!a.leaf) {
    162. var cs = node.childNodes;
    163. var csui;
    164. for(var i = 0; i < cs.length; i++) {
    165. csui = cs[i].getUI();
    166. if(csui.checkbox.checked ^ a.checked)
    167. csui.check(a.checked);
    168. }
    169. }
    170. },
    171. // private
    172. parentCheck : function(node ,checked){
    173. var checkbox = node.getUI().checkbox;
    174. if(typeof checkbox == 'undefined')return ;
    175. if(!(checked ^ checkbox.checked))return;
    176. if(!checked && this.childHasChecked(node))return;
    177. checkbox.checked = checked;
    178. node.attributes.checked = checked;
    179. node.getOwnerTree().fireEvent('check', node, checked);
    180. var parentNode = node.parentNode;
    181. if( parentNode !== null){
    182. this.parentCheck(parentNode,checked);
    183. }
    184. },
    185. // private
    186. childHasChecked : function(node){
    187. var childNodes = node.childNodes;
    188. if(childNodes || childNodes.length>0){
    189. for(var i=0;i<childNodes.length;i++){
    190. if(childNodes[i].getUI().checkbox.checked)
    191. return true;
    192. }
    193. }
    194. return false;
    195. },
    196. toggleCheck : function(value){
    197. var cb = this.checkbox;
    198. if(cb){
    199. var checked = (value === undefined ? !cb.checked : value);
    200. this.check(checked);
    201. }
    202. }
    203. });