Gantt Chart. Find Critical Path v3

With Specification. Code totally need 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.upStep   * 32 + 12 }}px; 
                               width:  {{ pred.leftStep * 20 + 5  }}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

// http://blog.thousandeyes.com/creating-extensible-widgets-part-1-jquery-to-angularjs/

angular.module('app',[]).controller('GanttCtrl', function($scope) {
    gc.init(ganttChart);
    
    $scope.tasks = [
        { name: "task A", duration: 3.0,
            isCritical: true, startTime: 0.0 },
        { name: "task B", duration: 4.5, 
            predecessors: [{ name: "task A", upStep: 0.0, leftStep: 0.0, 
                            isCritical: true }],
            isCritical: true, startTime: 3.0 },
        { name: "task C", duration: 2.5, 
            predecessors: [{ name: "task A", upStep: 1.0, leftStep: 0.0 }],
            isCritical: false, startTime: 3.0 },
        { name: "task C.2", duration: 3.5, 
            predecessors: [{ name: "task A", upStep: 2.0, leftStep: 0.0 }],
            isCritical: false, startTime: 3.0 },
        { name: "task D", duration: 3.5, 
            predecessors: 
                [{ name: "task B", upStep: 2.0, leftStep: 0.0, 
                    isCritical: true }, 
                { name: "task C", upStep: 1.0, leftStep: 2.0 },
                { name: "task C.2", upStep: 0.0, leftStep: 1.0 }], 
                    isCritical: true, startTime: 7.5 }
];
        
        //gc.get().tasks;
    console.log($scope.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",...