Skip to content

Commit 38b7304

Browse files
committed
Merge pull request #26 from dklawren/branch
fixed
2 parents e3e599c + 99a2ad1 commit 38b7304

File tree

3 files changed

+256
-7
lines changed

3 files changed

+256
-7
lines changed

index.html

+1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
<script src="js/vendor/require.min.js"></script>
106106
<script src="js/vendor/jquery.js"></script>
107107
<script src="js/vendor/jquery.flot.js"></script>
108+
<script src="js/vendor/jquery.flot.categories.js"></script>
108109
<script src="js/plugins.js"></script>
109110
<script src="js/vendor/bootstrap.min.js"></script>
110111
<script src="js/vendor/jquery.tablesorter.min.js"></script>

js/main.js

+65-7
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ require(['jquery', 'es-glue', 'd3'], function ($, ES, d3) {
9595
}
9696
return (ms / 86400000).toFixed(1) + " days";
9797
}
98+
function toDays(ms) {
99+
return (ms / 86400000).toFixed(1);
100+
}
98101
var aggregate = aggregateTimes(data);
99102
var row = d3.select("#component-times")
100103
.selectAll("tr")
@@ -158,17 +161,72 @@ require(['jquery', 'es-glue', 'd3'], function ($, ES, d3) {
158161
.text(formatTime(total[i]));
159162
});
160163

161-
var data1 = [];
162-
for (var i = 0; i < 14; i += 0.5) {
163-
data1.push([i, Math.sin(i)]);
164+
var total = {
165+
week: {
166+
count: 0,
167+
time: 0,
168+
min: Number.MAX_VALUE,
169+
max: Number.MIN_VALUE,
170+
},
171+
month: {
172+
count: 0,
173+
time: 0,
174+
min: Number.MAX_VALUE,
175+
max: Number.MIN_VALUE,
176+
},
177+
year: {
178+
count: 0,
179+
time: 0,
180+
min: Number.MAX_VALUE,
181+
max: Number.MIN_VALUE,
182+
},
183+
};
184+
for (var k in aggregate) {
185+
for (var l in aggregate[k]) {
186+
total[l].count = total[l].count + aggregate[k][l].count;
187+
total[l].time = total[l].time + aggregate[k][l].time;
188+
total[l].min = Math.min(total[l].min, aggregate[k][l].min);
189+
total[l].max = Math.max(total[l].max, aggregate[k][l].max);
190+
}
164191
}
165-
var data2 = [[0, 3], [4, 8], [8, 5], [9, 13]];
166-
var data3 = [[0, 12], [7, 12], null, [7, 2.5], [12, 2.5]];
167-
$.plot("#chart", [ data1, data2, data3 ]);
168-
169192
$(function(){
170193
$("#stats-table").tablesorter({ sortList: [[0, 0]] });
171194
});
172195

196+
total = [
197+
total.week.time / total.week.count,
198+
total.month.time / total.month.count,
199+
total.year.time / total.year.count,
200+
total.year.min,
201+
total.year.max,
202+
];
203+
var totalTimes = d3.select("#total-times")
204+
.selectAll("tr")
205+
.each(function(d, i) {
206+
d3.select(this)
207+
.select("td")
208+
.text(formatTime(total[i]));
209+
});
210+
211+
var chart_data = [
212+
["Week", toDays(total[0])],
213+
["Month", toDays(total[1])],
214+
["12 Months", toDays(total[2])],
215+
["Shortest", toDays(total[3])],
216+
["Longest", toDays(total[4])]
217+
];
218+
$.plot("#chart", [ chart_data ], {
219+
series: {
220+
bars: {
221+
show: true,
222+
barWidth: 0.6,
223+
align: "center"
224+
}
225+
},
226+
xaxis: {
227+
mode: "categories",
228+
tickLength: 0
229+
}
230+
});
173231
});
174232
});

js/vendor/jquery.flot.categories.js

