Gantt Chart. Find Critical Path v2
__REFACTORING__
by Ivan Gerasimenko
HTML
<div ng-app='app'>
<div id="logger"></div>
<h4>Gantt Chart</h4>
<div class="gantt-box" ng-controller="GanttCtrl">
<div class="cell" ng-repeat="task in tasks">
<div class="bar"
style="width: {{task.duration * 20}}px;
margin-left: {{task.startTime * 20}}px;"
ng-class="{true:'critical'}[task.isCritical]">
<div class="bar-arrow">
<div class="arrow-connector"
ng-repeat="pred in task.predecessors"
style="height: {{pred.height}}px;
width: {{pred.width}}px"
ng-class="{true:'critical'}[pred.isCritical]"
></div>
</div>
{{task.name}}
</div>
</div>
</div>
</div>
CSS
.cell {
border: 1px dashed #cccccc;
width: 300px;
height: 16px;
padding: 7px;
}
.bar {
position: relative;
height: 16px;
background: #cccccc;
text-align: center;
font-size: 12px;
font-weight: bold;
}
.bar.critical {
background: #ffcccc;
}
/*************** arrow connectors *****************/
.arrow-connector {
/* four params to position respectively parent element */
bottom: 11px;
right: -7px;
width: 5px;
height: 10px;
/******************************/
position: absolute;
border-top: 2px solid #8cc;
border-right: 2px solid #8cc;
border-top-right-radius: 4px;
}
.arrow-connector:before {
content: "";
display: inline-block;
position: absolute;
bottom: -12px;
right: -6px;
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 12px solid #8cc;
}
.arrow-connector { border-color: #8cc }
.arrow-connector:before { border-top-color: #8cc }
.arrow-connector.critical { border-color: #ff8888; z-index: 1000;}
.arrow-connector.critical:before { border-top-color: #ff8888; }
/*****************************************************/
.bar-arrow {
position: absolute;
width: 0;
height: 0;
top: 0;
bottom: 0;
}
JavaScript
angular.module('app',[]).controller('GanttCtrl', function($scope) {
gc.init(ganttChart);
$scope.tasks = gc.get().tasks;
console.log(gc.get().tasks);
});
console.clear();
var ganttChart = {
startDate: "Jul 23, 2006",
tasks: [
/*{ name: "task E",
predecessors: [
{name: "task B", height: 0, width: 0, isCritical: true},
{name: "task C"}], duration: 2.17, startTime: 8.5 },*/
{ name: "task A", predecessors: [], duration: 4},
{ name: "task B", predecessors: [], duration: 5.33},
{ name: "task C", predecessors: [{name: "task A"}],
duration: 4.5},
{ name: "task D", predecessors: [{name: "task A"}],
duration: 3},
{ name: "task E", predecessors: [{name: "task B"}, {name: "task C"}],
duration: 2.17},
{ name: "task F", predecessors: [{name: "task D"}, {name: "task E"}],
duration: 3}
]};
/* Finding critical path */
/****** module ****/
function GanttChart() {
var chartData;
var pathes;
function init(params) {
// check for isNaN, expected properties.
if(checkChartData(params)){
chartData = params;
// compute pathes
pathes = getPathes();
// compute critical start time startTime:
for(var i=0; i<chartData.tasks.length; i++) {
setTaskStartTime({ i: i, name: chartData.tasks[i].name });
}
// setCriticalPathMark
setCriticalPathMark();
// add connectors
AddConnectors();
console.log("Init complete.");
} else {
console.log("Incorrect input data.");
}
};
function checkChartData(params) {
if(typeof params === 'object' &&
typeof params.tasks === 'object' &&
typeof params.tasks.slice === 'function') {
return true;
}
else {
return...