浏览 3214 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-08-15
先看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); } 到这里,我把扩展节点样式和事件的方法介绍完了。即使在复杂的树,只要掌握了这两个要点,都可以很简单的构建出来。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |