A Family Tree
If you want to create a family homepage with corinis, you might as well include a family tree. We use the profiler and some sql to create the tree and some javascript to display the fields (so we can have a nice layout).
The first thing to be done is to create a profile we can use for the tree. Basically every user is a member of the family thus having a father, a mother, a partner and a gender (this is the information we need to successfully create the tree). All other information is optional (like include an email, maiden name and so on). I use quite a lot of java in this to simplify the xml tree (provides speed when parsing the tree to create the webpage and while building the xml-tree).
There is only one big problem with different branches. Not from the xml layout, but from the html layout. It is hard to almost impossible to create a layout that is able to support different family branches correctly, so we will have different branches.
The jsp
<%@include file="includes/header.ijsp"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>Family Tree</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="includes/style.css">
<script>
var x, y;
var lastlay;
function showLayer(id)
{
var lay = document.getElementById(id);
if (lastlay == lay)
return;
if (lastlay != null)
hideLayer();
lay.style.display = "block";
lay.style.left = x + "px";
lay.style.top = y + "px";
lastlay = lay;
}
function hideLayer ()
{
lastlay.style.display = "none";
lastlay.style.top=0;
}
function followMouse (e)
{
if (window.event)
{
x = window.event.clientX + document.body.scrollLeft;
y = window.event.clientY + document.body.scrollTop;
}
else
{
x = e.pageX;
y = e.pageY;
}
}
function init()
{
document.onmousemove = followMouse;
if (!window.event) document.captureEvents(Event.MOUSEDOWN | Event.MOUSEMOVE);
}
</script>
</head>
<body onload="init()">
<%
String startparent = request.getParameter("tree");
if (startparent == null)
startparent = "-100";
// Build the Family Tree
Profiler prof = new Profiler (core);
Connection conn = null;
ResultSet results;
Statement stmt = null;
Element root = core.getDoc().createElement("TREE");
debug = "";
try
{
// Step 1: get the first ones (both parents -1)
conn = core.getConfigurator().getConnPool().getConnection();
stmt = conn.createStatement();
results = stmt.executeQuery("select distinct cp1.localuserid id from corinisprofiler as cp1, corinisprofiler as cp2 where (cp1.profilerfield_name='mutter' and cp1.data="+startparent+") and (cp2.profilerfield_name='vater' and cp2.data="+startparent+") and cp1.localuserid=cp2.localuserid");
while (results.next ())
{
// add the top nodes in the tree
addPartner(createMember(results.getLong("id"), prof, core.getDoc()), root, core.getDoc());
}
results.close();
stmt.close();
// Step 2: lets do the *real* work
buildTree (root, conn, core.getDoc(), prof, core);
}
catch (Exception e)
{
out.println(e.getMessage());
}
%>
<div align="left">
<%
// each branch starts with partners with mother&father having id -100/-200/-300/... in their profile
String[] parents = {"Family Branch 1", "Family Branch 2", "Family Branch 3"};
%>
-
<%
for (int i=1; i <= parents.length; i++)
{
if (String.valueOf(i * -100).equals(startparent))
{
%><b><%=parents[i-1]%></b> - <%
}
else
{
%>
<a href="?tree=<%=i*-100%>"><u><%=parents[i-1]%> Baum</u></a> -
<%
}
}
%>
<br/>
<%=core.parseDomHtml(root, "famtree.xsl")%>
</div>
</body></html>
<%!
String debug;
public void buildTree(Element parent, Connection conn, Document doc, Profiler prof, Core core) throws Exception
{
for (Element child = (Element)parent.getFirstChild(); child != null; child = (Element)child.getNextSibling())
{
String mom = null;
String dad = null;
if (child.getNodeName().equals("PARTNER"))
{
// ok now find one of the parents
mom = child.getAttribute("partnerw");
dad = child.getAttribute("partnerm");
if (mom == null || mom.length()==0) mom = "-1";
if (dad == null || dad.length() == 0) dad = "-1";
// select the kids out of the db
Statement stmt = conn.createStatement();
ResultSet results = stmt.executeQuery("select distinct cp1.localuserid id from corinisprofiler as cp1, corinisprofiler as cp2 where (cp1.profilerfield_name='mutter' and cp1.data='"+mom+"') and (cp2.profilerfield_name='vater' and cp2.data='"+dad+"') and cp1.localuserid=cp2.localuserid");
while (results.next ())
{
// add the top nodes in the tree
addPartner(createMember(results.getLong("id"), prof, core.getDoc()), child, core.getDoc());
// find the partner
Statement stmt2 = conn.createStatement();
ResultSet results2 = stmt2.executeQuery("select distinct cp1.localuserid id from corinisprofiler as cp1 where (cp1.profilerfield_name='partner' and cp1.data='"+results.getLong("id")+"')");
if (results2.next())
addPartner(createMember(results2.getLong("id"), prof, core.getDoc()), child, core.getDoc());
results2.close();
stmt2.close();
}
results.close();
stmt.close();
}
buildTree(child, conn, doc, prof, core);
}
}
public void addPartner(Element member, Element parent, Document doc)
{
// got the partner id:
String partnerId = member.getAttribute("partner");
String sex = member.getAttribute("geschlecht");
String sexP = sex.equals("m")?"w":"m";
Element partnerNode = null;
for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling())
{
if (child.getNodeName().equals("PARTNER"))
{
if (((Element)child).getAttribute("partner" + sexP).equals(partnerId))
{
partnerNode = (Element)child;
break;
}
}
}
if (partnerNode == null)
{
partnerNode = doc.createElement("PARTNER");
parent.appendChild(partnerNode);
}
partnerNode.setAttribute("partner"+sex, member.getAttribute("id"));
partnerNode.appendChild(member);
}
public Element createMember (long id, Profiler prof, Document doc)
{
prof.pview.id = id;
Element e = prof.getEntry();
Element root = doc.createElement("MEMBER");
root.setAttribute ("id", String.valueOf(id));
// we should set the partner, sex and parent ids here... otherwise the other code may become quite messy
for (Node child = e.getFirstChild(); child != null; child = child.getNextSibling())
{
if (child.getNodeName().equals("ENTRY"))
{
root.setAttribute(DomUtil.getResultString(child, "NAME"), DomUtil.getResultString(child, "VALUE"));
}
}
// add the email address
root.setAttribute("EMail", prof.getCore().getUserEmail(id));
return root;
}
%>
the xsl
Make sure you edit the filter in the information according to your profiler names:
<?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:template match="/"> <table width="100%"> <tr> <xsl:apply-templates select="/TREE/PARTNER"/> </tr> </table> </xsl:template> <xsl:template match="PARTNER"> <td align="center" valign="top"> <span > <xsl:attribute name="onmouseover">showLayer('<xsl:value-of select="MEMBER[position()=1]/@id"/>')</xsl:attribute> <xsl:value-of select="MEMBER[position()=1]/@name"/> <xsl:if test="not(MEMBER[position()=1]/@mname='')"> (<i><xsl:value-of select="MEMBER[position()=1]/@mname"/></i>) </xsl:if> <div style="display:none;position:absolute;top:0px;left:0px;overflow:visible;width:200px;height:100px;"> <xsl:attribute name="id"><xsl:value-of select="MEMBER[position()=1]/@id"/></xsl:attribute> <table style="background-color:#ccc;border: 1px solid #444;"> <tr><td>Born:</td><td><xsl:value-of select="MEMBER[position()=1]/@gebTag"/>.<xsl:value-of select="MEMBER[position()=1]/@gebMonat"/> <xsl:value-of select="MEMBER[position()=1]/@gebJahr"/> in <xsl:value-of select="MEMBER[position()=1]/@gort"/></td></tr> <xsl:apply-templates select="MEMBER[position()=1]"/> </table> </div> </span> <xsl:if test="count(MEMBER) = 2"> <img src="images/rings.gif"/> <xsl:text> </xsl:text> <span> <xsl:attribute name="onmouseover">showLayer('<xsl:value-of select="MEMBER[position()=2]/@id"/>')</xsl:attribute> <xsl:value-of select="MEMBER[position()=2]/@vorname"/> <xsl:if test="not(MEMBER[position()=2]/@mname='')"> (<i><xsl:value-of select="MEMBER[position()=2]/@mname"/></i>) </xsl:if> <div style="display:none;position:absolute;top:0px;left:0px;overflow:visible;width:200px;height:100px;"> <xsl:attribute name="id"><xsl:value-of select="MEMBER[position()=2]/@id"/></xsl:attribute> <table style="background-color:#ccc;border: 1px solid #444;"> <tr><td>Geboren:</td><td><xsl:value-of select="MEMBER[position()=2]/@gebTag"/>.<xsl:value-of select="MEMBER[position()=2]/@gebMonat"/> <xsl:value-of select="MEMBER[position()=2]/@gebJahr"/> in <xsl:value-of select="MEMBER[position()=2]/@gort"/></td></tr> <xsl:apply-templates select="MEMBER[position()=2]"/> </table> </div> </span> </xsl:if> <br/> <xsl:value-of select="MEMBER/@nachname"/><br/> <table width="100%" style="border-top:1px solid"> <tr> <xsl:apply-templates select="PARTNER"/> </tr> </table> </td> </xsl:template> <xsl:template match="MEMBER"> <xsl:for-each select="@*"> <xsl:if test="(string-length(.) > 1) and not (name()='gort') and not (starts-with(name(), 'geb')) and not (name()='vorname') and not (name()='mname') and not (name()='mutter') and not (name()='vater') and not(name()='nachname') and not(name()='partner') and not (name()='id')"> <tr> <td><xsl:value-of select="name()"/>:</td> <td><xsl:value-of select="."/></td> </tr> </xsl:if> </xsl:for-each> </xsl:template> </xsl:stylesheet>
