# 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:

- Incorporate a notes field. These notes would be added to the Gantt chart data (the Gantt chart would ignore the extra data).
- Do away with the update buttons and have the data automatically saved using the onkeyup event.

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.

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>