1 /* 2 * Copyright (c) 2012-2016 LabKey Corporation 3 * 4 * Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0 5 */ 6 7 if(!LABKEY.vis.Geom){ 8 /** 9 * @namespace The Geom namespace. Used for all geoms, such as {@link LABKEY.vis.Geom.Point}, 10 * {@link LABKEY.vis.Geom.Path}, etc. 11 */ 12 LABKEY.vis.Geom = {}; 13 } 14 15 /** 16 * @class The base XY geom. Extended by all geoms that will be plotted on a grid using a Cartesian [X,Y] coordinate system. 17 * This is a base class meant to be used internally only. 18 */ 19 LABKEY.vis.Geom.XY = function(){ 20 this.type = "XY"; 21 this.xAes = null; 22 this.yAes = null; 23 this.typeSubtypeAes = null; 24 this.parentNameAes = null; 25 this.childNameAes = null; 26 this.xScale = null; 27 this.yScale = null; 28 this.colorAes = null; 29 this.colorScale = null; 30 return this; 31 }; 32 LABKEY.vis.Geom.XY.prototype.initAesthetics = function(scales, layerAes, parentAes, layerName, index){ 33 this.layerName = layerName; 34 this.index = index; 35 36 if(layerAes.x){ 37 this.xAes = layerAes.x; 38 this.xScale = scales.x; 39 } else if(layerAes.xTop){ 40 this.xAes = layerAes.xTop; 41 this.xScale = scales.xTop; 42 } else if(parentAes.x){ 43 this.xAes = parentAes.x; 44 this.xScale = scales.x; 45 } else if(parentAes.xTop){ 46 this.xAes = parentAes.xTop; 47 this.xScale = scales.xTop; 48 } 49 50 if(!this.xAes){ 51 console.error('x aesthetic is required for ' + this.type + ' geom to render.'); 52 return false; 53 } 54 55 if(layerAes.yLeft){ 56 this.yAes = layerAes.yLeft; 57 this.yScale = scales.yLeft; 58 } else if(layerAes.yRight){ 59 this.yAes = layerAes.yRight; 60 this.yScale = scales.yRight; 61 } else if(parentAes.yLeft){ 62 this.yAes = parentAes.yLeft; 63 this.yScale = scales.yLeft; 64 } else if(parentAes.yRight){ 65 this.yAes = parentAes.yRight; 66 this.yScale = scales.yRight; 67 } 68 69 this.colorAes = layerAes.color ? layerAes.color : parentAes.color; 70 this.colorScale = scales.color ? scales.color : null; 71 72 if(!this.yAes){ 73 console.error('y aesthetic is required for ' + this.type + ' geom to render.'); 74 return false; 75 } 76 77 if (parentAes.typeSubtype) { 78 this.typeSubtypeAes = parentAes.typeSubtype; 79 } 80 81 if (parentAes.parentName) { 82 this.parentNameAes = parentAes.parentName; 83 } 84 85 if (parentAes.childName) { 86 this.childNameAes = parentAes.childName; 87 } 88 89 return true; 90 }; 91 92 LABKEY.vis.Geom.XY.prototype.getVal = function(scale, map, row, isY){ 93 // Takes a row, returns the scaled y value. 94 var value = map.getValue(row); 95 96 if(!LABKEY.vis.isValid(value)){ 97 if(this.plotNullPoints){ 98 return isY ? scale(scale.domain()[0]) + 5 : scale(scale.domain()[0]) - 5; 99 } else { 100 return null; 101 } 102 } else { 103 return scale(value); 104 } 105 }; 106 107 LABKEY.vis.Geom.XY.prototype.getX = function(row){ 108 // Takes a row, returns the scaled x value. 109 return this.getVal(this.xScale.scale, this.xAes, row, false); 110 }; 111 112 LABKEY.vis.Geom.XY.prototype.getY = function(row){ 113 // Takes a row, returns the scaled y value. 114 return this.getVal(this.yScale.scale, this.yAes, row, true); 115 }; 116 117 LABKEY.vis.Geom.XY.prototype.getTypeSubtype = function(row){ 118 // Takes a row, returns the scaled y value. 119 return this.getVal(this.yScale.scale, this.typeSubtypeAes, row, true); 120 }; 121 122 LABKEY.vis.Geom.XY.prototype.getParentY = function(row){ 123 // Takes a row, returns the scaled parent name value. 124 return this.getVal(this.yScale.scale, this.parentNameAes, row, true); 125 }; 126 127 /** 128 * @class The Point geom, used to generate points of data on a plot such as points on a line or points in a scatter plot. 129 * This geom supports the use of size, color, shape, hoverText, and pointClickFn aesthetics from the 130 * {@link LABKEY.vis.Layer} and/or {@link LABKEY.vis.Plot} objects. 131 * @param {Object} config An object with the following properties: 132 * @param {String} [config.color] (Optional) String used to determine the color of all points. Defaults to black (#000000). 133 * @param {Number} [config.size] (Optional) Number used to determine the size of all points. Defaults to 5. 134 * @param {Number} [config.opacity] (Optional) Number between 0 and 1, used to determine the opacity of all points. Useful if 135 * there are overlapping points in the data. Defaults to 1. 136 * @param {Boolean} [config.plotNullPoints] (Optional) Used to toggle whether or not a row of data with the value of null will be 137 * plotted. If true null or undefined values will be plotted just outside the axis with data. For example if a 138 * row of data looks like {x: 50, y: null} the point would appear at 50 on the x-axis, and just below the x axis. 139 * If both x and y values are null the point will be drawn to the bottom left of the origin. Defaults to false. 140 * @param {String} [config.position] (Optional) String with possible value "jitter". If config.position is "jitter" and the 141 * x or y scale is discrete it will be moved just before or after the position on the grid by a random amount. 142 * Useful if there is overlapping data. Defaults to undefined. 143 */ 144 LABKEY.vis.Geom.Point = function(config){ 145 this.type = "Point"; 146 147 if(!config){ 148 config = {}; 149 } 150 this.color = ('color' in config && config.color != null && config.color != undefined) ? config.color : '#000000'; 151 this.size = ('size' in config && config.size != null && config.size != undefined) ? config.size : 5; 152 this.opacity = ('opacity' in config && config.opacity != null && config.opacity != undefined) ? config.opacity : 1; 153 this.plotNullPoints = ('plotNullPoints' in config && config.plotNullPoints != null && config.plotNullPoints != undefined) ? config.plotNullPoints : false; 154 this.position = ('position' in config && config.position != null && config.position != undefined) ? config.position : null; 155 156 return this; 157 }; 158 LABKEY.vis.Geom.Point.prototype = new LABKEY.vis.Geom.XY(); 159 LABKEY.vis.Geom.Point.prototype.render = function(renderer, grid, scales, data, layerAes, parentAes, name, index){ 160 if(!this.initAesthetics(scales, layerAes, parentAes, name, index)){ 161 return false; 162 } 163 164 this.shapeAes = layerAes.shape ? layerAes.shape : parentAes.shape; 165 this.shapeScale = scales.shape; 166 this.sizeAes = layerAes.size ? layerAes.size : parentAes.size; 167 this.sizeScale = scales.size; 168 this.hoverTextAes = layerAes.hoverText ? layerAes.hoverText : parentAes.hoverText; 169 this.pointClickFnAes = layerAes.pointClickFn ? layerAes.pointClickFn : parentAes.pointClickFn; 170 this.mouseOverFnAes = layerAes.mouseOverFn ? layerAes.mouseOverFn : parentAes.mouseOverFn; 171 this.mouseOutFnAes = layerAes.mouseOutFn ? layerAes.mouseOutFn : parentAes.mouseOutFn; 172 this.mouseUpFnAes = layerAes.mouseUpFn ? layerAes.mouseUpFn : parentAes.mouseUpFn; 173 174 renderer.renderPointGeom(data, this); 175 return true; 176 }; 177 178 /** 179 * @private 180 * @class The Bin geom, used to bin a set of data and generate a plot of binned points. Currently, under development and not for external use. Normally, this is used for scatter x-y based data. 181 * @param config 182 * @returns {LABKEY.vis.Geom.Bin} 183 * @constructor 184 */ 185 LABKEY.vis.Geom.Bin = function(config) { 186 this.type = "Bin"; 187 188 if (!config) { 189 config = {}; 190 } 191 192 this.shape = ('shape' in config && config.shape != null && config.shape != undefined) ? config.shape : 'hex'; 193 this.colorDomain = ('colorDomain' in config && config.colorDomain != null && config.colorDomain != undefined) ? config.colorDomain : undefined; 194 this.colorRange = ('colorRange' in config && config.colorRange != null && config.colorRange != undefined) ? config.colorRange : ["#e6e6e6", "#085D90"]; // lightish-gray -> labkey blue 195 this.size = ('size' in config && config.size != null && config.size != undefined) ? config.size : 5; 196 this.plotNullPoints = ('plotNullPoints' in config && config.plotNullPoints != null && config.plotNullPoints != undefined) ? config.plotNullPoints : false; 197 198 return this; 199 }; 200 LABKEY.vis.Geom.Bin.prototype = new LABKEY.vis.Geom.XY(); 201 LABKEY.vis.Geom.Bin.prototype.render = function(renderer, grid, scales, data, layerAes, parentAes, name, index){ 202 if(!this.initAesthetics(scales, layerAes, parentAes, name, index)){ 203 return false; 204 } 205 206 this.mouseOverFnAes = layerAes.mouseOverFn ? layerAes.mouseOverFn : parentAes.mouseOverFn; 207 this.mouseOutFnAes = layerAes.mouseOutFn ? layerAes.mouseOutFn : parentAes.mouseOutFn; 208 this.mouseUpFnAes = layerAes.mouseUpFn ? layerAes.mouseUpFn : parentAes.mouseUpFn; 209 210 renderer.renderBinGeom(data, this); 211 return true; 212 }; 213 214 /** 215 * @class The path geom, used to draw paths in a plot. In order to get multiple lines for a set of data the user must define an 216 * accessor with the name "group" in the config.aes object of the {LABKEY.vis.Plot} or {LABKEY.vis.Layer} object. For 217 * example if the data looked like {x: 12, y: 35, name: "Alan"} the config.aes.group accessor could be "Alan", or a 218 * function: function(row){return row.name}. Each unique name would get a separate line. The geom also supports color 219 * and size aesthetics from the {LABKEY.vis.Plot} and/or {LABKEY.vis.Layer} objects. 220 * @param {Object} config An object with the following properties: 221 * @param {String} [config.color] (Optional) String used to determine the color of all paths. Defaults to black (#000000). 222 * @param {Number} [config.size] (Optional) Number used to determine the size of all paths. Defaults to 3. 223 * @param {Number} [config.opacity] (Optional) Number between 0 and 1, used to determine the opacity of all paths. Useful 224 * if there are many overlapping paths. Defaults to 1. 225 */ 226 LABKEY.vis.Geom.Path = function(config){ 227 this.type = "Path"; 228 229 if(!config){ 230 config = {}; 231 } 232 this.color = ('color' in config && config.color != null && config.color != undefined) ? config.color : '#000000'; 233 this.size = ('size' in config && config.size != null && config.size != undefined) ? config.size : 3; 234 this.opacity = ('opacity' in config && config.opacity != null && config.opacity != undefined) ? config.opacity : 1; 235 236 return this; 237 }; 238 LABKEY.vis.Geom.Path.prototype = new LABKEY.vis.Geom.XY(); 239 LABKEY.vis.Geom.Path.prototype.render = function(renderer, grid, scales, data, layerAes, parentAes, name, index){ 240 if(!this.initAesthetics(scales, layerAes, parentAes, name, index)){ 241 return false; 242 } 243 244 this.groupAes = layerAes.group ? layerAes.group : parentAes.group; 245 this.sizeAes = layerAes.size ? layerAes.size : parentAes.size; 246 this.pathColorAes = layerAes.pathColor ? layerAes.pathColor : parentAes.pathColor; 247 this.sizeScale = scales.size; 248 249 renderer.renderPathGeom(data, this); 250 return true; 251 }; 252 253 /** 254 * @class Error bar geom. Generally used in conjunction with a {@link LABKEY.vis.Geom.Point} and/or {@link LABKEY.vis.Geom.Path} 255 * geom to show the known amount of error for a given point. In order to work the user must specify an error accessor 256 * in the config.aes object of the {LABKEY.vis.Plot} or {LABKEY.vis.Layer} object. This Geom also supports the color 257 * aesthetic from the {LABKEY.vis.Plot} and/or {LABKEY.vis.Layer} objects. 258 * @param config An object with the following properties: 259 * @param {String} [config.color] (Optional) String used to determine the color of all paths. Defaults to black (#000000). 260 * @param {Number} [config.size] (Optional) Number used to determine the size of all paths. Defaults to 2. 261 * @param {Boolean} [config.dashed] (Optional) Whether or not to use dashed lines for top and bottom bars. Defaults to false. 262 * @param {String} [config.altColor] (Optional) String used to determine the color of the vertical bar. Defaults to config.color. 263 */ 264 LABKEY.vis.Geom.ErrorBar = function(config){ 265 this.type = "ErrorBar"; 266 267 if(!config){ 268 config = {}; 269 } 270 this.color = ('color' in config && config.color != null && config.color != undefined) ? config.color : '#000000'; 271 this.size = ('size' in config && config.size != null && config.size != undefined) ? config.size : 2; 272 this.dashed = ('dashed' in config && config.dashed != null && config.dashed != undefined) ? config.dashed : false; 273 this.altColor = ('altColor' in config && config.altColor != null && config.altColor != undefined) ? config.altColor : null; 274 this.width = ('width' in config && config.width != null && config.width != undefined) ? config.width : 6; 275 276 return this; 277 }; 278 LABKEY.vis.Geom.ErrorBar.prototype = new LABKEY.vis.Geom.XY(); 279 LABKEY.vis.Geom.ErrorBar.prototype.render = function(renderer, grid, scales, data, layerAes, parentAes, name, index){ 280 if(!this.initAesthetics(scales, layerAes, parentAes, name, index)){ 281 return false; 282 } 283 284 this.errorAes = layerAes.error ? layerAes.error : parentAes.error; 285 286 if (!this.errorAes) { 287 console.error("The error aesthetic is required for the ErrorBar geom."); 288 return false; 289 } 290 291 renderer.renderErrorBarGeom(data, this); 292 return true; 293 }; 294 295 296 /** 297 * @class The Boxplot Geom, used to generate box plots for a given set of data. In order to get multiple box plots for a set of 298 * data with a continuous x-axis scale, the user must define an accessor with the name "group" in the config.aes object 299 * of the {LABKEY.vis.Plot} or {LABKEY.vis.Layer} object. For example if the data looked like {x: 12, y: 35, name: "Alan"} 300 * the config.aes.group accessor could be "Alan", or a function: function(row){return row.name}. Each unique name would 301 * get a separate box plot. If aes.group is not present one boxplot will be generated for all of the data. This geom 302 * also supports the outlierColor, outlierShape, hoverText, outlierHoverText, and pointClickFn aesthetics from the 303 * {LABKEY.vis.Plot} and/or {LABKEY.vis.Layer} objects. 304 * 305 * Boxplots are drawn as follows: 306 * <ul> 307 * <li>The top line of the box is the first quartile (Q1)</li> 308 * <li>The middle like is the second quartile (Q2, aka median)</li> 309 * <li>The bottom line is the third quartile (Q3)</li> 310 * <li>The whiskers extend to 3/2 times the inner quartile range (Q3 - Q1, aka IQR)</li> 311 * <li>All data points that are greater than 3/2 times the IQR are drawn as outliers</li> 312 * </ul> 313 * 314 * @param {Object} config An object with the following properties: 315 * @param {String} [config.color] (Optional) A string value used for the line colors in the box plot. Defaults to black 316 * (#000000) 317 * @param {String} [config.fill] (Optional) A string value used for the fill color in the box plot. Defaults to white 318 * (#ffffff) 319 * @param {Number} [config.lineWidth] (Optional) A used to set the width of the lines used in the box plot. Defaults to 1. 320 * @param {Number} [config.opacity] (Optional) A number between 0 and 1 used to set the opacity of the box plot. Defaults 321 * to 1. 322 * @param {String} [config.position] (Optional) A string used to determine how to position the outliers. Currently the 323 * only possible value is "jitter", which will move the points to the left or right of the center of the box plot by 324 * a random amount. Defaults to undefined. 325 * @param {Boolean} [config.showOutliers] (Optional) Used to toggle whether or not outliers are rendered. Defaults to true. 326 * @param {String} [config.outlierFill] (Optional) A string value used to set the fill color of the outliers. Defaults 327 * to black (#000000). 328 * @param {Number} [config.outlierOpacity] (Optional) A number between 0 and 1 used to set the opacity of the outliers. 329 * Defaults to 1. 330 * @param {Number} [config.outlierSize] (Optional) A used to set the size of outliers. Defaults to 3. 331 */ 332 LABKEY.vis.Geom.Boxplot = function(config){ 333 this.type = "Boxplot"; 334 335 if(!config){ 336 config = {}; 337 } 338 this.color = ('color' in config && config.color != null && config.color != undefined) ? config.color : '#000000'; // line color 339 this.fill = ('fill' in config && config.fill != null && config.fill != undefined) ? config.fill : '#ffffff'; // fill color 340 this.lineWidth = ('lineWidth' in config && config.lineWidth != null && config.lineWidth != undefined) ? config.lineWidth : 1; 341 this.opacity = ('opacity' in config && config.opacity != null && config.opacity != undefined) ? config.opacity : 1; 342 this.position = ('position' in config && config.position != null && config.position != undefined) ? config.position : null; 343 this.showOutliers = ('showOutliers' in config && config.showOutliers != null && config.showOutliers != undefined) ? config.showOutliers : true; 344 this.outlierFill = ('outlierFill' in config && config.outlierFill != null && config.outlierFill != undefined) ? config.outlierFill : '#000000'; 345 this.outlierOpacity = ('outlierOpacity' in config && config.outlierOpacity != null && config.outlierOpacity != undefined) ? config.outlierOpacity : .5; 346 this.outlierSize = ('outlierSize' in config && config.outlierSize != null && config.outlierSize != undefined) ? config.outlierSize : 3; 347 348 return this; 349 }; 350 LABKEY.vis.Geom.Boxplot.prototype = new LABKEY.vis.Geom.XY(); 351 LABKEY.vis.Geom.Boxplot.prototype.render = function(renderer, grid, scales, data, layerAes, parentAes, name, index){ 352 if(!this.initAesthetics(scales, layerAes, parentAes, name, index)){ 353 return false; 354 } 355 this.hoverTextAes = layerAes.hoverText ? layerAes.hoverText : parentAes.hoverText; 356 this.pointClickFnAes = layerAes.pointClickFn ? layerAes.pointClickFn : parentAes.pointClickFn; 357 this.groupAes = layerAes.group ? layerAes.group : parentAes.group; 358 this.outlierHoverTextAes = layerAes.outlierHoverText ? layerAes.outlierHoverText : parentAes.outlierHoverText; 359 this.outlierColorAes = layerAes.outlierColor ? layerAes.outlierColor : parentAes.outlierColor; 360 this.outlierShapeAes = layerAes.outlierShape ? layerAes.outlierShape : parentAes.outlierShape; 361 this.shapeScale = scales.shape; 362 363 renderer.renderBoxPlotGeom(data, this); 364 return true; 365 }; 366 367 LABKEY.vis.Geom.DataspaceBoxPlot = function(config){ 368 this.type = "DataspaceBoxplot"; 369 370 if(!config){ 371 config = {}; 372 } 373 374 this.color = ('color' in config && config.color != null && config.color != undefined) ? config.color : '#000000'; // line color 375 this.fill = ('fill' in config && config.fill != null && config.fill != undefined) ? config.fill : '#ffffff'; // fill color 376 this.lineWidth = ('lineWidth' in config && config.lineWidth != null && config.lineWidth != undefined) ? config.lineWidth : 1; 377 this.opacity = ('opacity' in config && config.opacity != null && config.opacity != undefined) ? config.opacity : 1; 378 this.showOutliers = ('showOutliers' in config && config.showOutliers != null && config.showOutliers != undefined) ? config.showOutliers : true; 379 this.outlierFill = ('outlierFill' in config && config.outlierFill != null && config.outlierFill != undefined) ? config.outlierFill : '#000000'; 380 this.pointOpacity = ('outlierOpacity' in config && config.outlierOpacity != null && config.outlierOpacity != undefined) ? config.outlierOpacity : .5; 381 this.pointSize = ('outlierSize' in config && config.outlierSize != null && config.outlierSize != undefined) ? config.outlierSize : 3; 382 this.size = ('binSize' in config && config.binSize != null && config.binSize != undefined) ? config.binSize : 5; 383 384 // binning geom specific 385 this.binRowLimit = ('binRowLimit' in config && config.binRowLimit != null && config.binRowLimit != undefined) ? config.binRowLimit : 5000; 386 this.colorRange = ('colorRange' in config && config.colorRange != null && config.colorRange != undefined) ? config.colorRange : ["#e6e6e6", "#000000"]; // lightish-gray -> black 387 388 return this; 389 }; 390 LABKEY.vis.Geom.DataspaceBoxPlot.prototype = new LABKEY.vis.Geom.XY(); 391 LABKEY.vis.Geom.DataspaceBoxPlot.prototype.render = function(renderer, grid, scales, data, layerAes, parentAes, name, index){ 392 if(!this.initAesthetics(scales, layerAes, parentAes, name, index)){ 393 return false; 394 } 395 396 this.hoverTextAes = layerAes.hoverText ? layerAes.hoverText : parentAes.hoverText; 397 this.groupAes = layerAes.group ? layerAes.group : parentAes.group; 398 this.pointClickFnAes = layerAes.pointClickFn ? layerAes.pointClickFn : parentAes.pointClickFn; 399 this.pointHoverTextAes = layerAes.pointHoverText ? layerAes.pointHoverText : parentAes.pointHoverText; 400 this.shapeAes = layerAes.shape ? layerAes.shape : parentAes.shape; 401 this.shapeScale = scales.shape; 402 this.sizeAes = layerAes.size ? layerAes.size : parentAes.size; 403 this.sizeScale = scales.size; 404 this.mouseOverFnAes = layerAes.mouseOverFn ? layerAes.mouseOverFn : parentAes.mouseOverFn; 405 this.mouseOutFnAes = layerAes.mouseOutFn ? layerAes.mouseOutFn : parentAes.mouseOutFn; 406 this.mouseUpFnAes = layerAes.mouseUpFn ? layerAes.mouseUpFn : parentAes.mouseUpFn; 407 this.boxMouseOverFnAes = layerAes.boxMouseOverFn ? layerAes.boxMouseOverFn : parentAes.boxMouseOverFn; 408 this.boxMouseOutFnAes = layerAes.boxMouseOutFn ? layerAes.boxMouseOutFn : parentAes.boxMouseOutFn; 409 this.boxMouseUpFnAes = layerAes.boxMouseUpFn ? layerAes.boxMouseUpFn : parentAes.boxMouseUpFn; 410 411 renderer.renderDataspaceBoxPlotGeom(data, this); 412 return true; 413 }; 414 415 /** 416 * @class Bar plot geom, used to generate bar plots for a given set of data. 417 * @param config An object with the following properties: 418 * @param {Function} [config.clickFn] (Optional) A click function 419 * @param {String} [config.color] (Optional) A string value used for the line colors in the bar plot. Defaults to black (#000000) 420 * @param {String} [config.fill] (Optional) A string value used for the fill color in the bar plot. Defaults to white (#ffffff) 421 * @param {Number} [config.lineWidth] (Optional) A used to set the width of the lines used in the bar plot. Defaults to 1. 422 * @param {Number} [config.opacity] (Optional) A number between 0 and 1 used to set the opacity of the bar plot. Defaults to 1. 423 * @param {Boolean} [config.showCumulativeTotals] (Optional) True to show cumulative totals next to the individual bars. 424 * @param {String} [config.colorTotal] (Optional) A string value used for the line colors in the cumulative bar plot. Defaults to black (#000000) 425 * @param {String} [config.fillTotal] (Optional) A string value used for the fill color in the cumulative bar plot. Defaults to black (#000000) 426 * @param {Number} [config.lineWidthTotal] (Optional) A used to set the width of the lines used in the cumulative bar plot. Defaults to 1. 427 * @param {Number} [config.opacityTotal] (Optional) A number between 0 and 1 used to set the opacity of the cumulative bar plot. Defaults to 1. 428 */ 429 LABKEY.vis.Geom.BarPlot = function(config){ 430 this.type = "Barplot"; 431 432 if(!config){ 433 config = {}; 434 } 435 this.clickFn = ('clickFn' in config && config.clickFn != null && config.clickFn != undefined) ? config.clickFn : undefined; 436 this.color = ('color' in config && config.color != null && config.color != undefined) ? config.color : '#000000'; 437 this.colorTotal = ('colorTotal' in config && config.colorTotal != null && config.colorTotal != undefined) ? config.colorTotal : '#000000'; 438 this.fill = ('fill' in config && config.fill != null && config.fill != undefined) ? config.fill : '#c0c0c0'; 439 this.fillTotal = ('fillTotal' in config && config.fillTotal != null && config.fillTotal != undefined) ? config.fillTotal : '#000000'; 440 this.lineWidth = ('lineWidth' in config && config.lineWidth != null && config.lineWidth != undefined) ? config.lineWidth : 1; 441 this.lineWidthTotal = ('lineWidthTotal' in config && config.lineWidthTotal != null && config.lineWidthTotal != undefined) ? config.lineWidthTotal : 1; 442 this.opacity = ('opacity' in config && config.opacity != null && config.opacity != undefined) ? config.opacity : 1; 443 this.opacityTotal = ('opacityTotal' in config && config.opacityTotal != null && config.opacityTotal != undefined) ? config.opacityTotal : 1; 444 this.showCumulativeTotals = ('showCumulativeTotals' in config && config.showCumulativeTotals != null && config.showCumulativeTotals != undefined) ? config.showCumulativeTotals : false; 445 446 return this; 447 }; 448 LABKEY.vis.Geom.BarPlot.prototype = new LABKEY.vis.Geom.XY(); 449 LABKEY.vis.Geom.BarPlot.prototype.render = function(renderer, grid, scales, data, layerAes, parentAes, name, index){ 450 451 if(!this.initAesthetics(scales, layerAes, parentAes, name, index)){ 452 return false; 453 } 454 455 renderer.renderBarPlotGeom(data, this); 456 return true; 457 }; 458 459 /** 460 * @class Timeline plot geom, used to generate a timeline plot for a given set of data. 461 * @param config An object with the following properties: 462 * @param {String} [config.size] (Optional) A numeric value used for the timeline event icon size in pixels. Defaults to 10. 463 * @param {String} [config.color] (Optional) A string value used for the timeline event icon border color. Defaults to black (#000000). 464 * @param {String} [config.fill] (Optional) A string value used for the timeline event icon fill color. Defaults to black (#000000). 465 * @param {String} [config.dateKey] (Optional) property name of the date value that data objects contain. Used to create 466 * tooltips on hover. Defaults to 'date'. 467 * @param {Boolean} [config.isCollapsed] (Optional) If true, the timeline collapses subtypes into their parent rows. Defaults to True. 468 * @param {Number} [config.rowHeight] (Optional) The height of individual rows in pixels. For expanded timelines, row height 469 * will resize to 75% of this value. Defaults to 40px. 470 * @param {Object} [config.highlight] (Optional) Special Data object containing information to highlight a specific row 471 * in the timeline. Must have the same shape & properties as all other input data. 472 * @param {String} [config.highlightRowColor] (Optional) Hex color to specifiy what color the highlighted row will be if, 473 * found in the data. Defaults to #74B0C4. 474 * @param {String} [config.activeEventKey] (Optional) Name of property that is paired with @param config.activeEventIdentifier to 475 * identify a unique event in the data. 476 * @param {String} [config.activeEventIdentifier] (Optional) Name of value that is paired with @param config.activeEventKey 477 * to identify a unique event in the data. 478 * @param {String} [config.activeEventStrokeColor] (Optional) Hex color to specifiy what color the active event rect's 479 * stroke will be, if found in the data. Defaults to red. 480 * @param {Object} [config.emphasisEvents] (Optional) Object containing key:[value] pairs whose keys are property names 481 * of a data object and whose value is an array of possible values that should have a highlight line drawn 482 * on the chart when found. Example: {'type': ['death', 'Withdrawal']} 483 * @param {String} [config.tickColor] (Optional) Hex color to specifiy the color of Axis ticks. Defaults to #DDDDDD. 484 * @param {String} [config.emphasisTickColor] (Optional) Hex color to specify the color of emphasis event ticks, if 485 * found in the data. Defaults to #1a969d. 486 * @param {String} [config.timeUnit] (Optional) Unit of time to use when calculating how far an event's date is from 487 * the start date. Default is years. Valid string values include minutes, hours, days, years, and decades. 488 * @param {Number} [config.eventIconSize] (Optional) Size of event square width/height dimensions. 489 * @param {String} [config.eventIconColor] (Optional) Hex color of event square stroke. 490 * @param {String} [config.eventIconFill] (Optional) Hex color of event square inner fill. Defaults to black (#000000). 491 * @param {Number} [config.eventIconOpacity] (Optional) Float between 0 - 1 (inclusive) to specify how transparent the 492 * fill of event icons will be. Defaults to 1. 493 * @param {Array} [config.rowColorDomain] (Optional) Array of length 2 containing string Hex values for the two 494 * alternating colors of timeline row rectangles. Defaults to ['#f2f2f2', '#ffffff']. 495 */ 496 LABKEY.vis.Geom.TimelinePlot = function(config){ 497 this.type = "TimelinePlot"; 498 499 if(!config){ 500 config = {}; 501 } 502 503 this.dateKey = ('dateKey' in config && config.dateKey != null && config.dateKey != undefined) ? config.dateKey : 'date'; 504 this.timeUnit = ('timeUnit' in config && config.timeUnit != null && config.timeUnit != undefined) ? config.timeUnit : 'years'; 505 this.highlight = ('highlight' in config && config.highlight != null && config.highlight != undefined) ? config.highlight : null; 506 this.highlightRowColor = ('highlightRowColor' in config && config.highlightRowColor != null && config.highlightRowColor != undefined) ? config.highlightRowColor : '#74B0C4'; 507 this.activeEventKey = ('activeEventKey' in config && config.activeEventKey != null && config.activeEventKey != undefined) ? config.activeEventKey : null; 508 this.activeEventIdentifier = ('activeEventIdentifier' in config && config.activeEventIdentifier != null && config.activeEventIdentifier != undefined) ? config.activeEventIdentifier : null; 509 this.activeEventStrokeColor = ('activeEventStrokeColor' in config && config.activeEventStrokeColor != null && config.activeEventStrokeColor != undefined) ? config.activeEventStrokeColor : 'red'; 510 this.marginLeft = ('marginLeft' in config && config.marginLeft != null && config.marginLeft != undefined) ? config.marginLeft : 200; 511 this.parentName = ('parentName' in config && config.parentName != null && config.parentName != undefined) ? config.parentName : 'type'; 512 this.childName = ('childName' in config && config.childName != null && config.childName != undefined) ? config.childName : 'subtype'; 513 this.width = ('width' in config && config.width != null && config.width != undefined) ? config.width : 900; 514 this.height = ('height' in config && config.height != null && config.height != undefined) ? config.height : 500; 515 this.rowHeight = ('rowHeight' in config && config.rowHeight != null && config.rowHeight != undefined) ? config.rowHeight : 40; 516 this.eventIconSize = ('eventIconSize' in config && config.eventIconSize != null && config.eventIconSize != undefined) ? config.eventIconSize : 10; 517 this.eventIconColor = ('eventIconColor' in config && config.eventIconColor != null && config.eventIconColor != undefined) ? config.eventIconColor : '#000000'; 518 this.eventIconFill = ('eventIconFill' in config && config.eventIconFill != null && config.eventIconFill != undefined) ? config.eventIconFill : '#000000'; 519 this.rowColorDomain = ('rowColorDomain' in config && config.rowColorDomain != null && config.rowColorDomain != undefined) ? config.rowColorDomain : ['#f2f2f2', '#ffffff']; 520 this.eventIconOpacity = ('eventIconOpacity' in config && config.eventIconOpacity != null && config.eventIconOpacity != undefined) ? config.eventIconOpacity : 1; 521 this.emphasisEvents = ('emphasisEvents' in config && config.emphasisEvents != null && config.emphasisEvents != undefined) ? config.emphasisEvents : null; 522 this.tickColor = ('tickColor' in config && config.tickColor != null && config.tickColor != undefined) ? config.tickColor : '#DDDDDD'; 523 this.emphasisTickColor = ('emphasisTickColor' in config && config.emphasisTickColor != null && config.emphasisTickColor != undefined) ? config.emphasisTickColor : '#1a969d'; 524 this.isCollapsed = ('isCollapsed' in config && config.isCollapsed != null && config.isCollapsed != undefined) ? config.isCollapsed : true; 525 return this; 526 }; 527 LABKEY.vis.Geom.TimelinePlot.prototype = new LABKEY.vis.Geom.XY(); 528 LABKEY.vis.Geom.TimelinePlot.prototype.render = function(renderer, grid, scales, data, layerAes, parentAes, name, index){ 529 530 if(!this.initAesthetics(scales, layerAes, parentAes, name, index)){ 531 return false; 532 } 533 534 this.mouseOverRowFnAes = layerAes.mouseOverRowFn ? layerAes.mouseOverRowFn : parentAes.mouseOverRowFn; 535 this.mouseOutRowFnAes = layerAes.mouseOutRowFn ? layerAes.mouseOutRowFn : parentAes.mouseOutRowFn; 536 this.rowClickFnAes = layerAes.rowClickFn ? layerAes.rowClickFn : parentAes.rowClickFn; 537 this.eventClickFnAes = layerAes.eventIconClickFn ? layerAes.eventIconClickFn : parentAes.eventIconClickFn; 538 this.mouseOverFnAes = layerAes.mouseOverEventIconFn ? layerAes.mouseOverEventIconFn : parentAes.mouseOverEventIconFn; 539 this.mouseOutFnAes = layerAes.mouseOutEventIconFn ? layerAes.mouseOutEventIconFn : parentAes.mouseOutEventIconFn; 540 541 if (renderer.renderTimelinePlotGeom) 542 { 543 renderer.renderTimelinePlotGeom(data, this); 544 return true; 545 } 546 else 547 { 548 return false; 549 } 550 };