ECO tree


最近公司用到Eco tree,感觉还不错,就贴出来跟大家分享,主要的功能是tree,但请注意,此tree非比tree,里面还有一个小tree,用于缩略图的效果。具体代码如下,不做过多解释:

主文件HTML

<%@ page language="java" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>ECOTree Advanced</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="../../lib/jquery-ui/css/ui-lightness/jquery-ui-1.8.19.custom.css" type="text/css">
<script type="text/javascript" src="scripts/init-iframe.js"></script>
<script type="text/javascript" src="../../lib/jquery-ui/dev/jquery-1.7.2.js"></script>

<link type="text/css" rel="stylesheet" href="style/ECOTree.css" />
<link type="text/css" rel="stylesheet" href="../../style/all.css" />
<xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v" />
<style>v\:*{ behavior:url(#default#VML);}
</style>
</head>
<body style="height:2200px;">
<div style="width:99%;height:40px;font-size:9pt; background:#9CC;position:fixed;border:1px solid #EFEFEF;padding:3px;">
2011年1-8月累计运营收入<span class="editor_number_input" title="编辑" id="earning" name="运营收入">47.26</span>亿元,同比增长<span class="editor_number_input" title="编辑-同比增长" name="同比增长" id="currYearGrowthrate">3.57</span>%,较10年同期增幅下降<span class="editor_number_input" title="编辑" name="同期增幅" id="sametermGrowthrate">5.63</span>个百分点;增幅下降主要影响因素为通话收入,其变动影响度为<span class="editor_number_input" name="影响度" id="effectChangeDegree">-0.19</span>%;其中漫游通话收入和非漫游收入下降为主要因素…...
</div>
<div id="abbreviative" style="float:left;width:178px;height:88px;position:fixed; top: 58px;left:8px;border:1px #CCC solid; z-index: 1000; background:URL('img/bg.png');">
<iframe src="tree-mini.html" width="100%" height="86px" name="MyIFrame" id="MyIFrame" frameborder='no' scrolling="no" left="0" top="0"></iframe>
</div>
<div style="float:left;width:558px;height:36px; line-height:36px;border:1px solid #EFEFEF; position: fixed;top:58px;left:198px;padding-top:3px; background:URL('img/bg.png');">
<label>月份:</label>
<span>
<select class="ui-datepicker-year" id="datepicker-year" name="year">
<option>请选择年</option>
</select>
<select class="ui-datepicker-month" name="month">
<option>请选择月份</option>
<option value="01">1</option>
<option value="02">2</option>
<option value="03">3</option>
<option value="04">4</option>
<option value="05">5</option>
<option value="06">6</option>
<option value="07">7</option>
<option value="08">8</option>
<option value="09">9</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12" selected="selected">12</option>
</select>
</span>
<label>地区:</label>
<span>
<select name="area" style="width:128px;">
</select>
</span>

<span id="search_btn" class="ui-state-default ui-corner-all">
<span class="ui-icon ui-icon-search"></span>
查询
</span>

<span id="release_btn" class="ui-state-default ui-corner-all">
<span class="ui-icon ui-icon-extlink"></span>
发布
</span>

</span>
</div>

<script type="text/javascript" src="scripts/app.js"></script>
<script type="text/javascript" src="scripts/ECOTree-1.1.js"></script>
<div id="sample1" style="clear: both;"></div>

<!--
<script type="text/javascript" src="scripts/init-page.js"></script>
-->
</body>
</html>

init-iframe.js

/**
 * 新增加的功能:初始化参数,参数包括iframe的document和window,对于html,可以使用document操作,函数方法,可以使用window操作
 */
var ifDoc = null;
var ifWin = null;
initIframeParam = function(){
    //console.log('进来 了?');
    if (document.all){//IE
        ifDoc = document.frames["MyIFrame"].document;
        ifWin = document.getElementById("MyIFrame").contentWindow;
        //alert('是这里吗?'+document.getElementById("MyIFrame").contentWindow.t);
    }else{//Firefox
        ifWin = document.getElementById('MyIFrame').contentWindow;
        ifDoc = document.getElementById('MyIFrame').contentDocument || document.getElementById('MyIFrame').contentWindow.document;
    }
}


scripts/app.js

var t = null;

/**
 * 被 子窗口调用测试
 */
test = function(){
    alert('子窗口调用父窗口方法成功!');
}


/**
 *页面加载完后事件
 */
$(function(){
    
    setNumberValueColor();
    
    initSelectInput();
    //初始化iframe
    initIframeParam();
    //初始树
    doSearch();
    
    //查询按钮单击后执行doSearch
    $('#search_btn').click(doSearch);
    //可编辑的数字双击后执行textfieldEditor
    $('.editor_number_input').dblclick(textfieldEditor);
    
    $('div').dblclick(selectedNode);
})

/**
 * 设置样式,如果是数值,如果小于零,则设置为红色 ; 否则为绿色,或蓝色
 * 设置遇到鼠标后的效果,移出鼠标后的效果
 */
setNumberValueColor = function(){
    $('.editor_number_input').each(function(){
        if($(this).text()<0){
            $(this).css("color",'#F00');
        }else{
            $(this).css("color",'#0E0');
        }
    });
    $(".editor_number_input").hover(
        function () {
            $(this).addClass("hover");
        },
        function () {
            $(this).removeClass("hover");
        }
        );
}

/**
 *执行编辑,
 *首先查找当前已经处在编辑状态下的input,将其置为非编辑状态,其次,将本节点置为编辑状态,
 *如果enter则验证、判断后再提交;暂缺数值组件与验证
 */
textfieldEditor = function(){
    if($('.currentEditor').length>0){
        var val = $('.currentEditor').val();
        $('.currentEditor').parent().html(val);
    }
    
    var oldVal = $(this).text();
    //一个表单,长度为当前取到的字符的长度3.14则为5
    var inputNode = '<input class="currentEditor" type="text" value="'+oldVal+'" size="'+(oldVal.length*2.65)+'"/>';
    
    $(this).html(inputNode);
    //移除双击事件,只监听enter or ESC键
    //$(this).unbind('dblclick');
    
    //接收键盘事件
    var newOldVal = "";
    $("input").keydown(function(){
        newOldVal=$('.currentEditor').val();
    });
    $(this).keyup( function() {
        if(isNaN($('.currentEditor').val())){
        //$('.currentEditor').val(newOldVal);
        }
    });
    /* 小键盘45(-),46(.),48,49,50,51,52,53,54,55,56,57
     */
    $(this).keypress(function(e) {
        //console.warn(e.charCode);
        if (e.keyCode == 13) {
            if(!isNaN($('.currentEditor').val())){
                $(this).text($('.currentEditor').val());
            }else{
                $(this).text(oldVal);
                alert("ERROR\n输入的参数值非数字类型!");
                $(this).focus();
            }
        }else if (e.keyCode == 27){
            $(this).text(oldVal);
        }
    //$(".editor_number_input").bind("dblclick", textfieldEditor);
    });
}

/**
 *初始化select表单,年份应该是动态的,明年后年,还可以选择当年,月份是死的,只有12月
 */
initSelectInput = function(){
    var d = new Date();
    var byYear = d.getYear();
    //var byMonth = d.getMonth()+1;
    if(!document.all){
        byYear+=1900;
    }
    for(var i=0;i<=15;i++){
        var oldYear = byYear-i;
        var optElement = $('<option value="'+oldYear+'">'+oldYear+'</option>');
        if(i==0){
            $(optElement).attr('selected','selected');
        }
        $("#datepicker-year").append(optElement);
    }
    
    $.ajax({
        url:'../..//action/common/getAreaCombobox.action',
        dataType:'json',
        async: false,
        success:function(response){
            if(response.areas.length>0){
                var obj = $('select[name="area"]').html('');
                for(var o in response.areas){
                    var n = response.areas[o].id;
                    var node = $('<option value='+n.areaCode+'>'+n.areaName+'</option>');
                    if(n.areaName=="天津分公司"){
                        $(node).attr('selected','selected');
                    }
                    $(obj).append(node);
                }
            }
        }
    });
}

/**
 *初始化树,查询树数据,都在此方法
 */
doSearch = function(){
    
    var d = new Date();
    var byMonth = d.getMonth()+1;
    
    var yNode = $('#datepicker-year');
    var byYear = d.getYear();
    
    var mNode = $('select[name="month"]');
    var areaNode = $('select[name="area"]');
    var pyear = $(yNode).val();
    if(!document.all){
        byYear=Number(Number(byYear)+1900);
    }
    var pmonth= $(mNode).val();
    if(pyear==byYear&&pmonth>byMonth){
        pmonth = byMonth;
    }
    
    //console.warn($(areaNode).val());
    //alert($(yNode).val()+"-"+$(mNode).val()+" / "+$(areaNode).val());
    $.ajax({
        url:'../../action/eco/getEcoTreeDate.action',
        type:'POST',
        async: false,
        data:{
            areaCode:$(areaNode).val(),
            year:pyear,
            month:pmonth
        },
        success:function(msg){
            //数据成功了,需要重装装载eco tree,并将缩略图的数据也重新装载
            //console.dir(msg.list);
            t = new ECOTree('t','sample1');
            $(msg.list).each(function(){
                //console.log(this.incomeId,this.parentId,this.title);
                var currYearGrowthrate = '<span class="currYearGrowthrate">同比'+this.currYearGrowthrate+'</span>';
                var sametermGrowthrate = '<span class="sametermGrowthrate">同期增幅'+this.sametermGrowthrate+'</span>';
                var effectChangeDegree = '<span class="effectChangeDegree">变动影响指数'+this.effectChangeDegree+'</span>';
                
                if(this.incomeId=='001'){
                    //console.dir(this);
                    $('#earning').html(this.currYearIncome);
                    $('#currYearGrowthrate').html(this.currYearGrowthrate.replace('%',''));
                    $('#sametermGrowthrate').html(this.sametermGrowthrate.replace('%',''));
                    $('#effectChangeDegree').html(this.effectChangeDegree.replace('%',''));
                    t.add(this.incomeId,-1,this.title+"<br/>"+currYearGrowthrate+sametermGrowthrate,null,null,"green","black");
                }else{
                    t.add(this.incomeId,this.parentId,this.title+"<br/>"+currYearGrowthrate+sametermGrowthrate+effectChangeDegree);
                }
            });
            t.UpdateTree();
            setNumberValueColor();
        }
    })
}

/*查询节点*/
function ChangeSearchMode() {
    var mode = parseInt(document.forms[0].searchMode.value);
    t.config.searchMode = mode;
}

/*节点选择模式*/
function ChangeSelMode() {				
    var mode = parseInt(document.forms[0].selMode.value);
    t.config.selectMode = mode;				
    t.unselectAll();
}

/*输出选择的节点*/
function selectedNode(node) {
    console.dir($(node));
}

/*输出选择的节点
function selectedNodes() {
    var selnodes = t.getSelectedNodes();
    var s = [];
    for (var n = 0; n < selnodes.length; n++){
        s.push('' + n + ': Id=' + selnodes[n].id + ', Title='+ selnodes[n].dsc + ', Metadata='+ selnodes[n].meta + '\n');
    }
    alert('The selected nodes are:\n\n' + ((selnodes.length >0) ? s.join(''): 'None.'));
}*/

/**
 *检测滚动条的座标,并设置iframe内容移动
 */
function  ScollPostion() {//滚动条位置
    var tt, ll, ww, hh;
    if (document.documentElement && document.documentElement.scrollTop) {
        tt = document.documentElement.scrollTop;
        ll = document.documentElement.scrollLeft;
        ww = document.documentElement.scrollWidth;
        hh = document.documentElement.scrollHeight;
    } else if (document.body) {
        tt = document.body.scrollTop;
        ll = document.body.scrollLeft;
        ww = document.body.scrollWidth;
        hh = document.body.scrollHeight;
    }
    //console.log(tt, ll, ww, hh);
    var sam = ifDoc.getElementById('sample1');
    
    //设置iframe的sample1的属性
    sam.scrollTop = tt/10;
    sam.scrollLeft = ll/10;
}

/**
 *监听滚动条
 */
var timeout = false;
$(window).scroll(function(){
    if (timeout){
        clearTimeout(timeout);
    }
    timeout = setTimeout(function(){
        ScollPostion();
    },100);
}); 


ECOTree-1.1.js

/*-------------------------------------------------------------------------------------------
|     ECOTree.js
ECONode = function (id, pid, dsc, w, h, c, bc, target, meta) {
    this.id = id;
    this.pid = pid;
    this.dsc = dsc;
    this.w = w;
    this.h = h;
    this.c = c;
    this.bc = bc;
    this.target = target;
    this.meta = meta;
	
    this.siblingIndex = 0;
    this.dbIndex = 0;
	
    this.XPosition = 0;
    this.YPosition = 0;
    this.prelim = 0;
    this.modifier = 0;
    this.leftNeighbor = null;
    this.rightNeighbor = null;
    this.nodeParent = null;
    this.nodeChildren = [];
	
    this.isCollapsed = false;
    this.canCollapse = false;
	
    this.isSelected = false;
}

ECONode.prototype._getLevel = function () {
    if (this.nodeParent.id == -1) {
        return 0;
    }
    else return this.nodeParent._getLevel() + 1;
}

ECONode.prototype._isAncestorCollapsed = function () {
    if (this.nodeParent.isCollapsed) {
        return true;
    } else {
        if (this.nodeParent.id == -1) {
            return false;
        } else {
            return this.nodeParent._isAncestorCollapsed();
        }
    }
}

ECONode.prototype._setAncestorsExpanded = function () {
    if (this.nodeParent.id == -1) {
        return;
    } else {
        this.nodeParent.isCollapsed = false;
        return this.nodeParent._setAncestorsExpanded(); 
    }	
}

ECONode.prototype._getChildrenCount = function () {
    if (this.isCollapsed) return 0;
    if(this.nodeChildren == null)
        return 0;
    else
        return this.nodeChildren.length;
}

ECONode.prototype._getLeftSibling = function () {
    if(this.leftNeighbor != null && this.leftNeighbor.nodeParent == this.nodeParent)
        return this.leftNeighbor;
    else
        return null;	
}

ECONode.prototype._getRightSibling = function () {
    if(this.rightNeighbor != null && this.rightNeighbor.nodeParent == this.nodeParent)
        return this.rightNeighbor;
    else
        return null;	
}

ECONode.prototype._getChildAt = function (i) {
    return this.nodeChildren[i];
}

ECONode.prototype._getChildrenCenter = function (tree) {
    node = this._getFirstChild();
    node1 = this._getLastChild();
    return node.prelim + ((node1.prelim - node.prelim) + tree._getNodeSize(node1)) / 2;	
}

ECONode.prototype._getFirstChild = function () {
    return this._getChildAt(0);
}

ECONode.prototype._getLastChild = function () {
    return this._getChildAt(this._getChildrenCount() - 1);
}

ECONode.prototype._drawChildrenLinks = function (tree) {
    var s = [];
    var xa = 0, ya = 0, xb = 0, yb = 0, xc = 0, yc = 0, xd = 0, yd = 0;
    var node1 = null;
	
    switch(tree.config.iRootOrientation)
    {
        case ECOTree.RO_TOP:
            xa = this.XPosition + (this.w / 2);
            ya = this.YPosition + this.h;
            break;
			
        case ECOTree.RO_BOTTOM:
            xa = this.XPosition + (this.w / 2);
            ya = this.YPosition;
            break;
			
        case ECOTree.RO_RIGHT:
            xa = this.XPosition;
            ya = this.YPosition + (this.h / 2);		
            break;
			
        case ECOTree.RO_LEFT:
            xa = this.XPosition + this.w;
            ya = this.YPosition + (this.h / 2);		
            break;		
    }
	
    for (var k = 0; k < this.nodeChildren.length; k++)
    {
        node1 = this.nodeChildren[k];
				
        switch(tree.config.iRootOrientation)
        {
            case ECOTree.RO_TOP:
                xd = xc = node1.XPosition + (node1.w / 2);
                yd = node1.YPosition;
                xb = xa;
                switch (tree.config.iNodeJustification)
                {
                    case ECOTree.NJ_TOP:
                        yb = yc = yd - tree.config.iLevelSeparation / 2;
                        break;
                    case ECOTree.NJ_BOTTOM:
                        yb = yc = ya + tree.config.iLevelSeparation / 2;
                        break;
                    case ECOTree.NJ_CENTER:
                        yb = yc = ya + (yd - ya) / 2;
                        break;
                }
                break;
				
            case ECOTree.RO_BOTTOM:
                xd = xc = node1.XPosition + (node1.w / 2);
                yd = node1.YPosition + node1.h;
                xb = xa;
                switch (tree.config.iNodeJustification)
                {
                    case ECOTree.NJ_TOP:
                        yb = yc = yd + tree.config.iLevelSeparation / 2;
                        break;
                    case ECOTree.NJ_BOTTOM:
                        yb = yc = ya - tree.config.iLevelSeparation / 2;
                        break;
                    case ECOTree.NJ_CENTER:
                        yb = yc = yd + (ya - yd) / 2;
                        break;
                }				
                break;

            case ECOTree.RO_RIGHT:
                xd = node1.XPosition + node1.w;
                yd = yc = node1.YPosition + (node1.h / 2);	
                yb = ya;
                switch (tree.config.iNodeJustification)
                {
                    case ECOTree.NJ_TOP:
                        xb = xc = xd + tree.config.iLevelSeparation / 2;
                        break;
                    case ECOTree.NJ_BOTTOM:
                        xb = xc = xa - tree.config.iLevelSeparation / 2;
                        break;
                    case ECOTree.NJ_CENTER:
                        xb = xc = xd + (xa - xd) / 2;
                        break;
                }								
                break;		
				
            case ECOTree.RO_LEFT:
                xd = node1.XPosition;
                yd = yc = node1.YPosition + (node1.h / 2);		
                yb = ya;
                switch (tree.config.iNodeJustification)
                {
                    case ECOTree.NJ_TOP:
                        xb = xc = xd - tree.config.iLevelSeparation / 2;
                        break;
                    case ECOTree.NJ_BOTTOM:
                        xb = xc = xa + tree.config.iLevelSeparation / 2;
                        break;
                    case ECOTree.NJ_CENTER:
                        xb = xc = xa + (xd - xa) / 2;
                        break;
                }								
                break;				
        }		
		
		
        switch(tree.render)
        {
            case "CANVAS":
                tree.ctx.save();
                tree.ctx.strokeStyle = tree.config.linkColor;
                tree.ctx.beginPath();			
                switch (tree.config.linkType)
                {
                    case "M":						
                        tree.ctx.moveTo(xa,ya);
                        tree.ctx.lineTo(xb,yb);
                        tree.ctx.lineTo(xc,yc);
                        tree.ctx.lineTo(xd,yd);						
                        break;
						
                    case "B":
                        tree.ctx.moveTo(xa,ya);
                        tree.ctx.bezierCurveTo(xb,yb,xc,yc,xd,yd);	
                        break;					
                }
                tree.ctx.stroke();
                tree.ctx.restore();
                break;
											
            case "VML":
                switch (tree.config.linkType)
                {
                    case "M":
                        s.push('<v:polyline points="');
                        s.push(xa + ' ' + ya + ' ' + xb + ' ' + yb + ' ' + xc + ' ' + yc + ' ' + xd + ' ' + yd); 		
                        s.push('" strokecolor="'+tree.config.linkColor+'"><v:fill on="false" /></v:polyline>');					
                        break;
                    case "B":
                        s.push('<v:curve from="');
                        s.push(xa + ' ' + ya + '" control1="' + xb + ' ' + yb + '" control2="' + xc + ' ' + yc + '" to="' + xd + ' ' + yd); 		
                        s.push('" strokecolor="'+tree.config.linkColor+'"><v:fill on="false" /></v:curve>');					
                        break;					
                }
                break;
				
        }			
    }	
	
    return s.join('');
}

ECOTree = function (obj, elm) {
    this.config = {
        iMaxDepth : 100,
        iLevelSeparation : 60,
        iSiblingSeparation : 60,
        iSubtreeSeparation : 160,
        iRootOrientation : ECOTree.RO_TOP,
        iNodeJustification : ECOTree.NJ_TOP,
        topXAdjustment : 0,
        topYAdjustment : 0,		
        render : "AUTO",
        linkType : "M",
        linkColor : "blue",
        nodeColor : "#CCCCFF",
        nodeFill : ECOTree.NF_GRADIENT,
        nodeBorderColor : "blue",
        nodeSelColor : "#FFFFCC",
        levelColors : ["#5555FF","#8888FF","#AAAAFF","#CCCCFF"],
        levelBorderColors : ["#5555FF","#8888FF","#AAAAFF","#CCCCFF"],
        colorStyle : ECOTree.CS_NODE,
        useTarget : true,
        searchMode : ECOTree.SM_DSC,
        selectMode : ECOTree.SL_MULTIPLE,
        defaultNodeWidth : 160,
        defaultNodeHeight : 60,
        defaultTarget : 'javascript:void(0);',
        expandedImage : './img/less.gif',
        collapsedImage : './img/plus.gif',
        transImage : './img/trans.gif'
    }
	
    this.version = "1.1";
    this.obj = obj;
    this.elm = document.getElementById(elm);
    this.self = this;
    this.render = (this.config.render == "AUTO" ) ? ECOTree._getAutoRenderMode() : this.config.render;
    this.ctx = null;
    this.canvasoffsetTop = 0;
    this.canvasoffsetLeft = 0;
	
    this.maxLevelHeight = [];
    this.maxLevelWidth = [];
    this.previousLevelNode = [];
	
    this.rootYOffset = 0;
    this.rootXOffset = 0;
	
    this.nDatabaseNodes = [];
    this.mapIDs = {};
	
    this.root = new ECONode(-1, null, null, 2, 2);
    this.iSelectedNode = -1;
    this.iLastSearch = 0;
	
}

//Constant values

//Tree orientation
ECOTree.RO_TOP = 0;
ECOTree.RO_BOTTOM = 1;
ECOTree.RO_RIGHT = 2;
ECOTree.RO_LEFT = 3;

//Level node alignment
ECOTree.NJ_TOP = 0;
ECOTree.NJ_CENTER = 1;
ECOTree.NJ_BOTTOM = 2;

//Node fill type
ECOTree.NF_GRADIENT = 0;
ECOTree.NF_FLAT = 1;

//Colorizing style
ECOTree.CS_NODE = 0;
ECOTree.CS_LEVEL = 1;

//Search method: Title, metadata or both
ECOTree.SM_DSC = 0;
ECOTree.SM_META = 1;
ECOTree.SM_BOTH = 2;

//Selection mode: single, multiple, no selection
ECOTree.SL_MULTIPLE = 0;
ECOTree.SL_SINGLE = 1;
ECOTree.SL_NONE = 2;


ECOTree._getAutoRenderMode = function() {
    var r = "VML";
    var is_ie6 = /msie 6\.0/i.test(navigator.userAgent);
    var is_ff = /Firefox/i.test(navigator.userAgent);	
    if (is_ff) r = "CANVAS";
    return r;
}

//CANVAS functions...
ECOTree._roundedRect = function (ctx,x,y,width,height,radius) {
    ctx.beginPath();
    ctx.moveTo(x,y+radius);
    ctx.lineTo(x,y+height-radius);
    ctx.quadraticCurveTo(x,y+height,x+radius,y+height);
    ctx.lineTo(x+width-radius,y+height);
    ctx.quadraticCurveTo(x+width,y+height,x+width,y+height-radius);
    ctx.lineTo(x+width,y+radius);
    ctx.quadraticCurveTo(x+width,y,x+width-radius,y);
    ctx.lineTo(x+radius,y);
    ctx.quadraticCurveTo(x,y,x,y+radius);
    ctx.fill();
    ctx.stroke();
}

ECOTree._canvasNodeClickHandler = function (tree,target,nodeid) {
    if (target != nodeid) return;
    tree.selectNode(nodeid,true);
}

//Layout algorithm
ECOTree._firstWalk = function (tree, node, level) {
    var leftSibling = null;
		
    node.XPosition = 0;
    node.YPosition = 0;
    node.prelim = 0;
    node.modifier = 0;
    node.leftNeighbor = null;
    node.rightNeighbor = null;
    tree._setLevelHeight(node, level);
    tree._setLevelWidth(node, level);
    tree._setNeighbors(node, level);
    if(node._getChildrenCount() == 0 || level == tree.config.iMaxDepth)
    {
        leftSibling = node._getLeftSibling();
        if(leftSibling != null)
            node.prelim = leftSibling.prelim + tree._getNodeSize(leftSibling) + tree.config.iSiblingSeparation;
        else
            node.prelim = 0;
    } 
    else
    {
        var n = node._getChildrenCount();
        for(var i = 0; i < n; i++)
        {
            var iChild = node._getChildAt(i);
            ECOTree._firstWalk(tree, iChild, level + 1);
        }

        var midPoint = node._getChildrenCenter(tree);
        midPoint -= tree._getNodeSize(node) / 2;
        leftSibling = node._getLeftSibling();
        if(leftSibling != null)
        {
            node.prelim = leftSibling.prelim + tree._getNodeSize(leftSibling) + tree.config.iSiblingSeparation;
            node.modifier = node.prelim - midPoint;
            ECOTree._apportion(tree, node, level);
        } 
        else
        {            	
            node.prelim = midPoint;
        }
    }	
}

ECOTree._apportion = function (tree, node, level) {
    var firstChild = node._getFirstChild();
    var firstChildLeftNeighbor = firstChild.leftNeighbor;
    var j = 1;
    for(var k = tree.config.iMaxDepth - level; firstChild != null && firstChildLeftNeighbor != null && j <= k;)
    {
        var modifierSumRight = 0;
        var modifierSumLeft = 0;
        var rightAncestor = firstChild;
        var leftAncestor = firstChildLeftNeighbor;
        for(var l = 0; l < j; l++)
        {
            rightAncestor = rightAncestor.nodeParent;
            leftAncestor = leftAncestor.nodeParent;
            modifierSumRight += rightAncestor.modifier;
            modifierSumLeft += leftAncestor.modifier;
        }

        var totalGap = (firstChildLeftNeighbor.prelim + modifierSumLeft + tree._getNodeSize(firstChildLeftNeighbor) + tree.config.iSubtreeSeparation) - (firstChild.prelim + modifierSumRight);
        if(totalGap > 0)
        {
            var subtreeAux = node;
            var numSubtrees = 0;
            for(; subtreeAux != null && subtreeAux != leftAncestor; subtreeAux = subtreeAux._getLeftSibling())
                numSubtrees++;

            if(subtreeAux != null)
            {
                var subtreeMoveAux = node;
                var singleGap = totalGap / numSubtrees;
                for(; subtreeMoveAux != leftAncestor; subtreeMoveAux = subtreeMoveAux._getLeftSibling())
                {
                    subtreeMoveAux.prelim += totalGap;
                    subtreeMoveAux.modifier += totalGap;
                    totalGap -= singleGap;
                }

            }
        }
        j++;
        if(firstChild._getChildrenCount() == 0)
            firstChild = tree._getLeftmost(node, 0, j);
        else
            firstChild = firstChild._getFirstChild();
        if(firstChild != null)
            firstChildLeftNeighbor = firstChild.leftNeighbor;
    }
}

ECOTree._secondWalk = function (tree, node, level, X, Y) {
    if(level <= tree.config.iMaxDepth)
    {
        var xTmp = tree.rootXOffset + node.prelim + X;
        var yTmp = tree.rootYOffset + Y;
        var maxsizeTmp = 0;
        var nodesizeTmp = 0;
        var flag = false;
            
        switch(tree.config.iRootOrientation)
        {            
            case ECOTree.RO_TOP:
            case ECOTree.RO_BOTTOM:	        	            	    	
                maxsizeTmp = tree.maxLevelHeight[level];
                nodesizeTmp = node.h;	                
                break;

            case ECOTree.RO_RIGHT:
            case ECOTree.RO_LEFT:
                maxsizeTmp = tree.maxLevelWidth[level];
                flag = true;
                nodesizeTmp = node.w;
                break;
        }
        switch(tree.config.iNodeJustification)
        {
            case ECOTree.NJ_TOP:
                node.XPosition = xTmp;
                node.YPosition = yTmp;
                break;
	
            case ECOTree.NJ_CENTER:
                node.XPosition = xTmp;
                node.YPosition = yTmp + (maxsizeTmp - nodesizeTmp) / 2;
                break;
	
            case ECOTree.NJ_BOTTOM:
                node.XPosition = xTmp;
                node.YPosition = (yTmp + maxsizeTmp) - nodesizeTmp;
                break;
        }
        if(flag)
        {
            var swapTmp = node.XPosition;
            node.XPosition = node.YPosition;
            node.YPosition = swapTmp;
        }
        switch(tree.config.iRootOrientation)
        {
            case ECOTree.RO_BOTTOM:
                node.YPosition = -node.YPosition - nodesizeTmp;
                break;
	
            case ECOTree.RO_RIGHT:
                node.XPosition = -node.XPosition - nodesizeTmp;
                break;
        }
        if(node._getChildrenCount() != 0)
            ECOTree._secondWalk(tree, node._getFirstChild(), level + 1, X + node.modifier, Y + maxsizeTmp + tree.config.iLevelSeparation);
        var rightSibling = node._getRightSibling();
        if(rightSibling != null)
            ECOTree._secondWalk(tree, rightSibling, level, X, Y);
    }	
}

ECOTree.prototype._positionTree = function () {	
    this.maxLevelHeight = [];
    this.maxLevelWidth = [];			
    this.previousLevelNode = [];		
    ECOTree._firstWalk(this.self, this.root, 0);
	
    switch(this.config.iRootOrientation)
    {            
        case ECOTree.RO_TOP:
        case ECOTree.RO_LEFT:
            this.rootXOffset = this.config.topXAdjustment + this.root.XPosition;
            this.rootYOffset = this.config.topYAdjustment + this.root.YPosition;
            break;    
	        
        case ECOTree.RO_BOTTOM:	
        case ECOTree.RO_RIGHT:
            this.rootXOffset = this.config.topXAdjustment + this.root.XPosition;
            this.rootYOffset = this.config.topYAdjustment + this.root.YPosition;
    }	
	
    ECOTree._secondWalk(this.self, this.root, 0, 0, 0);	
}

ECOTree.prototype._setLevelHeight = function (node, level) {	
    if (this.maxLevelHeight[level] == null) 
        this.maxLevelHeight[level] = 0;
    if(this.maxLevelHeight[level] < node.h)
        this.maxLevelHeight[level] = node.h;	
}

ECOTree.prototype._setLevelWidth = function (node, level) {
    if (this.maxLevelWidth[level] == null) 
        this.maxLevelWidth[level] = 0;
    if(this.maxLevelWidth[level] < node.w)
        this.maxLevelWidth[level] = node.w;		
}

ECOTree.prototype._setNeighbors = function(node, level) {
    node.leftNeighbor = this.previousLevelNode[level];
    if(node.leftNeighbor != null)
        node.leftNeighbor.rightNeighbor = node;
    this.previousLevelNode[level] = node;	
}

ECOTree.prototype._getNodeSize = function (node) {
    switch(this.config.iRootOrientation)
    {
        case ECOTree.RO_TOP: 
        case ECOTree.RO_BOTTOM:
            return node.w;

        case ECOTree.RO_RIGHT: 
        case ECOTree.RO_LEFT:
            return node.h;
    }
    return 0;
}

ECOTree.prototype._getLeftmost = function (node, level, maxlevel) {
    if(level >= maxlevel) return node;
    if(node._getChildrenCount() == 0) return null;
    
    var n = node._getChildrenCount();
    for(var i = 0; i < n; i++)
    {
        var iChild = node._getChildAt(i);
        var leftmostDescendant = this._getLeftmost(iChild, level + 1, maxlevel);
        if(leftmostDescendant != null)
            return leftmostDescendant;
    }

    return null;	
}

ECOTree.prototype._selectNodeInt = function (dbindex, flagToggle) {
    if (this.config.selectMode == ECOTree.SL_SINGLE)
    {
        if ((this.iSelectedNode != dbindex) && (this.iSelectedNode != -1))
        {
            this.nDatabaseNodes[this.iSelectedNode].isSelected = false;
        }		
        this.iSelectedNode = (this.nDatabaseNodes[dbindex].isSelected && flagToggle) ? -1 : dbindex;
    }	
    this.nDatabaseNodes[dbindex].isSelected = (flagToggle) ? !this.nDatabaseNodes[dbindex].isSelected : true;	
}

ECOTree.prototype._collapseAllInt = function (flag) {
    var node = null;
    for (var n = 0; n < this.nDatabaseNodes.length; n++)
    { 
        node = this.nDatabaseNodes[n];
        if (node.canCollapse) node.isCollapsed = flag;
    }	
    this.UpdateTree();
}

ECOTree.prototype._selectAllInt = function (flag) {
    var node = null;
    for (var k = 0; k < this.nDatabaseNodes.length; k++)
    { 
        node = this.nDatabaseNodes[k];
        node.isSelected = flag;
    }	
    this.iSelectedNode = -1;
    this.UpdateTree();
}

ECOTree.prototype._drawTree = function () {
    var s = [];
    var node = null;
    var color = "";
    var border = "";
			
    for (var n = 0; n < this.nDatabaseNodes.length; n++)
    {
        node = this.nDatabaseNodes[n];
		
        switch (this.config.colorStyle) {
            case ECOTree.CS_NODE:
                color = node.c;
                border = node.bc;
                break;
            case ECOTree.CS_LEVEL:
                var iColor = node._getLevel() % this.config.levelColors.length;
                color = this.config.levelColors[iColor];
                iColor = node._getLevel() % this.config.levelBorderColors.length;
                border = this.config.levelBorderColors[iColor];
                break;
        }
		
        if (!node._isAncestorCollapsed()){
            switch (this.render){
                case "CANVAS":
                    //Canvas part...
                    this.ctx.save();
                    this.ctx.strokeStyle = border;
                    switch (this.config.nodeFill) {
                        case ECOTree.NF_GRADIENT:							
                            var lgradient = this.ctx.createLinearGradient(node.XPosition,0,node.XPosition+node.w,0);
                            lgradient.addColorStop(0.0,((node.isSelected)?this.config.nodeSelColor:color));
                            lgradient.addColorStop(1.0,"#F5FFF5");
                            this.ctx.fillStyle = lgradient;
                            break;
							
                        case ECOTree.NF_FLAT:
                            this.ctx.fillStyle = ((node.isSelected)?this.config.nodeSelColor:color);
                            break;
                    }
					
                    ECOTree._roundedRect(this.ctx,node.XPosition,node.YPosition,node.w,node.h,5);
                    this.ctx.restore();
					
                    //HTML part...
                    s.push('<div id="' + node.id + '" class="econode" style="{top:'+(node.YPosition+this.canvasoffsetTop)+'; left:'+(node.XPosition+this.canvasoffsetLeft)+'; width:'+node.w+'; height:'+node.h+';}" ');
                    /*if (this.config.selectMode != ECOTree.SL_NONE)											
                        s.push('onclick="javascript:ECOTree._canvasNodeClickHandler('+this.obj+',event.target.id,\''+node.id+'\');" ');	*/									
                    s.push('>');
                    s.push('<font face=Verdana size=1>');
                    if (node.canCollapse) {
                        s.push('<a class="toggle" id="c'  + node.id + '" onClick="'+this.obj+'.collapseNode(\''+node.id+'\', true)" >');
                        s.push('<img border="0" src="'+((node.isCollapsed) ? this.config.collapsedImage : this.config.expandedImage)+'" >');
                        s.push('</a>');
                        s.push('<img src="'+this.config.transImage+'" >');
                    }					
                    if (node.target && this.config.useTarget) {
                        s.push('<a class="nodeDsc" id="t' + node.id + '" href="'+node.target+'">');
                        s.push(node.dsc);
                        s.push('</a>');
                    } else {
                        s.push(node.dsc);
                    }
                    s.push('</font>');
                    s.push('</div>');
                    break;
					
                case "VML":
                    s.push('<v:roundrect id="' + node.id + '" strokecolor="'+border+'" arcsize="0.18"	');
                    s.push('style="position:absolute; top:'+node.YPosition+'; left:'+node.XPosition+'; width:'+node.w+'; height:'+node.h+'" ');
                    if (this.config.selectMode != ECOTree.SL_NONE)
                        s.push('href="javascript:'+this.obj+'.selectNode(\''+node.id+'\', true);" ');
                    s.push('>');
                    s.push('<v:textbox inset="0.5px,0.5px,0.5px,0.5px" ><font face=Verdana size=1>');
                    if (node.canCollapse) {
                        s.push('<a style="clear:both;position: absolute;bottom: -3px;left: 45%; z-index: 10000;" onClick="'+this.obj+'.collapseNode(\''+node.id+'\', true);" >');
                        s.push('<img border=0 src="'+((node.isCollapsed) ? this.config.collapsedImage : this.config.expandedImage)+'" >');
                        s.push('</a>');
                        s.push('<img src="'+this.config.transImage+'" >');
                    }
                    if (node.target && this.config.useTarget){
                        s.push('<a href="'+node.target+'">');
                        s.push(node.dsc);
                        s.push('</a>');
                    } else {						
                        s.push(node.dsc);									
                    }
                    s.push('</font></v:textbox>');
                    switch (this.config.nodeFill) {
                        case ECOTree.NF_GRADIENT:
                            s.push('<v:fill type=gradient color2="'+((node.isSelected)?this.config.nodeSelColor:color)+'" color="#F5FFF5" angle=90 />');
                            break;
                        case ECOTree.NF_FLAT:
                            s.push('<v:fill type="solid" color="'+((node.isSelected)?this.config.nodeSelColor:color)+'" />');
                            break;
                    }
                    s.push('<v:shadow type="single" on="true" opacity="0.7" />');					
                    s.push('</v:roundrect>');																									
                    break;
            }	
            if (!node.isCollapsed)	s.push(node._drawChildrenLinks(this.self));
        }
    }	
    return s.join('');	
}

