source: Dev/branches/jQueryUI/client/RGraph/libraries/RGraph.gantt.js @ 249

Last change on this file since 249 was 249, checked in by hendrikvanantwerpen, 13 years ago

This one's for Subversion, because it's so close...

First widget (stripped down sequencer).
Seperated client and server code in two direcotry trees.

File size: 18.6 KB
Line 
17    /**
2    * o------------------------------------------------------------------------------o
3    * | This file is part of the RGraph package - you can learn more at:             |
4    * |                                                                              |
5    * |                          http://www.rgraph.net                               |
6    * |                                                                              |
7    * | This package is licensed under the RGraph license. For all kinds of business |
8    * | purposes there is a small one-time licensing fee to pay and for non          |
9    * | commercial  purposes it is free to use. You can read the full license here:  |
10    * |                                                                              |
11    * |                      http://www.rgraph.net/LICENSE.txt                       |
12    * o------------------------------------------------------------------------------o
13    */
14   
15    if (typeof(RGraph) == 'undefined') RGraph = {};
16
17    /**
18    * The gantt chart constructor
19    *
20    * @param object canvas The cxanvas object
21    * @param array  data   The chart data
22    */
23    RGraph.Gantt = function (id)
24    {
25        // Get the canvas and context objects
26        this.id      = id;
27        this.canvas  = document.getElementById(id);
28        this.context = this.canvas.getContext("2d");
29        this.canvas.__object__ = this;
30        this.type              = 'gantt';
31        this.isRGraph          = true;
32
33
34        /**
35        * Compatibility with older browsers
36        */
37        RGraph.OldBrowserCompat(this.context);
38
39       
40        // Set some defaults
41        this.properties = {
42            'chart.background.barcolor1':   'white',
43            'chart.background.barcolor2':   'white',
44            'chart.background.grid':        true,
45            'chart.background.grid.width':  1,
46            'chart.background.grid.color':  '#ddd',
47            'chart.background.grid.hsize':  20,
48            'chart.background.grid.vsize':  20,
49            'chart.background.grid.hlines': true,
50            'chart.background.grid.vlines': true,
51            'chart.background.grid.border': true,
52            'chart.background.grid.autofit':false,
53            'chart.background.grid.autofit.numhlines': 7,
54            'chart.background.grid.autofit.numvlines': 20,
55            'chart.background.vbars':       [],
56            'chart.text.size':              10,
57            'chart.text.font':              'Verdana',
58            'chart.text.color':             'black',
59            'chart.gutter.left':            75,
60            'chart.gutter.right':           25,
61            'chart.gutter.top':             35,
62            'chart.gutter.bottom':          25,
63            'chart.labels':                 [],
64            'chart.margin':                 2,
65            'chart.title':                  '',
66            'chart.title.background':       null,
67            'chart.title.hpos':             null,
68            'chart.title.vpos':             null,
69            'chart.title.yaxis':            '',
70            'chart.title.yaxis.pos':        this.canvas.width - 12.5,
71            'chart.title.yaxis.position':   'right',
72            'chart.events':                 [],
73            'chart.borders':                true,
74            'chart.defaultcolor':           'white',
75            'chart.coords':                 [],
76            'chart.tooltips':               [],
77            'chart.tooltips.effect':         'fade',
78            'chart.tooltips.css.class':      'RGraph_tooltip',
79            'chart.tooltips.highlight':     true,
80            'chart.highlight.stroke':       'black',
81            'chart.highlight.fill':         'rgba(255,255,255,0.5)',
82            'chart.xmin':                   0,
83            'chart.xmax':                   0,
84            'chart.contextmenu':            null,
85            'chart.annotatable':            false,
86            'chart.annotate.color':         'black',
87            'chart.zoom.factor':            1.5,
88            'chart.zoom.fade.in':           true,
89            'chart.zoom.fade.out':          true,
90            'chart.zoom.hdir':              'right',
91            'chart.zoom.vdir':              'down',
92            'chart.zoom.frames':            10,
93            'chart.zoom.delay':             50,
94            'chart.zoom.shadow':            true,
95            'chart.zoom.mode':              'canvas',
96            'chart.zoom.thumbnail.width':   75,
97            'chart.zoom.thumbnail.height':  75,
98            'chart.zoom.background':        true,
99            'chart.zoom.action':            'zoom',
100            'chart.resizable':              false,
101            'chart.resize.handle.adjust':   [0,0],
102            'chart.resize.handle.background': null,
103            'chart.adjustable':             false
104        }
105    }
106
107
108    /**
109    * A peudo setter
110    *
111    * @param name  string The name of the property to set
112    * @param value mixed  The value of the property
113    */
114    RGraph.Gantt.prototype.Set = function (name, value)
115    {
116        this.properties[name.toLowerCase()] = value;
117    }
118
119
120    /**
121    * A peudo getter
122    *
123    * @param name  string The name of the property to get
124    */
125    RGraph.Gantt.prototype.Get = function (name)
126    {
127        return this.properties[name.toLowerCase()];
128    }
129
130   
131    /**
132    * Draws the chart
133    */
134    RGraph.Gantt.prototype.Draw = function ()
135    {
136        /**
137        * Fire the onbeforedraw event
138        */
139        RGraph.FireCustomEvent(this, 'onbeforedraw');
140
141        /**
142        * Clear all of this canvases event handlers (the ones installed by RGraph)
143        */
144        RGraph.ClearEventListeners(this.id);
145       
146        /**
147        * This is new in May 2011 and facilitates indiviual gutter settings,
148        * eg chart.gutter.left
149        */
150        this.gutterLeft   = this.Get('chart.gutter.left');
151        this.gutterRight  = this.Get('chart.gutter.right');
152        this.gutterTop    = this.Get('chart.gutter.top');
153        this.gutterBottom = this.Get('chart.gutter.bottom');
154
155        /**
156        * Work out the graphArea
157        */
158        this.graphArea     = RGraph.GetWidth(this) - this.gutterLeft - this.gutterRight;
159        this.graphHeight   = RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom;
160        this.numEvents     = this.Get('chart.events').length
161        this.barHeight     = this.graphHeight / this.numEvents;
162        this.halfBarHeight = this.barHeight / 2;
163
164        /**
165        * Draw the background
166        */
167        RGraph.background.Draw(this);
168       
169        /**
170        * Draw a space for the left hand labels
171        */
172        //this.context.beginPath();
173            //this.context.lineWidth   = 1;
174            //this.context.strokeStyle = this.Get('chart.background.grid.color');
175            //this.context.fillStyle   = 'white';
176            //this.context.fillRect(0,gutter - 5,gutter * 3, RGraph.GetHeight(this) - (2 * gutter) + 10);
177            //this.context.moveTo(gutter * 3, gutter);
178            //this.context.lineTo(gutter * 3, RGraph.GetHeight(this) - gutter);
179        //this.context.stroke();
180        //this.context.fill();
181       
182        /**
183        * Draw the labels at the top
184        */
185        this.DrawLabels();
186       
187        /**
188        * Draw the events
189        */
190        this.DrawEvents();
191       
192       
193        /**
194        * Setup the context menu if required
195        */
196        if (this.Get('chart.contextmenu')) {
197            RGraph.ShowContext(this);
198        }
199       
200        /**
201        * If the canvas is annotatable, do install the event handlers
202        */
203        if (this.Get('chart.annotatable')) {
204            RGraph.Annotate(this);
205        }
206       
207        /**
208        * This bit shows the mini zoom window if requested
209        */
210        if (this.Get('chart.zoom.mode') == 'thumbnail' || this.Get('chart.zoom.mode') == 'area') {
211            RGraph.ShowZoomWindow(this);
212        }
213
214       
215        /**
216        * This function enables resizing
217        */
218        if (this.Get('chart.resizable')) {
219            RGraph.AllowResizing(this);
220        }
221
222
223        /**
224        * This function enables adjusting
225        */
226        if (this.Get('chart.adjustable')) {
227            RGraph.AllowAdjusting(this);
228        }
229
230
231        /**
232        * Fire the RGraph ondraw event
233        */
234        RGraph.FireCustomEvent(this, 'ondraw');
235    }
236
237   
238    /**
239    * Draws the labels at the top and the left of the chart
240    */
241    RGraph.Gantt.prototype.DrawLabels = function ()
242    {
243        this.context.beginPath();
244        this.context.fillStyle = this.Get('chart.text.color');
245
246        /**
247        * Draw the X labels at the top of the chart.
248        */
249        var labelSpace = (this.graphArea) / this.Get('chart.labels').length;
250        var xPos       = this.gutterLeft + (labelSpace / 2);
251        this.context.strokeStyle = 'black'
252
253        for (i=0; i<this.Get('chart.labels').length; ++i) {
254            RGraph.Text(this.context,this.Get('chart.text.font'),this.Get('chart.text.size'),xPos + (i * labelSpace),this.gutterTop - (this.Get('chart.text.size') / 2) - 5,String(this.Get('chart.labels')[i]),'center','center');
255        }
256       
257        // Draw the vertical labels
258        for (i=0; i<this.Get('chart.events').length; ++i) {
259            var ev = this.Get('chart.events')[i];
260            var x  = this.gutterLeft;
261            var y  = this.gutterTop + this.halfBarHeight + (i * this.barHeight);
262
263            RGraph.Text(this.context, this.Get('chart.text.font'), this.Get('chart.text.size'), x - 5, y, String(ev[3]), 'center', 'right');
264        }
265    }
266   
267    /**
268    * Draws the events to the canvas
269    */
270    RGraph.Gantt.prototype.DrawEvents = function ()
271    {
272        var canvas  = this.canvas;
273        var context = this.context;
274        var events  = this.Get('chart.events');
275
276        /**
277        * Reset the coords array to prevent it growing
278        */
279        this.coords = [];
280
281        /**
282        * First draw the vertical bars that have been added
283        */
284        if (this.Get('chart.vbars')) {
285            for (i=0; i<this.Get('chart.vbars').length; ++i) {
286                // Boundary checking
287                if (this.Get('chart.vbars')[i][0] + this.Get('chart.vbars')[i][1] > this.Get('chart.xmax')) {
288                    this.Get('chart.vbars')[i][1] = 364 - this.Get('chart.vbars')[i][0];
289                }
290   
291                var barX   = this.gutterLeft + (( (this.Get('chart.vbars')[i][0] - this.Get('chart.xmin')) / (this.Get('chart.xmax') - this.Get('chart.xmin')) ) * this.graphArea);
292
293                var barY   = this.gutterTop;
294                var width  = (this.graphArea / (this.Get('chart.xmax') - this.Get('chart.xmin')) ) * this.Get('chart.vbars')[i][1];
295                var height = RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom;
296               
297                // Right hand bounds checking
298                if ( (barX + width) > (RGraph.GetWidth(this) - this.gutterRight) ) {
299                    width = RGraph.GetWidth(this) - this.gutterRight - barX;
300                }
301   
302                context.fillStyle = this.Get('chart.vbars')[i][2];
303                context.fillRect(barX, barY, width, height);
304            }
305        }
306
307
308        /**
309        * Draw the events
310        */
311        for (i=0; i<events.length; ++i) {
312           
313            var ev  = events[i];
314            var min = this.Get('chart.xmin');
315
316            context.beginPath();
317            context.strokeStyle = 'black';
318            context.fillStyle = ev[4] ? ev[4] : this.Get('chart.defaultcolor');
319
320            var barStartX  = this.gutterLeft + (((ev[0] - min) / (this.Get('chart.xmax') - min)) * this.graphArea);
321            //barStartX += this.margin;
322            var barStartY  = this.gutterTop + (i * this.barHeight);
323            var barWidth   = (ev[1] / (this.Get('chart.xmax') - min) ) * this.graphArea;
324
325            /**
326            * If the width is greater than the graph atrea, curtail it
327            */
328            if ( (barStartX + barWidth) > (RGraph.GetWidth(this) - this.gutterRight) ) {
329                barWidth = RGraph.GetWidth(this) - this.gutterRight - barStartX;
330            }
331
332            /**
333            *  Draw the actual bar storing store the coordinates
334            */
335            this.coords.push([barStartX, barStartY + this.Get('chart.margin'), barWidth, this.barHeight - (2 * this.Get('chart.margin'))]);
336            context.fillRect(barStartX, barStartY + this.Get('chart.margin'), barWidth, this.barHeight - (2 * this.Get('chart.margin')) );
337
338            // Work out the completeage indicator
339            var complete = (ev[2] / 100) * barWidth;
340
341            // Draw the % complete indicator. If it's greater than 0
342            if (typeof(ev[2]) == 'number') {
343                context.beginPath();
344                context.fillStyle = ev[5] ? ev[5] : '#0c0';
345                context.fillRect(barStartX,
346                                      barStartY + this.Get('chart.margin'),
347                                      (ev[2] / 100) * barWidth,
348                                      this.barHeight - (2 * this.Get('chart.margin')) );
349               
350                context.beginPath();
351                context.fillStyle = this.Get('chart.text.color');
352                RGraph.Text(context, this.Get('chart.text.font'), this.Get('chart.text.size'), barStartX + barWidth + 5, barStartY + this.halfBarHeight, String(ev[2]) + '%', 'center');
353            }
354
355            // draw the border around the bar
356            if (this.Get('chart.borders') || events[i][6]) {
357                context.strokeStyle = typeof(events[i][6]) == 'string' ? events[i][6] : 'black';
358                context.lineWidth = (typeof(events[i][7]) == 'number' ? events[i][7] : 1);
359                context.beginPath();
360                context.strokeRect(barStartX, barStartY + this.Get('chart.margin'), barWidth, this.barHeight - (2 * this.Get('chart.margin')) );
361            }
362        }
363
364
365        /**
366        * If tooltips are defined, handle them
367        */
368        if (this.Get('chart.tooltips')) {
369
370            // Register the object for redrawing
371            RGraph.Register(this);
372
373            /**
374            * If the cursor is over a hotspot, change the cursor to a hand
375            */
376            var canvas_onmousemove_func = function (eventObj)
377            {
378                eventObj = RGraph.FixEventObject(eventObj);
379                var canvas = eventObj.target;
380                var obj    = canvas.__object__;
381                var len    = obj.coords.length;
382
383                /**
384                * Get the mouse X/Y coordinates
385                */
386                var mouseCoords = RGraph.getMouseXY(eventObj);
387
388                /**
389                * Loop through the bars determining if the mouse is over a bar
390                */
391                for (var i=0; i<len; i++) {
392
393                    var mouseX = mouseCoords[0];  // In relation to the canvas
394                    var mouseY = mouseCoords[1];  // In relation to the canvas
395                    var left   = obj.coords[i][0];
396                    var top    = obj.coords[i][1];
397                    var width  = obj.coords[i][2];
398                    var height = obj.coords[i][3];
399
400                    if (   mouseX >= left
401                        && mouseX <= (left + width)
402                        && mouseY >= top
403                        && mouseY <= (top + height)
404                        && (typeof(obj.Get('chart.tooltips')) == 'function' || obj.Get('chart.tooltips')[i]) ) {
405
406                        canvas.style.cursor = 'pointer';
407                        return;
408                    }
409                }
410
411                canvas.style.cursor = 'default';
412            }
413            this.canvas.addEventListener('mousemove', canvas_onmousemove_func, false);
414            RGraph.AddEventListener(this.id, 'mousemove', canvas_onmousemove_func);
415
416
417            var canvas_onclick_func = function (eventObj)
418            {
419                eventObj = RGraph.FixEventObject(eventObj);
420
421                var canvas  = eventObj.target;
422                var context = canvas.getContext('2d');
423                var obj     = canvas.__object__;
424
425                var mouseCoords = RGraph.getMouseXY(eventObj);
426                var mouseX      = mouseCoords[0];
427                var mouseY      = mouseCoords[1];
428               
429               
430                for (i=0; i<obj.coords.length; ++i) {
431                   
432                    var idx = i;
433                    var xCoord = obj.coords[i][0];
434                    var yCoord = obj.coords[i][1];
435                    var width  = obj.coords[i][2];
436                    var height = obj.coords[i][3];
437
438                    if (
439                           mouseX >= xCoord
440                        && (mouseX <= xCoord + width)
441                        && mouseY >= yCoord
442                        && (mouseY <= yCoord + height)
443                        && obj.Get('chart.tooltips')
444                       ) {
445
446                       // Redraw the graph
447                        RGraph.Redraw();
448
449                        /**
450                        * Get the tooltip text
451                        */
452                        if (typeof(obj.Get('chart.tooltips')) == 'function') {
453                            var text = obj.Get('chart.tooltips')(idx);
454                       
455                        } else if (typeof(obj.Get('chart.tooltips')) == 'object' && typeof(obj.Get('chart.tooltips')[idx]) == 'function') {
456                            var text = obj.Get('chart.tooltips')[idx](idx);
457                       
458                        } else if (typeof(obj.Get('chart.tooltips')) == 'object') {
459                            var text = obj.Get('chart.tooltips')[idx];
460
461                        } else {
462                            var text = null;
463                        }
464
465                        if (String(text).length && text != null) {
466
467                            // SHOW THE CORRECT TOOLTIP
468                            RGraph.Tooltip(canvas, text, eventObj.pageX, eventObj.pageY, idx);
469                           
470                            /**
471                            * Draw a rectangle around the correct bar, in effect highlighting it
472                            */
473                            context.strokeStyle = obj.Get('chart.highlight.stroke');
474                            context.fillStyle   = obj.Get('chart.highlight.fill');
475                            context.strokeRect(xCoord, yCoord, width, height);
476                            context.fillRect(xCoord, yCoord, width, height);
477   
478                            eventObj.stopPropagation();
479                        }
480                        return;
481                    }
482                }
483            }
484            this.canvas.addEventListener('click', canvas_onclick_func, false);
485            RGraph.AddEventListener(this.id, 'click', canvas_onclick_func);
486        }
487    }
Note: See TracBrowser for help on using the repository browser.