diff options
Diffstat (limited to 'schall/static/RGraph/libraries/RGraph.gantt.js')
-rw-r--r-- | schall/static/RGraph/libraries/RGraph.gantt.js | 514 |
1 files changed, 514 insertions, 0 deletions
diff --git a/schall/static/RGraph/libraries/RGraph.gantt.js b/schall/static/RGraph/libraries/RGraph.gantt.js new file mode 100644 index 0000000..1e0ae49 --- /dev/null +++ b/schall/static/RGraph/libraries/RGraph.gantt.js @@ -0,0 +1,514 @@ +7 /** + * o------------------------------------------------------------------------------o + * | This file is part of the RGraph package - you can learn more at: | + * | | + * | http://www.rgraph.net | + * | | + * | This package is licensed under the RGraph license. For all kinds of business | + * | purposes there is a small one-time licensing fee to pay and for non | + * | commercial purposes it is free to use. You can read the full license here: | + * | | + * | http://www.rgraph.net/LICENSE.txt | + * o------------------------------------------------------------------------------o + */ + + if (typeof(RGraph) == 'undefined') RGraph = {}; + + /** + * The gantt chart constructor + * + * @param object canvas The cxanvas object + * @param array data The chart data + */ + RGraph.Gantt = function (id) + { + // Get the canvas and context objects + this.id = id; + this.canvas = document.getElementById(id); + this.context = this.canvas.getContext("2d"); + this.canvas.__object__ = this; + this.type = 'gantt'; + this.isRGraph = true; + + + /** + * Compatibility with older browsers + */ + RGraph.OldBrowserCompat(this.context); + + + // Set some defaults + this.properties = { + 'chart.background.barcolor1': 'white', + 'chart.background.barcolor2': 'white', + 'chart.background.grid': true, + 'chart.background.grid.width': 1, + 'chart.background.grid.color': '#ddd', + 'chart.background.grid.hsize': 20, + 'chart.background.grid.vsize': 20, + 'chart.background.grid.hlines': true, + 'chart.background.grid.vlines': true, + 'chart.background.grid.border': true, + 'chart.background.grid.autofit':false, + 'chart.background.grid.autofit.numhlines': 7, + 'chart.background.grid.autofit.numvlines': 20, + 'chart.background.vbars': [], + 'chart.text.size': 10, + 'chart.text.font': 'Verdana', + 'chart.text.color': 'black', + 'chart.gutter.left': 75, + 'chart.gutter.right': 25, + 'chart.gutter.top': 35, + 'chart.gutter.bottom': 25, + 'chart.labels': [], + 'chart.margin': 2, + 'chart.title': '', + 'chart.title.background': null, + 'chart.title.hpos': null, + 'chart.title.vpos': null, + 'chart.title.bold': true, + 'chart.title.font': null, + 'chart.title.yaxis': '', + 'chart.title.yaxis.pos': null, + 'chart.title.yaxis.position': 'right', + 'chart.events': [], + 'chart.borders': true, + 'chart.defaultcolor': 'white', + 'chart.coords': [], + 'chart.tooltips': [], + 'chart.tooltips.effect': 'fade', + 'chart.tooltips.css.class': 'RGraph_tooltip', + 'chart.tooltips.highlight': true, + 'chart.highlight.stroke': 'black', + 'chart.highlight.fill': 'rgba(255,255,255,0.5)', + 'chart.xmin': 0, + 'chart.xmax': 0, + 'chart.contextmenu': null, + 'chart.annotatable': false, + 'chart.annotate.color': 'black', + 'chart.zoom.factor': 1.5, + 'chart.zoom.fade.in': true, + 'chart.zoom.fade.out': true, + 'chart.zoom.hdir': 'right', + 'chart.zoom.vdir': 'down', + 'chart.zoom.frames': 25, + 'chart.zoom.delay': 16.666, + 'chart.zoom.shadow': true, + 'chart.zoom.mode': 'canvas', + 'chart.zoom.thumbnail.width': 75, + 'chart.zoom.thumbnail.height': 75, + 'chart.zoom.background': true, + 'chart.zoom.action': 'zoom', + 'chart.resizable': false, + 'chart.resize.handle.adjust': [0,0], + 'chart.resize.handle.background': null, + 'chart.adjustable': false + } + + + /** + * Set the .getShape commonly named method + */ + this.getShape = this.getBar; + } + + + /** + * A peudo setter + * + * @param name string The name of the property to set + * @param value mixed The value of the property + */ + RGraph.Gantt.prototype.Set = function (name, value) + { + this.properties[name.toLowerCase()] = value; + } + + + /** + * A peudo getter + * + * @param name string The name of the property to get + */ + RGraph.Gantt.prototype.Get = function (name) + { + return this.properties[name.toLowerCase()]; + } + + + /** + * Draws the chart + */ + RGraph.Gantt.prototype.Draw = function () + { + /** + * Fire the onbeforedraw event + */ + RGraph.FireCustomEvent(this, 'onbeforedraw'); + + /** + * Clear all of this canvases event handlers (the ones installed by RGraph) + */ + RGraph.ClearEventListeners(this.id); + + /** + * This is new in May 2011 and facilitates indiviual gutter settings, + * eg chart.gutter.left + */ + this.gutterLeft = this.Get('chart.gutter.left'); + this.gutterRight = this.Get('chart.gutter.right'); + this.gutterTop = this.Get('chart.gutter.top'); + this.gutterBottom = this.Get('chart.gutter.bottom'); + + /** + * Work out the graphArea + */ + this.graphArea = this.canvas.width - this.gutterLeft - this.gutterRight; + this.graphHeight = this.canvas.height - this.gutterTop - this.gutterBottom; + this.numEvents = this.Get('chart.events').length + this.barHeight = this.graphHeight / this.numEvents; + this.halfBarHeight = this.barHeight / 2; + + /** + * Draw the background + */ + RGraph.background.Draw(this); + + /** + * Draw a space for the left hand labels + */ + //this.context.beginPath(); + //this.context.lineWidth = 1; + //this.context.strokeStyle = this.Get('chart.background.grid.color'); + //this.context.fillStyle = 'white'; + //this.context.fillRect(0,gutter - 5,gutter * 3, RGraph.GetHeight(this) - (2 * gutter) + 10); + //this.context.moveTo(gutter * 3, gutter); + //this.context.lineTo(gutter * 3, RGraph.GetHeight(this) - gutter); + //this.context.stroke(); + //this.context.fill(); + + /** + * Draw the labels at the top + */ + this.DrawLabels(); + + /** + * Draw the events + */ + this.DrawEvents(); + + + /** + * Setup the context menu if required + */ + if (this.Get('chart.contextmenu')) { + RGraph.ShowContext(this); + } + + /** + * If the canvas is annotatable, do install the event handlers + */ + if (this.Get('chart.annotatable')) { + RGraph.Annotate(this); + } + + /** + * This bit shows the mini zoom window if requested + */ + if (this.Get('chart.zoom.mode') == 'thumbnail' || this.Get('chart.zoom.mode') == 'area') { + RGraph.ShowZoomWindow(this); + } + + + /** + * This function enables resizing + */ + if (this.Get('chart.resizable')) { + RGraph.AllowResizing(this); + } + + + /** + * This function enables adjusting + */ + if (this.Get('chart.adjustable')) { + RGraph.AllowAdjusting(this); + } + + + /** + * Fire the RGraph ondraw event + */ + RGraph.FireCustomEvent(this, 'ondraw'); + } + + + /** + * Draws the labels at the top and the left of the chart + */ + RGraph.Gantt.prototype.DrawLabels = function () + { + this.context.beginPath(); + this.context.fillStyle = this.Get('chart.text.color'); + + /** + * Draw the X labels at the top of the chart. + */ + var labelSpace = (this.graphArea) / this.Get('chart.labels').length; + var xPos = this.gutterLeft + (labelSpace / 2); + this.context.strokeStyle = 'black' + + for (i=0; i<this.Get('chart.labels').length; ++i) { + 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'); + } + + // Draw the vertical labels + for (var i=0; i<this.Get('chart.events').length; ++i) { + var ev = this.Get('chart.events')[i]; + var x = this.gutterLeft; + var y = this.gutterTop + this.halfBarHeight + (i * this.barHeight); + + RGraph.Text(this.context, + this.Get('chart.text.font'), + this.Get('chart.text.size'), + x - 5, y, + RGraph.is_array(ev[0]) ? String(ev[0][3]) : String(ev[3]), + 'center', + 'right'); + } + } + + /** + * Draws the events to the canvas + */ + RGraph.Gantt.prototype.DrawEvents = function () + { + var canvas = this.canvas; + var context = this.context; + var events = this.Get('chart.events'); + + /** + * Reset the coords array to prevent it growing + */ + this.coords = []; + + /** + * First draw the vertical bars that have been added + */ + if (this.Get('chart.vbars')) { + for (i=0; i<this.Get('chart.vbars').length; ++i) { + // Boundary checking + if (this.Get('chart.vbars')[i][0] + this.Get('chart.vbars')[i][1] > this.Get('chart.xmax')) { + this.Get('chart.vbars')[i][1] = 364 - this.Get('chart.vbars')[i][0]; + } + + var barX = this.gutterLeft + (( (this.Get('chart.vbars')[i][0] - this.Get('chart.xmin')) / (this.Get('chart.xmax') - this.Get('chart.xmin')) ) * this.graphArea); + + var barY = this.gutterTop; + var width = (this.graphArea / (this.Get('chart.xmax') - this.Get('chart.xmin')) ) * this.Get('chart.vbars')[i][1]; + var height = RGraph.GetHeight(this) - this.gutterTop - this.gutterBottom; + + // Right hand bounds checking + if ( (barX + width) > (RGraph.GetWidth(this) - this.gutterRight) ) { + width = RGraph.GetWidth(this) - this.gutterRight - barX; + } + + context.fillStyle = this.Get('chart.vbars')[i][2]; + context.fillRect(barX, barY, width, height); + } + } + + + /** + * Draw the events + */ + for (i=0; i<events.length; ++i) { + if (typeof(events[i][0]) == 'number') { + this.DrawSingleEvent(events[i]); + } else { + for (var j=0; j<events[i].length; ++j) { + this.DrawSingleEvent(events[i][j]); + } + } + + } + + + /** + * If tooltips are defined, handle them + */ + if (this.Get('chart.tooltips')) { + + // Register the object for redrawing + RGraph.Register(this); + + /** + * If the cursor is over a hotspot, change the cursor to a hand + */ + var canvas_onmousemove_func = function (eventObj) + { + eventObj = RGraph.FixEventObject(eventObj); + var canvas = eventObj.target; + var obj = canvas.__object__; + var len = obj.coords.length; + var mouseCoords = RGraph.getMouseXY(eventObj); + var bar = obj.getBar(eventObj); + + /** + * Loop through the bars determining if the mouse is over a bar + */ + if (bar) { + canvas.style.cursor = 'pointer'; + return; + } + + canvas.style.cursor = 'default'; + } + this.canvas.addEventListener('mousemove', canvas_onmousemove_func, false); + RGraph.AddEventListener(this.id, 'mousemove', canvas_onmousemove_func); + + + var canvas_onclick_func = function (eventObj) + { + eventObj = RGraph.FixEventObject(eventObj); + + var canvas = eventObj.target; + var context = canvas.getContext('2d'); + var obj = canvas.__object__; + var mouseCoords = RGraph.getMouseXY(eventObj); + var mouseX = mouseCoords[0]; + var mouseY = mouseCoords[1]; + var bar = obj.getBar(eventObj); + + if (bar) { + + var idx = bar[5]; + + // Redraw the graph + RGraph.Redraw(); + + // Get the tooltip text + var text = RGraph.parseTooltipText(obj.Get('chart.tooltips'), idx); + + if (String(text).length && text != '') { + + // SHOW THE CORRECT TOOLTIP + RGraph.Tooltip(canvas, text, eventObj.pageX, eventObj.pageY, idx); + + /** + * Draw a rectangle around the correct bar, in effect highlighting it + */ + + context.lineWidth = 1; + context.strokeStyle = obj.Get('chart.highlight.stroke'); + context.fillStyle = obj.Get('chart.highlight.fill'); + context.strokeRect(bar[1], bar[2], bar[3], bar[4]); + context.fillRect(bar[1], bar[2], bar[3], bar[4]); + + eventObj.stopPropagation(); + } + + return; + } + } + this.canvas.addEventListener('click', canvas_onclick_func, false); + RGraph.AddEventListener(this.id, 'click', canvas_onclick_func); + } + } + + + /** + * Retrieves the bar (if any) that has been click on or is hovered over + * + * @param object e The event object + */ + RGraph.Gantt.prototype.getBar = function (e) + { + e = RGraph.FixEventObject(e); + + var canvas = e.target; + var context = canvas.getContext('2d'); + var obj = canvas.__object__; + var mouseCoords = RGraph.getMouseXY(e); + var mouseX = mouseCoords[0]; + var mouseY = mouseCoords[1]; + var coords = obj.coords; + + /** + * Loop through the bars determining if the mouse is over a bar + */ + for (var i=0; i<coords.length; i++) { + + var left = coords[i][0]; + var top = coords[i][1]; + var width = coords[i][2]; + var height = coords[i][3]; + + if ( mouseX >= left + && mouseX <= (left + width) + && mouseY >= top + && mouseY <= (top + height) + && (typeof(obj.Get('chart.tooltips')) == 'function' || obj.Get('chart.tooltips')[i]) ) { + + return [obj, left, top, width, height, i]; + } + } + } + + + /** + * Draws a single event + */ + RGraph.Gantt.prototype.DrawSingleEvent = function () + { + var min = this.Get('chart.xmin'); + var context = this.context; + var ev = RGraph.array_clone(arguments[0]); + + context.beginPath(); + context.strokeStyle = 'black'; + context.fillStyle = ev[4] ? ev[4] : this.Get('chart.defaultcolor'); + + var barStartX = this.gutterLeft + (((ev[0] - min) / (this.Get('chart.xmax') - min)) * this.graphArea); + //barStartX += this.margin; + var barStartY = this.gutterTop + (i * this.barHeight); + var barWidth = (ev[1] / (this.Get('chart.xmax') - min) ) * this.graphArea; + + /** + * If the width is greater than the graph atrea, curtail it + */ + if ( (barStartX + barWidth) > (RGraph.GetWidth(this) - this.gutterRight) ) { + barWidth = RGraph.GetWidth(this) - this.gutterRight - barStartX; + } + + /** + * Draw the actual bar storing store the coordinates + */ + this.coords.push([barStartX, barStartY + this.Get('chart.margin'), barWidth, this.barHeight - (2 * this.Get('chart.margin'))]); + context.fillRect(barStartX, barStartY + this.Get('chart.margin'), barWidth, this.barHeight - (2 * this.Get('chart.margin')) ); + + // Work out the completeage indicator + var complete = (ev[2] / 100) * barWidth; + + // Draw the % complete indicator. If it's greater than 0 + if (typeof(ev[2]) == 'number') { + context.beginPath(); + context.fillStyle = ev[5] ? ev[5] : '#0c0'; + context.fillRect(barStartX, + barStartY + this.Get('chart.margin'), + (ev[2] / 100) * barWidth, + this.barHeight - (2 * this.Get('chart.margin')) ); + + context.beginPath(); + context.fillStyle = this.Get('chart.text.color'); + RGraph.Text(context, this.Get('chart.text.font'), this.Get('chart.text.size'), barStartX + barWidth + 5, barStartY + this.halfBarHeight, String(ev[2]) + '%', 'center'); + } + + // draw the border around the bar + if (this.Get('chart.borders') || ev[6]) { + context.strokeStyle = typeof(ev[6]) == 'string' ? ev[6] : 'black'; + context.lineWidth = (typeof(ev[7]) == 'number' ? ev[7] : 1); + context.beginPath(); + context.strokeRect(barStartX, barStartY + this.Get('chart.margin'), barWidth, this.barHeight - (2 * this.Get('chart.margin')) ); + } + }
\ No newline at end of file |