HTMLcopy
1
<div id="container"></div>
CSScopy
8
1
html,
2
body,
3
#container {
4
width: 100%;
5
height: 100%;
6
margin: 0;
7
padding: 0;
8
}
JavaScriptcopy
x
1
// Filters
2
var regionFilter = null;
3
var deviceFilter = null;
4
var categoryFilter = null;
5
6
// Charting objects
7
var unitsChart = null;
8
var regionChart = null;
9
var deviceChart = null;
10
var categoryChart = null;
11
var unitSeries = null;
12
var regionSeries = null;
13
var deviceSeries = null;
14
var categorySeries = null;
15
16
var unitsTitle = null;
17
var titleFilter = 'to filter click on bar charts below';
18
19
// Raw dashboard data, see data format in the end of the file
20
var rawData = generateData();
21
22
anychart.onDocumentReady(function () {
23
function unitsSoldChart() {
24
var chart = anychart.area();
25
chart.padding(15, 0, 0, 0);
26
// Set chart title text
27
unitsTitle = chart
28
.title()
29
.useHtml(true)
30
.hAlign('center')
31
.enabled(true);
32
unitsTitle.text(
33
'Income per Month<br><span style="color:#929292; font-size: 12px;">(' +
34
titleFilter +
35
')</span>'
36
);
37
38
// Create xAxis
39
var xAxis = chart.xAxis();
40
xAxis.title(false);
41
xAxis.staggerMode(false);
42
chart
43
.yAxis()
44
.labels()
45
.format(function () {
46
return formatMoney(parseInt(this.value), 0, '.', ',');
47
});
48
49
// Create area series
50
unitSeries = chart.area();
51
unitSeries.tooltip().titleFormat(function () {
52
return this.x;
53
});
54
unitSeries.tooltip().format(function () {
55
return '$' + formatMoney(this.value, 0, '.', ',');
56
});
57
return chart;
58
}
59
60
// Create Units sold chart, Area
61
unitsChart = unitsSoldChart();
62
63
function filterBarChart() {
64
var chart = anychart.bar();
65
chart.title().enabled(true).fontSize(14);
66
chart.padding(35, 5, 0, 5);
67
chart.yAxis().enabled(false);
68
return chart;
69
}
70
71
// Create filter bar chart by regions
72
regionChart = filterBarChart();
73
regionChart.title().text('Sales by Region');
74
regionSeries = regionChart.bar();
75
regionSeries.name('regions');
76
setupBarSeriesSettings(regionSeries);
77
78
// Create filter bar chart by device type
79
deviceChart = filterBarChart();
80
deviceChart.title().text('Sales by Device Type');
81
deviceSeries = deviceChart.bar();
82
deviceSeries.name('devices');
83
setupBarSeriesSettings(deviceSeries);
84
85
// Create filter bar chart by device type
86
categoryChart = filterBarChart();
87
categoryChart.title().text('Sales by Category');
88
categorySeries = categoryChart.bar();
89
categorySeries.name('categories');
90
setupBarSeriesSettings(categorySeries);
91
92
updateData();
93
94
var layoutTable = anychart.standalones.table(4, 5);
95
layoutTable.cellBorder(null);
96
layoutTable.getCol(0).width('2.5%');
97
layoutTable.getCol(4).width('2.5%');
98
layoutTable.getRow(0).height(40);
99
layoutTable.getRow(2).height('35%');
100
layoutTable.getRow(3).height(20);
101
102
layoutTable
103
.getCell(0, 1)
104
.colSpan(3)
105
.content('Software Sales Dashboard')
106
.hAlign('center')
107
.vAlign('bottom')
108
.fontSize(18)
109
.fontColor('#212121');
110
layoutTable.getCell(1, 1).colSpan(3).content(unitsChart);
111
112
layoutTable.getCell(2, 1).content(regionChart);
113
layoutTable.getCell(2, 2).content(deviceChart);
114
layoutTable.getCell(2, 3).content(categoryChart);
115
116
layoutTable.container('container');
117
layoutTable.draw();
118
});
119
120
// Setup same settings for all charts
121
function setupBarSeriesSettings(series) {
122
series.tooltip().titleFormat(function () {
123
return this.x;
124
});
125
series.tooltip().format(function () {
126
return '$' + formatMoney(this.value, 0, '.', ',');
127
});
128
series.listen('pointClick', function (e) {
129
var series = e.target;
130
var seriesName = series.name();
131
var categoryName = e.iterator.get('x');
132
133
switch (seriesName) {
134
case 'regions':
135
regionFilter =
136
regionFilter && regionFilter === categoryName
137
? null
138
: categoryName;
139
break;
140
case 'devices':
141
deviceFilter =
142
deviceFilter && deviceFilter === categoryName
143
? null
144
: categoryName;
145
break;
146
case 'categories':
147
categoryFilter =
148
categoryFilter && categoryFilter === categoryName
149
? null
150
: categoryName;
151
break;
152
default:
153
}
154
155
updateData();
156
});
157
}
158
159
/**
160
* Apply filters to raw data.
161
* Set data to charts in the following format:
162
*
163
* var unitData = [
164
* // timestamp value
165
* [1409529600000, 100],
166
* [1409616000000, 200],
167
* [1409702400000, 300]
168
* ];
169
* var barData = [
170
* {x: 'Category Name 1', value: 100, fill: 'rgb(233, 234, 237)', stroke: 'anychart.color.darken(rgb(233, 234, 237))'},
171
* {x: 'Category Name 2', value: 200, fill: 'rgb(233, 234, 237)', stroke: 'anychart.color.darken(rgb(233, 234, 237))'},
172
* {x: 'Category Name 3', value: 300, fill: 'rgb(233, 234, 237)', stroke: 'anychart.color.darken(rgb(233, 234, 237))'}
173
* ];
174
*
175
*/
176
function updateData() {
177
var hoverBarsSeriesColor = '#ffd54f';
178
var unitMap = {};
179
var territoryMap = {};
180
var platformMap = {};
181
var categoryMap = {};
182
183
if (!(regionFilter || deviceFilter || categoryFilter)) { titleFilter = 'to filter click on bar charts below'; }
184
else {
185
titleFilter = '';
186
if (regionFilter) titleFilter = 'in ' + regionFilter + ' ';
187
if (deviceFilter) { titleFilter = titleFilter + 'on ' + deviceFilter + ' '; }
188
if (categoryFilter) { titleFilter = titleFilter + 'in category "' + categoryFilter + '"'; }
189
}
190
unitsTitle.text(
191
'Income per Month<br><span style="color:#929292; font-size: 12px;">(' +
192
titleFilter +
193
')</span>'
194
);
195
196
for (var i = 0, count = rawData.length; i < count; i++) {
197
var dataItem = rawData[i];
198
199
var fitTerritoryFilter =
200
!regionFilter || (regionFilter && regionFilter === dataItem.region);
201
var fitPlatformFilter =
202
!deviceFilter || (deviceFilter && deviceFilter === dataItem.device);
203
var fitCategoryFilter =
204
!categoryFilter ||
205
(categoryFilter && categoryFilter === dataItem.category);
206
207
if (fitTerritoryFilter && fitPlatformFilter && fitCategoryFilter) {
208
var unitsMapItem = unitMap[dataItem.x];
209
if (unitsMapItem) {
210
unitMap[dataItem.x] = [
211
dataItem.x,
212
unitsMapItem[1] + dataItem.value
213
];
214
} else {
215
unitMap[dataItem.x] = [dataItem.x, dataItem.value];
216
}
217
}
218
219
if (fitPlatformFilter && fitCategoryFilter) {
220
var territoryMapItem = territoryMap[dataItem.region];
221
if (territoryMapItem) {
222
territoryMapItem.value += dataItem.value;
223
} else {
224
territoryMapItem = { x: dataItem.region, value: dataItem.value };
225
territoryMap[dataItem.region] = territoryMapItem;
226
}
227
territoryMapItem.fill =
228
territoryMapItem.x === regionFilter
229
? hoverBarsSeriesColor
230
: undefined;
231
territoryMapItem.stroke =
232
territoryMapItem.x === regionFilter
233
? anychart.color.darken(hoverBarsSeriesColor)
234
: undefined;
235
}
236
237
if (fitTerritoryFilter && fitCategoryFilter) {
238
var platformMapItem = platformMap[dataItem.device];
239
if (platformMapItem) {
240
platformMapItem.value += dataItem.value;
241
} else {
242
platformMapItem = { x: dataItem.device, value: dataItem.value };
243
platformMap[dataItem.device] = platformMapItem;
244
}
245
platformMapItem.fill =
246
platformMapItem.x === deviceFilter
247
? hoverBarsSeriesColor
248
: undefined;
249
platformMapItem.stroke =
250
platformMapItem.x === deviceFilter
251
? anychart.color.darken(hoverBarsSeriesColor)
252
: undefined;
253
}
254
255
if (fitTerritoryFilter && fitPlatformFilter) {
256
var categoryMapItem = categoryMap[dataItem.category];
257
if (categoryMapItem) {
258
categoryMapItem += dataItem.value;
259
} else {
260
categoryMapItem = { x: dataItem.category, value: dataItem.value };
261
categoryMap[dataItem.category] = categoryMapItem;
262
}
263
categoryMapItem.fill =
264
categoryMapItem.x === categoryFilter
265
? hoverBarsSeriesColor
266
: undefined;
267
categoryMapItem.stroke =
268
categoryMapItem.x === categoryFilter
269
? anychart.color.darken(hoverBarsSeriesColor)
270
: undefined;
271
}
272
}
273
274
var territoryData = getValues(territoryMap);
275
276
var platformData = getValues(platformMap);
277
278
var categoryData = getValues(categoryMap);
279
280
var unitData = getValues(unitMap);
281
282
regionSeries.data(territoryData);
283
deviceSeries.data(platformData);
284
categorySeries.data(categoryData);
285
unitSeries.data(unitData);
286
}
287
288
/**
289
* Generate data in the following format:
290
* var data = [
291
* {x: Date.UTC(2014, 8, 1), value: 700, territory: 'Europe', device: 'iPhone', category: 'Games'},
292
* {x: Date.UTC(2014, 8, 1), value: 200, territory: 'Europe', device: 'iPad', category: 'Games'},
293
* {x: Date.UTC(2014, 8, 1), value: 400, territory: 'Europe', device: 'Desktop', category: 'Games'}
294
* ];
295
* @return {Array.<Object>}
296
*/
297
function generateData() {
298
var data = [];
299
var dates = [
300
Date.UTC(2014, 0, 1),
301
Date.UTC(2014, 1, 1),
302
Date.UTC(2014, 2, 1),
303
Date.UTC(2014, 3, 1),
304
Date.UTC(2014, 4, 1),
305
Date.UTC(2014, 5, 1),
306
Date.UTC(2014, 6, 1),
307
Date.UTC(2014, 7, 1),
308
Date.UTC(2014, 8, 1),
309
Date.UTC(2014, 9, 1),
310
Date.UTC(2014, 10, 1),
311
Date.UTC(2014, 11, 1)
312
];
313
var territories = ['Europe', 'Asia Pacific', 'USA and Canada'];
314
var platforms = ['iPhone', 'iPad', 'Desktop'];
315
var categories = ['Games', 'Social Networking', 'Photo & Video'];
316
var monthNames = [
317
'Jan',
318
'Feb',
319
'Mar',
320
'Apr',
321
'May',
322
'Jun',
323
'Jul',
324
'Aug',
325
'Sep',
326
'Oct',
327
'Nov',
328
'Dec'
329
];
330
for (var d = 0, datesCount = dates.length; d < datesCount; d++) {
331
for (
332
var t = 0, territoriesCount = territories.length;
333
t < territoriesCount;
334
t++
335
) {
336
for (
337
var p = 0, platformsCount = platforms.length;
338
p < platformsCount;
339
p++
340
) {
341
for (
342
var c = 0, categoriesCount = categories.length;
343
c < categoriesCount;
344
c++
345
) {
346
var date = new Date(dates[d]);
347
data.push({
348
x: monthNames[date.getMonth()],
349
value: Math.floor(Math.random() * 100 + 1),
350
region: territories[t],
351
device: platforms[p],
352
category: categories[c]
353
});
354
}
355
}
356
}
357
}
358
359
return data;
360
}
361
362
/**
363
* Return Object values as array.
364
* @param {Object} obj
365
* @return {Array}
366
*/
367
function getValues(obj) {
368
var res = [];
369
var i = 0;
370
for (var key in obj) {
371
if (obj.hasOwnProperty(key)) {
372
res[i++] = obj[key];
373
}
374
}
375
return res;
376
}
377
378
function formatMoney(value, c, d, t) {
379
var n = value;
380
c = isNaN(Math.abs(c)) ? 2 : Math.abs(c);
381
d = d === undefined ? '.' : d;
382
t = t === undefined ? ',' : t;
383
var s = n < 0 ? '-' : '';
384
var i = parseInt((n = Math.abs(+n || 0).toFixed(c))) + '';
385
var j = i.length > 3 ? i.length % 3 : 0;
386
return (
387
s +
388
(j ? i.substr(0, j) + t : '') +
389
i.substr(j).replace(/(\d{3})(?=\d)/g, '$1' + t) +
390
(c
391
? d +
392
Math.abs(n - i)
393
.toFixed(c)
394
.slice(2)
395
: '')
396
);
397
}