|
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.
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;
}
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 : '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 = "";
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()) {
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 + '">');
s.push(node.dsc);
s.push('</a>');
} else {
s.push(node.dsc);
}
s.push('</font>');
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) {
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;
}
}
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);
node.nodeParent = pnode;
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;
}
|
|
|
|
|
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
|
|
|
|
|
You are the best man
Really the new version help me and fix many problem, but still I have a problem with rtl (Right-to-Left layout), that needed for (Arabic, Urdu, Hebrew and Farsi languages).
You can try make body direction rtl and saw what happened.
The new suggestion is auto size of nodes, if you add a large text like "The root Mr. Smith (Administrator)" as example, you can see what I talking about.
And Thank you very much for your sharing
|
|
|
|
|
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 21-May-13 8:48am.
|
|
|
|
|
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.
|
|
|
|
|
|
Nice!!! It's awesome how you are still using this *old* piece of code... (and thanks)
|
|
|
|
|
I have fixed a problem with the tree drawing outside of the boundaries.
If you want the code Emilio, email me.
thx
Bob Good
|
|
|
|
|
I have the same problem. If i set the canvas size to (for example) 8000x8000 pixels then the ECOTree disappear (i.e. node's names (text) is visible, but the divs are not visible).
Please help.
|
|
|
|
|
the code works for IE,but not firefox,please help.
|
|
|
|
|
See my new post under this same thread for version 1.5. It works for me in Firefox now, (the text is back in the nodes).
|
|
|
|
|
What is ur fix for this? I have some nodes which are hidden to the left with a very wide tree (top down tree). It depends on which way the tree is drawn but 20% of the time some nodes are hidden......
Thanks
|
|
|
|
|
The fix is some new logic in ecotree.js.
|
|
|
|
|
Here is updated code.
var __isIE = navigator.appVersion.match(/MSIE/);
var __userAgent = navigator.userAgent;
var __isFireFox = __userAgent.match(/firefox/i);
var __isFireFoxOld = __isFireFox &&
(__userAgent.match(/firefox\/2./i) || __userAgent.match(/firefox\/1./i));
var __isFireFoxNew = __isFireFox && !__isFireFoxOld;
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 : 40,
iSiblingSeparation : 40,
iSubtreeSeparation : 80,
iRootOrientation : ECOTree.RO_TOP,
iNodeJustification : ECOTree.NJ_TOP,
topXCorrection : 0,
topYCorrection : 0,
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 : 80,
defaultNodeHeight : 40,
defaultTarget : 'javascript:void(0);',
expandedImage : './img/less.gif',
collapsedImage : './img/plus.gif',
transImage : './img/trans.gif'
}
this.version = "1.5";
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;
}
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._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;
}
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 = "";
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":
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();
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 + ';}" ');
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 + '">');
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 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 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('<div class="maindiv">');
s.push('<canvas id="ECOTreecanvas" width=2000 height=7000></canvas>');
s.push('</div>');
break;
case "HTML":
s.push('<div class="maindiv">');
s.push(this._drawTree());
s.push('</div>');
break;
case "VML":
s.push('<v:group coordsize="20000, 20000" coordorigin="0, 0" style="position:absolute;width=20000px;height=20000px;" >');
s.push(this._drawTree());
s.push('</v:group>');
break;
}
return s.join('');
}
ECOTree.prototype.UpdateTree = function () {
this.elm.innerHTML = this;
if (this.render == "CANVAS") {
var canvas = document.getElementById("ECOTreecanvas");
if (canvas && canvas.getContext) {
var canvasAbsoluteOffset = getElementAbsolutePos(canvas);
this.canvasoffsetLeft = canvas.offsetLeft + canvasAbsoluteOffset.x;
this.canvasoffsetTop = canvas.offsetTop + canvasAbsoluteOffset.y;
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.appendChild(parsedHTML);
}
}
}
ECOTree.prototype.add = function (id, pid, dsc, w, h, c, bc, target, meta) {
var nw = w || this.config.defaultNodeWidth;
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;
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);
node.nodeParent = pnode;
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;
}
function __parseBorderWidth(width) {
var res = 0;
if (typeof (width) == "string" && width != null
&& width != "") {
var p = width.indexOf("px");
if (p >= 0) {
res = parseInt(width.substring(0, p));
}
else {
res = 1;
}
}
return res;
}
function __getBorderWidth(element) {
var res = new Object();
res.left = 0; res.top = 0; res.right = 0; res.bottom = 0;
if (window.getComputedStyle) {
var elStyle = window.getComputedStyle(element, null);
res.left = parseInt(elStyle.borderLeftWidth.slice(0, -2));
res.top = parseInt(elStyle.borderTopWidth.slice(0, -2));
res.right = parseInt(elStyle.borderRightWidth.slice(0, -2));
res.bottom = parseInt(elStyle.borderBottomWidth.slice(0, -2));
}
else {
res.left = __parseBorderWidth(element.style.borderLeftWidth);
res.top = __parseBorderWidth(element.style.borderTopWidth);
res.right = __parseBorderWidth(element.style.borderRightWidth);
res.bottom = __parseBorderWidth(element.style.borderBottomWidth);
}
return res;
}
function getElementAbsolutePos(element) {
var res = new Object();
res.x = 0; res.y = 0;
if (element !== null) {
res.x = element.offsetLeft;
res.y = element.offsetTop;
var offsetParent = element.offsetParent;
var parentNode = element.parentNode;
var borderWidth = null;
while (offsetParent != null) {
res.x += offsetParent.offsetLeft;
res.y += offsetParent.offsetTop;
var parentTagName = offsetParent.tagName.toLowerCase();
if ((__isIE && parentTagName != "table") ||
(__isFireFoxNew && parentTagName == "td")) {
borderWidth = __getBorderWidth(offsetParent);
res.x += borderWidth.left;
res.y += borderWidth.top;
}
if (offsetParent != document.body &&
offsetParent != document.documentElement) {
res.x -= offsetParent.scrollLeft;
res.y -= offsetParent.scrollTop;
}
if (!__isIE) {
while (offsetParent != parentNode && parentNode !== null) {
res.x -= parentNode.scrollLeft;
res.y -= parentNode.scrollTop;
if (__isFireFoxOld) {
borderWidth = __getBorderWidth(parentNode);
res.x += borderWidth.left;
res.y += borderWidth.top;
}
parentNode = parentNode.parentNode;
}
}
parentNode = offsetParent.parentNode;
offsetParent = offsetParent.offsetParent;
}
}
return res;
}
modified on Monday, June 21, 2010 2:28 PM
|
|
|
|
|
tried some example likes sample1.htm with FF 3.6.12. a scrollbar appeared even through there is a few nodes. when I scroll, all nodes but the text moved. how to fix it ?
|
|
|
|
|
Anyone has the version 1.5. Could you send me? I also have the problem about the outside the bundaries.
email me. Thanks.
|
|
|
|
|
Viewing the Tree in chrome i have some problem.
The text is not rendered in the right position.
I added the patch for the correct browser detection but the problem is still there.
I think that chrome doesn't interpret correctly the line:
s.push('<div id="' + node.id + '" class="econode" style="{top:'+node.YPosition+'; left:'+node.XPosition+'; width:'+node.w+'; height:'+node.h+';}" >');
It looks like the style property is not Read.
Any Help ?
Thanks a Lot
|
|
|
|
|
Try removing the open and closing braces {} from the style.
|
|
|
|
|