Project S.T.A.R schedule for 2017

Here's an example of how the Gantt chart can be integrated into a mini-app, which in this case, is an example of project managment. The Gantt chart is dynamic - you can drag the events left and right and enlarge the event if you you click the event towards the right-hand side.

The data is loaded from and saved to the browsers localData variable (which is like a cookie but does not get sent back and forth to the server).

TODO:

If you want a skeleton/cut down version of this page, with no extraneous text and just the Gantt chart on it then you can find it here.

[No canvas support]

Name:
Start date: (dd/mm)
Duration: (days)
% Complete:

This goes in the documents header:
<script src="RGraph.common.core.js"></script>
<script src="RGraph.common.dynamic.js"></script>
<script src="RGraph.gantt.js"></script>
Put this where you want the chart to show up:
<canvas id="cvs" width="950" height="450">[No canvas support]</canvas>
<p />
<button onclick="addPerson()">Add...</button>
<button onclick="deletePerson()">Delete</button>


<p id="eventForm">
    <span class="formLabel">Name:</span>
    <input type="text" id="name" />
    <button onclick="updateName()">Update</button>
    
    <br />
    <span class="formLabel">Start date:</span>
    <input type="text" id="startdate" readonly />
    <i>(dd/mm)</i>
    
    <br />

    <span class="formLabel">Duration:</span>
    <input type="text" id="duration" readonly />
    <i>(days)</i>
    
    <br />

    <span class="formLabel">% Complete:</span>
    <input type="text" id="complete" />
    <button onclick="updateComplete()">Update</button>
    
    <p>
        <button id="reset" onclick="reset()" style="background-color: red; color: white">Reset data to defaults</button>
    </p>