ECOTree.prototype.toString = function () {	
    var s = [];
	
    this._positionTree();
	
    switch (this.render) {
        case "CANVAS":
            s.push('<canvas id="ECOTreecanvas" width="12600" height="6000"></canvas>');
            break;

        case "HTML":
            s.push('<div class="maindiv">');
            s.push(this._drawTree());
            s.push('</div>');
            break;
			
        case "VML":
            s.push('<v:group coordsize="5000, 5000" coordorigin="0, 0" style="position:absolute;width=5000px;height=5000px;" >');
            s.push(this._drawTree());
            s.push('</v:group>');
            break;
    }
	
    return s.join('');
}

// ECOTree API begins here...

ECOTree.prototype.UpdateTree = function () {	
    this.elm.innerHTML = this;
    if (this.render == "CANVAS") {
        var canvas = document.getElementById("ECOTreecanvas");
        if (canvas && canvas.getContext)  {
            this.canvasoffsetLeft = canvas.offsetLeft;
            this.canvasoffsetTop = canvas.offsetTop;
            this.ctx = canvas.getContext('2d');
            var h = this._drawTree();	
            var r = this.elm.ownerDocument.createRange();
            r.setStartBefore(this.elm);
            var parsedHTML = r.createContextualFragment(h);								
            //this.elm.parentNode.insertBefore(parsedHTML,this.elm)
            //this.elm.parentNode.appendChild(parsedHTML);
            this.elm.appendChild(parsedHTML);
        //this.elm.insertBefore(parsedHTML,this.elm.firstChild);
        }
    }
}

