|
|
Comments and Discussions
|
|
 |

|
Hey, it's me (I invented Walker's Algorithm, gosh, almost 25 years ago).
I'd like to do a Wikipedia page on the topic, and include some images of great tress people have drawn. I like the ones at the top of this article (how might I get permission to use them freely?), and wonder what other beautiful trees people might have that I could use for illustration -- with full attribution to whoever created them.
It gives me great pleasure to see this code downloaded here more than 350,000 times.
My best to all - John Q.
|
|
|
|

|
I noticed if the node's iLevelSeparation is huge, the tree starts way too far from top canvas. Can we position the tree's top yPosition? How? Thanks for the great code
|
|
|
|

|
Hi, do you know a solution for chrome ?
Many thanks.
|
|
|
|

|
Hello,in the article it said that
Sample include
"In the download you can find several simple examples you can play with. All the images in this article are made with the code on the examples. There is an advanced example which will let you play with almost all the options in the component. The data in the samples has been obtained in the Wikipedia."
here has already offered six simple example,they are so perfect! how can I find more example and advanced example? Could you offer some web url? Or how to search themin Wikipedia?
Thank you!
|
|
|
|

|
Great job, it works fine with Firefox,Chrome, but do not see any node IE.9. Could some help me? You may attach the latest release ? Thanks
info@sagt3k.com
|
|
|
|

|
I could not get this to render properly in ie9 either. when render is set to "AUTO", ie9 would render as VML (as did all versions of IE), which just was not working properly.
Since ie9 supports canvas, i changed the getAutoRenderMode function to check for the ability to create canvas, rather than checking browser. I feel this sort of approach is more future proof anyway.
Also, I noticed that ie8 does not render VML very well. To get around this, I added a javascript function that would change meta[http-equiv="X-UA-Compatible" to ie7 when the page was opened in ie8.
|
|
|
|

|
I have used this subtree . it is good to use but the problem i am facing is to delete the node. does any one know how to remove the node
|
|
|
|

|
aad this code:
ECOTree.prototype._getNodeById = function(id,retIndex){
if(this.mapIDs[id])
return retIndex?this.mapIDs[id]:this.nDatabaseNodes[this.mapIDs[id]];
for (var k = 0; k < this.nDatabaseNodes.length; k++) {
if (this.nDatabaseNodes[k].id == id)
return retIndex?k:this.nDatabaseNodes[k];
}
return null;
};
ECOTree.prototype._getChildById = function(node,chid,retIndex){
for (var k = 0; k < node.nodeChildren.length; k++) {
if (node.nodeChildren[k].id == chid)
return retIndex?k:node.nodeChildren[k];
}
return null;
};
ECOTree.prototype._remapNodes = function(){
this.mapIDs = {};
for(var i=0;i<this.nDatabaseNodes.length;i++)
this.mapIDs[this.nDatabaseNodes[i].id] = i;
};
ECOTree.prototype.removeNode = function(nodeid) {
var node_index = this._getNodeById(nodeid,true);
if(node_index !== null){
var node = this.nDatabaseNodes[node_index];
this.nDatabaseNodes.splice (node_index, 1);
this._remapNodes();
var pnode = this._getNodeById(node.pid);
if(pnode !== null){
for(var m=0;m<pnode.nodeChildren.length;m++){
if(pnode.nodeChildren[m].id == node.id){
pnode.nodeChildren.splice (m, 1);
if(!pnode.nodeChildren.length)
pnode.canCollapse = false;
break;
}
}
}
for(var i=0;i < node.nodeChildren.length; i++){
this.removeNode(node.nodeChildren[i].id);
}
}
};
ECOTree.prototype.changeParent = function(nodeid,pid){
var node = this._getNodeById(nodeid);
var pswitchnode = this._getNodeById(pid);
if(node !== null && pswitchnode !== null){
var pnode = this._getNodeById(node.pid);
if(pnode !== null){
var index_child = this._getChildById(pnode,nodeid,true);
if(index_child !== null)
pnode.nodeChildren.splice(index_child, 1);
}
node.nodeParent = pswitchnode;
node.pid = pid;
node.siblingIndex = node.nodeParent.length;
pswitchnode.nodeChildren[pswitchnode.nodeChildren.length] = node;
}
};
|
|
|
|

|
It's fine but unfortunately not compatible with google chrome
|
|
|
|

|
Hi, do you have a solution for chrome ?
Thanks
|
|
|
|

|
Hi,
To get this work in chrome just add the following line in _getAutoRenderMode function:
var is_ch = /chrome/.test(navigator.userAgent.toLowerCase());
Then modify line 368 (add is_ch test):
if (is_ff || is_ch) r = "CANVAS";
and line 708 (remove "{" and "}" chars from style definition):
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+';" ');
Hope this helps.
|
|
|
|

|
Hi
Anyone know how to get this to run under safari on apple mac/iOS
The tree works fine but the nodes and lines don't display
Thanks
Shaun
|
|
|
|

|
I have not tested my solution (see message just above) to get this work with Chrome in Safari, but using the same strategy and only changing the browser detection to Safari, or maybe even better generalizing to detect webkit browsers, should work.
|
|
|
|

|
This is perfect!
But I have got some problem while reading the source code.
Can someone explain how the "apportion" function works?
Thanks.
|
|
|
|
|
|

|
Really good solution but having display issues in Firefox.
1. How can you prevent the nodes being displayed outside boundaries of display/i.e. off screen
2. Once you add a good few nodes they loose their node color (ie blank)
Any suggestions anyone? Could not find any 1.5 code base, only a solution that required jsQuery and I could not seem to get it to work.
|
|
|
|

|
hi!
is it possible to add text to the lines between the nodes of the tree?
how?
thanks
|
|
|
|

|
Here's a minor update that specifically enables some things I needed to do. It adds more node options such as the provision for HTML in each node box, overriding text color, a combination of level and fixed coloring and some other stuff
ECONode = function (id, pid, dsc, w, h, c, bc, target, meta, noCollapse, nodeHTML, forceColor, textColor) {
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.noCollapse = ((typeof noCollapse != "undefined") ? noCollapse : true);
this.nodeHTML = ((typeof nodeHTML != "undefined") ? nodeHTML : "");
this.forceColor = ((typeof forceColor != "undefined") ? forceColor : false);
this.textColor = textColor;
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;
}
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();
}
return s.join('');
}
ECOTree = function (obj, elm) {
this.config = {
iMaxDepth: 100,
iLevelSeparation: 40,
iSiblingSeparation: 40,
iSubtreeSeparation: 80,
iRootOrientation: ECOTree.RO_TOP,
iNodeJustification: ECOTree.NJ_TOP,
topXCorrection: 0,
topYCorrection: 0,
topXAdjustment: 0,
topYAdjustment: 0,
linkType: "M",
linkColor: "blue",
nodeColor: "#CCCCFF",
nodeFill: ECOTree.NF_GRADIENT,
nodeBorderColor: "blue",
nodeSelColor: "#FFFFCC",
textColor: "#000000",
nodeRadius: 5,
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: 80,
defaultNodeHeight: 40,
defaultTarget: 'javascript:void(0);',
expandedImage: './img/less.gif',
collapsedImage: './img/plus.gif',
transImage: './img/trans.gif'
};
if (jQuery("#eco_tree_ruler_span").length == 0) {
jQuery("body").append("<span id='eco_tree_ruler_span' class='econode' style='visibility:hidden'></span>");
}
this.version = "1.5-icb";
this.obj = obj;
this.treeContainer = jQuery("#" + elm);
this.self = this;
this.ctx = null;
this.canvasoffsetTop = 0;
this.canvasoffsetLeft = 0;
this.chartHeight = -1;
this.chartWidth = -1;
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;
}
ECOTree.RO_TOP = 0;
ECOTree.RO_BOTTOM = 1;
ECOTree.RO_RIGHT = 2;
ECOTree.RO_LEFT = 3;
ECOTree.NJ_TOP = 0;
ECOTree.NJ_CENTER = 1;
ECOTree.NJ_BOTTOM = 2;
ECOTree.NF_GRADIENT = 0;
ECOTree.NF_FLAT = 1;
ECOTree.CS_NODE = 0;
ECOTree.CS_LEVEL = 1;
ECOTree.SM_DSC = 0;
ECOTree.SM_META = 1;
ECOTree.SM_BOTH = 2;
ECOTree.SL_MULTIPLE = 0;
ECOTree.SL_SINGLE = 1;
ECOTree.SL_NONE = 2;
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);
}
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 corrTmp = 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);
}
if (node.XPosition < 0) {
corrTmp = 0 - node.XPosition;
if (corrTmp > tree.config.topXCorrection) {
tree.config.topXCorrection = corrTmp;
}
}
if (node.YPosition < 0) {
corrTmp = 0 - node.YPosition;
if (corrTmp > tree.config.topYCorrection) {
tree.config.topYCorrection = corrTmp;
}
}
}
}
ECOTree._thirdWalk = function (tree, node, level) {
if (level <= tree.config.iMaxDepth) {
node.XPosition = node.XPosition + tree.config.topXCorrection;
node.YPosition = node.YPosition + tree.config.topYCorrection;
if (node._getChildrenCount() != 0) {
ECOTree._thirdWalk(tree, node._getFirstChild(), level + 1);
}
var rightSibling = node._getRightSibling();
if (rightSibling != null) {
ECOTree._thirdWalk(tree, rightSibling, level);
}
}
}
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;
}
this.config.topXCorrection = 0;
this.config.topYCorrection = 0;
ECOTree._secondWalk(this.self, this.root, 0, 0, 0);
if ((this.config.topXCorrection > 0) || (this.config.topYCorrection > 0)) {
ECOTree._thirdWalk(this.self, this.root, 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 = "";
var textColor = "";
for (var n = 0; n < this.nDatabaseNodes.length; n++) {
node = this.nDatabaseNodes[n];
textColor = node.textColor;
switch (this.config.colorStyle) {
case ECOTree.CS_NODE:
color = node.c;
border = node.bc;
break;
case ECOTree.CS_LEVEL:
if (node.forceColor == true) {
color = node.c;
border = node.bc;
} else {
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()) {
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, this.config.nodeRadius);
this.ctx.restore();
s.push('<div id="' + node.id + '" class="econode" style="position:absolute;top:' + (node.YPosition + this.canvasoffsetTop) + 'px; left:' + (node.XPosition + this.canvasoffsetLeft) + 'px; width:' + node.w + '; height:' + node.h + ';z-index:100;" ');
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 id="c' + node.id + '" href="javascript:' + 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 id="t' + node.id + '" href="' + node.target + '" style="color:' + textColor + '">');
s.push(node.dsc);
s.push('</a>');
} else {
s.push('<span style="color:' + textColor + '">');
s.push(node.dsc);
s.push('</span>');
}
s.push('</font>');
if (node.nodeHTML != "") {
s.push('<div>');
s.push(node.nodeHTML);
s.push('</div>');
}
s.push('</div>');
if (!node.isCollapsed) {
s.push(node._drawChildrenLinks(this.self));
}
}
}
return s.join('');
}
ECOTree.prototype._calcWidthAndHeight = function () {
this.chartWidth = 0;
this.chartHeight = 0;
for (var n = 0; n < this.nDatabaseNodes.length; n++) {
node = this.nDatabaseNodes[n];
if (!node._isAncestorCollapsed()) {
this.chartWidth = Math.max(this.chartWidth, node.XPosition + node.w);
this.chartHeight = Math.max(this.chartHeight, node.YPosition + node.h);
}
}
this.chartWidth += 2;
this.chartHeight += 2;
}
ECOTree.prototype.UpdateTree = function () {
this.treeContainer.empty();
this._positionTree();
this._calcWidthAndHeight();
this.treeContainer.css({
'position': 'relative',
'width': this.chartWidth,
'height': this.chartHeight,
'overflow': 'hidden'
});
var canvas = document.createElement('canvas');
jQuery(canvas).attr('width', 2000).attr('height', 7000).attr('id', 'ECOTreecanvas').appendTo(this.treeContainer);
if (jQuery.browser.msie) {
canvas = G_vmlCanvasManager.initElement(canvas);
}
if (canvas && canvas.getContext) {
this.ctx = canvas.getContext("2d");
var h = this._drawTree();
this.treeContainer.append(h);
}
}
ECOTree.prototype.add = function (id, pid, dsc, w, h, c, bc, target, meta, noCollapse, nodeHTML, forceColor, textColor) {
var nw = w || this.config.defaultNodeWidth; var nh = h || this.config.defaultNodeHeight;
if (nw == -1 || nh == -1) {
var ruler = jQuery("#eco_tree_ruler_span");
ruler.css({ 'width': '', 'height': '' });
if (nw != -1) {
ruler.css({ 'width': nw });
}
if (nh != -1) {
ruler.css({ 'height': nh });
}
ruler.html(dsc);
if (nw == -1) {
nw = ruler.innerWidth() + 18;
}
if (nh == -1) {
nh = ruler.innerHeight() + 4;
}
}
textColor = textColor || this.config.textColor;
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; 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, noCollapse, nodeHTML, forceColor, textColor); node.nodeParent = pnode; if (noCollapse == false) {
pnode.canCollapse = true; };
var i = this.nDatabaseNodes.length; node.dbIndex = this.mapIDs[id] = i;
this.nDatabaseNodes[i] = node;
var h = pnode.nodeChildren.length; 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);
}
ECOTree.prototype.collapseNode = function (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;
}
|
|
|
|
|

|
that means i have node data in database now that data coming to bean how i read bean data in to script to create dynamic tree
|
|
|
|

|
Your Tree View works fine for few levels but its does not show the left part of the tree when using with a bulk Data
|
|
|
|

|
Does anyone knows where can I download the latest version? I want to display the tree on Google Chrome. Any help will be appreciated.
|
|
|
|

|
I could display the tree in Chrome thanks to below a message. I am sorry for what I have posted a poor question.
Titile "Re: Bad Rendering in Chrome"
|
|
|
|

|
I am not able to see the style of the nodes and the lines between the nodes and not able to see tree from top to bottom (means only horizontal rendering).
the style opened on the internet explorer only , i need to open it on the other browsers
Please help me get it.
|
|
|
|

|
I am using the i.e version 8.0.7600.16585, I am not able to see the lines between the nodes and not able to see tree from top to bottom (means only horizontal rendering). Please help me get it.
|
|
|
|

|
"I am using the i.e version 8.0.7600.16585, I am not able to see the lines between the nodes and not able to see tree from top to bottom (means only horizontal rendering). Please help me get it."
Try adding this:
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7"/>
immediately after <head>
|
|
|
|

|
Does anyone have an example that support drag & drop feature?
Thanks.
|
|
|
|

|
I have been looking for a tool to do this with for 2 days and mostly people are just not doing what i want. This fits the scope exactly thank for your contribution.
|
|
|
|

