I came across a very useful plug-in few days back for drawing Gantt charts using JQuery. You can find all the information plus the files you need to download from here (https://github.com/thegrubbsian/jquery.ganttView).

As I described previously from a blog when we drew JQuery charts, we can use the power of JSON to get serialized data from the server side to populate the needed data model. In this case the the data model looked something like this.

var ganttData =
[
    {
        id: 1, name: "Feature 1"
        series: 
        [
            { name: "Planned", start: new Date(2010,00,01), end: new Date(2010,00,03) },
            { name: "Actual", start: new Date(2010,00,02), end: new Date(2010,00,05) }
        ]
    },
    {
        id: 2, name: "Feature 2" 

        series: 
        [
            { name: "Planned", start: new Date(2010,00,05), end: new Date(2010,00,20) },
            { name: "Actual", start: new Date(2010,00,06), end: new Date(2010,00,17) },
            { name: "Projected", start: new Date(2010,00,06), end: new Date(2010,00,17) }
        ]
    }
]

 
In order to tackle this, my server side data model should look something like this.

public class ContainerModel

{
   public String id { get; set; }
   public String name { get; set; }
   public List<DataModel> series { get; set; }

}
public class DataModel
{
   public string name { get; set; }
   public DateTime start { get; set; }
   public DateTime end { get; set; }

}
 

Let's write a sample method to populate the data model with some dummy data.

public static List<ContainerModel> PopulateData(){
  var startDate = new DateTime(2010, 5, 12);
  var endDate = new DateTime(2010, 12, 5);


  var planned = new DataModel { name = "Planned", start = startDate, end = endDate };
  var actual = new DataModel { name = "Actual", start = startDate, end = endDate };
  var projected = new DataModel { name = "Projected", start = startDate, end = endDate };


  var dataSet = new List<ContainerModel>();
  for (int k = 0; k < 10; k++)
{
    var container = new ContainerModel
{
                          id = k.ToString(),
                          name = string.Format("Feature {0}", k),
                          series = new List<DataModel> { planned, actual, projected }
                        };
    dataSet.Add(container); 

  }
  return dataSet;

}

And these methods were used to serialize the data model to JSON so we can use it from the JavaScript side.

private static  string ToJson(this object obj){
  var serializer = new DataContractJsonSerializer(obj.GetType());
  var ms = new MemoryStream();

  serializer.WriteObject(ms, obj);
  var json = Encoding.Default.GetString(ms.ToArray());
  return json;

}

public static string GetJason(List<ContainerModel> dataModel)
{
  return dataModel.ToJson();

}


Let's write a web method so we can use a JQuery AJAX call back to retrieve the prepared data.
I have embedded the above mentioned PopulateData, ToJson, GetJason methods in to a Helper class for more code clarity

[WebMethod]
public static string GetData()
{
  var modelData = Helper.PopulateData();
  var jsonData = Helper.GetJason(modelData);
  return jsonData;

}

Now all our server side codes are completed, but then come the fun part. As you can see in the above mentioned data model the dates are represented as JavaScript Date objects
{ name: "Planned", start: new Date(2010,00,05), end: new Date(2010,00,20) },
But date returned by Json is a string that looks something like this "/Date(1273602600000+0530)/" .
In order to convert that JSON serialized millisecond date string to a JavaScript Date object, we can use JavaScript substring function with eval
startDate = eval("new " + start.substring(1, start.length - 7) + ")");
Resulting in returning a JavaScript Date object with a value like
"Wed May 12 2010 00:00:00 GMT+0530 (Sri Lanka Standard Time)"

So let's replace the DateUtils Class in the jQuery.ganttView.js with this one

var DateUtils = {
  daysBetweenBothString: function (start, end){
    var startDate, endDate;

    startDate = eval("new " + start.substring(1, start.length - 7) + ")");
    endDate = eval("new " + end.substring(1, end.length - 7) + ")");
    var count = 0, date = startDate.clone();
    while (date.compareTo(endDate) == -1) { count = count + 1; date.addDays(1); }
    return count;

  },
  daysBetweenEndString: function (start, end){
   endDate = eval("new " + end.substring(1, end.length - 7) + ")");
    var count = 0, date = start.clone();
    while (date.compareTo(endDate) == -1) { count = count + 1; date.addDays(1); }
    return count;

  },
  daysBetween: function (start, end){
    var count = 0, date = start.clone();
    while (date.compareTo(end) == -1) { count = count + 1; date.addDays(1); }
    return count;

  },
  isWeekend: function (date){
    return date.getDay() % 6 == 0;

  }
};

And the addBlocks method with this

addBlocks: function (div, data, cellWidth, start){
  var rows = jQuery("div.ganttview-blocks div.ganttview-block-container", div);
  var rowIdx = 0;
  for (var i = 0; i < data.length; i++) {
   for (var j = 0; j < data[i].series.length; j++) {
   var size = DateUtils.daysBetweenBothString(data[i].series[j].start, data[i].series[j].end);
   var offset = DateUtils.daysBetweenEndString(start, data[i].series[j].start);
   var blockDiv = jQuery("<div>", {
     "class": "ganttview-block",
     "title": data[i].series[j].name + ", " + size + " days",
     "css": {
     "width": ((size * cellWidth) - 9) + "px",
     "margin-left": ((offset * cellWidth) + 3) + "px"

    }});
  if (data[i].series[j].color){

   blockDiv.css("background-color", data[i].series[j].color);
  }
  blockDiv.append($("<div>", { "class": "ganttview-block-text" }).text(size));
  jQuery(rows[rowIdx]).append(blockDiv);
  rowIdx = rowIdx + 1;
  }
  }
}

Now you can use this modified version of the JS file to support your JSON serialized data object.
In the aspx page (in this case Default.aspx ) where we need to draw the chart insert the following script

<script type="text/javascript">
$(document).ready(function (){
var ganttData = [];

$("#btnGetData").live("click", function (e){
  var button = $(this);

  function onDataReceived(series){

    ganttData = series.d;
    $("#ganttChart").ganttView({
    data: $.parseJSON(ganttData),
    start: new Date(2010, 05, 01),
    end: new Date(2010, 12, 31),
    slideWidth: 900
   });
  }
  var dataUrl = "Default.aspx/GetData";

  $.ajax({
   type: "POST",
   url: dataUrl,
   data: "{}",
   contentType: "application/json; charset=utf-8",
   dataType: "json",
   success: onDataReceived
  });
  });
});
</script>

And add the following div tag to the page so the JS file can inject the rendered Chart inside it
<div id="ganttChart"></div>
Accompanied with the button to trigger the AJAX call back
<div><input id="btnGetData" type="button" value="Get Data" /></div>

Now you are all set for your first JQuery Gantt Chart.




 

7 comments:

da[D0T]executor[-a-T]mr2tuning[d0t]ch said...

Hey Dhan!

First of all thanks for your post. I'm also using ganttView in one of my own projects but currently gettin into a problem while init the ganttView with livequery.

Firebug tells me: minStart.compareTo is not a function

Any idea? I'm still using the static data.js from the example.

And again, thanks for sharing your knowledge!

Greetings from Switzerland

Hi,
Sorry for the late reply.

In the jquery.ganttview library dates are represented using strings. but in our code we converted them to date objects right!!. so now you cant use javascript compareTo method which compare two string objects. instead do a simple date object comparison

hope this helps!!

This is a superb information and you have described everything very clearly and really..Thanks for spreading this information here, now i am going to bookmark this blog because i love to read this type of blogs.

i am also gonna bookmark this blog and also share it to my friends because i love to read this type of informational blogs.

This is something definitely value awareness. There are a lot of internet sites that just make no feeling. Please commence the excellent and more people will keep returning.

I Need Task Hold and release Option for this chart.

I Need Task Hold and release Option for this chart.

Post a Comment