ECOTree.prototype.add = function (id, pid, dsc, w, h, c, bc, target, meta) {	
    var nw = w || this.config.defaultNodeWidth; //Width, height, colors, target and metadata defaults...
    var nh = h || this.config.defaultNodeHeight;
    var color = c || this.config.nodeColor;
    var border = bc || this.config.nodeBorderColor;
    var tg = (this.config.useTarget) ? ((typeof target == "undefined") ? (this.config.defaultTarget) : target) : null;
    var metadata = (typeof meta != "undefined")	? meta : "";
	
    var pnode = null; //Search for parent node in database
    if (pid == -1)  {
        pnode = this.root;
    } else {
        for (var k = 0; k < this.nDatabaseNodes.length; k++) {
            if (this.nDatabaseNodes[k].id == pid) {
                pnode = this.nDatabaseNodes[k];
                break;
            }
        }	
    }
	
    var node = new ECONode(id, pid, dsc, nw, nh, color, border, tg, metadata);	//New node creation...
    node.nodeParent = pnode;  //Set it's parent
    pnode.canCollapse = true; //It's obvious that now the parent can collapse	
    var i = this.nDatabaseNodes.length;	//Save it in database
    node.dbIndex = this.mapIDs[id] = i;
    this.nDatabaseNodes[i] = node;
    var h = pnode.nodeChildren.length; //Add it as child of it's parent
    node.siblingIndex = h;
    pnode.nodeChildren[h] = node;
}

