I'm trying to create a gantt chart in a visualforce page WITHOUT using an app. So far I have tried both
http://www.jitendrazaa.com/blog/salesforce/gantt-chart-in-salesforce-using-jquery-and-json/
and
https://developer.salesforce.com/forums/?id=906F000000097EkIAI AND
Both of these are not giving me any errors, but they only show a blank screen. My code is exactly the same as in their examples. What am I missing?
For example one–
/**
Author - Jitendra Zaa
This controller class is used by the VF page "GanttChartData" to generate the JSON
*/
public with sharing class GanttChartData {
public String jsonString {get;set;}
//Constructor
public GanttChartData()
{
jsonString = prepareData();
}
//Temp Method to prepare the Data
private String prepareData()
{
List<ReservationDetail> dtlObj = new List<ReservationDetail>();
ReservationDetail obj1 = new ReservationDetail();
ReservationDetail obj2 = new ReservationDetail();
ReservationDetail obj3 = new ReservationDetail();
obj1.setFromDate(String.valueOf(datetime.newInstanceGmt(2012,04, 17, 0, 0, 0).getTime()));
obj1.setToDate(String.valueOf(datetime.newInstanceGmt(2012,04, 17, 05, 30, 0).getTime()));
obj1.desc_PH = 'Booked by : Jitendra <br /> for JQuery Demo';
obj1.label = 'Jitendra';
obj1.customClass = 'ganttRed';
obj2.setFromDate(String.valueOf(datetime.newInstanceGmt(2012,04, 17, 20, 30, 0).getTime()));
obj2.setToDate(String.valueOf(datetime.newInstanceGmt(2012,04, 17, 23, 30, 2).getTime()));
obj2.desc_PH = 'Booked by : Tuiya <br /> for Wireless Lecture';
obj2.label = 'Tuiya';
obj2.customClass = 'ganttOrange';
obj3.setFromDate(String.valueOf(datetime.newInstanceGmt(2012,04, 19, 09, 30, 0).getTime()));
obj3.setToDate(String.valueOf(datetime.newInstanceGmt(2012,04, 19, 16, 30, 2).getTime()));
obj3.desc_PH = 'Booked by : Santosh <br /> for SAP Basis';
obj3.label = 'Santosh';
obj3.customClass = 'ganttGreen';
dtlObj.add(obj1);
dtlObj.add(obj2);
dtlObj.add(obj3);
Room r = new Room();
r.name = 'Training Room';
r.desc_PH = 'This is Training Room';
r.values = dtlObj;
List<Room> r1 = new List<Room>();
r1.add(r);
return JSON.serialize(r1);
}
public class RoomList
{
public List<Room> rooms;
}
public class Room
{
public String name{get;set;}
//Below var name - desc
public String desc_PH{get;set;}
public List<ReservationDetail> values{get;set;}
}
public class ReservationDetail
{
//actual variable name needed was "from", but it is keyword so we cant use that
public String frm_PH{get;set;}
public String to{get;set;}
public String desc_PH{get;set;}
public String label{get;set;}
/*
Custom class Can be anything from below:
ganttRed
ganttGreen
ganttOrange
*/
public String customClass{get;set;}
public void setToDate(String val)
{
to = setDate(val);
}
public void setFromDate(String val)
{
frm_PH = setDate(val);
}
//Date should be in special format as it is used in regular expression
private String setDate(String val)
{
return '/Date('+val+')/';
}
}
}
VF1:
<apex:page controller="GanttChartData" contentType="application/x-JavaScript; charset=utf-8" showHeader="false" standardStylesheets="false" sidebar="false">
{!jsonString}
</apex:page>
VF2:
<apex:page standardStylesheets="false" sidebar="false">
<apex:stylesheet value="{!URLFOR($Resource.GanttChart, 'style.css')}"/>
<apex:includeScript value="{!URLFOR($Resource.GanttChart, 'js/jquery-1.5.1.min.js')}"/>
<apex:includeScript value="{!URLFOR($Resource.GanttChart, 'js/jquery.fn.gantt.js')}"/>
<div class="gantt" />
<script type="text/javascript">
$gc = jQuery.noConflict();
function getHostName()
{
var p = $gc(location).attr('href');
pathArray = p.split( '/' );
var protocol = pathArray[0];
var host = pathArray[2];
return protocol+'//'+host;
}
var jsonDataURL = getHostName()+'/apex/GanttChartData?core.apexpages.devmode.url=0';
$gc(function () {
$gc(".gantt").gantt({source: jsonDataURL, navigate: 'scroll', scale: 'hours', maxScale: 'hours', minScale: 'hours', hollydays: ["/Date(1293836400000)/"]});
});
</script>
</apex:page>
For example two, same Apex, new VF page–
<apex:page standardStylesheets="false" showHeader="false">
<style>
body {font-size:12px; background: #F3F3EC; padding-top: 0px;}
.{font-family:arial;font-size:12px}
h1 {cursor:hand;font-size:16px;margin-left:10px;line-height:10px}
xmp {color:green;font-size:12px;margin:0px;font-family:courier;background-color:#e6e6fa;padding:2px}
.hdr{
background-color:lightgrey;
margin-bottom:10px;
padding-left:10px;
}
</style>
<head>
<apex:stylesheet value="{!URLFOR($Resource.Timeline, 'codebase/dhtmlxgantt.css')}"/>
<apex:includeScript value="{!URLFOR($Resource.Timeline, 'codebase/dhtmlxcommon.js')}"/>
<apex:includeScript value="{!URLFOR($Resource.Timeline, 'codebase/dhtmlxgantt.js')}"/>
<script language="JavaScript" type="text/javascript">
function createChartControl(htmlDiv1)
{
//project 1
var project1 = new GanttProjectInfo(1, "Institutional Sales", new Date(2010, 5, 11));
var parentTask1 = new GanttTaskInfo(1, "IS Planning Timeline", new Date(2010, 5, 11), 208, 100, "");
parentTask1.addChildTask(new GanttTaskInfo(2, "Plan Development", new Date(2010, 5, 11), 100, 100, ""));
parentTask1.addChildTask(new GanttTaskInfo(3, "Finalize Your Plan", new Date(2010, 5, 21), 24, 100, ""));
parentTask1.addChildTask(new GanttTaskInfo(4, "Manager Discussions", new Date(2010, 5, 24), 80, 100, ""));
parentTask1.addChildTask(new GanttTaskInfo(4, "Final Revisions", new Date(2010, 6, 4), 24, 100, ""));
project1.addTask(parentTask1);
var ganttChartControl = new GanttChart();
ganttChartControl.setImagePath("{!URLFOR($Resource.Timeline, 'codebase/imgs/')}");
ganttChartControl.setEditable(false);
ganttChartControl.addProject(project1);
ganttChartControl.showTooltip(false);
ganttChartControl.create(htmlDiv1);
}
</script>
</head>
<body onload="createChartControl('GanttDiv')">
<div style="width:100%;height:240px;position:absolute;" id="GanttDiv"></div>
</body>
</apex:page>
Best Answer
The Gantt Chart code is expecting some variable names that are reserved keywords in Apex Code; they can't be used as variable or class or variable names (e.g. FROM, DESC). Usually, when I'm constructing JSON, I choose to use a
Map<String, Object>
, which works for serialization all of the time, regardless of reserved names/etc.Here's a cleaned up, optimized version of how this library is expecting the data to be rendered: