官方文档:
http://www.extjs.com/deploy/ext/docs/
最近用了一次extjs2.0.2 的 tree, 由于以前没用过, 所以用起来挺痛苦的, 边用边查官方的文档.
感觉extjs 的tree 功能很强大, 我也只是学到皮毛, 在这里整理一下所学的东西
用到的元素:
Ext.tree.TreePanel ----ext树的类, 父类是 Ext.data.Tree
Ext.tree.TreeLoader ----ext树节点加载器
Ext.tree.AsyncTreeNode ----ext树异步节点, 父类是 Ext.data.Node
JsonTreeLoader ----自定义的节点加载器
由于我是用json 数据产生节点的, 并且根据数据修改节点的样式, 所以用JsonTreeLoader 继承于 TreeLoader
主要是覆盖 createNode 方法, 产生 createNode 的参数 attr, 然后调用父类TreeLoader 的createNode(attr) 产生节点.
TreeNodeUI -- 找不到文档的一个类, 晕
对象: tree 树对象
tree 中需要定义的属性有 el, loader, root, listeners
el: 对应的页面元素id, 基本是一个div;
loader: JsonTreeLoader 对象, 需要定义的属性有dataUrl, baseParams,
dataUrl 为获取节点数据的连接请求;
baseParams 请求的参数, 数据格式如 baseParams : {id : 1, type: 2}
root: Ext.tree.AsyncTreeNode 对象, 需要定义的属性有 id, text, 当然也可以有自定义的实现, 如type
id 节点的标识字段, 可以用tree.getNodeById(nodeId) 查询到该节点. 这个id 非页面元素的id;
text 根节点的标题;
type 自定义的属性;
listeners: tree 的监听事件, 需要监听的事件有render, click
render 树的呈现;
'render' : function() {
this.loader
.on(
"beforeload",
function(treeLoader, node) { //设置加载子节点的请求的参数
treeLoader.baseParams.id = node.attributes.id;
treeLoader.baseParams.type = node.attributes.type;
});
}
click 节点元素点击事件;
一切OK, 执行tree.render(); //显示树
tree.getRootNode().expand(); //展开根节点
tree.getRootNode().getUI().getEl().click(); //触发根节点的点击事件, 没测试过, 纯猜测
更多的属性和方法请参考
http://www.extjs.com/deploy/ext/docs/output/Ext.tree.TreeNode.html
对象: node 树节点对象
产生节点的方法一:
var node = new Ext.tree.AsyncTreeNode( { id : '12345' , //节点id text :'新增子项目', //节点标题 type: 2, //自己定义的实现 iconCls: 'iconCss', //图标样式 cls: 'nodeCss', //节点样式 leaf: true //是否叶子 });
node 的id, text, iconCls, cls, leaf 都是固定的属性, 并且都有其意义, 并且是大小写敏感的.
详细属性参考:
http://www.extjs.com/deploy/ext/docs/output/Ext.tree.TreeNode.html#configs
http://www.extjs.com/deploy/ext/docs/output/Ext.data.Node.html#configs
再把这个节点 node 添加到另一个节点 下面. (值得注意的是, 要把这个node 注册到 tree里面,不然tree.getNodeById(node.id) 是获取不到该节点的)
parentNode.appendChild(node); //添加node 为子节点 parentNode.expand(); //展开parentNode tree.registerNode(node); //注册节点, 不然是找不到这个节点的
产生节点的方法二:
在 createNode(attr) 前, 可以用一个方法处理 attr参数,
processNodeAttr : function(attr, data) { //data数据 attr.id = data.id; //树节点id attr.text = data.name;//树节点name attr.type= data.type; //自定义数据 if (data.hasChildren) { //通过自定义数据进行判断 } else { attr.leaf = true; } }
用父类的 createNode方法
var node = JsonTreeLoader.superclass.createNode.call(this, attr);
如果上面的两种操作正确, 那么一个树节点 node 就产生了,
那么这个node 的属性呢, 怎么获取呢 ?
node.id
node.attributes.id
node.attributes.text
node.attributes.type
node.attributes.cls
从上面可以看出, node 的属性都放在attributes 属性里面了
直接 node.attributes.cls = 'newCSS' 是可以改变节点的样式, 但是不提倡
规范点还是要用 node.getUI().addClass('newCSS'); //修改节点样式 node.setText(newName); //修改节点标题 node.getUI().getIconEl().addClass('newIconClass'); //没测试过, getIconEl()到底是DOM 元素还是 EXT的NODE, 要测试下, 如果是后者就没问题了
node 的获取:
var node = tree.getNodeById(nodeId);
node 的注销
tree.unregisterNode(node); //注销节点
更多的属性和方法请参考:
http://www.extjs.com/deploy/ext/docs/output/Ext.tree.TreeNode.html
Ext.tree.TreeNodeUI
为节点输出而设计,如果想创建自己的ui,应该继承此类
方法
addClass( String/Array className ) : void
增加样式类
getAnchor() : HtmlElement
返回<a>元素
getIconEl() : HtmlElement
返回<img>元素
getTextEl() : HtmlNode
返回文本节点
hide() : void
隐藏
isChecked() : Boolean
选中?
removeClass( String/Array className ) : void
移除样式
show() : void
显示
toggleCheck( Boolean (optional) ) : void
切换选中状态
这个网上找的, 但是应该不止这些而已
下面是 ext-all.js 的东东, 用了一个小时才排好版
Ext.tree.TreeNodeUI=function(A) //A为node{this.node=A; this.rendered=false; this.animating=false; this.wasLeaf=true; this.ecc="x-tree-ec-icon x-tree-elbow"; this.emptyIcon=Ext.BLANK_IMAGE_URL }; Ext.tree.TreeNodeUI.prototype={ removeChild:function(A){ if(this.rendered){ this.ctNode.removeChild(A.ui.getEl()) } }, beforeLoad:function(){ this.addClass("x-tree-node-loading") }, afterLoad:function(){ this.removeClass("x-tree-node-loading") }, onTextChange:function(B,C,A){ if(this.rendered) { this.textNode.innerHTML=C } }, onDisableChange:function(A,B){ this.disabled=B; if(this.checkbox) { this.checkbox.disabled=B } if(B) { this.addClass("x-tree-node-disabled") }else { this.removeClass("x-tree-node-disabled") } }, onSelectedChange:function(A){ if(A){ this.focus(); this.addClass("x-tree-selected") }else{ this.removeClass("x-tree-selected") } }, onMove:function(A,G,E,F,D,B){ this.childIndent=null; if(this.rendered){ var H=F.ui.getContainer(); if(!H){ this.holder=document.createElement("div"); this.holder.appendChild(this.wrap); return } var C=B?B.ui.getEl():null; if(C){ H.insertBefore(this.wrap,C) }else{ H.appendChild(this.wrap) } this.node.renderIndent(true) } }, addClass:function(A){ if(this.elNode){ Ext.fly(this.elNode).addClass(A) } }, removeClass:function(A){ if(this.elNode){ Ext.fly(this.elNode).removeClass(A) } }, remove:function(){ if(this.rendered){ this.holder=document.createElement("div"); this.holder.appendChild(this.wrap) } }, fireEvent:function(){ return this.node.fireEvent.apply(this.node,arguments) }, initEvents:function(){ this.node.on("move",this.onMove,this); if(this.node.disabled){ this.addClass("x-tree-node-disabled"); if(this.checkbox){ this.checkbox.disabled=true } } if(this.node.hidden){ this.hide() } var B=this.node.getOwnerTree(); var A=B.enableDD||B.enableDrag||B.enableDrop; if(A&&(!this.node.isRoot||B.rootVisible)){ Ext.dd.Registry.register(this.elNode, {node:this.node, handles:this.getDDHandles(), isHandle:false} ) } }, getDDHandles:function(){ return[this.iconNode,this.textNode,this.elNode] }, hide:function(){ this.node.hidden=true; if(this.wrap){ this.wrap.style.display="none" } }, show:function(){ this.node.hidden=false;if(this.wrap){ this.wrap.style.display="" } }, onContextMenu:function(A){ if(this.node.hasListener("contextmenu")|| this.node.getOwnerTree().hasListener("contextmenu")) { A.preventDefault(); this.focus(); this.fireEvent("contextmenu",this.node,A) } }, onClick:function(B){ if(this.dropping){ B.stopEvent(); return } if(this.fireEvent("beforeclick",this.node,B)!==false){ var A=B.getTarget("a"); if(!this.disabled&&this.node.attributes.href&&A){ this.fireEvent("click",this.node,B); return }else{ if(A&&B.ctrlKey){ B.stopEvent() } } B.preventDefault(); if(this.disabled){ return }if(this.node.attributes.singleClickExpand&& !this.animating&&this.node.hasChildNodes()){ this.node.toggle() } this.fireEvent("click",this.node,B) }else{ B.stopEvent() } }, onDblClick:function(A){ A.preventDefault(); if(this.disabled){ return } if(this.checkbox){ this.toggleCheck() } if(!this.animating&& this.node.hasChildNodes()){ this.node.toggle() } this.fireEvent("dblclick",this.node,A) }, onOver:function(A){ this.addClass("x-tree-node-over") }, onOut:function(A){ this.removeClass("x-tree-node-over") }, onCheckChange:function(){ var A=this.checkbox.checked; this.node.attributes.checked=A; this.fireEvent("checkchange",this.node,A) }, ecClick:function(A){ if(!this.animating&& (this.node.hasChildNodes()|| this.node.attributes.expandable)){ this.node.toggle() } }, startDrop:function(){ this.dropping=true }, endDrop:function(){ setTimeout(function(){this.dropping=false}.createDelegate(this),50) }, expand:function(){ this.updateExpandIcon(); this.ctNode.style.display="" }, focus:function(){ if(!this.node.preventHScroll){ try{ this.anchor.focus() }catch(C){} }else{ if(!Ext.isIE){ try{ var B=this.node.getOwnerTree().getTreeEl().dom; var A=B.scrollLeft; this.anchor.focus(); B.scrollLeft=A }catch(C){} } } }, toggleCheck:function(B){ var A=this.checkbox; if(A){ A.checked=(B===undefined?!A.checked:B) } }, blur:function(){ try{ this.anchor.blur() }catch(A){} }, animExpand:function(B){ var A=Ext.get(this.ctNode); A.stopFx(); if(!this.node.hasChildNodes()){ this.updateExpandIcon(); this.ctNode.style.display=""; Ext.callback(B); return } this.animating=true; this.updateExpandIcon(); A.slideIn("t",{ callback:function(){ this.animating=false; Ext.callback(B) }, scope:this, duration:this.node.ownerTree.duration||0.25}) }, highlight:function(){ var A=this.node.getOwnerTree(); Ext.fly(this.wrap).highlight(A.hlColor||"C3DAF9", {endColor:A.hlBaseColor} ) }, collapse:function(){ this.updateExpandIcon(); this.ctNode.style.display="none" }, animCollapse:function(B){ var A=Ext.get(this.ctNode); A.enableDisplayMode("block"); A.stopFx(); this.animating=true; this.updateExpandIcon(); A.slideOut("t",{callback:function(){ this.animating=false;Ext.callback(B) }, scope:this, duration:this.node.ownerTree.duration||0.25} ) }, getContainer:function(){ return this.ctNode }, getEl:function(){ return this.wrap }, appendDDGhost:function(A){ A.appendChild(this.elNode.cloneNode(true)) }, getDDRepairXY:function(){ return Ext.lib.Dom.getXY(this.iconNode) }, onRender:function(){ this.render() }, render:function(B){ var D=this.node,A=D.attributes; var C=D.parentNode?D.parentNode.ui.getContainer():D.ownerTree.innerCt.dom; if(!this.rendered){ this.rendered=true; this.renderElements(D,A,C,B); if(A.qtip){ if(this.textNode.setAttributeNS){ this.textNode.setAttributeNS("ext","qtip",A.qtip); if(A.qtipTitle){ this.textNode.setAttributeNS("ext","qtitle",A.qtipTitle) } }else{ this.textNode.setAttribute("ext:qtip",A.qtip); if(A.qtipTitle){ this.textNode.setAttribute("ext:qtitle",A.qtipTitle) } } }else{ if(A.qtipCfg){ A.qtipCfg.target=Ext.id(this.textNode); Ext.QuickTips.register(A.qtipCfg) } } this.initEvents(); if(!this.node.expanded){ this.updateExpandIcon(true) } }else{ if(B===true){ C.appendChild(this.wrap) } } }, renderElements:function(D,I,H,J){ this.indentMarkup=D.parentNode?D.parentNode.ui.getChildIndent():""; var E=typeof I.checked=="boolean"; var B=I.href?I.href:Ext.isGecko?"":"#"; var C=["<li class=/"x-tree-node/"><div ext:tree-node-id=/"",D.id,"/" class=/"x-tree-node-el x-tree-node-leaf x-unselectable ",I.cls,"/" unselectable=/"on/">","<span class=/"x-tree-node-indent/">",this.indentMarkup,"</span>","<img src="/" mce_src="/""",this.emptyIcon,"/" class=/"x-tree-ec-icon x-tree-elbow/" />","<img src="/" mce_src="/""",I.icon||this.emptyIcon,"/" class=/"x-tree-node-icon",(I.icon?" x-tree-node-inline-icon":""),(I.iconCls?" "+I.iconCls:""),"/" unselectable=/"on/" />",E?("<input class=/"x-tree-node-cb/" type=/"checkbox/" "+(I.checked?"checked=/"checked/" />":"/>")):"","<a hidefocus=/"on/" class=/"x-tree-node-anchor/" href="/" mce_href="/""",B,"/" tabIndex=/"1/" ",I.hrefTarget?" target=/""+I.hrefTarget+"/"":"","><span unselectable=/"on/">",D.text,"</span></a></div>","<ul class=/"x-tree-node-ct/" style="/" mce_style="/""display:none;/"></ul>","</li>"].join(""); var A; if(J!==true&&D.nextSibling &&(A=D.nextSibling.ui.getEl())){ this.wrap=Ext.DomHelper.insertHtml("beforeBegin",A,C) }else{ this.wrap=Ext.DomHelper.insertHtml("beforeEnd",H,C) } this.elNode=this.wrap.childNodes[0]; this.ctNode=this.wrap.childNodes[1]; var G=this.elNode.childNodes; this.indentNode=G[0]; this.ecNode=G[1]; this.iconNode=G[2]; var F=3; if(E){ this.checkbox=G[3]; F++ } this.anchor=G[F]; this.textNode=G[F].firstChild }, getAnchor:function(){ return this.anchor }, getTextEl:function(){ return this.textNode }, getIconEl:function(){ return this.iconNode }, isChecked:function(){ return this.checkbox?this.checkbox.checked:false }, updateExpandIcon:function(){ if(this.rendered){ var F=this.node,D,C; var A=F.isLast()?"x-tree-elbow-end":"x-tree-elbow"; var E=F.hasChildNodes(); if(E||F.attributes.expandable){ if(F.expanded){ A+="-minus"; D="x-tree-node-collapsed"; C="x-tree-node-expanded" }else{ A+="-plus"; D="x-tree-node-expanded"; C="x-tree-node-collapsed" }if(this.wasLeaf){ this.removeClass("x-tree-node-leaf"); this.wasLeaf=false }if(this.c1!=D||this.c2!=C){ Ext.fly(this.elNode).replaceClass(D,C); this.c1=D; this.c2=C } }else{ if(!this.wasLeaf){ Ext.fly(this.elNode).replaceClass("x-tree-node-expanded","x-tree-node-leaf"); delete this.c1; delete this.c2; this.wasLeaf=true } } var B="x-tree-ec-icon "+A; if(this.ecc!=B){ this.ecNode.className=B; this.ecc=B } } }, getChildIndent:function(){ if(!this.childIndent){ var A=[]; var B=this.node; while(B){ if(!B.isRoot||(B.isRoot&&B.ownerTree.rootVisible)){ if(!B.isLast()){ A.unshift("<img src="/" mce_src="/"""+this.emptyIcon+"/" class=/"x-tree-elbow-line/" />") }else{ A.unshift("<img src="/" mce_src="/"""+this.emptyIcon+"/" class=/"x-tree-icon/" />") } } B=B.parentNode } this.childIndent=A.join("") } return this.childIndent }, renderIndent:function(){ if(this.rendered){ var A=""; var B=this.node.parentNode; if(B){ A=B.ui.getChildIndent() }if(this.indentMarkup!=A){ this.indentNode.innerHTML=A; this.indentMarkup=A } this.updateExpandIcon() } }, destroy:function(){ if(this.elNode){ Ext.dd.Registry.unregister(this.elNode.id) } delete this.elNode; delete this.ctNode; delete this.indentNode; delete this.ecNode; delete this.iconNode; delete this.checkbox; delete this.anchor; delete this.textNode; Ext.removeNode(this.ctNode) } }; Ext.tree.RootTreeNodeUI=Ext.extend(Ext.tree.TreeNodeUI, { render:function(){ if(!this.rendered){ var A=this.node.ownerTree.innerCt.dom; this.node.expanded=true; A.innerHTML="<div class=/"x-tree-root-node/"></div>"; this.wrap=this.ctNode=A.firstChild } }, collapse:Ext.emptyFn,expand:Ext.emptyFn } );