</p>
This is the code that generates the chart:
<script>

    // This function converts day numbers to dates
    function day2date (num)
    {
        var ret = '';

        if (num < 31)  {ret = (num + 1) + '/01/17';return ret; 
        } else if (num < 59)  {ret = (num - 31 + 1) + '/02/17';return ret;
        } else if (num < 90)  {ret = (num - 59 + 1) + '/03/17';return ret;
        } else if (num < 120) {ret = (num - 90 + 1) + '/04/17';return ret;
        } else if (num < 151) {ret = (num - 120 + 1) + '/05/17';return ret;
        } else if (num < 181) {ret = (num - 151 + 1) + '/06/17';return ret;
        } else if (num < 212) {ret = (num - 181 + 1) + '/07/17';return ret;
        } else if (num < 243) {ret = (num - 212 + 1) + '/08/17';return ret;
        } else if (num < 273) {ret = (num - 243 + 1) + '/09/17';return ret;
        } else if (num < 304) {ret = (num - 273 + 1) + '/10/17';return ret;
        } else if (num < 334) {ret = (num - 304 + 1) + '/11/17';return ret;
        } else if (num < 365) {ret = (num - 334 + 1) + '/12/17';return ret;}
    }

    defaults = {};
    
    // This is the maximum value thats repesented on the chart.
    // Here it is 365 - ie one year
    defaults.max = 365;          

    // The labels for the chart
    defaults.labels = ['Jan', 'Feb', 'Mar', 'Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
        
        
    // Some colors
    defaults.background = '#cfc';
    defaults.foreground = '#0f0';

    // These are the defaults for a new event
    defaults.event = [0, 90, 0, 'No name',defaults.background, defaults.foreground]
    
        
    // This is the default data that is represented on the chart.
    // You could modify this to get this data from your database.
    defaults.data = load();  
    
    state = {
        selected: null
    };
    











    myGantt = new RGraph.Gantt({
        id: 'cvs',
        data: defaults.data,
        options: {
            xmax: defaults.max,
            gutterLeft: 100,
            gutterRight: 50,
            labels: defaults.labels,
            backgroundGridAutofitNumvlines: 12,
            borders: false,
            textSize: 18,
            adjustable: true,
            textAccessiblePointerevents: false
        }
    }).on('firstdraw', function (obj)
    {
        var gutterLeft = getLongestLabel(obj);
        
        obj.set('gutterLeft', gutterLeft);
        RGraph.cache = [];
        setTimeout(function () {RGraph.redraw();}, 25)
        
    }).draw().on('adjustend', function (obj)
    {
        var el = RGraph.Registry.get('chart.adjusting.gantt');

    }).on('adjust', function ()
    {
        save(myGantt.data);

        var el = RGraph.Registry.get('chart.adjusting.gantt');

        document.getElementById('name').value      = el.object.data[el.index][3];
        document.getElementById('startdate').value = day2date(el.object.data[el.index][0]);
        document.getElementById('duration').value  = el.object.data[el.index][1];
        document.getElementById('complete').value  = el.object.data[el.index][2];

    
    }).on('draw', function (obj)
    {
        if (typeof state.selected === 'number') {
            
            var index  = state.selected;
            var coords = obj.coords[index];

            RGraph.path2(
                obj.context,
                'b r % % % % s red',
                coords[0],
                coords[1],
                coords[2],
                coords[3]
            );
        }


    }).exec(function (obj)
    {
        obj.canvas.onmousedown = function (e)
        {
            var shape = obj.getShape(e);
            
            state.selected =  (shape && typeof shape.index === 'number') ? shape.index : null;
            
            RGraph.redraw();
        }
    });
    
    






    
    
    
    






    //
    // This function is where you would load the data from the server
    // using, for example, AJAX. By default it uses localData which
    // means that the data is persistent - but only to the one computer
    // and only the one browser.
    function load ()
    {
        if (localStorage['rgraph-gantt-chart-mini-app']) {
            return JSON.parse(localStorage['rgraph-gantt-chart-mini-app']);
        } else {
            return [
                [0, 59, 0, 'Richard',defaults.background, defaults.foreground],
                [28, 43, 70, 'Rachel', defaults.background, defaults.foreground],
                [43, 65, 0, 'Fred', defaults.background, defaults.foreground],
                [26, 31, 0, 'Jane', defaults.background, defaults.foreground],
                [143, 84, 0, 'John', defaults.background, defaults.foreground],
                [108, 100, 0, 'Lucy', defaults.background, defaults.foreground],
                [185, 68, 0, 'Carl', defaults.background, defaults.foreground],
                [303, 60, 0, 'Steven', defaults.background, defaults.foreground]
            ]
        }
    }
    
    
    






    //
    // This function is where you would send the data to the server
    // You could use the jQuery $.post() function to do this. Then you'd
    // need to write server-side script (egPHP, ASP) to take this post
    // data and save it into a database or file).
    function save ()
    {
        localStorage['rgraph-gantt-chart-mini-app'] = JSON.stringify(myGantt.data);
    }








    function addPerson ()
    {
        var name = prompt('Enter the persons name:','')
        
        if (name) {
            
            var event = RGraph.arrayClone(defaults.event);
            event[3] = name;

            myGantt.data.push(event);

            myGantt.set('gutterLeft', getLongestLabel(myGantt));
            

            save();
        
            reindex();
            
            
            RGraph.redraw();
        }
    }







    //
    // This deletes a person from the Gantt chart. It confirms it
    // but there is no backup!!
    //
    function deletePerson ()
    {
        if (confirm('Are you sure that you wish to delete this person?')) {
            myGantt.data[state.selected] = null;
            
            reindex();
            
            RGraph.redraw();
        }
    }
    
    
    
    
    
    
    
    // This functions goes through the gantt chart data and gets rid
    // of null values
    function reindex ()
    {
        var arr = [];

        for (var i=0; i<myGantt.data.length; ++i) {
            if (myGantt.data[i]) {
                arr.push(RGraph.arrayClone(myGantt.data[i]));
            }
        }
        
        myGantt.data = RGraph.arrayClone(arr);
        
        state.selected = null;
        
        save();

        myGantt.set('gutterLeft', Number(getLongestLabel()));
        
        RGraph.cache = [];

        RGraph.redraw();
    }
    
    
    
    
    
    function getLongestLabel ()
    {
        var obj = arguments[0] ? arguments[0] : myGantt;

        // Go through the data and get the size of the longest label
        for (var i=0,length = 0; i<obj.data.length; i++) {
            var length = Math.max(
                length,
                RGraph.MeasureText(obj.data[i][3], false, 'Arial', 18)[0]
            );
        }
        
        return length;
    }
    
    
    
    
    
    
    
    
    
    
    function updateComplete ()
    {
        var complete = parseInt(document.getElementById('complete').value);
        
        myGantt.data[state.selected][2] = Math.min(complete, 100);
        document.getElementById('complete').value = myGantt.data[state.selected][2];

        save();
        
        RGraph.redraw();
    }
    
    
    
    
    
    
    
    
    
    
    function updateName ()
    {
        var name = document.getElementById('name').value;
        
        myGantt.data[state.selected][3] = name;
        document.getElementById('name').value = name;

        save();
        
        RGraph.redraw();
    }
    
    
    
    
    
    
    
    
    
    function reset ()
    {
        if (confirm('Are you sure that you\'d like to reset the data to defaults?')) {
            
            localStorage['rgraph-gantt-chart-mini-app'] = '';
            
            myGantt.data = load();
            
            RGraph.redraw();
        }
    }











    myGantt.canvas.parentNode.style.display = 'inline-block';
</script>