-
1. Re: How to display a Binary Tree ?
sandy4you Apr 1, 2015 6:30 AM (in response to sandy4you)Any guidance or direction on how to proceed will be helpful.
-
2. Re: How to display a Binary Tree ?
michpetrov Apr 2, 2015 5:05 AM (in response to sandy4you)I am not clear on what your problem is. Do you want to know how to hand the SelectionNode to a rich:tree?
-
3. Re: How to display a Binary Tree ?
sandy4you Apr 6, 2015 1:41 AM (in response to michpetrov)Yes Michal, thats right.
Wanted to know if there is any way to display the above tree structure using in built jsf/richfaces component ?
If not then I don't have any other option then to go for html with js and css.
In short looks like for the above requirements currently jsf and richfaces are useless for me.
-
4. Re: How to display a Binary Tree ?
michpetrov Apr 7, 2015 6:55 AM (in response to sandy4you)You can make your class implement org.richfaces.model.TreeNode and then just put the root node as @value of the rich:tree. But you'll need CSS if you want the tree to look like that picture.
-
5. Re: How to display a Binary Tree ?
sandy4you Apr 8, 2015 4:40 AM (in response to michpetrov)Hi Michal,
Can I get some examples or code snippet to starts with.
I got your view from overall perspective but still looking from where to start.
-
6. Re: How to display a Binary Tree ?
sandy4you Jun 19, 2015 1:06 AM (in response to sandy4you)Finally was able to get it right as per the diagram shown above using java script.
/**
* Selection object provides the means to parse a selection defined in json and
* display it as a graph on the screen. This object relies heavily on JQuery to
* handle the DOM. The main methods of this object are:
* <ul>
* <li>buildGraph(json) - read in the provided json string and create the
* graphical display
* <li>tableDOM() - returns the DOM representation for the build graph.
* <li>debug() - provides a stirng representation of the graph logging it at
* the same time to the console object
* </ul>
*/
var Selection = function() {
var rows = [];
/**
* Possible cell types
*/
var NODE = "node"; // selection node
var LEAF = "leaf"; // end node
var EMPTY = "empty"; // empty cell
var TRUE_CON = "trueConnector"; // connection for true
var FALSE_CON = "falseConnector"; // connection for false
var ROOT = "root"; // root node
/**
* Values for node types in the json
*/
var LEAF_NODE = "ResultingTemplate";
var ROOT_NODE = "RootNode";
/**
* Represents a cell in the layout table for the graph.
*
* @param domData -
* the DOM data contained within the cell
* @param cellType -
* the type of this cell. See the cell types constants.
*/
var Cell = function(domData, cellType) {
var data = domData;
var type = cellType;
var toString = function() {
return 'Cell(' + data + ', ' + type + ')';
};
return {
"data" : data,
"type" : type,
"toString" : toString
};
};
/**
* Represents a row in the layout table for the graph. A row consists of a
* list of cells.
*/
var Row = function() {
var cells = [];
var addCell = function(cell) {
cells.push(cell);
return this;
};
var peek = function() {
return cells[cells.length - 1];
};
var toString = function() {
return 'Row(size=' + cells.length + ')';
};
return {
"cells" : cells, // returns the cells contained within this row
"addCell" : addCell, // adds a cell to the end of the row
"peek" : peek, // looks at the last cell in the row
"toString" : toString
// returns a string representation of this row
};
};
/**
* Create the DOM data for a node from its json representation.
*
* @param jsonData -
* the json representation of the node
* @param isTrueNode -
* <code>true<code> when the node represents a node on the true connection path.
*/
var createNode = function(jsonData, isTrueNode) {
var newNode;
var cellType;
if (jsonData.type === ROOT_NODE) {
cellType = ROOT;
newNode = $('#root-node div.node').clone();
newNode.children('.type').append(jsonData.name);
} else if (jsonData.type === LEAF_NODE) {
cellType = LEAF;
newNode = $('#leaf-node div.node').clone();
var typeTag = newNode.children('.type')
typeTag.children('.leaf-type').html(jsonData.type);
typeTag.children('.leaf-name').html(jsonData.name);
var contentTag = newNode.children('.content');
contentTag.find('.email-tmpl').html(jsonData.email ? jsonData.email : '');
contentTag.find('.sms-tmpl').html(jsonData.sms ? jsonData.sms : '');
contentTag.find('.letter-tmpl').html(jsonData.letter ? jsonData.letter : '');
if (isTrueNode)
newNode.addClass('true-node');
else
newNode.addClass('false-node');
} else {
cellType = NODE;
newNode = $('#selection-node div.node').clone();
var typeTag = newNode.children('.type');
typeTag.children('.leaf-type').html(jsonData.type);
typeTag.children('.leaf-name').html(jsonData.name);
if (jsonData.values) {
newNode.find('.selection-vals').html(jsonData.values.join(","));
}
}
return new Cell(newNode, cellType);
};
/**
* Creates a connector DOM element for the seleciton graph. A connector is
* represented by a div tag with an optional image of an arrow pointing in
* the direction of the connection.
*
* @param type
* of the connector either <code>true</code> or
* <code>false</code>
* @param withArrow
* when <code>true</code> display a small error pointing in the
* direction of the connector.
*/
var createConnector = function(type, withArrow) {
var el;
if (type) {
el = new Cell($('<div class="true-connector"><div class="true-arrow" /></div>'), TRUE_CON);
} else {
var divTag = $('<div class="false-connector">');
if (withArrow) {
divTag.append('<div class="false-arrow" />');
}
el = new Cell(divTag, FALSE_CON);
}
return el
};
/**
* create an empty cell. An empty cell contains an empty div DOM element
* with the css class empty assigned.
*/
var empty = function() {
return new Cell($('<div class="empty"></div>'), EMPTY);
};
/**
* Create the layout structure including DOM elements for a node and its
* corresponding true connector from the passed json representation. If the
* true node is at the bottom of the current layout table new rows are added
* if not then the appropriate cells are replaced with the newly created DOM
* elements.
*
* @param jsonData
* the json element to create the DOM elements from.
* @param currRow
* the row in the layout table where this true node is being
* added.
* @param currCol
* the column in the layout table where this true node is being
* added.
*/
var addTrueNode = function(jsonData, currRow, currCol) {
var row1, row2;
var con = createConnector(true);
var sel = createNode(jsonData, true)
if (currRow + 2 > rows.length) {
row1 = new Row();
row2 = new Row();
rows.push(row1);
rows.push(row2);
for (var i = 0; i < currCol; i++) {
row1.addCell(empty());
row2.addCell(empty());
}
row1.addCell(con);
row2.addCell(sel);
} else {
rows[currRow + 1].cells[currCol] = con;
rows[currRow + 2].cells[currCol] = sel;
}
};
/**
* Create the layout structure including DOM elements for a node and its
* corresponding false connector from the passed json representation. If the
* true node is at the bottom of the current layout table new rows are added
* if not then the appropriate cells are replaced with the newly created DOM
* elements.
*
* @param jsonData
* the json element to create the DOM elements from.
* @param currRow
* the row in the layout table where this true node is being
* added.
* @param currCol
* the column in the layout table where this true node is being
* added.
*/
var addFalseNode = function(jsonData, currRow, currCol) {
var el1, el2;
for (idx in rows) {
var row = rows[idx];
var leftCell = row.peek();
if (leftCell.type === NODE || leftCell.type === FALSE_CON) {
if (idx == currRow) {
el1 = createConnector(false, true);
el2 = createNode(jsonData, false)
} else {
el1 = createConnector(false);
el2 = createConnector(false);
}
if (currCol <= row.cells.length) {
row.addCell(el1);
row.addCell(el2);
} else {
row[currCol + 1] = el1;
row[currCol + 2] = el2;
}
} else {
if (currCol <= row.cells.length) {
row.addCell(empty());
row.addCell(empty());
} else {
row[currCol + 1] = empty();
row[currCol + 2] = empty();
}
}
}
};
/**
* Returns a string representation of the current build selection graph and
* logs it to the console. The output shows the root node as 'P', an empty
* cell as ' ', a true connector as '|', a false connector as '-', a
* selection node as '*', a leave note as 'o' and any other cell as 'E' for
* error.
*
* @returns <code>String</code> representing the graph.
*/
var debug = function() {
var retVal = "";
retVal += "table\n";
for (idx in rows) {
var tableRow = rows[idx];
var output = "";
for (cIdx in tableRow.cells) {
var col = tableRow.cells[cIdx];
if (col.type === NODE)
output += '*';
else if (col.type === LEAF)
output += 'o';
else if (col.type === EMPTY)
output += ' ';
else if (col.type === TRUE_CON)
output += '|';
else if (col.type === FALSE_CON)
output += '-';
else if (col.type === ROOT)
output += 'P';
else
output += 'E';
}
retVal += output + '\n';
}
retVal += "/table\n";
console.log(retVal);
return retVal;
};
/**
* Returns the jquery DOM elements making up the graph.
*/
var layoutDOM = function() {
var tableEl = $('<table class="selection-table">');
for (idx in rows) {
var row = rows[idx];
var rowEl = $('<tr class="selection-row">');
for (cIdx in row.cells) {
var col = row.cells[cIdx];
rowEl.append($('<td class="selection-cell">').append(col.data));
}
tableEl.append(rowEl);
}
return tableEl;
};
/**
* Build a graph from the passed in json. The layout table is created by
* walking the tree from the root to the leafs. First passing the true
* connection creating the connector and the node along the way. Secondly
* passing the false connections creating the nodes. This will result in the
* table being created from the top to the bottom by adding new rows to the
* end of the table as needed. When passing the false connections cells are
* added to each row as needed until the last leaf node has been passed.
* This spans open the layout table for displaying the graph.
*
* @param jsonRoot
* the root of the json defining the seleciton.
*/
var buildGraph = function(jsonRoot) {
function buildSubTree(jsonNode, currRow, currCol) {
addTrueNode(jsonNode.trueNode, currRow, currCol);
if (jsonNode.trueNode.type !== LEAF_NODE) {
currCol = buildSubTree(jsonNode.trueNode, currRow + 2, currCol);
}
if (jsonNode.type !== ROOT_NODE) {
addFalseNode(jsonNode.falseNode, currRow, currCol);
currCol += 2;
if (jsonNode.falseNode.type !== LEAF_NODE) {
currCol = buildSubTree(jsonNode.falseNode, currRow, currCol);
}
}
return currCol;
}
var row = new Row();
rows.push(row);
row.addCell(createNode(jsonRoot, true));
buildSubTree(jsonRoot, 0, 0);
return layoutDOM();
};
return {
"debug" : debug,
"buildGraph" : buildGraph
};
};
$(document).ready(function() {
var treeString = document.getElementById(":jsonTree").value;
var jsonTree = JSON.parse(treeString);
var selection = new Selection();
$('#tree').append(selection.buildGraph(jsonTree));
});