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