ECOTree.prototype.searchNodes = function (str) {
    var node = null;
    var m = this.config.searchMode;
    var sm = (this.config.selectMode == ECOTree.SL_SINGLE);	 
	
    if (typeof str == "undefined") return;
    if (str == "") return;
	
    var found = false;
    var n = (sm) ? this.iLastSearch : 0;
    if (n == this.nDatabaseNodes.length) n = this.iLastSeach = 0;
	
    str = str.toLocaleUpperCase();
	
    for (; n < this.nDatabaseNodes.length; n++)
    { 		
        node = this.nDatabaseNodes[n];				
        if (node.dsc.toLocaleUpperCase().indexOf(str) != -1 && ((m == ECOTree.SM_DSC) || (m == ECOTree.SM_BOTH))) {
            node._setAncestorsExpanded();
            this._selectNodeInt(node.dbIndex, false);
            found = true;
        }
        if (node.meta.toLocaleUpperCase().indexOf(str) != -1 && ((m == ECOTree.SM_META) || (m == ECOTree.SM_BOTH))) {
            node._setAncestorsExpanded();
            this._selectNodeInt(node.dbIndex, false);
            found = true;
        }
        if (sm && found) {
            this.iLastSearch = n + 1;
            break;
        }
    }	
    this.UpdateTree();	
}