|
I have been looking for a tool to do this with for 2 days and mostly people are just not doing what i want. This fits the scope exactly thank for your contribution.
|
|
|
|

|
when i display simple tree in joomla1.5 text of the tree display bottum of the scree what can do for this???
|
|
|
|

|
I have the problem of text ouside the nodes in Firefox. People have mentioned a later version (1.5?) that fixes the problem, can you point me to it or upload to google docs?
|
|
|
|

|
Hi,
Firstly, thanks for posting this excellent piece of code. It has really helped me a lot. One thing I was trying to do was provide an option to save an image of the tree as a jpg or png for printing or embedding in a presentation etc.
I did some research on the html canvas element and discovered some options for saving it to an image. However when I do, the outline of the tree is rendered but the node content (descritpion) is not.
Here's the code I am using to save the tree to an image element on the page.
var canvas = document.getElementById("ECOTreecanvas");
var context = canvas.getContext("2d");
var img = canvas.toDataURL("image/png");
jQuery("#img").attr("src",img);
And below is a modified version of sample1.htm which will demonstrate what I am seeing.
Does anyone have any suggestions on how to work around this ?
thanks,
Barry.
<html>
<head>
<title>ECOTree Simple Tree 1</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script type="text/javascript" src="ECOTree.js"></script>
<link type="text/css" rel="stylesheet" href="ECOTree.css" />
<xml:namespace ns="urn:schemas-microsoft-com:vml" prefix="v"/>
<style>v\:*{ behavior:url(#default#VML);}</style>
<style>
.copy {
font-family : "Verdana";
font-size : 10px;
color : #CCCCCC;
}
</style>
<script>
function log(msg) {
$("#log").append(msg+"<br/>");
}
var myTree = null;
function CreateTree() {
myTree = new ECOTree('myTree','myTreeContainer');
myTree.config.iRootOrientation = ECOTree.RO_LEFT;
myTree.config.render = "CANVAS";
myTree.add(0,-1,"Apex Node");
myTree.add(1,0,"Left Child");
myTree.add(2,0,"Right Child");
for (i = 0 ; i < 5 ; i++) {
myTree.add(i+3,0,""+i);
log(""+i);
}
myTree.UpdateTree();
var canvas = document.getElementById("ECOTreecanvas");
var context = canvas.getContext("2d");
var img = canvas.toDataURL("image/png");
jQuery("#img").attr("src",img);
}
</script>
</head>
<body onload="CreateTree();">
<h4>ECOTree Simple Tree 1 <span class="copy">©2006 Emilio Cortegoso Lobato</span></h4>
<div id="myTreeContainer">
</div>
<div id="log"></div>
<img id="img"/>
</body>
</html>
|
|
|
|

|
I would also like to save the generated tree as an image. Has anybody had any success with this? Any suggestions? - Jeff UPDATE: There's a tool (for Macs) called Paparazzi! that can capture and output an image of your trees. You can find it at: http://derailer.org/paparazzi/
-- modified 7 Sep '12 - 13:53.
|
|
|
|

|
I have met the problem which some nodes will be outside of bundaries. Could anyone kindly send me the lastest version of this javascript? Thanks in advance. Email me.
|
|
|
|

|
I have found a link in Code Project http://www.codeproject.com/KB/scripting/graphic_javascript_tree.aspx posted by Emilio CL. I have used the Walker's algorithm shown in the Figure 4. in the article. I have used it to show the tree of member's sub-members of a binary MLM system. the nodes show members' ID and Name. When I developed the site in my machine it worked fine but when I published it in a IIS server and tried to show tree in my machine it shows fine but in many machine it does not show node content. What is the problem? Are there any configuration problem in browsers to show node contents?
|
|
|
|

|
Hi
First let me say how great this project is, very useful.
I've created a sharepoint page which generates a company organisation chart from a sharepoint list which includes vacancies, it has images and hover over tooltips for contact details.
I have added MS Communicator status which is displayed next to the person's name in the node by adding the following code to the display variable of the node. -
<img id="imn0",type=smtp name="imnmark" sip="me@emailaddress.com" border="0" height="12" src="/_layouts/images/imnhdr.gif" onclick="IMNImageOnClick();return false;" class="ms-imnlink" önload="IMNRC('me@emailaddress.com')" ShowOfflinePawn="1" alt="" >
this works perfectly (where the id and email addresses are unique for each node).
The only small problem is when you expand or collapse nodes all the status indicators revert to grey (offline), but if you click them they show the correct status, just the unclicked one stays grey. If someone then updates their status in communicator the status indicator on their node updates correctly.
It seems to be basically a refresh issue when expanding and contracting nodes and I wondered if anyone has had this issue and can offer a resolution.
Many thanks
|
|
|
|

|
Please help... how to create organisation chart that supports the rendering of assistants, it's not sub ordinat.
|
|
|
|

|
I was looking for something just like it to build into a genealogical application I'm writing!
One note on using it in IE9 (Beta). Seems the advanced sample have some issues with expanding/collapsing nodes when the selection mode is anything other than none. It's a trivial issue for me as I won't be using it that way but others might complain.
[Update]
Using the 'new version' seems to break IE9 (Beta) completely. It does not render anything at all. Guess I'll be using the old version then.
|
|
|
|

|
Hi,
The examples seem to fail when I add the following markup:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
When I say fail, I mean the labels do not appear on the nodes. They seem to be rendering in the bottom left corner of the page.
I am using Firefox 3.6.10 for Windows.
Any solutions?
Thanks
Update:
Kevin Dorff's version (posted below) seems to fix the problem (at the cost of requiring jquery).
modified on Monday, September 27, 2010 7:08 PM
|
|
|
|

|
I can't drow tree into <td>, or anything else.
|
|
|
|

|
You put a link in the menu cam i put a javascript code or a php code in the inside the node? If yes can you give a simple exemple.
Tanks
|
|
|
|

|
I've been playing with this for the last few days (based on the 1.5 codebase). I've made a few changes which I don't necessary expect will be adopted into the "next" release, but I thought I'd share them with the group. This now REQUIRES jQuery. If you were relying on VML or HTML, sorry the code I am submitting ONLY supports Canvas (use "excanvas" for IE).
The rough outline of my changes:
* Requires jQuery (tested with 1.4.2)
* Requires excanvas (tested with r3, assuming you want to support Internet Explorer)
* Now that you can use Canvas in IE (with excanvas), Firefox, Chrome, Safari, this code ONLY supports rendering to Canvas (removed VML). It is possible this version won't work properly with old browsers, as it has not been extensively tested.
* When adding a node, if you specify a width or height of -1 it will "measure" the text and size the box and size it accordingly
* Size the div surrounding the canvas so it fit the constraints of the visible graph and hide the overflow
* Ability to specify the radius of the node corners via config.nodeRadius
* Reformatted code (braces and such).
Suggestions are welcome.
/*-------------------------------------------------------------------------------------------
| ECOTree.js
|--------------------------------------------------------------------------------------------
| (c) 2006 Emilio Cortegoso Lobato
|
| ECOTree is a javascript component for tree drawing. It implements the node positioning
| algorithm of John Q. Walker II "Positioning nodes for General Trees".
|
| Basic features include:
| - Layout features: Different node sizes, colors, link types, alignments, separations
| root node positions, etc...
| - Nodes can include a title and an hyperlink, and a hidden metadata.
| - Subtrees can be collapsed and expanded at will.
| - Single and Multiple selection modes.
| - Search nodes using title and metadata as well.
|
| This code is free source, but you will be kind if you don | with the same name, to avoid version collisions. Otherwise, please hack it!
|
| References:
|
| Walker II, J. Q., "A Node-Positioning Algorithm for General Trees"
| Software — Practice and Experience 10, 1980 553-561.
| (Obtained from C++ User |
| Last updated: June 21, 2010, Bob Good
| Version: 1.5 - Couple of more Firefox issues with text offset
|
| Last updated: June 21, 2010, Bob Good
| Version: 1.4 - fixed some FireFox issues
|
| Last updated: June 4, 2010, Bob Good
| Version: 1.3 - fixed color problem caused by "change all" ECOlor => eColor
|
| Last updated: May 11, 2010, Bob Good
| Version: 1.2 - added thirdwalk correction factors because was drawing nodes off the screen
|
| Last updated: October 26th, 2006
| Version: 1.0
|
| Modifications from version 1.5 made July 15, 2010 by
| Kevin Dorff of the
| Institute for Computational Biomedicine
| Weill Cornell Medical College
| http://icb.med.cornell.edu
|
| Original code from:
| http://www.codeproject.com/KB/scripting/graphic_javascript_tree.aspx
|
| Changes from 1.5
| * Requires jQuery (tested with 1.4.2)
| * Requires excanvas (tested with r3, assuming you want to support Internet Explorer)
| * Now that you can use Canvas in IE (with excanvas), Firefox, Chrome, Safari,
| this code ONLY supports rendering to Canvas (removed VML).
| It is possible this version won | not been extensively tested.
| * When adding a node, if you specify a width or height of -1 it will
| "measure" the text and size the box and size it accordingly
| * Size the div surrounding the canvas so it fit the constraints
| of the visible graph and hide the overflow
| * Ability to specify the radius of the node corners via config.nodeRadius
| * Reformatted code (braces and such).
|
\------------------------------------------------------------------------------------------*/
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;
}
// Canvas Rendering
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();
}
return s.join(}
ECOTree = function (obj, elm) {
this.config = {
iMaxDepth : 100,
iLevelSeparation : 40,
iSiblingSeparation : 40,
iSubtreeSeparation : 80,
iRootOrientation : ECOTree.RO_TOP,
iNodeJustification : ECOTree.NJ_TOP,
topXCorrection : 0,
topYCorrection : 0,
topXAdjustment : 0,
topYAdjustment : 0,
linkType : "M",
linkColor : "blue",
nodeColor : "#CCCCFF",
nodeFill : ECOTree.NF_GRADIENT,
nodeBorderColor : "blue",
nodeSelColor : "#FFFFCC",
nodeRadius : 5,
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 : 80,
defaultNodeHeight : 40,
defaultTarget : expandedImage : collapsedImage : transImage : };
if (jQuery("#eco_tree_ruler_span").length == 0) {
jQuery("body").append("<span id='eco_tree_ruler_span' class='econode' style='visibility:hidden'></span>");
}
this.version = "1.5-icb";
this.obj = obj;
this.treeContainer = jQuery("#" + elm);
this.self = this;
this.ctx = null;
this.canvasoffsetTop = 0;
this.canvasoffsetLeft = 0;
this.chartHeight = -1;
this.chartWidth = -1;
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;
//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 corrTmp = 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);
}
// adjust for large tree, where "left:' offset has gone negative (off the screen)
if (node.XPosition < 0) {
corrTmp = 0 - node.XPosition;
if (corrTmp > tree.config.topXCorrection) {
tree.config.topXCorrection = corrTmp;
}
}
// adjust for large tree, where "top: if (node.YPosition < 0) {
corrTmp = 0 - node.YPosition;
if (corrTmp > tree.config.topYCorrection) {
tree.config.topYCorrection = corrTmp;
}
}
}
}
ECOTree._thirdWalk = function (tree, node, level) {
if (level <= tree.config.iMaxDepth) {
node.XPosition = node.XPosition + tree.config.topXCorrection;
node.YPosition = node.YPosition + tree.config.topYCorrection;
if (node._getChildrenCount() != 0) {
ECOTree._thirdWalk(tree, node._getFirstChild(), level + 1);
}
var rightSibling = node._getRightSibling();
if (rightSibling != null) {
ECOTree._thirdWalk(tree, rightSibling, level);
}
}
}
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;
}
this.config.topXCorrection = 0;
this.config.topYCorrection = 0;
ECOTree._secondWalk(this.self, this.root, 0, 0, 0);
// Adjust for very large trees off of the screen
if ((this.config.topXCorrection > 0) || (this.config.topYCorrection > 0)) {
ECOTree._thirdWalk(this.self, this.root, 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()) {
// Canvas rendering
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, this.config.nodeRadius);
this.ctx.restore();
//HTML elements for text ... DIVs to be placed over the Canvas
s.push(
if (this.config.selectMode != ECOTree.SL_NONE) {
s.push( }
s.push( s.push( if (node.canCollapse) {
s.push( s.push( s.push( s.push( }
if (node.target && this.config.useTarget) {
s.push( s.push(node.dsc);
s.push( } else {
s.push(node.dsc);
}
s.push( s.push(
if (!node.isCollapsed) {
s.push(node._drawChildrenLinks(this.self));
}
}
}
return s.join(}
ECOTree.prototype._calcWidthAndHeight = function () {
this.chartWidth = 0;
this.chartHeight = 0;
for (var n = 0; n < this.nDatabaseNodes.length; n++) {
node = this.nDatabaseNodes[n];
if (!node._isAncestorCollapsed()) {
this.chartWidth = Math.max(this.chartWidth, node.XPosition + node.w);
this.chartHeight = Math.max(this.chartHeight, node.YPosition + node.h);
}
}
this.chartWidth += 2;
this.chartHeight += 2;
}
// ECOTree API begins here...
ECOTree.prototype.UpdateTree = function () {
// Empty the tree container so we can refill it
this.treeContainer.empty();
this._positionTree();
this._calcWidthAndHeight();
// Set the size on the tree container
this.treeContainer.css({
});
// Make the <canvas> element.
var canvas = document.createElement( jQuery(canvas).attr( if (jQuery.browser.msie) {
// For Internet Explorer, have excanvas initialize the canvas method
canvas = G_vmlCanvasManager.initElement(canvas);
}
if (canvas && canvas.getContext) {
this.ctx = canvas.getContext("2d");
var h = this._drawTree();
this.treeContainer.append(h);
}
}
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;
// See if we need to calculate the width or the height
if (nw == -1 || nh == -1) {
var ruler = jQuery("#eco_tree_ruler_span");
ruler.css({ if (nw != -1) {
ruler.css({ }
if (nh != -1) {
ruler.css({ }
ruler.html(dsc);
if (nw == -1) {
nw = ruler.innerWidth() + 18;
}
if (nh == -1) {
nh = ruler.innerHeight() + 4;
}
}
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 pnode.canCollapse = true; //It 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 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);
}
ECOTree.prototype.collapseNode = function (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;
}
|
|
|
|

|
Thanks for keeping this updated, just discovered this little *gem* Today and it seems to work pretty well!
While testing on a rather big set of data I discovered a bug in the code where the width and height of the canvas is hardcoded.
The call to jQuery in UpdateTree should be as follows:
jQuery(canvas).attr('width', this.chartWidth).attr('height', this.chartHeight).attr('id', 'ECOTreecanvas').appendTo(this.treeContainer);
In the function _calcWidthAndHeight, I also rounded the width and height, as for some reason the width was a decimal number. Not sure if it is needed:
this.chartWidth = Math.round(this.chartWidth) + 2;
this.chartHeight = Math.round(this.chartHeight) + 2;
|
|
|
|

|
Hi,
i tested your code. On FF its fine but when i open IE I see only a Img icon and have some error:
"Webpage error details
User Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET4.0C; .NET4.0E; .NET CLR 3.5.30729; .NET CLR 3.0.30729)
Timestamp: Sat, 28 Aug 2010 11:25:08 UTC
Message: HTML Parsing Error: Unable to modify the parent container element before the child element is closed (KB927917)
Line: 0
Char: 0
Code: 0
URI: http://ascan/SitePages/testing.aspx
"
when i click on + button then all its ok.
|
|
|
|

|
Hi,
First of all Many Thanks for this new version.
I am using these changes in my code. It renders fine in Firefox now. However in IE 7, when first time this control renders, it shows nothing just '-' signs and when I click on one of '-' signs it gets rendered properly.
Can you please provide me some solution to this issue, as this issue is stopping me from using this control?
Regards,
Narendra
|
|
|
|
|

|
ECOTree.prototype._getNodeById = function(id,retIndex){
if(this.mapIDs[id])
return retIndex?this.mapIDs[id]:this.nDatabaseNodes[this.mapIDs[id]];
for (var k = 0; k < this.nDatabaseNodes.length; k++) {
if (this.nDatabaseNodes[k].id == id)
return retIndex?k:this.nDatabaseNodes[k];
}
return null;
};
ECOTree.prototype._getChildById = function(node,chid,retIndex){
for (var k = 0; k < node.nodeChildren.length; k++) {
if (node.nodeChildren[k].id == chid)
return retIndex?k:node.nodeChildren[k];
}
return null;
};
ECOTree.prototype._remapNodes = function(){
this.mapIDs = {};
for(var i=0;i<this.nDatabaseNodes.length;i++)
this.mapIDs[this.nDatabaseNodes[i].id] = i;
};
ECOTree.prototype.removeNode = function(nodeid) {
var node_index = this._getNodeById(nodeid,true);
if(node_index !== null){
var node = this.nDatabaseNodes[node_index];
this.nDatabaseNodes.splice (node_index, 1);
this._remapNodes();
var pnode = this._getNodeById(node.pid);
if(pnode !== null){
for(var m=0;m<pnode.nodeChildren.length;m++){
if(pnode.nodeChildren[m].id == node.id){
pnode.nodeChildren.splice (m, 1);
if(!pnode.nodeChildren.length)
pnode.canCollapse = false;
break;
}
}
}
for(var i=0;i < node.nodeChildren.length; i++){
this.removeNode(node.nodeChildren[i].id);
}
}
};
ECOTree.prototype.changeParent = function(nodeid,pid){
var node = this._getNodeById(nodeid);
var pswitchnode = this._getNodeById(pid);
if(node !== null && pswitchnode !== null){
var pnode = this._getNodeById(node.pid);
if(pnode !== null){
var index_child = this._getChildById(pnode,nodeid,true);
if(index_child !== null)
pnode.nodeChildren.splice(index_child, 1);
}
node.nodeParent = pswitchnode;
node.pid = pid;
node.siblingIndex = node.nodeParent.length;
pswitchnode.nodeChildren[pswitchnode.nodeChildren.length] = node;
}
};
modified 16 hrs ago.
|
|
|
|

|
How to make the nodes without curved corners.
|
|
|
|

|
If you look at the post I just made titled "New version, suggestions welcome" it supports non-rounded nodes which is quite trivial to add. You can try my version or search for "radius" in the code. The code defaults to 5. I made it a configurable options in my version.
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.
|
A JavaScript Tree component which implements the J.Q.Walker II layout algorithm.
| Type | Article |
| Licence | CPOL |
| First Posted | 1 Nov 2006 |
| Views | 374,502 |
| Bookmarked | 145 times |
|
|