Introduction
This tool created using Asp.net, C# and JQuery. This tool generates based on the math logic, it will be explained below.
What is Timeline Family Tree
A record or table of the descent of a person, family, or group from an ancestor or ancestors a family tree. Time line will show the node’s exact position on the tree.
Prerequisites
To generate Timeline family tree there is no prerequisites required. It works best on .Net framework 4.0 and all other files embedded with the assembly.
Code
Step 1:
Create Class library named “RBPTimeLineFamilyTreeGenerator”
Step 2:
Create Class named “RBPTimeLineFamilyTree.cs” within the class library “RBPTimeLineFamilyTreeGenerator”
Step 3:
Create a Folder named “RBPTimeLineFamilyTreeGenerator” within the class library “RBPTimeLineFamilyTreeGenerator”
It should contain the Javascript files and Css files used for this tool. I have used Jquery files, JsPlumbs files, Css files for design
Files used for this tool generation are FamilyTreeGenerator.js, jquery-ui.min.js,jquery.jsPlumb-1.3.5-all-min.js, jquery.min.js, jsPlumbDemo.css
Step 4:
Embedd jsfile and cssfiles into Assembly to make security
To create assembly webresource include System.web reference in class library
- Right click class library project and select add reference from .net “System.Web”
-
-
Before embed change the Build action property of files to embed resource.
- Right click on Js/css files and click properties
- Change the Build Action from “Content” to “Embedded Resource”
-
Create assembly webresource in RBPTimeLineFamilyTree.cs use the following code.
using System.Web;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.Web.UI.HtmlControls;
[assembly: WebResource("RBPTimeLineFamilyTreeGenerator.RBPTimeLineFamilyTreeGenerator.jquery.min.js",
"application/x-javascript")]
[assembly: WebResource("RBPTimeLineFamilyTreeGenerator.RBPTimeLineFamilyTreeGenerator.jquery-ui.min.js",
"application/x-javascript")]
[assembly: WebResource("RBPTimeLineFamilyTreeGenerator.RBPTimeLineFamilyTreeGenerator.jquery.jsPlumb-1.3.5-all-min.js",
"application/x-javascript")]
[assembly: WebResource("RBPTimeLineFamilyTreeGenerator.RBPTimeLineFamilyTreeGenerator.FamilyTreeGenerator.js",
"application/x-javascript")]
[assembly: WebResource("RBPTimeLineFamilyTreeGenerator.RBPTimeLineFamilyTreeGenerator.jsPlumbDemo.css", "text-css", PerformSubstitution = true)]
Step 5:
Create constants names for the assemblies as below
namespace RBPTimeLineFamilyTreeGenerator
{
public class RBPTimeLineFamilyTree
{
private const string NAME_JQUERY =
"RBPTimeLineFamilyTreeGenerator.RBPTimeLineFamilyTreeGenerator.jquery.min.js";
private const string NAME_JQUERY_MIN =
"RBPTimeLineFamilyTreeGenerator.RBPTimeLineFamilyTreeGenerator.jquery-ui.min.js";
private const string NAME_JPLUMB =
"RBPTimeLineFamilyTreeGenerator.RBPTimeLineFamilyTreeGenerator.jquery.jsPlumb-1.3.5-all-min.js";
private const string NAME_FAMILYTREE =
"RBPTimeLineFamilyTreeGenerator.RBPTimeLineFamilyTreeGenerator.FamilyTreeGenerator.js";
private const string NAME_CSSJPLUMB =
"RBPTimeLineFamilyTreeGenerator.RBPTimeLineFamilyTreeGenerator.jsPlumbDemo.css";
…….(etc code)
}
}
Step 6:
Create method to initialize the Assembly files
public static void RBP_IncludeSupportFiles(ClientScriptManager manager, Page manager2)
{
Include_JsFiles(manager);
Include_CssFiles(manager, manager2);
}
Add supporting functions
private static void Include_JsFiles(ClientScriptManager manager)
{
IncludeJavaScript(manager, NAME_JQUERY);
IncludeJavaScript(manager, NAME_JQUERY_MIN);
IncludeJavaScript(manager, NAME_JPLUMB);
IncludeJavaScript(manager, NAME_FAMILYTREE);
}
private static void Include_CssFiles(ClientScriptManager manager, Page manager2)
{
IncludeCss(manager, NAME_CSSJPLUMB, manager2);
}
private static void IncludeJavaScript(ClientScriptManager manager, string resourceName)
{
var type = typeof(RBPTimeLineFamilyTreeGenerator.RBPTimeLineFamilyTree);
manager.RegisterClientScriptResource(type, resourceName);
}
private static void IncludeCss(ClientScriptManager manager, string resourceName, Page manager2)
{
var type = typeof(RBPTimeLineFamilyTreeGenerator.RBPTimeLineFamilyTree);
string cssUrl = manager.GetWebResourceUrl(type, resourceName);
HtmlLink cssLink = new HtmlLink();
cssLink.Href = cssUrl;
cssLink.Attributes.Add("rel", "stylesheet");
cssLink.Attributes.Add("type", "text/css");
manager2.Header.Controls.Add(cssLink);
}
Step 7:
Generate Chart function
Parameter definition given as follows
/// <summary>
/// To get the Get Chart content based on the input
/// </summary>
/// <param name="inputdatatable">DataTable inputdatatable – Input datatable it should contains nodeid, node name, parent id, node date</param>
/// <param name="nodeidfieldname">string nodeidfieldname – Node Id field name in datatable </param>
/// <param name="nodeparentidfieldname">string nodeparentidfieldname – Parent node Id field name in datatable</param>
/// <param name="datefieldname">string datefieldname – Date column of Node id field name in datatable</param>
/// <param name="yearfieldname">string yearfieldname – Date column year field in datatable (date should be formatted as year in this field)</param>
/// <param name="addtimelineyears">int addtimelineyears – Adding years in timeline chart before start year and end year (ex:- 5 will add 5 years before start year and after end year)</param>
/// <param name="widthinterval">int widthinterval – Timeline width interval, node will be placed based on this width (ex:- 200)</param>
/// <param name="nodeheight">int nodeheight – specifying node height in the family tree (ex:- 100)</param>
/// <param name="nodewidht">int nodewidht – specifying node width in the family tree (ex:- 100)</param>
/// <param name="displayfields">int[] displayfields – it is int array to display fields in node (ex:- 0,1,2 will display specified index from input datatable)</param>
/// <param name="scrollbarrequired">Boolean scrollbarrequired – scroll bar enabled or disabled based on the Boolean value input (ex: true will provide scrollbar on family tree)</param>
/// <returns>Panel control to display in aspx page</returns>
public static Panel GetChartContent(DataTable inputdatatable, string nodeidfieldname, string nodeparentidfieldname, string datefieldname, string yearfieldname, int addtimelineyears, int widthinterval, int nodeheight, int nodewidht, int[] displayfields, Boolean scrollbarrequired = true)
{
DateTime[] dateyears = GetSmallestLargestDates(inputdatatable, datefieldname);
int startyear = Convert.ToInt32(dateyears[0].ToString("yyyy"));
int endyear = Convert.ToInt32(dateyears[1].ToString("yyyy"));
StringBuilder sb = new StringBuilder();
StringBuilder sbLinks = new StringBuilder();
int startposition = 1;
int leftposition = 0;
int topposition = 0;
int tempstartyear = 0;
Hashtable hsDateCount = new Hashtable();
//Timeline positioning
sb.Append("<div style='vertical-align:bottom;position:relative;'>");
tempstartyear = startyear;
for (int i = tempstartyear - addtimelineyears; i <= endyear + addtimelineyears; i++)
{
startposition = (i % (startyear - addtimelineyears)) + 1;
sb.Append(string.Format("<span style='vertical-align:bottom;left:{0}px;background-color:ivory;position:absolute;'>", startposition * widthinterval));
sb.Append(i.ToString());
sb.Append("</span>");
tempstartyear++;
}
sb.Append("</div><br/>");
//Node positioning
sb.Append("<div style='background-color:white;position:relative;'> ");
sbLinks.Append("<script type='text/javascript'>");
for (int j = 0; j < inputdatatable.Rows.Count; j++)
{
if (hsDateCount.ContainsKey(inputdatatable.Rows[j][yearfieldname].ToString()))
{
hsDateCount[inputdatatable.Rows[j][yearfieldname].ToString()] = Convert.ToInt32(hsDateCount[inputdatatable.Rows[j][yearfieldname].ToString()]) + 1;
}
else
{
hsDateCount.Add(inputdatatable.Rows[j][yearfieldname].ToString(), 1);
}
startposition = (Convert.ToInt32(inputdatatable.Rows[j][yearfieldname].ToString()) % (startyear - addtimelineyears)) + 1;
leftposition = startposition * widthinterval;
topposition = Convert.ToInt32(hsDateCount[inputdatatable.Rows[j][yearfieldname].ToString()]) * (widthinterval + 1);
//Display fields
string strDisplay = "";
foreach (var item in displayfields)
{
strDisplay += inputdatatable.Rows[j][item].ToString() + "<br/>";
}
sb.Append(string.Format("<div style='position:absolute;left:{0}px;top:{1}px;height:{4}px;width:{5}px;background-color:orange;float:left;' id='divless{2}'>{3}</div>", leftposition, topposition, inputdatatable.Rows[j][nodeidfieldname].ToString(), strDisplay, nodeheight, nodewidht));
//Creating links
if (inputdatatable.Rows[j][nodeparentidfieldname].ToString() == "")
{
//sbLinks.Append(string.Format("jsPlumb.bind(\"ready\", function () {{createLinks(\"divless{0}\", \"divless{1}\", CipConnector); }});", inputdatatable.Rows[j][nodeparentidfieldname].ToString(), inputdatatable.Rows[j][nodeidfieldname].ToString()));
}
else
{
sbLinks.Append(string.Format("jsPlumb.bind(\"ready\", function () {{createLinks(\"divless{0}\", \"divless{1}\", DivConnector); }});", inputdatatable.Rows[j][nodeparentidfieldname].ToString(), inputdatatable.Rows[j][nodeidfieldname].ToString()));
}
}
sb.Append("</div> <br/>");
sbLinks.Append("</script>");
//Timeline positioning bottom
//sb.Append("<div style='vertical-align:bottom;position:relative;'>");
//tempstartyear = startyear;
//for (int i = tempstartyear - addtimelineyears; i <= endyear + addtimelineyears; i++)
//{
// startposition = (i % (startyear - addtimelineyears)) + 1;
// sb.Append(string.Format("<span style='vertical-align:bottom;left:{0}px;background-color:ivory;position:absolute;'>", startposition * widthinterval));
// sb.Append(i.ToString());
// sb.Append("</span>");
// tempstartyear++;
//}
//sb.Append("</div>");
//Adding script to page
sb.Append(sbLinks.ToString());
System.Web.UI.HtmlControls.HtmlGenericControl dynDiv1 = new System.Web.UI.HtmlControls.HtmlGenericControl("DIV");
dynDiv1.InnerHtml = sb.ToString();
Panel pnlChart = new Panel();
pnlChart.ID = "RBPTimeLineChartPanel";
pnlChart.Controls.Add(dynDiv1);
if (scrollbarrequired)
{
pnlChart.ScrollBars = ScrollBars.Both;
pnlChart.Height = 500;
}
return pnlChart;
}
/// <summary>
/// This function return minimum and maximum date from the given datatable input and from the specified column name
/// </summary>
/// <param name="dsInput">Datatable input</param>
/// <param name="strColumnName">Column name to get Start year and end year</param>
/// <returns>Datetime array for minimum date and maximum date from datatable</returns>
private static DateTime[] GetSmallestLargestDates(DataTable dsInput, string strColumnName)
{
DateTime[] dtdates = new DateTime[2];
dtdates[0] = (from r in dsInput.AsEnumerable()
select Convert.ToDateTime(r[strColumnName])).Min();
dtdates[1] = (from r in dsInput.AsEnumerable()
select Convert.ToDateTime(r[strColumnName])).Max();
return dtdates;
}
Step 8:
Now we can use the dll from the Classlibrary “RBPTimeLineFamilyTreeGenerator”
Create New Web site/Web Application paste RBPTimeLineFamilyTreeGenerator.dll in the project
Step 9:
Add reference in the Aspx.cs file
using RBPTimeLineFamilyTreeGenerator;
Step 10:
Add following Prerender code to merge the JS Files and CSS Files into the project
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
RBPTimeLineFamilyTreeGenerator.RBPTimeLineFamilyTree.RBP_IncludeSupportFiles(Page.ClientScript, Page);
}
Step 11:
To Display the Chart Create Datatable with the specified columns and add the following line
Page.Form.Controls.Add(RBPTimeLineFamilyTreeGenerator.RBPTimeLineFamilyTree.GetChartContent(dsNodeLinks, "node_id","node_parent_id", "node_start_date", "node_start_year", 0, 200, 70, 100, new int[6] { 0, 1, 2,3,4,5 }, false));
Step 12:
Now Run the project to see the Timeline Family tree generator
References