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