source: Dev/branches/rest-dojo-ui/jQueryUI/client/RGraph/libraries/RGraph.gantt.js @ 312

Last change on this file since 312 was 312, checked in by jkraaijeveld, 13 years ago
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.