ECOTree.prototype.selectAll = function () {
    if (this.config.selectMode != ECOTree.SL_MULTIPLE) return;
    this._selectAllInt(true);
}

ECOTree.prototype.unselectAll = function () {
    this._selectAllInt(false);
}

ECOTree.prototype.collapseAll = function () {
    this._collapseAllInt(true);
}

ECOTree.prototype.expandAll = function () {
    this._collapseAllInt(false);
}
/*增加了一个调用iframe.window函数*/
ECOTree.prototype.collapseNode = function (nodeid, upd) {
    //alert(nodeid+', '+upd);
    //ifDoc.getElementById("sample1").style.background="red";
    ifWin.t.collapseNode(nodeid, upd);
    var dbindex = this.mapIDs[nodeid];
    this.nDatabaseNodes[dbindex].isCollapsed = !this.nDatabaseNodes[dbindex].isCollapsed;
    if (upd) this.UpdateTree();
}

ECOTree.prototype.selectNode = function (nodeid, upd) {		
    this._selectNodeInt(this.mapIDs[nodeid], true);
    if (upd) this.UpdateTree();
}

ECOTree.prototype.setNodeTitle = function (nodeid, title, upd) {
    var dbindex = this.mapIDs[nodeid];
    this.nDatabaseNodes[dbindex].dsc = title;
    if (upd) this.UpdateTree();
}