+190
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
/* Flot plugin for plotting textual data or categories.
2+
3+
Copyright (c) 2007-2013 IOLA and Ole Laursen.
4+
Licensed under the MIT license.
5+
6+
Consider a dataset like [["February", 34], ["March", 20], ...]. This plugin
7+
allows you to plot such a dataset directly.
8+
9+
To enable it, you must specify mode: "categories" on the axis with the textual
10+
labels, e.g.
11+
12+
$.plot("#placeholder", data, { xaxis: { mode: "categories" } });
13+
14+
By default, the labels are ordered as they are met in the data series. If you
15+
need a different ordering, you can specify "categories" on the axis options
16+
and list the categories there:
17+
18+
xaxis: {
19+
mode: "categories",
20+
categories: ["February", "March", "April"]
21+
}
22+
23+
If you need to customize the distances between the categories, you can specify
24+
"categories" as an object mapping labels to values
25+
26+
xaxis: {
27+
mode: "categories",
28+
categories: { "February": 1, "March": 3, "April": 4 }
29+
}
30+
31+
If you don't specify all categories, the remaining categories will be numbered
32+
from the max value plus 1 (with a spacing of 1 between each).
33+
34+
Internally, the plugin works by transforming the input data through an auto-
35+
generated mapping where the first category becomes 0, the second 1, etc.
36+
Hence, a point like ["February", 34] becomes [0, 34] internally in Flot (this
37+
is visible in hover and click events that return numbers rather than the
38+
category labels). The plugin also overrides the tick generator to spit out the
39+
categories as ticks instead of the values.
40+
41+
If you need to map a value back to its label, the mapping is always accessible
42+
as "categories" on the axis object, e.g. plot.getAxes().xaxis.categories.
43+
44+
*/
45+
46+
(function ($) {
47+
var options = {
48+
xaxis: {
49+
categories: null
50+
},
51+
yaxis: {
52+
categories: null
53+
}
54+
};
55+
56+
function processRawData(plot, series, data, datapoints) {
57+
// if categories are enabled, we need to disable
58+
// auto-transformation to numbers so the strings are intact
59+
// for later processing
60+
61+
var xCategories = series.xaxis.options.mode == "categories",
62+
yCategories = series.yaxis.options.mode == "categories";
63+
64+
if (!(xCategories || yCategories))
65+
return;
66+
67+
var format = datapoints.format;
68+
69+
if (!format) {
70+
// FIXME: auto-detection should really not be defined here
71+
var s = series;
72+
format = [];
73+
format.push({ x: true, number: true, required: true });
74+
format.push({ y: true, number: true, required: true });
75+
76+
if (s.bars.show || (s.lines.show && s.lines.fill)) {
77+
var autoscale = !!((s.bars.show && s.bars.zero) || (s.lines.show && s.lines.zero));
78+
format.push({ y: true, number: true, required: false, defaultValue: 0, autoscale: autoscale });
79+
if (s.bars.horizontal) {
80+
delete format[format.length - 1].y;
81+
format[format.length - 1].x = true;
82+
}
83+
}
84+
85+
datapoints.format = format;
86+
}
87+
88+
for (var m = 0; m < format.length; ++m) {
89+
if (format[m].x && xCategories)
90+
format[m].number = false;
91+
92+
if (format[m].y && yCategories)
93+
format[m].number = false;
94+
}
95+
}
96+
97+
function getNextIndex(categories) {
98+
var index = -1;
99+
100+
for (var v in categories)
101+
if (categories[v] > index)
102+
index = categories[v];
103+
104+
return index + 1;
105+
}
106+
107+
function categoriesTickGenerator(axis) {
108+
var res = [];
109+
for (var label in axis.categories) {
110+
var v = axis.categories[label];
111+
if (v >= axis.min && v <= axis.max)
112+
res.push([v, label]);
113+
}
114+
115+
res.sort(function (a, b) { return a[0] - b[0]; });
116+
117+
return res;
118+
}
119+
120+
function setupCategoriesForAxis(series, axis, datapoints) {
121+
if (series[axis].options.mode != "categories")
122+
return;
123+
124+
if (!series[axis].categories) {
125+
// parse options
126+
var c = {}, o = series[axis].options.categories || {};
127+
if ($.isArray(o)) {
128+
for (var i = 0; i < o.length; ++i)
129+
c[o[i]] = i;
130+
}
131+
else {
132+
for (var v in o)
133+
c[v] = o[v];
134+
}
135+
136+
series[axis].categories = c;
137+
}
138+
139+
// fix ticks
140+
if (!series[axis].options.ticks)
141+
series[axis].options.ticks = categoriesTickGenerator;
142+
143+
transformPointsOnAxis(datapoints, axis, series[axis].categories);
144+
}
145+
146+
function transformPointsOnAxis(datapoints, axis, categories) {
147+
// go through the points, transforming them
148+
var points = datapoints.points,
149+
ps = datapoints.pointsize,
150+
format = datapoints.format,
151+
formatColumn = axis.charAt(0),
152+
index = getNextIndex(categories);
153+
154+
for (var i = 0; i < points.length; i += ps) {
155+
if (points[i] == null)
156+
continue;
157+
158+
for (var m = 0; m < ps; ++m) {
159+
var val = points[i + m];
160+
161+
if (val == null || !format[m][formatColumn])
162+
continue;
163+
164+
if (!(val in categories)) {
165+
categories[val] = index;
166+
++index;
167+
}
168+
169+
points[i + m] = categories[val];
170+
}
171+
}
172+
}
173+
174+
function processDatapoints(plot, series, datapoints) {
175+
setupCategoriesForAxis(series, "xaxis", datapoints);
176+
setupCategoriesForAxis(series, "yaxis", datapoints);
177+
}
178+
179+
function init(plot) {
180+
plot.hooks.processRawData.push(processRawData);
181+
plot.hooks.processDatapoints.push(processDatapoints);
182+
}
183+
184+
$.plot.plugins.push({
185+
init: init,
186+
options: options,
187+
name: 'categories',
188+
version: '1.0'
189+
});
190+
})(jQuery);

0 commit comments

Comments
 (0)