接着上一次的介绍,这次主要说一下如何扩展YUI的tree。使用YUI的Tree需要引入两个文件,一个是treeview.css,一个是treeview.js,从这个文件结构上来看不发现,如果需要扩展一棵树,无非就是从显示(css)和控制(Js)上来实现。首先分析一下css文件在Js是如何被引用的。
先看getStyle()这个方法:
/**
* Returns the css style name for the toggle
* @method getStyle
* @return {string} the css class for this node's toggle
*/
getStyle: function() {
// this.logger.log("No children, " + " isDyanmic: " + this.isDynamic() + " expanded: " + this.expanded);
if (this.isLoading) {
this.logger.log("returning the loading icon");
return "ygtvloading";
} else {
// location top or bottom, middle nodes also get the top style
var loc = (this.nextSibling) ? "t" : "l";
// type p=plus(expand), m=minus(collapase), n=none(no children)
var type = "n";
if (this.hasChildren(true) || (this.isDynamic() && !this.getIconMode())) {
// if (this.hasChildren(true)) {
type = (this.expanded) ? "m" : "p";
}
// this.logger.log("ygtv" + loc + type);
return "ygtv" + loc + type;
}
},
这个方法返回的是一个ygtv开头的字符串,查看treeview.css
会发现很多ygtv开头的class,下面列出几个。
需要说明的是,Treeview中用到的那些虚线,加号,减号等图片全都在同一张图片上,就是下面class中的sprite-orig.gif,如果你打开图片可以发现这个图片很长,最上面有加号,一段虚线链接之后又有减号,而在Css中就是通过Y方向上的偏移来实现定位,如下面的.ygtvm在y方向上偏移4000px,正好指向加号那个图标。
/*第一个或者是中间节点,合拢状态,就是显示一个加号*/
.ygtvtm {
width:18px; height:22px;
cursor:pointer ;
background: url(sprite-orig.gif) 0 -4000px no-repeat;
}
/*这个显示与上一个相同是一个加号,只是加了一个h,表示鼠标移上时显示的,加了高亮效果*/
.ygtvtmh {
width:18px; height:22px;
cursor:pointer ;
background: url(sprite-orig.gif) 0 -4800px no-repeat;
}
/*在Load节点的时候,显示动态的转动图标*/
.ygtvloading {
width:18px; height:22px;
background: url(treeview-loading.gif) 0 0 no-repeat;
}
回过头来看getStyle()方法,这个方法就是通过该节点当前所处的位置,设置节点之前应该显示的图标,当树被展开或者是合拢的时候,都会调用updateIcon这个方法,我们看看这个方法的实现,其实它就是调用了getStyle()方法。
updateIcon: function() {
if (this.hasIcon) {
var el = this.getToggleEl();
if (el) {
el.className = el.className.replace(/\bygtv(([tl][pmn]h?)|(loading))\b/gi,this.getStyle());
}
}
getStyle()这个方法是设置树的骨架的显示,而不是设置每个节点的显示。那么要修改每一个节点的显示应该如何来做呢?
之前的文章中介绍过Node中的一个方法,叫做getNodeHtml(),这个方法才是设置每一个Node的状态,包括这个Node上可以响应的事件。下面看看TextNode.js文件中的getNodeHtml()方法的源码:
// overrides YAHOO.widget.Node
getNodeHtml: function() {
this.logger.log("Generating html");
var sb = [];
sb[sb.length] = '<table border="0" cellpadding="0" cellspacing="0">';
sb[sb.length] = '<tr>';
for (var i=0;i<this.depth;++i) { //第一个Td,根据该节点的depth,把之前没有内容的地方设置为空白,构成树的层次结构
sb[sb.length] = '<td class="' + this.getDepthStyle(i) + '"><div class="ygtvspacer"></div></td>';
}
var getNode = 'YAHOO.widget.TreeView.getNode(\'' +
this.tree.id + '\',' + this.index + ')'; //这个变量是代表该节点自身,在之后的事件触发出有用
sb[sb.length] = '<td'; //第二个Td,通过之前介绍的getStyle() 方法,设置该节点前面的图标
// sb[sb.length] = ' onselectstart="return false"';
sb[sb.length] = ' id="' + this.getToggleElId() + '"';
sb[sb.length] = ' class="' + this.getStyle() + '"';
if (this.hasChildren(true)) { //通过判断该节点是否有children来判断显示展开状态还是合拢状态
sb[sb.length] = ' onmouseover="this.className=';
sb[sb.length] = getNode + '.getHoverStyle()"'; //鼠标滑过的高亮效果
sb[sb.length] = ' onmouseout="this.className=';
sb[sb.length] = getNode + '.getStyle()"'; //鼠标移开之后的正常效果
}
sb[sb.length] = ' onclick="javascript:' + this.getToggleLink() + '">'; //点击节点前面图标时触发的事件(事件处理稍后介绍)
sb[sb.length] = '<div class="ygtvspacer">';
sb[sb.length] = '</div>';
sb[sb.length] = '</td>';
sb[sb.length] = '<td '; //第三个Td,主要是显示内容,通过this.label属性,把label的值显示出来
sb[sb.length] = (this.nowrap) ? ' nowrap="nowrap" ' : '';
sb[sb.length] = ' >';
sb[sb.length] = '<a'; //在this.label上使用一个超链接
sb[sb.length] = ' id="' + this.labelElId + '"';
if (this.title) {
sb[sb.length] = ' title="' + this.title + '"';
}
sb[sb.length] = ' class="' + this.labelStyle + '"';
sb[sb.length] = ' href="' + this.href + '"';
sb[sb.length] = ' target="' + this.target + '"';
sb[sb.length] = ' onclick="return ' + getNode + '.onLabelClick(' + getNode +')"'; //点击超链接时触发的事件(事件处理稍后介绍)
if (this.hasChildren(true)) { //当该节点不是最后一个节点,他还有children的时候,设置显示当前是展开还是合拢状态
sb[sb.length] = ' onmouseover="document.getElementById(\'';
sb[sb.length] = this.getToggleElId() + '\').className=';
sb[sb.length] = getNode + '.getHoverStyle()"'; //鼠标滑过的高亮效果
sb[sb.length] = ' onmouseout="document.getElementById(\'';
sb[sb.length] = this.getToggleElId() + '\').className=';
sb[sb.length] = getNode + '.getStyle()"'; //鼠标移开之后的正常效果
}
sb[sb.length] = ' >';
sb[sb.length] = this.label; //Node上面显示label属性上对应的内容
sb[sb.length] = '</a>';
sb[sb.length] = '</td>';
sb[sb.length] = '</tr>';
sb[sb.length] = '</table>';
return sb.join(""); //返回动态生成的Html
},
在代码里面附了一些注释,这边在总体说一下。Sb是一个数组,用来存储动态生成的Html,从Html元素上来看,每一个Node节点是一个Table,这个Table只有一行,有多个列,看第一个Td是通过这个节点处在哪一层(也就是depth是多少)用空白来填补没有内容的地方。第二个Td开始调用getStyle()来判断这个节点之前是否有图标要显示,一般是虚线,加号或者减号。第三个Td是显示一些具体的内容,可以说文本或则是图片等等。
从Node显示的构成来看,如果想要改变Node的显示样式,只要修改各个Td里面对应元素的Css,要想增加显示效果或者增加新的元素,只要增加Td在对应的位置上,就可以简单的实现。比如我在第三个Td(显示Label的Td)之前插入一个Checkbox,那么只要加入下面几行代码即可:
sb[sb.length] = '<td>';
sb[sb.length] = '<input type="checkbox"';
sb[sb.length] = '/>';
sb[sb.length] = '</td>';
当然这是一个很简单的例子,只要了解一点,要增加元素,只需要增加一个Td,在Td中可以设置任何你想要的。
在上面的代码中,有看到几个事件,比如:
sb[sb.length] = ' onclick="javascript:' + this.getToggleLink() + '">';
点击节点前面的加号减号时候,触发this.getToggleLink()这个方法,这个方法的实现在Node.js里面,查看源码,可以发现,他最后是调用了节点的expand()和collapse()方法。也就是点击它,要么是把节点展开,要么是把节点合拢。
sb[sb.length] = ' onclick="return ' + getNode + '.onLabelClick(' + getNode +')"';
点击节点的Label时,触发上面的事件,即:onLabelClick(),看看这个方法的源码:
onLabelClick: function(me) {
me.logger.log("onLabelClick " + me.label);
return me.tree.fireEvent("labelClick", me);
//return true;
},
这个方法就是把节点上的labelClick事件注册到了treeView上面。这边并没有直接给出任何实现,那么点击label的时候会有什么效果呢?默认的情况下是不会有任何反应的,这样的设置主要是要用户自己去实现labelClick的动作,需要用户去给labelClick设置一个监听方法。在我们使用Tree的时候,可以这样来做事件的监听:
tree.subScribe(‘labelClick’,clickHandler);
function clickHandler(node){
//注意,这个方法有一个参数node,这个node是你点击的那个node,labelClick会把点击//的那个Node传递给处理函数,这样可以很简单的取得你所点击的几点上的属性。
}
这是一种很好的封装模式,在Node上面把所有节点自身的显示和事件控制都写在内部,把需要与外部交互的地方设置一个出口,就像上面labelClick一样,只在需要的地方设置一个监听事件。这样使得外部和Node之间只通过方法来通信。
我之前举例子时在label之前增加了一个checkBox一样,如果我要在点击选中checkbox的时候,打印当前节点的label值,可以通过下面的方式来把事件传递到外部:
//加入checkbox的代码片段
sb[sb.length] = '<td>';
sb[sb.length] = '<input type="checkbox"';
sb[sb.length] = ' onclick="return ' + getNode + '.onCheckBoxClick(' + getNode +')"';
sb[sb.length] = '/>';
sb[sb.length] = '</td>';
//onCheckBoxClick方法
onCheckBoxClick: function(node){
return me.tree.fireEvent("onCheckBoxClick", me);
}
//外部监听代码片段
tree.subScribe('onCheckBoxClick', checkBoxHandler);
function checkBoxHandler(node){
alert(node.label);
}
到这里,我把扩展节点样式和事件的方法介绍完了。即使在复杂的树,只要掌握了这两个要点,都可以很简单的构建出来。
分享到:
相关推荐
在“YUI3 中tree的两种实现”博文中,作者可能介绍了利用Gallery中的扩展来创建更复杂或具有特定功能的树。例如,可能使用了`treeview-dragdrop`模块,允许用户通过拖放操作重新排序或移动节点。 ```javascript var...
在这个场景中,我们讨论的是如何使用`YUI3`实现一个特殊的组件——一个可展开的`Overlay`,它内部展示了一个树形结构(Tree),并且树节点支持拖放(Drag and Drop)功能。 首先,`Overlay`是`YUI3`中的一个基础...
YUI是一个开源的JavaScript和CSS库,旨在帮助开发者创建高性能、可扩展的Web应用程序。在本文中,我们将深入探讨Yahoo Tree组件的核心功能、使用方法以及如何在实际项目中应用。 首先,让我们了解树组件的基本概念...
在JavaScript和EasyUI框架中,处理树形控件(如Tree)时,有时我们需要获取当前选中节点的所有顶级父节点。这在数据层次结构中非常常见,例如在组织结构、文件系统或者菜单导航中。标题提到的问题就是这样一个场景,...
它还允许轻松集成现有的树形UI,如xtree、ext tree和yuimenu。 为了开始使用E3.Tree,你需要确保系统满足以下条件:JDK 1.4X或更高版本。对于API的使用,仅需要jsp1.2和servlet2.3,而使用taglib则需要jsp2.0和...
* 1)扩展jquery easyui tree的节点检索方法。使用方法如下: * $("#treeId").tree("search", searchText); * 其中,treeId为easyui tree的根UL元素的ID,searchText为检索的文本。 * 如果searchText为空或"",...
YUI Tree控件支持多种功能,如可折叠节点、拖放操作、多选模式等。使用YUI创建Tree控件的基本步骤包括: 1. 引入YUI库:在HTML文件中,你需要链接到YUI的CSS和JavaScript文件,确保库在页面加载时可用。 2. 创建树...
最近在弄一个产品分类管理,是一个树形菜单的形式,用的是layui-tree ,由于它并没有动态添加节点,所以只能自己刚了。 大概效果如图 体的实现是当我鼠标移入“长袖”这个分类时,出现三个icon (如图),按“增加”...
- YUI TreeView Control 支持通过XMLHttpRequest动态加载节点数据,允许自定义节点元数据。 - 它是免费的。 9. **Fonshen JS MenuTree** - 风声JS菜单树基于JavaScript、XHTML和CSS实现,支持无限级别和多种展开...
- 易于集成现有树形UI:支持集成如xtree、exttree和yuimenu等。 - 功能丰富:支持多种类型的树,例如普通树、单选树、复选树、动态树等。 #### 二、开发环境与要求 - **开发环境**:本文档以Struts + Hibernate +...
由于项目树形节点比较多需要增加节点搜索功能,所以研究了一下加上社区伙伴的支持,目前功能可以简单实现但细节还需要修改,添加上了组件的基本使用方法和属性,现在分享出来~ HTML: <button class=layui-btn...
尽管YUI自身已经提供了TREE VIEW组件,但开发者Jack Slocum选择重新开发TreePanel,以提供更丰富的功能和更好的用户体验。以下是一些关键知识点: 1. **TreePanel的创建**: 创建TreePanel时,需要指定一个容器...
### 学习YUI.Ext 第六天--关于树TreePanel(Part 2异步获取节点) #### 引言 在本篇文章中,我们将深入探讨如何使用YUI.Ext库中的TreePanel组件来实现异步获取树节点的功能。不同于同步加载方式,异步加载能够显著...
其中,“Y梨”(可能是“YAHAA Tree”或者“YUI Tree”的误写)指的是EXTJS中的树形组件,用于展示层次结构的数据。在这个名为“Y梨Ext动态树的完整示例代码”的压缩包中,我们很可能会找到一个完整的EXTJS应用,...
User Interface Library),并扩展了YUI的功能,提供了丰富的用户界面组件,如表格、树形结构、窗口等。EXT适用于快速开发复杂的客户端应用程序,尤其是在企业级应用中非常常见。 #### 二、EXT树形控件(TreePanel)...
layui.use([ 'tree' ], function() { $ = layui.jquery; form = layui.form; //获取节点数据 getTreeData(); }); function getTreeData() { $.ajax({ url : path+/RoleController/getResourceTree.do, type : post, ...
前台页面: <pre name=code class=html><td xss=removed colspan=7> <input id=fm_AEType class=easyui-combotree style=width: 240px /> </td></pre> JavaScript页面(包括数据初始化): ...
3.9.1. 树形节点的拖拽有三种形式 3.9.2. 用事件控制拖拽 3.9.2.1. 叶子不能append 3.9.2.2. 把节点扔到哪里啦 3.9.2.3. 裟椤双树,常与无常 3.10. 树形过滤器TreeFilter 3.11. TreeSorter对树形排序 4. 祝福吧!把...
-优化Tree节点的NodeId自动生成,减少ViewState占用。 +2009-08-09 v2.0 beta5 +ExtAspNet和Asp.net的提交按钮兼容问题(feedback:千帆)。 -在2009-03-03 v1.3.0曾经提到这个兼容问题,并有这样的规则,如果...