
Introduction
I am developing a web based application which allows the management of tasks and events of projects. A Gantt chart is needed for displaying a task list visually, and I tried to find a freely available solution (because I didn't want the budget to increase). I found some, but not really good ones. So, I decided to build one on my own. This is the first result of my work. This first version of SIcon was built in just a few hours, so I think it still has some problems. However, I want to share with you the idea. Hope this helps.
SIcon now supports FireFox!
Background
Some knowledge about JScript and CSS is enough for understanding and using this.
Using the code
The code is not really complex, so I will show all of it here:
function Task(from, to, task, resource, progress)
{
var _from = new Date();
var _to = new Date();
var _task = task;
var _resource = resource;
var _progress = progress;
var dvArr = from.split('/');
_from.setFullYear(parseInt(dvArr[2], 10), parseInt(dvArr[0], 10) - 1,
parseInt(dvArr[1], 10));
dvArr = to.split('/');
_to.setFullYear(parseInt(dvArr[2], 10), parseInt(dvArr[0], 10) - 1,
parseInt(dvArr[1], 10));
this.getFrom = function(){ return _from};
this.getTo = function(){ return _to};
this.getTask = function(){ return _task};
this.getResource = function(){ return _resource};
this.getProgress = function(){ return _progress};
}
function Gantt(gDiv)
{
var _GanttDiv = gDiv;
var _taskList = new Array();
this.AddTaskDetail = function(value)
{
_taskList.push(value);
}
this.Draw = function()
{
var _offSet = 0;
var _dateDiff = 0;
var _currentDate = new Date();
var _maxDate = new Date();
var _minDate = new Date();
var _dTemp = new Date();
var _firstRowStr = "<table border=1 style='border-collapse:collapse'><tr>
<td rowspan='2' width='200px' style='width:200px;'>
<div class='GTaskTitle' style='width:200px;'>Task</div></td>";
var _thirdRow = "";
var _gStr = "";
var _colSpan = 0;
var counter = 0;
_currentDate.setFullYear(_currentDate.getFullYear(), _currentDate.getMonth(),
_currentDate.getDate());
if(_taskList.length > 0)
{
_maxDate.setFullYear(_taskList[0].getTo().getFullYear(),
_taskList[0].getTo().getMonth(), _taskList[0].getTo().getDate());
_minDate.setFullYear(_taskList[0].getFrom().getFullYear(),
_taskList[0].getFrom().getMonth(), _taskList[0].getFrom().getDate());
for(i = 0; i < _taskList.length; i++)
{
if(Date.parse(_taskList[i].getFrom()) < Date.parse(_minDate))
_minDate.setFullYear(_taskList[i].getFrom().getFullYear(),
_taskList[i].getFrom().getMonth(), _taskList[i].getFrom().getDate());
if(Date.parse(_taskList[i].getTo()) > Date.parse(_maxDate))
_maxDate.setFullYear(_taskList[i].getTo().getFullYear(),
_taskList[i].getTo().getMonth(), _taskList[i].getTo().getDate());
}
if(_maxDate.getMonth() == 11)
{
if(_maxDate.getDay() + 5 > getDaysInMonth(_maxDate.getMonth() + 1,
_maxDate.getFullYear()))
_maxDate.setFullYear(_maxDate.getFullYear() + 1, 1, 5);
else
_maxDate.setFullYear(_maxDate.getFullYear(), _maxDate.getMonth(),
_maxDate.getDate() + 5); }
else
{
if(_maxDate.getDay() + 5 > getDaysInMonth(_maxDate.getMonth() + 1,
_maxDate.getFullYear()))
_maxDate.setFullYear(_maxDate.getFullYear(), _maxDate.getMonth() + 1,
5);
else
_maxDate.setFullYear(_maxDate.getFullYear(), _maxDate.getMonth(),
_maxDate.getDate() + 5);
}
_gStr = "";
_gStr += "</tr><tr>";
_thirdRow = "<tr><td> </td>";
_dTemp.setFullYear(_minDate.getFullYear(), _minDate.getMonth(),
_minDate.getDate());
while(Date.parse(_dTemp) <= Date.parse(_maxDate))
{
if(_dTemp.getDay() % 6 == 0)
{
_gStr += "<td class='GWeekend'><div style='width:24px;'>" +
_dTemp.getDate() + "</div></td>";
if(Date.parse(_dTemp) == Date.parse(_currentDate))
_thirdRow += "<td id='GC_" + (counter++) +
"' class='GToDay' style='height:" +
(_taskList.length * 21) + "'> </td>";
else
_thirdRow += "<td id='GC_" + (counter++) +
"' class='GWeekend' style='height:" + (_taskList.length * 21) +
"'> </td>";
}
else
{
_gStr += "<td class='GDay'><div style='width:24px;'>" +
_dTemp.getDate() + "</div></td>";
if(Date.parse(_dTemp) == Date.parse(_currentDate))
_thirdRow += "<td id='GC_" + (counter++) +
"' class='GToDay' style='height:" + (_taskList.length * 21) +
"'> </td>";
else
_thirdRow += "<td id='GC_" + (counter++) +
"' class='GDay'> </td>";
}
if(_dTemp.getDate() < getDaysInMonth(_dTemp.getMonth() + 1,
_dTemp.getFullYear()))
{
if(Date.parse(_dTemp) == Date.parse(_maxDate))
{
_firstRowStr += "<td class='GMonth' colspan='" +
(_colSpan + 1) + "'>T" + (_dTemp.getMonth() + 1) + "/" +
_dTemp.getFullYear() + "</td>";
}
_dTemp.setDate(_dTemp.getDate() + 1);
_colSpan++;
}
else
{
_firstRowStr += "<td class='GMonth' colspan='" +
(_colSpan + 1) + "'>T" + (_dTemp.getMonth() + 1) +
"/" + _dTemp.getFullYear() + "</td>";
_colSpan = 0;
if(_dTemp.getMonth() == 11)
{
_dTemp.setFullYear(_dTemp.getFullYear() + 1, 0, 1);
}
else
{
_dTemp.setFullYear(_dTemp.getFullYear(),
_dTemp.getMonth() + 1, 1);
}
}
}
_thirdRow += "</tr>";
_gStr += "</tr>" + _thirdRow;
_gStr += "</table>";
_gStr = _firstRowStr + _gStr;
for(i = 0; i < _taskList.length; i++)
{
_offSet = (Date.parse(_taskList[i].getFrom()) - Date.parse(_minDate)) /
(24 * 60 * 60 * 1000);
_dateDiff = (Date.parse(_taskList[i].getTo()) -
Date.parse(_taskList[i].getFrom())) / (24 * 60 * 60 * 1000) + 1;
_gStr += "<div style='position:absolute; top:" + (20 * (i + 2)) +
"; left:" + (_offSet * 27 + 204) + "; width:" +
(27 * _dateDiff - 1 + 100) + "'><div title='" +
_taskList[i].getTask() + "' class='GTask' style='float:left; width:" +
(27 * _dateDiff - 1) + "px;'>" +
getProgressDiv(_taskList[i].getProgress()) +
"</div><div style='float:left; padding-left:3'>" +
_taskList[i].getResource() + "</div></div>";
_gStr += "<div style='position:absolute; top:" +
(20 * (i + 2) + 1) + "; left:5px'>" + _taskList[i].getTask() +
"</div>";
}
_GanttDiv.innerHTML = _gStr;
}
}
}
function getProgressDiv(progress)
{
return "<div class='GProgress' style='width:" + progress +
"%; overflow:hidden'></div>"
}
function getDaysInMonth(month, year)
{
var days;
switch(month)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
days = 31;
break;
case 4:
case 6:
case 9:
case 11:
days = 30;
break;
case 2:
if (((year% 4)==0) && ((year% 100)!=0) || ((year% 400)==0))
days = 29;
else
days = 28;
break;
}
return (days);
}
How to Use this Script
In the body of your HTML, ASCX, ASPX, or PHP document... put these lines where you want to display the Gantt chart.
<body>
<h3>Diagram</h3>
<div style="position:relative" class="Gantt" id="GanttChart"></div>
</body>
<script>
var g = new Gantt(document.all.GanttChart);
g.AddTaskDetail(new Task(
g.AddTaskDetail(new Task(
g.AddTaskDetail(new Task(
g.AddTaskDetail(new Task(
g.Draw();
</script>
Use the var g = new Gantt(document.all.GanttChart); statement for rendering your Gantt chart to the div element named "GanttChart" (you can see it in the body).
The g.AddTaskDetail() method adds a task to the task list. You can use AJAX or anything you like to generate these commands for adding the set of tasks.
Use g.Draw() for rendering the Gantt chart based on the task list which was added to the Gantt chart object.
How can I change the look of this component
Here, I have defined some classes for customizing the Gantt chart, with full source code provided. You can define more classes and also can change the face of the Gantt chart very easily.
By changing the style sheets, and adding some attributes for the task object in my code, you can make yourself a smart Gantt chart. For example: a different color for the task bar, a nice background image, a better tooltip for the chart,..
/*----- SICON GANTT CHART STYLE CLASSES --------------------------
* DESCRIPTION : Theses class is required for SIcon Gantt Chart
* NOTE : Should change the color, the text style only
*----------------------------------------------------------------*/
.Gantt
{
font-family:tahoma, arial, verdana;
font-size:11px;
}
.GTaskTitle
{
font-family:tahoma, arial, verdana;
font-size:11px;
font-weight:bold;
}
.GMonth
{
padding-left:5px;
font-family:tahoma, arial, verdana;
font-size:11px;
font-weight:bold;
}
.GToday
{
background-color: #FDFDE0;
}
.GWeekend
{
font-family:tahoma, arial, verdana;
font-size:11px;
background-color:#F5F5F5;
text-align:center;
}
.GDay
{
font-family:tahoma, arial, verdana;
font-size:11px;
text-align:center;
}
.GTask
{
border-top:1px solid #CACACA;
border-bottom:1px solid #CACACA;
height:14px;
background-color:yellow;
}
.GProgress
{
background-color:black;
height:2px;
overflow: hidden;
margin-top:5px;
}
Diagram
var g = new Gantt(document.all.GanttChart);
g.AddTaskDetail(new Task('2/11/2008', '2/19/2008', 'Sample task 1 1', 'Dathq', 50));
g.AddTaskDetail(new Task('2/16/2008', '2/19/2008', '... Sample task 1.1',
'Dathq, Thanhdo', 30));
g.AddTaskDetail(new Task('2/12/2008', '3/2/2008', 'Sample task 2', 'Hanhnd', 60));
g.AddTaskDetail(new Task('2/11/2008', '2/16/2008', 'Sample task 3', 'Dathq', 50));
g.AddTaskDetail(new Task('2/11/2008', '2/19/2008', 'Sample task 1 1', 'Dathq', 50));
g.AddTaskDetail(new Task('2/16/2008', '2/19/2008', '... Sample task 1.1',
'Dathq, Thanhdo', 30));
g.AddTaskDetail(new Task('2/12/2008', '3/2/2008', 'Sample task 2', 'Hanhnd', 60));
g.AddTaskDetail(new Task('2/11/2008', '2/16/2008', 'Sample task 3', 'Dathq', 50));
g.AddTaskDetail(new Task('2/11/2008', '2/19/2008', 'Sample task 1 1', 'Dathq', 50));
g.AddTaskDetail(new Task('2/16/2008', '2/19/2008', '... Sample task 1.1',
'Dathq, Thanhdo', 30));
g.AddTaskDetail(new Task('2/12/2008', '3/2/2008', 'Sample task 2', 'Hanhnd', 60));
g.AddTaskDetail(new Task('2/11/2008', '2/16/2008', 'Sample task 3', 'Dathq', 50));
g.AddTaskDetail(new Task('2/11/2008', '2/19/2008', 'Sample task 1 1', 'Dathq', 50));
g.AddTaskDetail(new Task('2/16/2008', '2/19/2008', '... Sample task 1.1',
'Dathq, Thanhdo', 30));
g.AddTaskDetail(new Task('2/12/2008', '3/2/2008', 'Sample task 2', 'Hanhnd', 60));
g.AddTaskDetail(new Task('5/11/2008', '5/16/2008', 'Sample task 3', 'Dathq', 50));
g.Draw();
Points of Interest
The first point you will notice about the chart is that it runs very fast.
SIcon Gantt chart is built with JavaScript, which means you can use it in most cases of web development. With me, I like ASP.NET, and of course I can use this component with ASP.NET. Additionally, you can use it with AJAX for cooler applications. You can customize the CSS classes as you like, and get a "good looking" Gantt chart. I will try to add a link to the tasks for describing their relations and also a parent task displayed, as we can see in MS Project.
The Gantt chart is displayed withs HTML giving it a light weight structure, so you can add more features to the chart. For example, tooltip, link, image... with some basic changes within the Jscript code.
And the last one, it is total free.
Happy coding! :)
History
- 27 Feb 2008: First version of SIcon Gantt chart.
- 07 Jun 2008: Fixed display error with Firefox.
| You must Sign In to use this message board. |
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
 |
Hi
I have made a modification to the original code which allows for more than 1 task per row. It also allows for a change in colors.
Cheers Glen
<div> <script> /* --------- SICON GANTT CHART ----------------------------------------------------------- * AUTHOR : Dathq - ICT Service Engineering Jsc, - dathq@ise.com.vn * LICENSE : Free * DESCRIPTION : Create a new task item with these info * - from: start date (format: mm/dd/dddd) * - to: deadline of task (format: mm/dd/dddd) * - task: name of the task, what has to be solved (not includes * - resource: who have to solve this task (not includes * - progress: how is it going? (format: integer value from 0 to 100, not includes %) *----------------------------------------------------------------------------------------*/ function Task(from, to, task, resource, progress, color) { var _from = new Date(); var _to = new Date(); var _task = task; var _resource = resource; var _progress = progress; var _color = color; var dvArr = from.split( _from.setFullYear(parseInt(dvArr[2], 10), parseInt(dvArr[0], 10) - 1, parseInt(dvArr[1], 10)); dvArr = to.split( _to.setFullYear(parseInt(dvArr[2], 10), parseInt(dvArr[0], 10) - 1, parseInt(dvArr[1], 10)); this.getFrom = function(){ return _from}; this.getTo = function(){ return _to}; this.getTask = function(){ return _task}; this.getResource = function(){ return _resource}; this.getProgress = function(){ return _progress}; this.getcolor = function(){return _color}; } function Gantt(gDiv) { var _GanttDiv = gDiv; var _taskList = new Array(); var _projectList = new Array(); this.getRowList = function(){return _rowList}; this.getTaskList = function() {return _taskList}; this.AddTaskDetail = function(value) { _taskList.push(value); } this.AddProjects = function(value) { _projectList.push(value); } this.Draw = function() { var _offSet = 0; var _dateDiff = 0; var _currentDate = new Date(); var _maxDate = new Date(); var _minDate = new Date(); var _dTemp = new Date(); var _firstRowStr = "<table border=1 style='border-collapse:collapse'><tr><td rowspan='2' width='200px' style='width:200px;'><div class='GTaskTitle' style='width:200px;'>Task</div></td>"; var _thirdRow = ""; var _gStr = ""; var _colSpan = 0; var counter = 0; _currentDate.setFullYear(_currentDate.getFullYear(), _currentDate.getMonth(), _currentDate.getDate()); if(_projectList.length > 0) {
//Get Max Date var MaxDate = 0; var MaxCounter = 0; var MaxProject = 0;
for (x = 0; x < _projectList.length; x++ ) { for (z = 0; z < _projectList[x].length; z++) { if (_projectList[x][z].getTo().getDate() > MaxDate) { MaxDate = _projectList[x][z].getTo().getDate() MaxCounter = z; MaxProject = x; } } } var MinDate = 0; var MinCounter = 0; var MinProject = 0; for (b = 0; b < _projectList.length; b++ ) { for (y = 0; y < _projectList[b].length; y++) { if (_projectList[b][y].getTo().getDate() < MinDate) { MinDate = _projectList[b][y].getTo().getDate() MinCounter = y; MinProject = b; } } } _maxDate.setFullYear(_projectList[MaxProject][MaxCounter].getTo().getFullYear(), _projectList[0][MaxCounter].getTo().getMonth(), _projectList[0][MaxCounter].getTo().getDate()); _minDate.setFullYear(_projectList[MinProject][MinCounter].getFrom().getFullYear(), _projectList[0][MinCounter].getFrom().getMonth(), _projectList[0][MinCounter].getFrom().getDate()); for (c = 0; c < _projectList.length; c++ ) { for(i = 0; i < _projectList[c].length; i++) { if(Date.parse(_projectList[c][i].getFrom()) < Date.parse(_minDate)) _minDate.setFullYear(_projectList[c][i].getFrom().getFullYear(), _projectList[c][i].getFrom().getMonth(), _projectList[c][i].getFrom().getDate()); if(Date.parse(_projectList[c][i].getTo()) > Date.parse(_maxDate)) _maxDate.setFullYear(_projectList[c][i].getTo().getFullYear(), _projectList[c][i].getTo().getMonth(), _projectList[c][i].getTo().getDate()); } } //---- Fix _maxDate value for better displaying----- // Add at least 5 days if(_maxDate.getMonth() == 11) //December { if(_maxDate.getDay() + 5 > getDaysInMonth(_maxDate.getMonth() + 1, _maxDate.getFullYear())) _maxDate.setFullYear(_maxDate.getFullYear() + 1, 1, 5); //The fifth day of next month will be used else _maxDate.setFullYear(_maxDate.getFullYear(), _maxDate.getMonth(), _maxDate.getDate() + 5); //The fifth day of next month will be used } else { if(_maxDate.getDay() + 5 > getDaysInMonth(_maxDate.getMonth() + 1, _maxDate.getFullYear())) _maxDate.setFullYear(_maxDate.getFullYear(), _maxDate.getMonth() + 1, 5); //The fifth day of next month will be used else _maxDate.setFullYear(_maxDate.getFullYear(), _maxDate.getMonth(), _maxDate.getDate() + 5); //The fifth day of next month will be used } //-------------------------------------------------- _gStr = ""; _gStr += "</tr><tr>"; _thirdRow = "<tr><td> </td>"; _dTemp.setFullYear(_minDate.getFullYear(), _minDate.getMonth(), _minDate.getDate()); while(Date.parse(_dTemp) <= Date.parse(_maxDate)) { if(_dTemp.getDay() % 6 == 0) //Weekend { _gStr += "<td class='GWeekend'><div style='width:24px;'>" + _dTemp.getDate() + "</div></td>"; if(Date.parse(_dTemp) == Date.parse(_currentDate)) _thirdRow += "<td id='GC_" + (counter++) + "' class='GToDay' style='height:" + (_projectList[0].length * 21) + "'> </td>"; else _thirdRow += "<td id='GC_" + (counter++) + "' class='GWeekend' style='height:" + (_projectList[0].length * 21) + "'> </td>"; } else { _gStr += "<td class='GDay'><div style='width:24px;'>" + _dTemp.getDate() + "</div></td>"; if(Date.parse(_dTemp) == Date.parse(_currentDate)) _thirdRow += "<td id='GC_" + (counter++) + "' class='GToDay' style='height:" + (_projectList[0].length * 21) + "'> </td>"; else _thirdRow += "<td id='GC_" + (counter++) + "' class='GDay'> </td>"; } if(_dTemp.getDate() < getDaysInMonth(_dTemp.getMonth() + 1, _dTemp.getFullYear())) { if(Date.parse(_dTemp) == Date.parse(_maxDate)) { _firstRowStr += "<td class='GMonth' colspan='" + (_colSpan + 1) + "'>T" + (_dTemp.getMonth() + 1) + "/" + _dTemp.getFullYear() + "</td>"; } _dTemp.setDate(_dTemp.getDate() + 1); _colSpan++; } else { _firstRowStr += "<td class='GMonth' colspan='" + (_colSpan + 1) + "'>T" + (_dTemp.getMonth() + 1) + "/" + _dTemp.getFullYear() + "</td>"; _colSpan = 0; if(_dTemp.getMonth() == 11) //December { _dTemp.setFullYear(_dTemp.getFullYear() + 1, 0, 1); } else { _dTemp.setFullYear(_dTemp.getFullYear(), _dTemp.getMonth() + 1, 1); } } } _thirdRow += "</tr>"; _gStr += "</tr>" + _thirdRow; _gStr += "</table>"; _gStr = _firstRowStr + _gStr; for(n = 0; n < _projectList.length; n++) { for(i = 0; i < _projectList[n].length; i++) { _offSet = (Date.parse(_projectList[n][i].getFrom()) - Date.parse(_minDate)) / (24 * 60 * 60 * 1000); _dateDiff = (Date.parse(_projectList[n][i].getTo()) - Date.parse(_projectList[n][i].getFrom())) / (24 * 60 * 60 * 1000) + 1; _gStr += "<div style='position:absolute; top:" + (20 * (n + 2)) + "; left:" + (_offSet * 27 + 204) + "; width:" + (27 * _dateDiff - 1 + 100) + "'><div title='" + _projectList[n][i].getTask() + "' style='background-color:" + _projectList[n][i].getcolor() +";border-top:1px solid #CACACA; border-bottom:1px solid #CACACA; height:14px; float:left; width:" + (27 * _dateDiff - 1) + "px;'>" + getProgressDiv(_projectList[n][i].getProgress()) + "</div><div style='float:left; padding-left:3'>" + _projectList[n][i].getResource() + "</div></div>"; _gStr += "<div style='position:absolute; top:" + (20 * (n + 2) + 1) + "; left:5px'>" + _projectList[n][i].getTask() + "</div>"; } } _GanttDiv.innerHTML = _gStr; } } } function getProgressDiv(progress) { return "<div class='GProgress' style='width:" + progress + "%; overflow:hidden'></div>" } // GET NUMBER OF DAYS IN MONTH function getDaysInMonth(month, year) { var days; switch(month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: days = 31; break; case 4: case 6: case 9: case 11: days = 30; break; case 2: if (((year% 4)==0) && ((year% 100)!=0) || ((year% 400)==0)) days = 29; else days = 28; break; } return (days); } /*----- END OF MY CODE FOR Gantt CHART GENERATOR -----*/ </script> <style> /*----- SICON GANTT CHART STYLE CLASSES -------------------------- * DESCRIPTION : Theses class is required for SIcon Gantt Chart * NOTE : Should change the color, the text style only *----------------------------------------------------------------*/ .Gantt { font-family:tahoma, arial, verdana; font-size:11px; } .GTaskTitle { font-family:tahoma, arial, verdana; font-size:11px; font-weight:bold; } .GMonth { padding-left:5px; font-family:tahoma, arial, verdana; font-size:11px; font-weight:bold; } .GToday { background-color: #FDFDE0; } .GWeekend { font-family:tahoma, arial, verdana; font-size:11px; background-color:#F5F5F5; text-align:center; } .GDay { font-family:tahoma, arial, verdana; font-size:11px; text-align:center; } .GTask { border-top:1px solid #CACACA; border-bottom:1px solid #CACACA; height:14px; background-color:yellow; } .GProgress { background-color:black; height:2px; overflow: hidden; margin-top:5px; } </style>
<body> <h3>Diagram</h3> <div style="position:relative" class="Gantt" id="GanttChart"></div> </body>
<script> var g = new Gantt(document.all.GanttChart);
var ProjectList = new Array(); ProjectList.push(new Task( ProjectList.push(new Task( g.AddProjects(ProjectList);
var ProjectList = new Array(); ProjectList.push(new Task( ProjectList.push(new Task( ProjectList.push(new Task( g.AddProjects(ProjectList);
g.Draw(); </script> </div>
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Thanks, would it be possible zip the source for download, I tried to copy'n'paste but this doesn't work.
Thanks again!
|
| Sign In·View Thread·PermaLink | 1.00/5 |
|
|
|
 |
|
 |
I'm not sure either (how to / if your allowed to) upload directly to this site so i uploaded it here
Use the "Download with FileFactory Basic" link towards the bottom of the page.
Hopefully it works this time... I also tried copy and paste from what i added yesterday and it didn't work for me either. I have a theory its becuase i forgot to tick the "Ignore HTML tags in this message (good for code snippets)" when i posted the message.
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
|
 |
|
 |
<script> /* --------- SICON GANTT CHART ----------------------------------------------------------- * AUTHOR : Dathq - ICT Service Engineering Jsc, - dathq@ise.com.vn * LICENSE : Free * DESCRIPTION : Create a new task item with these info * - from: start date (format: mm/dd/dddd) * - to: deadline of task (format: mm/dd/dddd) * - task: name of the task, what has to be solved (not includes * - resource: who have to solve this task (not includes * - progress: how is it going? (format: integer value from 0 to 100, not includes %) *----------------------------------------------------------------------------------------*/ function Task(from, to, task, resource, progress) { var _from = new Date(); var _to = new Date(); var _task = task; var _resource = resource; var _progress = progress; var dvArr = from.split( _from.setFullYear(parseInt(dvArr[2], 10), parseInt(dvArr[0], 10) - 1, parseInt(dvArr[1], 10)); dvArr = to.split( _to.setFullYear(parseInt(dvArr[2], 10), parseInt(dvArr[0], 10) - 1, parseInt(dvArr[1], 10)); this.getFrom = function(){ return _from}; this.getTo = function(){ return _to}; this.getTask = function(){ return _task}; this.getResource = function(){ return _resource}; this.getProgress = function(){ return _progress}; this.getTaskNameSize= function() {return _task.length*7;} } function Gantt(gDiv) { var _GanttDiv = gDiv; var _taskList = new Array(); var max_task_length=0; this.AddTaskDetail = function(value) { if (value.getTaskNameSize()>max_task_length) max_task_length=value.getTaskNameSize(); _taskList.push(value); } this.Draw = function() { var _offSet = 0; var _dateDiff = 0; var _currentDate = new Date(); var _maxDate = new Date(); var _minDate = new Date(); var _dTemp = new Date(); var _firstRowStr = "<table border=1 style='border-collapse:collapse'><tr><td rowspan='2' width='200px' style='width:200px;'><div class='GTaskTitle' style='width:" + max_task_length + "px;'>Task</div></td>"; var _thirdRow = ""; var _gStr = ""; var _colSpan = 0; var counter = 0; _currentDate.setFullYear(_currentDate.getFullYear(), _currentDate.getMonth(), _currentDate.getDate()); if(_taskList.length > 0) { _maxDate.setFullYear(_taskList[0].getTo().getFullYear(), _taskList[0].getTo().getMonth(), _taskList[0].getTo().getDate()); _minDate.setFullYear(_taskList[0].getFrom().getFullYear(), _taskList[0].getFrom().getMonth(), _taskList[0].getFrom().getDate()); for(i = 0; i < _taskList.length; i++) { if(Date.parse(_taskList[i].getFrom()) < Date.parse(_minDate)) _minDate.setFullYear(_taskList[i].getFrom().getFullYear(), _taskList[i].getFrom().getMonth(), _taskList[i].getFrom().getDate()); if(Date.parse(_taskList[i].getTo()) > Date.parse(_maxDate)) _maxDate.setFullYear(_taskList[i].getTo().getFullYear(), _taskList[i].getTo().getMonth(), _taskList[i].getTo().getDate()); } //---- Fix _maxDate value for better displaying----- // Add at least 5 days if(_maxDate.getMonth() == 11) //December { if(_maxDate.getDay() + 5 > getDaysInMonth(_maxDate.getMonth() + 1, _maxDate.getFullYear())) _maxDate.setFullYear(_maxDate.getFullYear() + 1, 1, 5); //The fifth day of next month will be used else _maxDate.setFullYear(_maxDate.getFullYear(), _maxDate.getMonth(), _maxDate.getDate() + 5); //The fifth day of next month will be used } else { if(_maxDate.getDay() + 5 > getDaysInMonth(_maxDate.getMonth() + 1, _maxDate.getFullYear())) _maxDate.setFullYear(_maxDate.getFullYear(), _maxDate.getMonth() + 1, 5); //The fifth day of next month will be used else _maxDate.setFullYear(_maxDate.getFullYear(), _maxDate.getMonth(), _maxDate.getDate() + 5); //The fifth day of next month will be used } //-------------------------------------------------- _gStr = ""; _gStr += "</tr><tr>"; _thirdRow = "<tr><td> </td>"; _dTemp.setFullYear(_minDate.getFullYear(), _minDate.getMonth(), _minDate.getDate()); while(Date.parse(_dTemp) <= Date.parse(_maxDate)) { if(_dTemp.getDay() % 6 == 0) //Weekend { _gStr += "<td class='GWeekend'><div style='width:24px;'>" + _dTemp.getDate() + "</div></td>"; if(Date.parse(_dTemp) == Date.parse(_currentDate)) _thirdRow += "<td id='GC_" + (counter++) + "' class='GToDay' style='height:" + (_taskList.length * 21) + "'> </td>"; else _thirdRow += "<td id='GC_" + (counter++) + "' class='GWeekend' style='height:" + (_taskList.length * 21) + "'> </td>"; } else { _gStr += "<td class='GDay'><div style='width:24px;'>" + _dTemp.getDate() + "</div></td>"; if(Date.parse(_dTemp) == Date.parse(_currentDate)) _thirdRow += "<td id='GC_" + (counter++) + "' class='GToDay' style='height:" + (_taskList.length * 21) + "'> </td>"; else _thirdRow += "<td id='GC_" + (counter++) + "' class='GDay'> </td>"; } if(_dTemp.getDate() < getDaysInMonth(_dTemp.getMonth() + 1, _dTemp.getFullYear())) { if(Date.parse(_dTemp) == Date.parse(_maxDate)) { _firstRowStr += "<td class='GMonth' colspan='" + (_colSpan + 1) + "'>" + (getMonthName(_dTemp.getMonth())) + "/" + _dTemp.getFullYear() + "</td>"; } _dTemp.setDate(_dTemp.getDate() + 1); _colSpan++; } else { _firstRowStr += "<td class='GMonth' colspan='" + (_colSpan + 1) + "'>" + (getMonthName(_dTemp.getMonth())) + "/" + _dTemp.getFullYear() + "</td>"; _colSpan = 0; if(_dTemp.getMonth() == 11) //December { _dTemp.setFullYear(_dTemp.getFullYear() + 1, 0, 1); } else { _dTemp.setFullYear(_dTemp.getFullYear(), _dTemp.getMonth() + 1, 1); } } } _thirdRow += "</tr>"; _gStr += "</tr>" + _thirdRow; _gStr += "</table>"; _gStr = _firstRowStr + _gStr; for(i = 0; i < _taskList.length; i++) { _offSet = (Date.parse(_taskList[i].getFrom()) - Date.parse(_minDate)) / (24 * 60 * 60 * 1000); _dateDiff = (Date.parse(_taskList[i].getTo()) - Date.parse(_taskList[i].getFrom())) / (24 * 60 * 60 * 1000) + 1; _gStr += "<div style='position:absolute; top:" + (20 * (i + 2)) + "; left:" + (_offSet * 27 + max_task_length) + "; width:" + (27 * _dateDiff - 1 + 100) + "'><div title='" + _taskList[i].getTask() + "' class='GTask' style='float:left; width:" + (27 * _dateDiff - 1) + "px;'>" + getProgressDiv(_taskList[i].getProgress()) + "</div><div style='float:left; padding-left:3'>" + _taskList[i].getResource() + "</div></div>"; _gStr += "<div style='position:absolute; top:" + (20 * (i + 2) + 1) + "; left:5px'>" + _taskList[i].getTask() +"</div>"; } _GanttDiv.innerHTML = _gStr; } } } function getProgressDiv(progress) { return "<div class='GProgress' style='width:" + progress + "%; overflow:hidden'></div>" } function getMonthName(month) { var mname; switch(month) { case 0: mname= break; case 1: mname= break; case 2: mname= break; case 3: mname= break; case 4: mname= break; case 5: mname= break; case 6: mname= break; case 7: mname= break; case 8: mname= break; case 9: mname= break; case 10: mname= break; case 11: mname= break; } return (mname); } // GET NUMBER OF DAYS IN MONTH function getDaysInMonth(month, year) { var days; switch(month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: days = 31; break; case 4: case 6: case 9: case 11: days = 30; break; case 2: if (((year% 4)==0) && ((year% 100)!=0) || ((year% 400)==0)) days = 29; else days = 28; break; } return (days); } /*----- END OF MY CODE FOR Gantt CHART GENERATOR -----*/ </script>
I changed your code to handle the task name sizes and customized month names (in my case i'm portuguese so they are in that language (function getMonthName(month)).
With your code if a task has a long name then it overlaps the gantt task bars.
With my code i compute the biggest task name size by testing the sizes in the insertion of tasks in the array _taskList. With that value i generate the correct size for the task name label in the table.
The function to get month names is simple and easy to adapt to any language needed.
The UPDATES to the code are in bold.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
...
this.getResource = function(){ return _resource}; this.getProgress = function(){ return _progress}; this.getTaskNameSize= function() {return _task.length*7;}
....
var max_task_length=0; this.AddTaskDetail = function(value) { if (value.getTaskNameSize()>max_task_length) max_task_length=value.getTaskNameSize();
...
var _firstRowStr = "<table border=1 style='border-collapse:collapse'><tr><td rowspan='2' width='200px' style='width:200px;'> <div class='GTaskTitle' style='width:" + max_task_length + "px;'>Task</div></td>";
...
_firstRowStr += "<td class='GMonth' colspan='" + (_colSpan + 1) + "'>" + (getMonthName(_dTemp.getMonth())) + "/" + _dTemp.getFullYear() + "</td>";
...
_dateDiff = (Date.parse(_taskList[i].getTo()) - Date.parse(_taskList[i].getFrom())) / (24 * 60 * 60 * 1000) + 1; _gStr += "<div style='position:absolute; top:" + (20 * (i + 2)) + "; left:" + (_offSet * 27 + max_task_length) + "; width:"
...
function getMonthName(month) { var mname; switch(month) { case 0: mname='Janeiro'; break; case 1: mname='Fevereiro'; break; case 2: mname='Março'; break; case 3: mname='Abril'; break; case 4: mname='Maio'; break; case 5: mname='Junho'; break; case 6: mname='Julho'; break; case 7: mname='Agosto'; break; case 8: mname='Setembro'; break; case 9: mname='Outubro'; break; case 10: mname='Novembro'; break; case 11: mname='Dezembro'; break; } return (mname); }
The post is big so i resumed the alterations to the code here.
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
 |
When running this in FireFox 2.0.0.16, I get the message in FireFox's Error Console: "document.all has no properties" in the line "var g = new Gantt(document.all.GanttChart);"
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Using document.getElementById('GanttChart') fixes the error, but I still can't make FireFox display the chart properly. Upgraded to FireFox3, but no change.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I really like the idea of your software ... BUT I can't get it to work in ASP.net.
I am trying to put this into an ASP.net web page. I am having problems understanding what parts go where and what changes I need to make. Can you give me some basic suggestions? I have put all the functions in a javascript in the .aspx page ... but don't know where to put the code found in the "Diagram". If it put it in a sub ... I get syntax errors ... if include it in the javascript there are no syntax errors but I don't get any results.
Thanks
Dave Potter davidjohnpotter@hotmail.com
|
| Sign In·View Thread·PermaLink | 1.00/5 |
|
|
|
 |
|
 |
hi,, i am getting error as "gantt is undefined".. can any one tell me whats place i goen wrong..
thanks.
modified on Tuesday, July 15, 2008 9:43 AM
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
 |
Can anyone tell me where it is that I can adjust the width of the day AND the width of the tasks so that they align properly? I know the base width of the days is 24px but am having trouble calculating out to get the tasks adjusted accordingly.
Sorry if this is an obvious question but I would appreciate the guidance.
(Love the chart though!)
|
| Sign In·View Thread·PermaLink | 1.00/5 |
|
|
|
 |
|
 |
Yes, I also would like to know about this because I am showing my data from 1st of every month If I got the task from 15th or 20th or any of the date of that particular month. So when I am showing the data the process line is not coming at the same place. I have tried to debug it but what I felt is u are using _offSet = (Date.parse(_taskList[i].getFrom()) - Date.parse(_minDate)) / (24 * 60 * 60 * 1000); for the starting point. but I don't want this thing. I want to show the data with my effective date on which exactly the task has been started.
I would appreciate the help.
Thanks in Advance
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Any ideas about how to make updateable this awesome chart??, the idea is that i want to drag the task schedule and setting the new values and update it to the Server, thank you in advance
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
 |
Yes, you can do much more with javascript and ajax technical: - Resiable control. - Drag and drop. - Or a popup modal to change to task detail. ... Let see the Ajax Control Toolkit http:ajax.asp.net and http://extjs.com for more detail.
The next task after updating is refresh the chart. You can use AJAX, and it will be more interesting with using JSON with.
Regards,
dathq
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
If you use BOSH (Bidirectional Open Streams over Http) you can notify instantly instead of polling.
He who asks a question is a fool for five minutes. He who does not ask a question remains a fool forever. [Chineese Proverb]
Jonathan C Dickinson (C# Software Engineer)
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
 |
Could you explain more detail about this idea? I have google for "BOSH" and it have just draf version now.
dathq
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I would love to!!! Basically your server-side code does not close client-side requests, instead it keeps them open and sends events down the wire. When a client needs to send a new request it closes the previous one and opens a new one to the server. Thus (very pseudo-ish code):
SendRequest(request) { ClosePreviousConnection(); OpenConnectionAndSendData(request); }
OpenConnectionAndSendData(request) { XmlHttpConnection con = new XmlHttpConnection("host/bosh.ashx"); con.DataRecieved = DataRecieved; con.Request(request); previousConnection = con; }
ClosePreviousConnection() { if(previousConnection != null) previousConnection.Close(); }
DataRecieved(string data) { currentData += data; if(currentData.IndexOf('\0') != -1) { packet = currentData.SubString(0, currentData.IndexOf('\0'); currentData = currentData.SubString(currentData.IndexOf('\0') + 1); HandlePacket(packet); } }
So that is the general outline what you would do with the client-side javascript. Now the server code:
In BOSH.ashx:
public class bosh : IHttpHandler { private ManualResetEvent stopEvent = new ManualResetEvent(false); private HttpContext ctx;
public void ProcessRequest(HttpContext context) { ctx = context; context.Response.BufferOutput = false;
ThreadStart ts = new ThreadStart(Worker); ts.BeginInvoke(null, null);
stopEvent.Reset(); stopEvent.WaitOne(); }
private void Worker() { for(int i = 0; i < 100; i++) { ctx.Response.Write("Time: " + DateTime.Now.ToLongTimeString()); ctx.Response.Write('\0'); ctx.Response.Flush(); if (!ctx.Response.IsClientConnected) return;
Thread.Sleep(1000); }
stopEvent.Set(); }
public bool IsReusable { get { return false; } } }
That is the bare-bones of a BOSH request. If you visit http://localhost:[port]/bosh.ashx you will see the time coming through every second.
HTH
He who asks a question is a fool for five minutes. He who does not ask a question remains a fool forever. [Chineese Proverb]
Jonathan C Dickinson (C# Software Engineer)
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
 | good  Abhijit Jana | 6:33 12 Jun '08 |
|
|
 |
|
 |
Hi,
Are you able to provide the same code in ASP.NET please?
I would very much like to have the ability to generate a HTML-based gantt chart, such as this, via ASP.NET (VB). This would allow for the chart to be exported to a Word document.
Thank you very much!
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
|
 |
|
 |
Very nice job! I've really enjoyed playing around with this and will definitely be using it in the future.
I've made some modifications for use in Firefox to some CSS classes.
Change:
.GToday { background-color: rgb(253, 253, 224); }
.GWeekend { font-family:tahoma, arial, verdana; font-size:11px; background-color:rgb(245, 245, 245); text-align:center; }
.GDay { font-family:tahoma, arial, verdana; font-size:11px; text-align:center; }
To:
.GToday { width: 24px; background-color: rgb(253, 253, 224); }
.GWeekend { width: 24px; font-family:tahoma, arial, verdana; font-size:11px; background-color:rgb(245, 245, 245); text-align:center; }
.GDay { width: 24px; font-family:tahoma, arial, verdana; font-size:11px; text-align:center; }
I also added XML functionality to the programming. Just a simple function called CreateChart().
function CreateChart() { var xmlDoc = null;
if (window.ActiveXObject) { xmlDoc = new ActiveXObject('Microsoft.XMLDOM'); }
if (document.implementation.createDocument) { xmlDoc = document.implementation.createDocument('', '', null); }
if (xmlDoc != null) { xmlDoc.async = false; xmlDoc.load('gantt.xml'); }
var xmlTasks = xmlDoc.documentElement.childNodes;
for (var i = 0; i < xmlTasks.length; i++) { if (xmlTasks[i].nodeType == 1) { var xmlTask = xmlTasks[i];
var ganttDiv = document.createElement('div'); ganttDiv.style.position = 'relative'; ganttDiv.class = 'Gantt'; ganttDiv.id = xmlTask.getAttribute('id');
document.body.insertBefore(ganttDiv, null);
var g = new Gantt(ganttDiv);
for (var j = 0; j < xmlTask.childNodes.length; j++) { var xmlTaskDetail = xmlTask.childNodes[j]; if (xmlTaskDetail.nodeType == 1) { if (xmlTaskDetail.nodeName == 'BeginDate'){var beginDate = xmlTaskDetail.firstChild.nodeValue;} if (xmlTaskDetail.nodeName == 'EndDate'){var endDate = xmlTaskDetail.firstChild.nodeValue;} if (xmlTaskDetail.nodeName == 'TaskTitle'){var taskTitle = xmlTaskDetail.firstChild.nodeValue;} if (xmlTaskDetail.nodeName == 'Resource'){var taskResource = xmlTaskDetail.firstChild.nodeValue;} if (xmlTaskDetail.nodeName == 'Progress'){var taskProgress = xmlTaskDetail.firstChild.nodeValue;} if (xmlTaskDetail.nodeName == 'Progress'){g.AddTaskDetail(new Task(beginDate, endDate, taskTitle, taskResource, taskProgress));} } } g.Draw(); } } }
This is my first real venture to actually parsing XML so anyone please feel free to beef it up some. Also the XML file looks like this:
"SampleChart"> 2/11/2008 2/12/2008 Sample task 1 1 Dathq
2/16/2008 2/19/2008 ...Sample task 1.1 Dathq, Thanhdd
2/12/2008 3/4/2008 Sample task 2 Hanhnd
2/11/2008 2/16/2008 Sample task 3 Dathq "SampleChart2"> 2/11/2008 2/12/2008 Sample task 1.1 Dathq
Again, thanks for a great app!
|
| Sign In·View Thread·PermaLink | 2.00/5 |
|
|
|
 |
|
|