Removed the js graph crap.
This commit is contained in:
parent
43aae333e2
commit
fce863fc1e
@ -82,25 +82,6 @@ body {
|
|||||||
width: 25%;
|
width: 25%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#weekly_history {
|
|
||||||
width:100%;
|
|
||||||
height:200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#weekday_averages {
|
|
||||||
width:100%;
|
|
||||||
height:200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#tooltip {
|
|
||||||
position: absolute;
|
|
||||||
display: none;
|
|
||||||
border: 1px solid #fdd;
|
|
||||||
padding: 2px;
|
|
||||||
background-color: #fee;
|
|
||||||
opacity: 0.80;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Footer *********************************************************************/
|
/* Footer *********************************************************************/
|
||||||
#bottom_footer {
|
#bottom_footer {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
|
|||||||
@ -1,191 +0,0 @@
|
|||||||
/* Flot plugin for plotting textual data or categories.
|
|
||||||
|
|
||||||
Copyright (c) 2007-2014 IOLA and Ole Laursen.
|
|
||||||
Licensed under the MIT license.
|
|
||||||
|
|
||||||
Consider a dataset like [["February", 34], ["March", 20], ...]. This plugin
|
|
||||||
allows you to plot such a dataset directly.
|
|
||||||
|
|
||||||
To enable it, you must specify mode: "categories" on the axis with the textual
|
|
||||||
labels, e.g.
|
|
||||||
|
|
||||||
$.plot("#placeholder", data, { xaxis: { mode: "categories" } });
|
|
||||||
|
|
||||||
By default, the labels are ordered as they are met in the data series. If you
|
|
||||||
need a different ordering, you can specify "categories" on the axis options
|
|
||||||
and list the categories there:
|
|
||||||
|
|
||||||
xaxis: {
|
|
||||||
mode: "categories",
|
|
||||||
categories: ["February", "March", "April"]
|
|
||||||
}
|
|
||||||
|
|
||||||
If you need to customize the distances between the categories, you can specify
|
|
||||||
"categories" as an object mapping labels to values
|
|
||||||
|
|
||||||
xaxis: {
|
|
||||||
mode: "categories",
|
|
||||||
categories: { "February": 1, "March": 3, "April": 4 }
|
|
||||||
}
|
|
||||||
|
|
||||||
If you don't specify all categories, the remaining categories will be numbered
|
|
||||||
from the max value plus 1 (with a spacing of 1 between each).
|
|
||||||
|
|
||||||
Internally, the plugin works by transforming the input data through an auto-
|
|
||||||
generated mapping where the first category becomes 0, the second 1, etc.
|
|
||||||
Hence, a point like ["February", 34] becomes [0, 34] internally in Flot (this
|
|
||||||
is visible in hover and click events that return numbers rather than the
|
|
||||||
category labels). The plugin also overrides the tick generator to spit out the
|
|
||||||
categories as ticks instead of the values.
|
|
||||||
|
|
||||||
If you need to map a value back to its label, the mapping is always accessible
|
|
||||||
as "categories" on the axis object, e.g. plot.getAxes().xaxis.categories.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function ($) {
|
|
||||||
var options = {
|
|
||||||
xaxis: {
|
|
||||||
categories: null
|
|
||||||
},
|
|
||||||
yaxis: {
|
|
||||||
categories: null
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function processRawData(plot, series, data, datapoints) {
|
|
||||||
// if categories are enabled, we need to disable
|
|
||||||
// auto-transformation to numbers so the strings are intact
|
|
||||||
// for later processing
|
|
||||||
|
|
||||||
var xCategories = series.xaxis.options.mode == "categories",
|
|
||||||
yCategories = series.yaxis.options.mode == "categories";
|
|
||||||
|
|
||||||
if (!(xCategories || yCategories))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var format = datapoints.format;
|
|
||||||
|
|
||||||
if (!format) {
|
|
||||||
// FIXME: auto-detection should really not be defined here
|
|
||||||
var s = series;
|
|
||||||
format = [];
|
|
||||||
format.push({ x: true, number: true, required: true });
|
|
||||||
format.push({ y: true, number: true, required: true });
|
|
||||||
|
|
||||||
if (s.bars.show || (s.lines.show && s.lines.fill)) {
|
|
||||||
var autoscale = !!((s.bars.show && s.bars.zero) || (s.lines.show && s.lines.zero));
|
|
||||||
format.push({ y: true, number: true, required: false, defaultValue: 0, autoscale: autoscale });
|
|
||||||
if (s.bars.horizontal) {
|
|
||||||
delete format[format.length - 1].y;
|
|
||||||
format[format.length - 1].x = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
datapoints.format = format;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var m = 0; m < format.length; ++m) {
|
|
||||||
if (format[m].x && xCategories)
|
|
||||||
format[m].number = false;
|
|
||||||
|
|
||||||
if (format[m].y && yCategories)
|
|
||||||
format[m].number = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getNextIndex(categories) {
|
|
||||||
var index = -1;
|
|
||||||
|
|
||||||
for (var v in categories)
|
|
||||||
if (categories[v] > index)
|
|
||||||
index = categories[v];
|
|
||||||
|
|
||||||
return index + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function categoriesTickGenerator(axis) {
|
|
||||||
var res = [];
|
|
||||||
for (var label in axis.categories) {
|
|
||||||
var v = axis.categories[label];
|
|
||||||
if (v >= axis.min && v <= axis.max)
|
|
||||||
res.push([v, label]);
|
|
||||||
}
|
|
||||||
|
|
||||||
res.sort(function (a, b) { return a[0] - b[0]; });
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setupCategoriesForAxis(series, axis, datapoints) {
|
|
||||||
if (series[axis].options.mode != "categories")
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!series[axis].categories) {
|
|
||||||
// parse options
|
|
||||||
var c = {}, o = series[axis].options.categories || {};
|
|
||||||
if ($.isArray(o)) {
|
|
||||||
for (var i = 0; i < o.length; ++i)
|
|
||||||
c[o[i]] = i;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (var v in o)
|
|
||||||
c[v] = o[v];
|
|
||||||
}
|
|
||||||
|
|
||||||
series[axis].categories = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
// fix ticks
|
|
||||||
if (!series[axis].options.ticks)
|
|
||||||
series[axis].options.ticks = categoriesTickGenerator;
|
|
||||||
|
|
||||||
transformPointsOnAxis(datapoints, axis, series[axis].categories);
|
|
||||||
}
|
|
||||||
|
|
||||||
function transformPointsOnAxis(datapoints, axis, categories) {
|
|
||||||
// go through the points, transforming them
|
|
||||||
var points = datapoints.points,
|
|
||||||
ps = datapoints.pointsize,
|
|
||||||
format = datapoints.format,
|
|
||||||
formatColumn = axis.charAt(0),
|
|
||||||
index = getNextIndex(categories);
|
|
||||||
|
|
||||||
for (var i = 0; i < points.length; i += ps) {
|
|
||||||
if (points[i] == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (var m = 0; m < ps; ++m) {
|
|
||||||
var val = points[i + m];
|
|
||||||
|
|
||||||
if (val == null || !format[m][formatColumn])
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!(val in categories)) {
|
|
||||||
categories[val] = index;
|
|
||||||
++index;
|
|
||||||
}
|
|
||||||
|
|
||||||
points[i + m] = categories[val];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function processDatapoints(plot, series, datapoints) {
|
|
||||||
setupCategoriesForAxis(series, "xaxis", datapoints);
|
|
||||||
setupCategoriesForAxis(series, "yaxis", datapoints);
|
|
||||||
}
|
|
||||||
|
|
||||||
function init(plot) {
|
|
||||||
plot.hooks.processRawData.push(processRawData);
|
|
||||||
plot.hooks.processDatapoints.push(processDatapoints);
|
|
||||||
}
|
|
||||||
|
|
||||||
$.plot.plugins.push({
|
|
||||||
init: init,
|
|
||||||
options: options,
|
|
||||||
name: 'categories',
|
|
||||||
version: '1.0'
|
|
||||||
});
|
|
||||||
})(jQuery);
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,432 +0,0 @@
|
|||||||
/* Pretty handling of time axes.
|
|
||||||
|
|
||||||
Copyright (c) 2007-2014 IOLA and Ole Laursen.
|
|
||||||
Licensed under the MIT license.
|
|
||||||
|
|
||||||
Set axis.mode to "time" to enable. See the section "Time series data" in
|
|
||||||
API.txt for details.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function($) {
|
|
||||||
|
|
||||||
var options = {
|
|
||||||
xaxis: {
|
|
||||||
timezone: null, // "browser" for local to the client or timezone for timezone-js
|
|
||||||
timeformat: null, // format string to use
|
|
||||||
twelveHourClock: false, // 12 or 24 time in time mode
|
|
||||||
monthNames: null // list of names of months
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// round to nearby lower multiple of base
|
|
||||||
|
|
||||||
function floorInBase(n, base) {
|
|
||||||
return base * Math.floor(n / base);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a string with the date d formatted according to fmt.
|
|
||||||
// A subset of the Open Group's strftime format is supported.
|
|
||||||
|
|
||||||
function formatDate(d, fmt, monthNames, dayNames) {
|
|
||||||
|
|
||||||
if (typeof d.strftime == "function") {
|
|
||||||
return d.strftime(fmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
var leftPad = function(n, pad) {
|
|
||||||
n = "" + n;
|
|
||||||
pad = "" + (pad == null ? "0" : pad);
|
|
||||||
return n.length == 1 ? pad + n : n;
|
|
||||||
};
|
|
||||||
|
|
||||||
var r = [];
|
|
||||||
var escape = false;
|
|
||||||
var hours = d.getHours();
|
|
||||||
var isAM = hours < 12;
|
|
||||||
|
|
||||||
if (monthNames == null) {
|
|
||||||
monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dayNames == null) {
|
|
||||||
dayNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
||||||
}
|
|
||||||
|
|
||||||
var hours12;
|
|
||||||
|
|
||||||
if (hours > 12) {
|
|
||||||
hours12 = hours - 12;
|
|
||||||
} else if (hours == 0) {
|
|
||||||
hours12 = 12;
|
|
||||||
} else {
|
|
||||||
hours12 = hours;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < fmt.length; ++i) {
|
|
||||||
|
|
||||||
var c = fmt.charAt(i);
|
|
||||||
|
|
||||||
if (escape) {
|
|
||||||
switch (c) {
|
|
||||||
case 'a': c = "" + dayNames[d.getDay()]; break;
|
|
||||||
case 'b': c = "" + monthNames[d.getMonth()]; break;
|
|
||||||
case 'd': c = leftPad(d.getDate()); break;
|
|
||||||
case 'e': c = leftPad(d.getDate(), " "); break;
|
|
||||||
case 'h': // For back-compat with 0.7; remove in 1.0
|
|
||||||
case 'H': c = leftPad(hours); break;
|
|
||||||
case 'I': c = leftPad(hours12); break;
|
|
||||||
case 'l': c = leftPad(hours12, " "); break;
|
|
||||||
case 'm': c = leftPad(d.getMonth() + 1); break;
|
|
||||||
case 'M': c = leftPad(d.getMinutes()); break;
|
|
||||||
// quarters not in Open Group's strftime specification
|
|
||||||
case 'q':
|
|
||||||
c = "" + (Math.floor(d.getMonth() / 3) + 1); break;
|
|
||||||
case 'S': c = leftPad(d.getSeconds()); break;
|
|
||||||
case 'y': c = leftPad(d.getFullYear() % 100); break;
|
|
||||||
case 'Y': c = "" + d.getFullYear(); break;
|
|
||||||
case 'p': c = (isAM) ? ("" + "am") : ("" + "pm"); break;
|
|
||||||
case 'P': c = (isAM) ? ("" + "AM") : ("" + "PM"); break;
|
|
||||||
case 'w': c = "" + d.getDay(); break;
|
|
||||||
}
|
|
||||||
r.push(c);
|
|
||||||
escape = false;
|
|
||||||
} else {
|
|
||||||
if (c == "%") {
|
|
||||||
escape = true;
|
|
||||||
} else {
|
|
||||||
r.push(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return r.join("");
|
|
||||||
}
|
|
||||||
|
|
||||||
// To have a consistent view of time-based data independent of which time
|
|
||||||
// zone the client happens to be in we need a date-like object independent
|
|
||||||
// of time zones. This is done through a wrapper that only calls the UTC
|
|
||||||
// versions of the accessor methods.
|
|
||||||
|
|
||||||
function makeUtcWrapper(d) {
|
|
||||||
|
|
||||||
function addProxyMethod(sourceObj, sourceMethod, targetObj, targetMethod) {
|
|
||||||
sourceObj[sourceMethod] = function() {
|
|
||||||
return targetObj[targetMethod].apply(targetObj, arguments);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
var utc = {
|
|
||||||
date: d
|
|
||||||
};
|
|
||||||
|
|
||||||
// support strftime, if found
|
|
||||||
|
|
||||||
if (d.strftime != undefined) {
|
|
||||||
addProxyMethod(utc, "strftime", d, "strftime");
|
|
||||||
}
|
|
||||||
|
|
||||||
addProxyMethod(utc, "getTime", d, "getTime");
|
|
||||||
addProxyMethod(utc, "setTime", d, "setTime");
|
|
||||||
|
|
||||||
var props = ["Date", "Day", "FullYear", "Hours", "Milliseconds", "Minutes", "Month", "Seconds"];
|
|
||||||
|
|
||||||
for (var p = 0; p < props.length; p++) {
|
|
||||||
addProxyMethod(utc, "get" + props[p], d, "getUTC" + props[p]);
|
|
||||||
addProxyMethod(utc, "set" + props[p], d, "setUTC" + props[p]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return utc;
|
|
||||||
};
|
|
||||||
|
|
||||||
// select time zone strategy. This returns a date-like object tied to the
|
|
||||||
// desired timezone
|
|
||||||
|
|
||||||
function dateGenerator(ts, opts) {
|
|
||||||
if (opts.timezone == "browser") {
|
|
||||||
return new Date(ts);
|
|
||||||
} else if (!opts.timezone || opts.timezone == "utc") {
|
|
||||||
return makeUtcWrapper(new Date(ts));
|
|
||||||
} else if (typeof timezoneJS != "undefined" && typeof timezoneJS.Date != "undefined") {
|
|
||||||
var d = new timezoneJS.Date();
|
|
||||||
// timezone-js is fickle, so be sure to set the time zone before
|
|
||||||
// setting the time.
|
|
||||||
d.setTimezone(opts.timezone);
|
|
||||||
d.setTime(ts);
|
|
||||||
return d;
|
|
||||||
} else {
|
|
||||||
return makeUtcWrapper(new Date(ts));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// map of app. size of time units in milliseconds
|
|
||||||
|
|
||||||
var timeUnitSize = {
|
|
||||||
"second": 1000,
|
|
||||||
"minute": 60 * 1000,
|
|
||||||
"hour": 60 * 60 * 1000,
|
|
||||||
"day": 24 * 60 * 60 * 1000,
|
|
||||||
"month": 30 * 24 * 60 * 60 * 1000,
|
|
||||||
"quarter": 3 * 30 * 24 * 60 * 60 * 1000,
|
|
||||||
"year": 365.2425 * 24 * 60 * 60 * 1000
|
|
||||||
};
|
|
||||||
|
|
||||||
// the allowed tick sizes, after 1 year we use
|
|
||||||
// an integer algorithm
|
|
||||||
|
|
||||||
var baseSpec = [
|
|
||||||
[1, "second"], [2, "second"], [5, "second"], [10, "second"],
|
|
||||||
[30, "second"],
|
|
||||||
[1, "minute"], [2, "minute"], [5, "minute"], [10, "minute"],
|
|
||||||
[30, "minute"],
|
|
||||||
[1, "hour"], [2, "hour"], [4, "hour"],
|
|
||||||
[8, "hour"], [12, "hour"],
|
|
||||||
[1, "day"], [2, "day"], [3, "day"],
|
|
||||||
[0.25, "month"], [0.5, "month"], [1, "month"],
|
|
||||||
[2, "month"]
|
|
||||||
];
|
|
||||||
|
|
||||||
// we don't know which variant(s) we'll need yet, but generating both is
|
|
||||||
// cheap
|
|
||||||
|
|
||||||
var specMonths = baseSpec.concat([[3, "month"], [6, "month"],
|
|
||||||
[1, "year"]]);
|
|
||||||
var specQuarters = baseSpec.concat([[1, "quarter"], [2, "quarter"],
|
|
||||||
[1, "year"]]);
|
|
||||||
|
|
||||||
function init(plot) {
|
|
||||||
plot.hooks.processOptions.push(function (plot, options) {
|
|
||||||
$.each(plot.getAxes(), function(axisName, axis) {
|
|
||||||
|
|
||||||
var opts = axis.options;
|
|
||||||
|
|
||||||
if (opts.mode == "time") {
|
|
||||||
axis.tickGenerator = function(axis) {
|
|
||||||
|
|
||||||
var ticks = [];
|
|
||||||
var d = dateGenerator(axis.min, opts);
|
|
||||||
var minSize = 0;
|
|
||||||
|
|
||||||
// make quarter use a possibility if quarters are
|
|
||||||
// mentioned in either of these options
|
|
||||||
|
|
||||||
var spec = (opts.tickSize && opts.tickSize[1] ===
|
|
||||||
"quarter") ||
|
|
||||||
(opts.minTickSize && opts.minTickSize[1] ===
|
|
||||||
"quarter") ? specQuarters : specMonths;
|
|
||||||
|
|
||||||
if (opts.minTickSize != null) {
|
|
||||||
if (typeof opts.tickSize == "number") {
|
|
||||||
minSize = opts.tickSize;
|
|
||||||
} else {
|
|
||||||
minSize = opts.minTickSize[0] * timeUnitSize[opts.minTickSize[1]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < spec.length - 1; ++i) {
|
|
||||||
if (axis.delta < (spec[i][0] * timeUnitSize[spec[i][1]]
|
|
||||||
+ spec[i + 1][0] * timeUnitSize[spec[i + 1][1]]) / 2
|
|
||||||
&& spec[i][0] * timeUnitSize[spec[i][1]] >= minSize) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var size = spec[i][0];
|
|
||||||
var unit = spec[i][1];
|
|
||||||
|
|
||||||
// special-case the possibility of several years
|
|
||||||
|
|
||||||
if (unit == "year") {
|
|
||||||
|
|
||||||
// if given a minTickSize in years, just use it,
|
|
||||||
// ensuring that it's an integer
|
|
||||||
|
|
||||||
if (opts.minTickSize != null && opts.minTickSize[1] == "year") {
|
|
||||||
size = Math.floor(opts.minTickSize[0]);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
var magn = Math.pow(10, Math.floor(Math.log(axis.delta / timeUnitSize.year) / Math.LN10));
|
|
||||||
var norm = (axis.delta / timeUnitSize.year) / magn;
|
|
||||||
|
|
||||||
if (norm < 1.5) {
|
|
||||||
size = 1;
|
|
||||||
} else if (norm < 3) {
|
|
||||||
size = 2;
|
|
||||||
} else if (norm < 7.5) {
|
|
||||||
size = 5;
|
|
||||||
} else {
|
|
||||||
size = 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
size *= magn;
|
|
||||||
}
|
|
||||||
|
|
||||||
// minimum size for years is 1
|
|
||||||
|
|
||||||
if (size < 1) {
|
|
||||||
size = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
axis.tickSize = opts.tickSize || [size, unit];
|
|
||||||
var tickSize = axis.tickSize[0];
|
|
||||||
unit = axis.tickSize[1];
|
|
||||||
|
|
||||||
var step = tickSize * timeUnitSize[unit];
|
|
||||||
|
|
||||||
if (unit == "second") {
|
|
||||||
d.setSeconds(floorInBase(d.getSeconds(), tickSize));
|
|
||||||
} else if (unit == "minute") {
|
|
||||||
d.setMinutes(floorInBase(d.getMinutes(), tickSize));
|
|
||||||
} else if (unit == "hour") {
|
|
||||||
d.setHours(floorInBase(d.getHours(), tickSize));
|
|
||||||
} else if (unit == "month") {
|
|
||||||
d.setMonth(floorInBase(d.getMonth(), tickSize));
|
|
||||||
} else if (unit == "quarter") {
|
|
||||||
d.setMonth(3 * floorInBase(d.getMonth() / 3,
|
|
||||||
tickSize));
|
|
||||||
} else if (unit == "year") {
|
|
||||||
d.setFullYear(floorInBase(d.getFullYear(), tickSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset smaller components
|
|
||||||
|
|
||||||
d.setMilliseconds(0);
|
|
||||||
|
|
||||||
if (step >= timeUnitSize.minute) {
|
|
||||||
d.setSeconds(0);
|
|
||||||
}
|
|
||||||
if (step >= timeUnitSize.hour) {
|
|
||||||
d.setMinutes(0);
|
|
||||||
}
|
|
||||||
if (step >= timeUnitSize.day) {
|
|
||||||
d.setHours(0);
|
|
||||||
}
|
|
||||||
if (step >= timeUnitSize.day * 4) {
|
|
||||||
d.setDate(1);
|
|
||||||
}
|
|
||||||
if (step >= timeUnitSize.month * 2) {
|
|
||||||
d.setMonth(floorInBase(d.getMonth(), 3));
|
|
||||||
}
|
|
||||||
if (step >= timeUnitSize.quarter * 2) {
|
|
||||||
d.setMonth(floorInBase(d.getMonth(), 6));
|
|
||||||
}
|
|
||||||
if (step >= timeUnitSize.year) {
|
|
||||||
d.setMonth(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
var carry = 0;
|
|
||||||
var v = Number.NaN;
|
|
||||||
var prev;
|
|
||||||
|
|
||||||
do {
|
|
||||||
|
|
||||||
prev = v;
|
|
||||||
v = d.getTime();
|
|
||||||
ticks.push(v);
|
|
||||||
|
|
||||||
if (unit == "month" || unit == "quarter") {
|
|
||||||
if (tickSize < 1) {
|
|
||||||
|
|
||||||
// a bit complicated - we'll divide the
|
|
||||||
// month/quarter up but we need to take
|
|
||||||
// care of fractions so we don't end up in
|
|
||||||
// the middle of a day
|
|
||||||
|
|
||||||
d.setDate(1);
|
|
||||||
var start = d.getTime();
|
|
||||||
d.setMonth(d.getMonth() +
|
|
||||||
(unit == "quarter" ? 3 : 1));
|
|
||||||
var end = d.getTime();
|
|
||||||
d.setTime(v + carry * timeUnitSize.hour + (end - start) * tickSize);
|
|
||||||
carry = d.getHours();
|
|
||||||
d.setHours(0);
|
|
||||||
} else {
|
|
||||||
d.setMonth(d.getMonth() +
|
|
||||||
tickSize * (unit == "quarter" ? 3 : 1));
|
|
||||||
}
|
|
||||||
} else if (unit == "year") {
|
|
||||||
d.setFullYear(d.getFullYear() + tickSize);
|
|
||||||
} else {
|
|
||||||
d.setTime(v + step);
|
|
||||||
}
|
|
||||||
} while (v < axis.max && v != prev);
|
|
||||||
|
|
||||||
return ticks;
|
|
||||||
};
|
|
||||||
|
|
||||||
axis.tickFormatter = function (v, axis) {
|
|
||||||
|
|
||||||
var d = dateGenerator(v, axis.options);
|
|
||||||
|
|
||||||
// first check global format
|
|
||||||
|
|
||||||
if (opts.timeformat != null) {
|
|
||||||
return formatDate(d, opts.timeformat, opts.monthNames, opts.dayNames);
|
|
||||||
}
|
|
||||||
|
|
||||||
// possibly use quarters if quarters are mentioned in
|
|
||||||
// any of these places
|
|
||||||
|
|
||||||
var useQuarters = (axis.options.tickSize &&
|
|
||||||
axis.options.tickSize[1] == "quarter") ||
|
|
||||||
(axis.options.minTickSize &&
|
|
||||||
axis.options.minTickSize[1] == "quarter");
|
|
||||||
|
|
||||||
var t = axis.tickSize[0] * timeUnitSize[axis.tickSize[1]];
|
|
||||||
var span = axis.max - axis.min;
|
|
||||||
var suffix = (opts.twelveHourClock) ? " %p" : "";
|
|
||||||
var hourCode = (opts.twelveHourClock) ? "%I" : "%H";
|
|
||||||
var fmt;
|
|
||||||
|
|
||||||
if (t < timeUnitSize.minute) {
|
|
||||||
fmt = hourCode + ":%M:%S" + suffix;
|
|
||||||
} else if (t < timeUnitSize.day) {
|
|
||||||
if (span < 2 * timeUnitSize.day) {
|
|
||||||
fmt = hourCode + ":%M" + suffix;
|
|
||||||
} else {
|
|
||||||
fmt = "%b %d " + hourCode + ":%M" + suffix;
|
|
||||||
}
|
|
||||||
} else if (t < timeUnitSize.month) {
|
|
||||||
fmt = "%b %d";
|
|
||||||
} else if ((useQuarters && t < timeUnitSize.quarter) ||
|
|
||||||
(!useQuarters && t < timeUnitSize.year)) {
|
|
||||||
if (span < timeUnitSize.year) {
|
|
||||||
fmt = "%b";
|
|
||||||
} else {
|
|
||||||
fmt = "%b %Y";
|
|
||||||
}
|
|
||||||
} else if (useQuarters && t < timeUnitSize.year) {
|
|
||||||
if (span < timeUnitSize.year) {
|
|
||||||
fmt = "Q%q";
|
|
||||||
} else {
|
|
||||||
fmt = "Q%q %Y";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt = "%Y";
|
|
||||||
}
|
|
||||||
|
|
||||||
var rt = formatDate(d, fmt, opts.monthNames, opts.dayNames);
|
|
||||||
|
|
||||||
return rt;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$.plot.plugins.push({
|
|
||||||
init: init,
|
|
||||||
options: options,
|
|
||||||
name: 'time',
|
|
||||||
version: '1.0'
|
|
||||||
});
|
|
||||||
|
|
||||||
// Time-axis support used to be in Flot core, which exposed the
|
|
||||||
// formatDate function on the plot object. Various plugins depend
|
|
||||||
// on the function, so we need to re-expose it here.
|
|
||||||
|
|
||||||
$.plot.formatDate = formatDate;
|
|
||||||
$.plot.dateGenerator = dateGenerator;
|
|
||||||
|
|
||||||
})(jQuery);
|
|
||||||
@ -34,7 +34,6 @@
|
|||||||
</span>ago.
|
</span>ago.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
<h3>Players</h3>
|
<h3>Players</h3>
|
||||||
<table id="player_stats" class="table table-hover">
|
<table id="player_stats" class="table table-hover">
|
||||||
<thead>
|
<thead>
|
||||||
@ -56,84 +55,9 @@
|
|||||||
|
|
||||||
<h3>Weekly history</h3>
|
<h3>Weekly history</h3>
|
||||||
<img src="{% static 'graphs/' %}week-{{graph_file}}.png" />
|
<img src="{% static 'graphs/' %}week-{{graph_file}}.png" />
|
||||||
<div id="weekly_history"></div>
|
|
||||||
<h3>Average per day</h3>
|
<h3>Average per day</h3>
|
||||||
<img src="{% static 'graphs/' %}avg_days-{{graph_file}}.png" />
|
<img src="{% static 'graphs/' %}avg_days-{{graph_file}}.png" />
|
||||||
<div id="weekday_averages"></div>
|
|
||||||
<div id="tooltip"></div>
|
|
||||||
|
|
||||||
<script type="text/javascript" src="{% static 'js/jquery.min.js' %}"></script>
|
|
||||||
<script type="text/javascript" src="{% static 'js/jquery.flot.js' %}"></script>
|
|
||||||
<script type="text/javascript" src="{% static 'js/jquery.flot.time.js' %}"></script>
|
|
||||||
<script type="text/javascript" src="{% static 'js/jquery.flot.categories.js' %}"></script>
|
|
||||||
<script type="text/javascript">
|
|
||||||
$(function() {
|
|
||||||
var data = [
|
|
||||||
{# convert timestamp to ms, because javascript... #}
|
|
||||||
{% for item in weekly_history %}
|
|
||||||
[{{item.created|date:'U'}} * 1000, {{item.players}}],
|
|
||||||
{% endfor %}
|
|
||||||
];
|
|
||||||
$.plot("#weekly_history", [data], {
|
|
||||||
xaxis: {
|
|
||||||
mode: "time",
|
|
||||||
timezone: "browser",
|
|
||||||
},
|
|
||||||
lines: {
|
|
||||||
show: true,
|
|
||||||
fill: true,
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
hoverable: true,
|
|
||||||
borderWidth: 0,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
var data= [
|
|
||||||
{% for day, players in averages_for_weekdays %}
|
|
||||||
["{{day}}", {{players}}],
|
|
||||||
{% endfor %}
|
|
||||||
];
|
|
||||||
$.plot("#weekday_averages", [data], {
|
|
||||||
xaxis: {
|
|
||||||
mode: "categories",
|
|
||||||
},
|
|
||||||
bars: {
|
|
||||||
show: true,
|
|
||||||
barWidth: 0.75,
|
|
||||||
align: "center",
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
hoverable: true,
|
|
||||||
borderWidth: 0,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#weekly_history").bind("plothover", function (event, pos, item) {
|
|
||||||
if (item) {
|
|
||||||
var time = item.datapoint[0];
|
|
||||||
var players = item.datapoint[1];
|
|
||||||
var timestamp = new Date(time).toString();
|
|
||||||
$("#tooltip")
|
|
||||||
.html(players + " players at " + timestamp)
|
|
||||||
.css({top: item.pageY+5, left: item.pageX+5})
|
|
||||||
.fadeIn(200);
|
|
||||||
} else {
|
|
||||||
$("#tooltip").hide();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$("#weekday_averages").bind("plothover", function (event, pos, item) {
|
|
||||||
if (item) {
|
|
||||||
var players = item.datapoint[1];
|
|
||||||
$("#tooltip")
|
|
||||||
.html(players + " players")
|
|
||||||
.css({top: item.pageY+5, left: item.pageX+5})
|
|
||||||
.fadeIn(200);
|
|
||||||
} else {
|
|
||||||
$("#tooltip").hide();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user