- 1 :
/* global Spyral, Highcharts */
- 2 :
- 3 :
import NetworkGraph from './networkgraph';
- 4 :
- 5 :
import Util from './util.js';
- 6 :
- 7 :
/**
- 8 :
* The Chart class in Spyral.
- 9 :
* This class provides methods for creating a variety of charts.
- 10 :
* Charts are created using the [Highcharts Library]{@link https://api.highcharts.com/highcharts/}.
- 11 :
* Highcharts have many configuration options and Spyral.Chart helps to streamline the process.
- 12 :
* A simple example:
- 13 :
*
- 14 :
* Spyral.Chart.line({ series: [{ data: [0,2,1,3] }] })
- 15 :
*
- 16 :
* A more complex example:
- 17 :
*
- 18 :
* Spyral.Chart.column({
- 19 :
* title: 'Wildflowers',
- 20 :
* series: [{
- 21 :
* name: 'Ontario',
- 22 :
* data: [13, 39, 139, 38]
- 23 :
* },{
- 24 :
* name: 'Quebec',
- 25 :
* data: [14, 33, 94, 30]
- 26 :
* }],
- 27 :
* xAxis: {
- 28 :
* title: 'Number of Petals',
- 29 :
* categories: [3, 4, 5, 6]
- 30 :
* }
- 31 :
* })
- 32 :
*
- 33 :
* @memberof Spyral
- 34 :
* @class
- 35 :
*/
- 36 :
class Chart {
- 37 :
/**
- 38 :
* The Highcharts config object
- 39 :
* @typedef {Object} Spyral.Chart~HighchartsConfig
- 40 :
* @property {(string|object)} title
- 41 :
* @property {(string|object)} subtitle
- 42 :
* @property {Object} credits
- 43 :
* @property {Object} xAxis
- 44 :
* @property {Object} yAxis
- 45 :
* @property {Object} chart
- 46 :
* @property {Array<Spyral.Chart~HighchartsSeriesConfig>} series
- 47 :
* @property {Object} plotOptions
- 48 :
*/
- 49 :
- 50 :
/**
- 51 :
* The series config object
- 52 :
* @typedef {Object} Spyral.Chart~HighchartsSeriesConfig
- 53 :
* @property {Array} data
- 54 :
* @property {string} [name]
- 55 :
*/
- 56 :
- 57 :
/**
- 58 :
* Construct a new Chart class
- 59 :
* @constructor
- 60 :
* @param {(String|Element)} [target] An element or ID to use as the chart's target. If not specified, one will be created.
- 61 :
* @param {Array} data An array of data to visualize.
- 62 :
*/
- 63 :
constructor(target, data) {
- 64 :
if (Util.isNode(target)) {
- 65 :
if (target.isConnected === false) {
- 66 :
throw new Error('The target node does not exist within the document.');
- 67 :
}
- 68 :
} else if (Util.isString(target) === false) {
- 69 :
data = target;
- 70 :
target = undefined;
- 71 :
}
- 72 :
this.target = target;
- 73 :
this.data = data;
- 74 :
}
- 75 :
- 76 :
/**
- 77 :
* Create a new chart.
- 78 :
* See [Highcharts API]{@link https://api.highcharts.com/highcharts/} for full set of config options.
- 79 :
* @param {(String|Element)} [target] An element or ID to use as the chart's target. If not specified, one will be created.
- 80 :
* @param {Spyral.Chart~HighchartsConfig} config
- 81 :
* @returns {Highcharts.Chart}
- 82 :
*/
- 83 :
create(target, config) {
- 84 :
[target, config] = Chart._handleTargetAndConfig(target, config);
- 85 :
return Highcharts.chart(target, config);
- 86 :
}
- 87 :
- 88 :
/**
- 89 :
* Create a new chart.
- 90 :
* See [Highcharts API]{@link https://api.highcharts.com/highcharts/} for full set of config options.
- 91 :
* @param {(String|Element)} [target] An element or ID to use as the chart's target. If not specified, one will be created.
- 92 :
* @param {Spyral.Chart~HighchartsConfig} config
- 93 :
* @returns {Highcharts.Chart}
- 94 :
* @static
- 95 :
*/
- 96 :
static create(target, config) {
- 97 :
[target, config] = Chart._handleTargetAndConfig(target, config);
- 98 :
return Highcharts.chart(target, config);
- 99 :
}
- 100 :
- 101 :
static _handleTargetAndConfig(target, config) {
- 102 :
if (Util.isNode(target) === false && typeof target === 'object') {
- 103 :
config = target;
- 104 :
target = undefined;
- 105 :
}
- 106 :
- 107 :
if (target === undefined) {
- 108 :
if (typeof Spyral !== 'undefined' && Spyral.Notebook) {
- 109 :
target = Spyral.Notebook.getTarget();
- 110 :
if (target.clientHeight <= 40) {
- 111 :
target.style.height = '400px'; // 400 is the default Highcharts height
- 112 :
}
- 113 :
} else {
- 114 :
target = document.createElement('div');
- 115 :
document.body.appendChild(target);
- 116 :
}
- 117 :
} else {
- 118 :
if (Util.isNode(target) && target.isConnected === false) {
- 119 :
throw new Error('The target node does not exist within the document.');
- 120 :
}
- 121 :
}
- 122 :
- 123 :
// convert title and suppress if not provided
- 124 :
if ('title' in config) {
- 125 :
if (typeof config.title === 'string') {
- 126 :
config.title = {text: config.title};
- 127 :
}
- 128 :
} else {
- 129 :
config.title = false;
- 130 :
}
- 131 :
- 132 :
// convert subtitle and convert if not provided
- 133 :
if ('subtitle' in config) {
- 134 :
if (typeof config.subtitle === 'string') {
- 135 :
config.subtitle = {text: config.subtitle};
- 136 :
}
- 137 :
} else {
- 138 :
config.subtitle = false;
- 139 :
}
- 140 :
- 141 :
// convert credits
- 142 :
if (!('credits' in config)) {
- 143 :
config.credits = false;
- 144 :
}
- 145 :
- 146 :
// suppress xAxis title unless provided
- 147 :
if (!('xAxis' in config)) {config.xAxis = {};}
- 148 :
if (!('title' in config.xAxis)) {
- 149 :
config.xAxis.title = false;
- 150 :
} else if (typeof config.xAxis.title === 'string') {
- 151 :
config.xAxis.title = {text: config.xAxis.title};
- 152 :
}
- 153 :
- 154 :
// suppress xAxis title unless provided
- 155 :
if (!('yAxis' in config)) {config.yAxis = {};}
- 156 :
if (!('title' in config.yAxis)) {
- 157 :
config.yAxis.title = false;
- 158 :
} else if (typeof config.yAxis.title === 'string') {
- 159 :
config.yAxis.title = {text: config.yAxis.title};
- 160 :
}
- 161 :
- 162 :
return [target, config];
- 163 :
}
- 164 :
- 165 :
static _setDefaultChartType(config, type) {
- 166 :
if ('type' in config) {
- 167 :
config.chart.type = config.type;
- 168 :
delete config.type;
- 169 :
return;
- 170 :
}
- 171 :
- 172 :
// TODO: check plot options and series?
- 173 :
- 174 :
if ('chart' in config) {
- 175 :
if ('type' in config.chart) {return;} // already set
- 176 :
} else {
- 177 :
config.chart = {};
- 178 :
}
- 179 :
- 180 :
config.chart.type = type;
- 181 :
return config;
- 182 :
}
- 183 :
- 184 :
/**
- 185 :
* Add the provided data to the config as a series
- 186 :
* @param {Spyral.Chart~HighchartsConfig} config
- 187 :
* @param {Array} data
- 188 :
* @static
- 189 :
*/
- 190 :
static setSeriesData(config, data) {
- 191 :
if (Array.isArray(data)) {
- 192 :
if (Array.isArray(data[0])) {
- 193 :
config.series = data.map(subArray => { return {data: subArray}; });
- 194 :
} else {
- 195 :
config.series = [{data: data}];
- 196 :
}
- 197 :
}
- 198 :
}
- 199 :
- 200 :
/**
- 201 :
* Create a bar chart
- 202 :
* @param {Spyral.Chart~HighchartsConfig} [config]
- 203 :
* @returns {Highcharts.Chart}
- 204 :
*/
- 205 :
bar(config={}) {
- 206 :
Chart.setSeriesData(config, this.data);
- 207 :
return Chart.bar(this.target, config);
- 208 :
}
- 209 :
/**
- 210 :
* Create a bar chart
- 211 :
* @param {(String|Element)} [target] An element or ID to use as the chart's target. If not specified, one will be created.
- 212 :
* @param {Spyral.Chart~HighchartsConfig} config
- 213 :
* @returns {Highcharts.Chart}
- 214 :
* @static
- 215 :
*/
- 216 :
static bar(target, config) {
- 217 :
[target, config] = Chart._handleTargetAndConfig(target, config);
- 218 :
Chart._setDefaultChartType(config, 'bar');
- 219 :
return Highcharts.chart(target, config);
- 220 :
}
- 221 :
- 222 :
/**
- 223 :
* Create a column chart
- 224 :
* @param {Spyral.Chart~HighchartsConfig} [config]
- 225 :
* @returns {Highcharts.Chart}
- 226 :
*/
- 227 :
column(config={}) {
- 228 :
Chart.setSeriesData(config, this.data);
- 229 :
return Chart.column(this.target, config);
- 230 :
}
- 231 :
/**
- 232 :
* Create a column chart
- 233 :
* @param {(String|Element)} [target] An element or ID to use as the chart's target. If not specified, one will be created.
- 234 :
* @param {Spyral.Chart~HighchartsConfig} config
- 235 :
* @returns {Highcharts.Chart}
- 236 :
* @static
- 237 :
*/
- 238 :
static column(target, config) {
- 239 :
[target, config] = Chart._handleTargetAndConfig(target, config);
- 240 :
Chart._setDefaultChartType(config, 'column');
- 241 :
return Highcharts.chart(target, config);
- 242 :
}
- 243 :
- 244 :
/**
- 245 :
* Create a line chart
- 246 :
* @param {Spyral.Chart~HighchartsConfig} [config]
- 247 :
* @returns {Highcharts.Chart}
- 248 :
*/
- 249 :
line(config={}) {
- 250 :
Chart.setSeriesData(config, this.data);
- 251 :
return Chart.line(this.target, config);
- 252 :
}
- 253 :
/**
- 254 :
* Create a line chart
- 255 :
* @param {(String|Element)} [target] An element or ID to use as the chart's target. If not specified, one will be created.
- 256 :
* @param {Spyral.Chart~HighchartsConfig} config
- 257 :
* @returns {Highcharts.Chart}
- 258 :
* @static
- 259 :
*/
- 260 :
static line(target, config) {
- 261 :
[target, config] = Chart._handleTargetAndConfig(target, config);
- 262 :
Chart._setDefaultChartType(config, 'line');
- 263 :
return Highcharts.chart(target, config);
- 264 :
}
- 265 :
- 266 :
/**
- 267 :
* Create a scatter plot
- 268 :
* @param {Spyral.Chart~HighchartsConfig} [config]
- 269 :
* @returns {Highcharts.Chart}
- 270 :
*/
- 271 :
scatter(config={}) {
- 272 :
Chart.setSeriesData(config, this.data);
- 273 :
return Chart.scatter(this.target, config);
- 274 :
}
- 275 :
/**
- 276 :
* Create a scatter plot
- 277 :
* @param {(String|Element)} [target] An element or ID to use as the chart's target. If not specified, one will be created.
- 278 :
* @param {Spyral.Chart~HighchartsConfig} config
- 279 :
* @returns {Highcharts.Chart}
- 280 :
* @static
- 281 :
*/
- 282 :
static scatter(target, config) {
- 283 :
[target, config] = Chart._handleTargetAndConfig(target, config);
- 284 :
Chart._setDefaultChartType(config, 'scatter');
- 285 :
return Highcharts.chart(target, config);
- 286 :
}
- 287 :
- 288 :
/**
- 289 :
* Create a network graph
- 290 :
* @param {NetworkGraph~Config} [config]
- 291 :
* @returns {NetworkGraph}
- 292 :
*/
- 293 :
networkgraph(config={}) {
- 294 :
return Chart.networkgraph(this.target, config);
- 295 :
}
- 296 :
/**
- 297 :
* Create a network graph
- 298 :
* @param {(String|Element)} [target] An element or ID to use as the chart's target. If not specified, one will be created.
- 299 :
* @param {NetworkGraph~Config} config
- 300 :
* @returns {NetworkGraph}
- 301 :
* @static
- 302 :
*/
- 303 :
static networkgraph(target, config) {
- 304 :
[target, config] = Chart._handleTargetAndConfig(target, config);
- 305 :
return new NetworkGraph(target, config);
- 306 :
}
- 307 :
}
- 308 :
- 309 :
export default Chart;