// version: 2014-08-16 /** * 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 Creative Commons BY-NC license. That means | * | that for non-commercial purposes it's free to use and for business use there's | * | a 99 GBP per-company fee to pay. You can read the full license here: | * | | * | http://www.rgraph.net/license | * o--------------------------------------------------------------------------------o */ RGraph = window.RGraph || {isRGraph: true}; /** * The chart constuctor * * @param object canvas * @param array data */ RGraph.RScatter = RGraph.Rscatter = function (conf) { /** * Allow for object config style */ if ( typeof conf === 'object' && typeof conf.data === 'object' && typeof conf.id === 'string') { var parseConfObjectForOptions = true; // Set this so the config is parsed (at the end of the constructor) this.data = new Array(conf.data.length); // Store the data set(s) this.data = RGraph.arrayClone(conf.data); // Account for just one dataset being given if (typeof conf.data === 'object' && typeof conf.data[0] === 'object' && typeof conf.data[0][0] === 'number') { var tmp = RGraph.arrayClone(conf.data); conf.data = new Array(); conf.data[0] = RGraph.arrayClone(tmp); this.data = RGraph.arrayClone(conf.data); } } else { var conf = {id: conf}; conf.data = arguments[1]; this.data = []; // Handle multiple datasets being given as one argument if (arguments[1][0] && arguments[1][0][0] && typeof arguments[1][0][0] == 'object') { // Store the data set(s) for (var i=0; i 0 && prop['chart.key'].length >= 3) { this.centerx = this.centerx - prop['chart.gutter.right'] + 5; } /** * Populate the colors array for the purposes of generating the key */ if (typeof(prop['chart.key']) == 'object' && RG.is_array(prop['chart.key']) && prop['chart.key'][0]) { // Reset the colors array prop['chart.colors'] = []; for (var i=0; i -1) RG.Text2(this, {'tag': 'scale','font':font,'size':size,'x':centerx,'y':centery - (r * ((i+1) / len)),'text':this.scale2.labels[i],'valign':'center','halign':'center','bounding':true,'boundingFill':color}); if (axes.indexOf('s') > -1) RG.Text2(this, {'tag': 'scale','font':font,'size':size,'x':centerx,'y':centery + (r * ((i+1) / len)),'text':this.scale2.labels[i],'valign':'center','halign':'center','bounding':true,'boundingFill':color}); if (axes.indexOf('e') > -1) RG.Text2(this, {'tag': 'scale','font':font,'size':size,'x':centerx + (r * ((i+1) / len)),'y':centery,'text':this.scale2.labels[i],'valign':'center','halign':'center','bounding':true,'boundingFill':color}); if (axes.indexOf('w') > -1) RG.Text2(this, {'tag': 'scale','font':font,'size':size,'x':centerx - (r * ((i+1) / len)),'y':centery,'text':this.scale2.labels[i],'valign':'center','halign':'center','bounding':true,'boundingFill':color}); } // Draw the center minimum value (but only if there's at least one axes labels stipulated) if (prop['chart.labels.axes'].length > 0) { RG.Text2(this, {'font':font, 'size':size, 'x':centerx, 'y':centery, 'text':RG.number_format(this, Number(this.scale2.min).toFixed(this.scale2.decimals), this.scale2.units_pre, this.scale2.units_post), 'valign':'center', 'halign':'center', 'bounding':true, 'boundingFill':color, 'tag': 'scale' }); } /** * Draw the key */ if (key && key.length) { RG.DrawKey(this, key, prop['chart.colors']); } }; /** * Draws the circular labels that go around the charts * * @param labels array The labels that go around the chart */ this.drawCircularLabels = this.DrawCircularLabels = function (context, labels, font_face, font_size, r) { var position = prop['chart.labels.position']; var r = r + 10; for (var i=0; i (x - offset) && mouseY < (y + offset) && mouseY > (y - offset) ) { var tooltip = RG.parseTooltipText(prop['chart.tooltips'], i); return {0:this,1:x,2:y,3:i,'object':this, 'x':x, 'y':y, 'index':i, 'tooltip': tooltip}; } } }; /** * This function facilitates the installation of tooltip event listeners if * tooltips are defined. */ this.allowTooltips = this.AllowTooltips = function () { // Preload any tooltip images that are used in the tooltips RG.PreLoadTooltipImages(this); /** * This installs the window mousedown event listener that lears any * highlight that may be visible. */ RG.InstallWindowMousedownTooltipListener(this); /** * This installs the canvas mousemove event listener. This function * controls the pointer shape. */ RG.InstallCanvasMousemoveTooltipListener(this); /** * This installs the canvas mouseup event listener. This is the * function that actually shows the appropriate tooltip (if any). */ RG.InstallCanvasMouseupTooltipListener(this); }; /** * Each object type has its own Highlight() function which highlights the appropriate shape * * @param object shape The shape to highlight */ this.highlight = this.Highlight = function (shape) { // Add the new highlight RG.Highlight.Point(this, shape); }; /** * The getObjectByXY() worker method. Don't call this call: * * RGraph.ObjectRegistry.getObjectByXY(e) * * @param object e The event object */ this.getObjectByXY = function (e) { var mouseXY = RG.getMouseXY(e); var mouseX = mouseXY[0]; var mouseY = mouseXY[1]; var centerx = this.centerx; var centery = this.centery; var radius = this.radius; if ( mouseX > (centerx - radius) && mouseX < (centerx + radius) && mouseY > (centery - radius) && mouseY < (centery + radius) ) { return this; } }; /** * This function positions a tooltip when it is displayed * * @param obj object The chart object * @param int x The X coordinate specified for the tooltip * @param int y The Y coordinate specified for the tooltip * @param objec tooltip The tooltips DIV element */ this.positionTooltip = function (obj, x, y, tooltip, idx) { var coordX = obj.coords[tooltip.__index__][0]; var coordY = obj.coords[tooltip.__index__][1]; var canvasXY = RG.getCanvasXY(obj.canvas); var gutterLeft = obj.gutterLeft; var gutterTop = obj.gutterTop; var width = tooltip.offsetWidth; // Set the top position tooltip.style.left = 0; tooltip.style.top = parseInt(tooltip.style.top) - 7 + 'px'; // By default any overflow is hidden tooltip.style.overflow = ''; // The arrow var img = new Image(); img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAFCAYAAACjKgd3AAAARUlEQVQYV2NkQAN79+797+RkhC4M5+/bd47B2dmZEVkBCgcmgcsgbAaA9GA1BCSBbhAuA/AagmwQPgMIGgIzCD0M0AMMAEFVIAa6UQgcAAAAAElFTkSuQmCC'; img.style.position = 'absolute'; img.id = '__rgraph_tooltip_pointer__'; img.style.top = (tooltip.offsetHeight - 2) + 'px'; tooltip.appendChild(img); // Reposition the tooltip if at the edges: // LEFT edge if ((canvasXY[0] + coordX - (width / 2)) < 10) { tooltip.style.left = (canvasXY[0] + coordX - (width * 0.1)) + 'px'; img.style.left = ((width * 0.1) - 8.5) + 'px'; // RIGHT edge } else if ((canvasXY[0] + coordX + (width / 2)) > doc.body.offsetWidth) { tooltip.style.left = canvasXY[0] + coordX - (width * 0.9) + 'px'; img.style.left = ((width * 0.9) - 8.5) + 'px'; // Default positioning - CENTERED } else { tooltip.style.left = (canvasXY[0] + coordX - (width * 0.5)) + 'px'; img.style.left = ((width * 0.5) - 8.5) + 'px'; } }; /** * This function returns the radius (ie the distance from the center) for a particular * value. * * @param number value The value you want the radius for */ this.getRadius = function (value) { var max = this.max; if (value < 0 || value > max) { return null; } var r = (value / max) * this.radius; return r; }; /** * This allows for easy specification of gradients */ this.parseColors = function () { // Save the original colors so that they can be restored when the canvas is reset if (this.original_colors.length === 0) { this.original_colors['data'] = RG.array_clone(this.data); this.original_colors['chart.highlight.stroke'] = RG.array_clone(prop['chart.highlight.stroke']); this.original_colors['chart.highlight.fill'] = RG.array_clone(prop['chart.highlight.fill']); this.original_colors['chart.colors.default'] = RG.array_clone(prop['chart.colors.default']); } // Go through the data for (var i=0; i