ECOTree.prototype.setNodeMetadata = function (nodeid, meta, upd) {
    var dbindex = this.mapIDs[nodeid];
    this.nDatabaseNodes[dbindex].meta = meta;
    if (upd) this.UpdateTree();
}

ECOTree.prototype.setNodeTarget = function (nodeid, target, upd) {
    var dbindex = this.mapIDs[nodeid];
    this.nDatabaseNodes[dbindex].target = target;
    if (upd) this.UpdateTree();	
}

ECOTree.prototype.setNodeColors = function (nodeid, color, border, upd) {
    var dbindex = this.mapIDs[nodeid];
    if (color) this.nDatabaseNodes[dbindex].c = color;
    if (border) this.nDatabaseNodes[dbindex].bc = border;
    if (upd) this.UpdateTree();	
}

ECOTree.prototype.getSelectedNodes = function () {
    var node = null;
    var selection = [];
    var selnode = null;	
	
    for (var n=0; n<this.nDatabaseNodes.length; n++) {
        node = this.nDatabaseNodes[n];
        if (node.isSelected)
        {			
            selnode = {
                "id" : node.id,
                "dsc" : node.dsc,
                "meta" : node.meta
            }
            selection[selection.length] = selnode;
        }
    }
    return selection;
}

缩略图效果HTML

公司网络封锁文件外传,所以不能截图上来。请自行运行查看效果。

你可能感兴趣的:(tree)