columbus3 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.textile +62 -0
- data/bower_components/flot/.bower.json +19 -0
- data/bower_components/flot/.gitignore +3 -0
- data/bower_components/flot/.travis.yml +3 -0
- data/bower_components/flot/API.md +1498 -0
- data/bower_components/flot/CONTRIBUTING.md +98 -0
- data/bower_components/flot/FAQ.md +75 -0
- data/bower_components/flot/LICENSE.txt +22 -0
- data/bower_components/flot/Makefile +12 -0
- data/bower_components/flot/NEWS.md +1026 -0
- data/bower_components/flot/PLUGINS.md +143 -0
- data/bower_components/flot/README.md +110 -0
- data/bower_components/flot/component.json +8 -0
- data/bower_components/flot/examples/ajax/data-eu-gdp-growth-1.json +4 -0
- data/bower_components/flot/examples/ajax/data-eu-gdp-growth-2.json +4 -0
- data/bower_components/flot/examples/ajax/data-eu-gdp-growth-3.json +4 -0
- data/bower_components/flot/examples/ajax/data-eu-gdp-growth-4.json +4 -0
- data/bower_components/flot/examples/ajax/data-eu-gdp-growth-5.json +4 -0
- data/bower_components/flot/examples/ajax/data-eu-gdp-growth.json +4 -0
- data/bower_components/flot/examples/ajax/data-japan-gdp-growth.json +4 -0
- data/bower_components/flot/examples/ajax/data-usa-gdp-growth.json +4 -0
- data/bower_components/flot/examples/ajax/index.html +173 -0
- data/bower_components/flot/examples/annotating/index.html +87 -0
- data/bower_components/flot/examples/axes-interacting/index.html +97 -0
- data/bower_components/flot/examples/axes-multiple/index.html +77 -0
- data/bower_components/flot/examples/axes-time-zones/date.js +893 -0
- data/bower_components/flot/examples/axes-time-zones/index.html +114 -0
- data/bower_components/flot/examples/axes-time-zones/tz/africa +1181 -0
- data/bower_components/flot/examples/axes-time-zones/tz/antarctica +413 -0
- data/bower_components/flot/examples/axes-time-zones/tz/asia +2717 -0
- data/bower_components/flot/examples/axes-time-zones/tz/australasia +1719 -0
- data/bower_components/flot/examples/axes-time-zones/tz/backward +117 -0
- data/bower_components/flot/examples/axes-time-zones/tz/etcetera +81 -0
- data/bower_components/flot/examples/axes-time-zones/tz/europe +2856 -0
- data/bower_components/flot/examples/axes-time-zones/tz/factory +10 -0
- data/bower_components/flot/examples/axes-time-zones/tz/iso3166.tab +276 -0
- data/bower_components/flot/examples/axes-time-zones/tz/leapseconds +100 -0
- data/bower_components/flot/examples/axes-time-zones/tz/northamerica +3235 -0
- data/bower_components/flot/examples/axes-time-zones/tz/pacificnew +28 -0
- data/bower_components/flot/examples/axes-time-zones/tz/solar87 +390 -0
- data/bower_components/flot/examples/axes-time-zones/tz/solar88 +390 -0
- data/bower_components/flot/examples/axes-time-zones/tz/solar89 +395 -0
- data/bower_components/flot/examples/axes-time-zones/tz/southamerica +1711 -0
- data/bower_components/flot/examples/axes-time-zones/tz/systemv +38 -0
- data/bower_components/flot/examples/axes-time-zones/tz/yearistype.sh +38 -0
- data/bower_components/flot/examples/axes-time-zones/tz/zone.tab +441 -0
- data/bower_components/flot/examples/axes-time/index.html +137 -0
- data/bower_components/flot/examples/background.png +0 -0
- data/bower_components/flot/examples/basic-options/index.html +91 -0
- data/bower_components/flot/examples/basic-usage/index.html +57 -0
- data/bower_components/flot/examples/canvas/index.html +75 -0
- data/bower_components/flot/examples/categories/index.html +64 -0
- data/bower_components/flot/examples/examples.css +97 -0
- data/bower_components/flot/examples/image/hs-2004-27-a-large-web.jpg +0 -0
- data/bower_components/flot/examples/image/index.html +69 -0
- data/bower_components/flot/examples/index.html +80 -0
- data/bower_components/flot/examples/interacting/index.html +118 -0
- data/bower_components/flot/examples/navigate/arrow-down.gif +0 -0
- data/bower_components/flot/examples/navigate/arrow-left.gif +0 -0
- data/bower_components/flot/examples/navigate/arrow-right.gif +0 -0
- data/bower_components/flot/examples/navigate/arrow-up.gif +0 -0
- data/bower_components/flot/examples/navigate/index.html +153 -0
- data/bower_components/flot/examples/percentiles/index.html +79 -0
- data/bower_components/flot/examples/realtime/index.html +122 -0
- data/bower_components/flot/examples/resize/index.html +76 -0
- data/bower_components/flot/examples/selection/index.html +152 -0
- data/bower_components/flot/examples/series-errorbars/index.html +150 -0
- data/bower_components/flot/examples/series-pie/index.html +818 -0
- data/bower_components/flot/examples/series-toggle/index.html +121 -0
- data/bower_components/flot/examples/series-types/index.html +90 -0
- data/bower_components/flot/examples/shared/jquery-ui/jquery-ui.min.css +6 -0
- data/bower_components/flot/examples/stacking/index.html +107 -0
- data/bower_components/flot/examples/symbols/index.html +76 -0
- data/bower_components/flot/examples/threshold/index.html +76 -0
- data/bower_components/flot/examples/tracking/index.html +135 -0
- data/bower_components/flot/examples/visitors/index.html +147 -0
- data/bower_components/flot/examples/zooming/index.html +144 -0
- data/bower_components/flot/excanvas.js +1428 -0
- data/bower_components/flot/excanvas.min.js +1 -0
- data/bower_components/flot/flot.jquery.json +27 -0
- data/bower_components/flot/jquery.colorhelpers.js +180 -0
- data/bower_components/flot/jquery.flot.canvas.js +345 -0
- data/bower_components/flot/jquery.flot.categories.js +190 -0
- data/bower_components/flot/jquery.flot.crosshair.js +176 -0
- data/bower_components/flot/jquery.flot.errorbars.js +353 -0
- data/bower_components/flot/jquery.flot.fillbetween.js +226 -0
- data/bower_components/flot/jquery.flot.image.js +241 -0
- data/bower_components/flot/jquery.flot.js +3168 -0
- data/bower_components/flot/jquery.flot.navigate.js +346 -0
- data/bower_components/flot/jquery.flot.pie.js +820 -0
- data/bower_components/flot/jquery.flot.resize.js +59 -0
- data/bower_components/flot/jquery.flot.selection.js +360 -0
- data/bower_components/flot/jquery.flot.stack.js +188 -0
- data/bower_components/flot/jquery.flot.symbol.js +71 -0
- data/bower_components/flot/jquery.flot.threshold.js +142 -0
- data/bower_components/flot/jquery.flot.time.js +432 -0
- data/bower_components/flot/jquery.js +9472 -0
- data/bower_components/flot/package.json +11 -0
- data/bower_components/jquery/.bower.json +38 -0
- data/bower_components/jquery/MIT-LICENSE.txt +21 -0
- data/bower_components/jquery/bower.json +28 -0
- data/bower_components/jquery/dist/jquery.js +9210 -0
- data/bower_components/jquery/dist/jquery.min.js +5 -0
- data/bower_components/jquery/dist/jquery.min.map +1 -0
- data/bower_components/jquery/src/ajax.js +786 -0
- data/bower_components/jquery/src/ajax/jsonp.js +89 -0
- data/bower_components/jquery/src/ajax/load.js +75 -0
- data/bower_components/jquery/src/ajax/parseJSON.js +13 -0
- data/bower_components/jquery/src/ajax/parseXML.js +28 -0
- data/bower_components/jquery/src/ajax/script.js +64 -0
- data/bower_components/jquery/src/ajax/var/nonce.js +5 -0
- data/bower_components/jquery/src/ajax/var/rquery.js +3 -0
- data/bower_components/jquery/src/ajax/xhr.js +136 -0
- data/bower_components/jquery/src/attributes.js +11 -0
- data/bower_components/jquery/src/attributes/attr.js +141 -0
- data/bower_components/jquery/src/attributes/classes.js +158 -0
- data/bower_components/jquery/src/attributes/prop.js +94 -0
- data/bower_components/jquery/src/attributes/support.js +35 -0
- data/bower_components/jquery/src/attributes/val.js +161 -0
- data/bower_components/jquery/src/callbacks.js +205 -0
- data/bower_components/jquery/src/core.js +502 -0
- data/bower_components/jquery/src/core/access.js +60 -0
- data/bower_components/jquery/src/core/init.js +123 -0
- data/bower_components/jquery/src/core/parseHTML.js +39 -0
- data/bower_components/jquery/src/core/ready.js +97 -0
- data/bower_components/jquery/src/core/var/rsingleTag.js +4 -0
- data/bower_components/jquery/src/css.js +450 -0
- data/bower_components/jquery/src/css/addGetHookIf.js +22 -0
- data/bower_components/jquery/src/css/curCSS.js +57 -0
- data/bower_components/jquery/src/css/defaultDisplay.js +70 -0
- data/bower_components/jquery/src/css/hiddenVisibleSelectors.js +15 -0
- data/bower_components/jquery/src/css/support.js +96 -0
- data/bower_components/jquery/src/css/swap.js +28 -0
- data/bower_components/jquery/src/css/var/cssExpand.js +3 -0
- data/bower_components/jquery/src/css/var/getStyles.js +12 -0
- data/bower_components/jquery/src/css/var/isHidden.js +13 -0
- data/bower_components/jquery/src/css/var/rmargin.js +3 -0
- data/bower_components/jquery/src/css/var/rnumnonpx.js +5 -0
- data/bower_components/jquery/src/data.js +178 -0
- data/bower_components/jquery/src/data/Data.js +181 -0
- data/bower_components/jquery/src/data/accepts.js +20 -0
- data/bower_components/jquery/src/data/var/data_priv.js +5 -0
- data/bower_components/jquery/src/data/var/data_user.js +5 -0
- data/bower_components/jquery/src/deferred.js +149 -0
- data/bower_components/jquery/src/deprecated.js +13 -0
- data/bower_components/jquery/src/dimensions.js +50 -0
- data/bower_components/jquery/src/effects.js +648 -0
- data/bower_components/jquery/src/effects/Tween.js +114 -0
- data/bower_components/jquery/src/effects/animatedSelector.js +13 -0
- data/bower_components/jquery/src/event.js +868 -0
- data/bower_components/jquery/src/event/ajax.js +13 -0
- data/bower_components/jquery/src/event/alias.js +39 -0
- data/bower_components/jquery/src/event/support.js +9 -0
- data/bower_components/jquery/src/exports/amd.js +24 -0
- data/bower_components/jquery/src/exports/global.js +32 -0
- data/bower_components/jquery/src/intro.js +44 -0
- data/bower_components/jquery/src/jquery.js +37 -0
- data/bower_components/jquery/src/manipulation.js +580 -0
- data/bower_components/jquery/src/manipulation/_evalUrl.js +18 -0
- data/bower_components/jquery/src/manipulation/support.js +32 -0
- data/bower_components/jquery/src/manipulation/var/rcheckableType.js +3 -0
- data/bower_components/jquery/src/offset.js +207 -0
- data/bower_components/jquery/src/outro.js +1 -0
- data/bower_components/jquery/src/queue.js +142 -0
- data/bower_components/jquery/src/queue/delay.js +22 -0
- data/bower_components/jquery/src/selector-native.js +172 -0
- data/bower_components/jquery/src/selector-sizzle.js +14 -0
- data/bower_components/jquery/src/selector.js +1 -0
- data/bower_components/jquery/src/serialize.js +111 -0
- data/bower_components/jquery/src/sizzle/dist/sizzle.js +2067 -0
- data/bower_components/jquery/src/sizzle/dist/sizzle.min.js +3 -0
- data/bower_components/jquery/src/sizzle/dist/sizzle.min.map +1 -0
- data/bower_components/jquery/src/traversing.js +199 -0
- data/bower_components/jquery/src/traversing/findFilter.js +100 -0
- data/bower_components/jquery/src/traversing/var/rneedsContext.js +6 -0
- data/bower_components/jquery/src/var/arr.js +3 -0
- data/bower_components/jquery/src/var/class2type.js +4 -0
- data/bower_components/jquery/src/var/concat.js +5 -0
- data/bower_components/jquery/src/var/hasOwn.js +5 -0
- data/bower_components/jquery/src/var/indexOf.js +5 -0
- data/bower_components/jquery/src/var/pnum.js +3 -0
- data/bower_components/jquery/src/var/push.js +5 -0
- data/bower_components/jquery/src/var/rnotwhite.js +3 -0
- data/bower_components/jquery/src/var/slice.js +5 -0
- data/bower_components/jquery/src/var/strundefined.js +3 -0
- data/bower_components/jquery/src/var/support.js +4 -0
- data/bower_components/jquery/src/var/toString.js +5 -0
- data/bower_components/jquery/src/wrap.js +79 -0
- data/columbus3.gemspec +1 -1
- data/exe/columbus3 +72 -7
- data/lib/columbus3.rb +2 -1
- data/lib/columbus3/metadata/sidecar.rb +10 -1
- data/lib/columbus3/renderer/flot_renderer.rb +66 -0
- data/lib/columbus3/renderer/{renderer.rb → leaflet_renderer.rb} +0 -0
- data/lib/columbus3/version.rb +1 -1
- data/lib/html/flot.html.erb +106 -0
- metadata +194 -5
- data/README.md +0 -41
@@ -0,0 +1,190 @@
|
|
1
|
+
/* Flot plugin for plotting textual data or categories.
|
2
|
+
|
3
|
+
Copyright (c) 2007-2014 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,0 +1,176 @@
|
|
1
|
+
/* Flot plugin for showing crosshairs when the mouse hovers over the plot.
|
2
|
+
|
3
|
+
Copyright (c) 2007-2014 IOLA and Ole Laursen.
|
4
|
+
Licensed under the MIT license.
|
5
|
+
|
6
|
+
The plugin supports these options:
|
7
|
+
|
8
|
+
crosshair: {
|
9
|
+
mode: null or "x" or "y" or "xy"
|
10
|
+
color: color
|
11
|
+
lineWidth: number
|
12
|
+
}
|
13
|
+
|
14
|
+
Set the mode to one of "x", "y" or "xy". The "x" mode enables a vertical
|
15
|
+
crosshair that lets you trace the values on the x axis, "y" enables a
|
16
|
+
horizontal crosshair and "xy" enables them both. "color" is the color of the
|
17
|
+
crosshair (default is "rgba(170, 0, 0, 0.80)"), "lineWidth" is the width of
|
18
|
+
the drawn lines (default is 1).
|
19
|
+
|
20
|
+
The plugin also adds four public methods:
|
21
|
+
|
22
|
+
- setCrosshair( pos )
|
23
|
+
|
24
|
+
Set the position of the crosshair. Note that this is cleared if the user
|
25
|
+
moves the mouse. "pos" is in coordinates of the plot and should be on the
|
26
|
+
form { x: xpos, y: ypos } (you can use x2/x3/... if you're using multiple
|
27
|
+
axes), which is coincidentally the same format as what you get from a
|
28
|
+
"plothover" event. If "pos" is null, the crosshair is cleared.
|
29
|
+
|
30
|
+
- clearCrosshair()
|
31
|
+
|
32
|
+
Clear the crosshair.
|
33
|
+
|
34
|
+
- lockCrosshair(pos)
|
35
|
+
|
36
|
+
Cause the crosshair to lock to the current location, no longer updating if
|
37
|
+
the user moves the mouse. Optionally supply a position (passed on to
|
38
|
+
setCrosshair()) to move it to.
|
39
|
+
|
40
|
+
Example usage:
|
41
|
+
|
42
|
+
var myFlot = $.plot( $("#graph"), ..., { crosshair: { mode: "x" } } };
|
43
|
+
$("#graph").bind( "plothover", function ( evt, position, item ) {
|
44
|
+
if ( item ) {
|
45
|
+
// Lock the crosshair to the data point being hovered
|
46
|
+
myFlot.lockCrosshair({
|
47
|
+
x: item.datapoint[ 0 ],
|
48
|
+
y: item.datapoint[ 1 ]
|
49
|
+
});
|
50
|
+
} else {
|
51
|
+
// Return normal crosshair operation
|
52
|
+
myFlot.unlockCrosshair();
|
53
|
+
}
|
54
|
+
});
|
55
|
+
|
56
|
+
- unlockCrosshair()
|
57
|
+
|
58
|
+
Free the crosshair to move again after locking it.
|
59
|
+
*/
|
60
|
+
|
61
|
+
(function ($) {
|
62
|
+
var options = {
|
63
|
+
crosshair: {
|
64
|
+
mode: null, // one of null, "x", "y" or "xy",
|
65
|
+
color: "rgba(170, 0, 0, 0.80)",
|
66
|
+
lineWidth: 1
|
67
|
+
}
|
68
|
+
};
|
69
|
+
|
70
|
+
function init(plot) {
|
71
|
+
// position of crosshair in pixels
|
72
|
+
var crosshair = { x: -1, y: -1, locked: false };
|
73
|
+
|
74
|
+
plot.setCrosshair = function setCrosshair(pos) {
|
75
|
+
if (!pos)
|
76
|
+
crosshair.x = -1;
|
77
|
+
else {
|
78
|
+
var o = plot.p2c(pos);
|
79
|
+
crosshair.x = Math.max(0, Math.min(o.left, plot.width()));
|
80
|
+
crosshair.y = Math.max(0, Math.min(o.top, plot.height()));
|
81
|
+
}
|
82
|
+
|
83
|
+
plot.triggerRedrawOverlay();
|
84
|
+
};
|
85
|
+
|
86
|
+
plot.clearCrosshair = plot.setCrosshair; // passes null for pos
|
87
|
+
|
88
|
+
plot.lockCrosshair = function lockCrosshair(pos) {
|
89
|
+
if (pos)
|
90
|
+
plot.setCrosshair(pos);
|
91
|
+
crosshair.locked = true;
|
92
|
+
};
|
93
|
+
|
94
|
+
plot.unlockCrosshair = function unlockCrosshair() {
|
95
|
+
crosshair.locked = false;
|
96
|
+
};
|
97
|
+
|
98
|
+
function onMouseOut(e) {
|
99
|
+
if (crosshair.locked)
|
100
|
+
return;
|
101
|
+
|
102
|
+
if (crosshair.x != -1) {
|
103
|
+
crosshair.x = -1;
|
104
|
+
plot.triggerRedrawOverlay();
|
105
|
+
}
|
106
|
+
}
|
107
|
+
|
108
|
+
function onMouseMove(e) {
|
109
|
+
if (crosshair.locked)
|
110
|
+
return;
|
111
|
+
|
112
|
+
if (plot.getSelection && plot.getSelection()) {
|
113
|
+
crosshair.x = -1; // hide the crosshair while selecting
|
114
|
+
return;
|
115
|
+
}
|
116
|
+
|
117
|
+
var offset = plot.offset();
|
118
|
+
crosshair.x = Math.max(0, Math.min(e.pageX - offset.left, plot.width()));
|
119
|
+
crosshair.y = Math.max(0, Math.min(e.pageY - offset.top, plot.height()));
|
120
|
+
plot.triggerRedrawOverlay();
|
121
|
+
}
|
122
|
+
|
123
|
+
plot.hooks.bindEvents.push(function (plot, eventHolder) {
|
124
|
+
if (!plot.getOptions().crosshair.mode)
|
125
|
+
return;
|
126
|
+
|
127
|
+
eventHolder.mouseout(onMouseOut);
|
128
|
+
eventHolder.mousemove(onMouseMove);
|
129
|
+
});
|
130
|
+
|
131
|
+
plot.hooks.drawOverlay.push(function (plot, ctx) {
|
132
|
+
var c = plot.getOptions().crosshair;
|
133
|
+
if (!c.mode)
|
134
|
+
return;
|
135
|
+
|
136
|
+
var plotOffset = plot.getPlotOffset();
|
137
|
+
|
138
|
+
ctx.save();
|
139
|
+
ctx.translate(plotOffset.left, plotOffset.top);
|
140
|
+
|
141
|
+
if (crosshair.x != -1) {
|
142
|
+
var adj = plot.getOptions().crosshair.lineWidth % 2 ? 0.5 : 0;
|
143
|
+
|
144
|
+
ctx.strokeStyle = c.color;
|
145
|
+
ctx.lineWidth = c.lineWidth;
|
146
|
+
ctx.lineJoin = "round";
|
147
|
+
|
148
|
+
ctx.beginPath();
|
149
|
+
if (c.mode.indexOf("x") != -1) {
|
150
|
+
var drawX = Math.floor(crosshair.x) + adj;
|
151
|
+
ctx.moveTo(drawX, 0);
|
152
|
+
ctx.lineTo(drawX, plot.height());
|
153
|
+
}
|
154
|
+
if (c.mode.indexOf("y") != -1) {
|
155
|
+
var drawY = Math.floor(crosshair.y) + adj;
|
156
|
+
ctx.moveTo(0, drawY);
|
157
|
+
ctx.lineTo(plot.width(), drawY);
|
158
|
+
}
|
159
|
+
ctx.stroke();
|
160
|
+
}
|
161
|
+
ctx.restore();
|
162
|
+
});
|
163
|
+
|
164
|
+
plot.hooks.shutdown.push(function (plot, eventHolder) {
|
165
|
+
eventHolder.unbind("mouseout", onMouseOut);
|
166
|
+
eventHolder.unbind("mousemove", onMouseMove);
|
167
|
+
});
|
168
|
+
}
|
169
|
+
|
170
|
+
$.plot.plugins.push({
|
171
|
+
init: init,
|
172
|
+
options: options,
|
173
|
+
name: 'crosshair',
|
174
|
+
version: '1.0'
|
175
|
+
});
|
176
|
+
})(jQuery);
|
@@ -0,0 +1,353 @@
|
|
1
|
+
/* Flot plugin for plotting error bars.
|
2
|
+
|
3
|
+
Copyright (c) 2007-2014 IOLA and Ole Laursen.
|
4
|
+
Licensed under the MIT license.
|
5
|
+
|
6
|
+
Error bars are used to show standard deviation and other statistical
|
7
|
+
properties in a plot.
|
8
|
+
|
9
|
+
* Created by Rui Pereira - rui (dot) pereira (at) gmail (dot) com
|
10
|
+
|
11
|
+
This plugin allows you to plot error-bars over points. Set "errorbars" inside
|
12
|
+
the points series to the axis name over which there will be error values in
|
13
|
+
your data array (*even* if you do not intend to plot them later, by setting
|
14
|
+
"show: null" on xerr/yerr).
|
15
|
+
|
16
|
+
The plugin supports these options:
|
17
|
+
|
18
|
+
series: {
|
19
|
+
points: {
|
20
|
+
errorbars: "x" or "y" or "xy",
|
21
|
+
xerr: {
|
22
|
+
show: null/false or true,
|
23
|
+
asymmetric: null/false or true,
|
24
|
+
upperCap: null or "-" or function,
|
25
|
+
lowerCap: null or "-" or function,
|
26
|
+
color: null or color,
|
27
|
+
radius: null or number
|
28
|
+
},
|
29
|
+
yerr: { same options as xerr }
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
Each data point array is expected to be of the type:
|
34
|
+
|
35
|
+
"x" [ x, y, xerr ]
|
36
|
+
"y" [ x, y, yerr ]
|
37
|
+
"xy" [ x, y, xerr, yerr ]
|
38
|
+
|
39
|
+
Where xerr becomes xerr_lower,xerr_upper for the asymmetric error case, and
|
40
|
+
equivalently for yerr. Eg., a datapoint for the "xy" case with symmetric
|
41
|
+
error-bars on X and asymmetric on Y would be:
|
42
|
+
|
43
|
+
[ x, y, xerr, yerr_lower, yerr_upper ]
|
44
|
+
|
45
|
+
By default no end caps are drawn. Setting upperCap and/or lowerCap to "-" will
|
46
|
+
draw a small cap perpendicular to the error bar. They can also be set to a
|
47
|
+
user-defined drawing function, with (ctx, x, y, radius) as parameters, as eg.
|
48
|
+
|
49
|
+
function drawSemiCircle( ctx, x, y, radius ) {
|
50
|
+
ctx.beginPath();
|
51
|
+
ctx.arc( x, y, radius, 0, Math.PI, false );
|
52
|
+
ctx.moveTo( x - radius, y );
|
53
|
+
ctx.lineTo( x + radius, y );
|
54
|
+
ctx.stroke();
|
55
|
+
}
|
56
|
+
|
57
|
+
Color and radius both default to the same ones of the points series if not
|
58
|
+
set. The independent radius parameter on xerr/yerr is useful for the case when
|
59
|
+
we may want to add error-bars to a line, without showing the interconnecting
|
60
|
+
points (with radius: 0), and still showing end caps on the error-bars.
|
61
|
+
shadowSize and lineWidth are derived as well from the points series.
|
62
|
+
|
63
|
+
*/
|
64
|
+
|
65
|
+
(function ($) {
|
66
|
+
var options = {
|
67
|
+
series: {
|
68
|
+
points: {
|
69
|
+
errorbars: null, //should be 'x', 'y' or 'xy'
|
70
|
+
xerr: { err: 'x', show: null, asymmetric: null, upperCap: null, lowerCap: null, color: null, radius: null},
|
71
|
+
yerr: { err: 'y', show: null, asymmetric: null, upperCap: null, lowerCap: null, color: null, radius: null}
|
72
|
+
}
|
73
|
+
}
|
74
|
+
};
|
75
|
+
|
76
|
+
function processRawData(plot, series, data, datapoints){
|
77
|
+
if (!series.points.errorbars)
|
78
|
+
return;
|
79
|
+
|
80
|
+
// x,y values
|
81
|
+
var format = [
|
82
|
+
{ x: true, number: true, required: true },
|
83
|
+
{ y: true, number: true, required: true }
|
84
|
+
];
|
85
|
+
|
86
|
+
var errors = series.points.errorbars;
|
87
|
+
// error bars - first X then Y
|
88
|
+
if (errors == 'x' || errors == 'xy') {
|
89
|
+
// lower / upper error
|
90
|
+
if (series.points.xerr.asymmetric) {
|
91
|
+
format.push({ x: true, number: true, required: true });
|
92
|
+
format.push({ x: true, number: true, required: true });
|
93
|
+
} else
|
94
|
+
format.push({ x: true, number: true, required: true });
|
95
|
+
}
|
96
|
+
if (errors == 'y' || errors == 'xy') {
|
97
|
+
// lower / upper error
|
98
|
+
if (series.points.yerr.asymmetric) {
|
99
|
+
format.push({ y: true, number: true, required: true });
|
100
|
+
format.push({ y: true, number: true, required: true });
|
101
|
+
} else
|
102
|
+
format.push({ y: true, number: true, required: true });
|
103
|
+
}
|
104
|
+
datapoints.format = format;
|
105
|
+
}
|
106
|
+
|
107
|
+
function parseErrors(series, i){
|
108
|
+
|
109
|
+
var points = series.datapoints.points;
|
110
|
+
|
111
|
+
// read errors from points array
|
112
|
+
var exl = null,
|
113
|
+
exu = null,
|
114
|
+
eyl = null,
|
115
|
+
eyu = null;
|
116
|
+
var xerr = series.points.xerr,
|
117
|
+
yerr = series.points.yerr;
|
118
|
+
|
119
|
+
var eb = series.points.errorbars;
|
120
|
+
// error bars - first X
|
121
|
+
if (eb == 'x' || eb == 'xy') {
|
122
|
+
if (xerr.asymmetric) {
|
123
|
+
exl = points[i + 2];
|
124
|
+
exu = points[i + 3];
|
125
|
+
if (eb == 'xy')
|
126
|
+
if (yerr.asymmetric){
|
127
|
+
eyl = points[i + 4];
|
128
|
+
eyu = points[i + 5];
|
129
|
+
} else eyl = points[i + 4];
|
130
|
+
} else {
|
131
|
+
exl = points[i + 2];
|
132
|
+
if (eb == 'xy')
|
133
|
+
if (yerr.asymmetric) {
|
134
|
+
eyl = points[i + 3];
|
135
|
+
eyu = points[i + 4];
|
136
|
+
} else eyl = points[i + 3];
|
137
|
+
}
|
138
|
+
// only Y
|
139
|
+
} else if (eb == 'y')
|
140
|
+
if (yerr.asymmetric) {
|
141
|
+
eyl = points[i + 2];
|
142
|
+
eyu = points[i + 3];
|
143
|
+
} else eyl = points[i + 2];
|
144
|
+
|
145
|
+
// symmetric errors?
|
146
|
+
if (exu == null) exu = exl;
|
147
|
+
if (eyu == null) eyu = eyl;
|
148
|
+
|
149
|
+
var errRanges = [exl, exu, eyl, eyu];
|
150
|
+
// nullify if not showing
|
151
|
+
if (!xerr.show){
|
152
|
+
errRanges[0] = null;
|
153
|
+
errRanges[1] = null;
|
154
|
+
}
|
155
|
+
if (!yerr.show){
|
156
|
+
errRanges[2] = null;
|
157
|
+
errRanges[3] = null;
|
158
|
+
}
|
159
|
+
return errRanges;
|
160
|
+
}
|
161
|
+
|
162
|
+
function drawSeriesErrors(plot, ctx, s){
|
163
|
+
|
164
|
+
var points = s.datapoints.points,
|
165
|
+
ps = s.datapoints.pointsize,
|
166
|
+
ax = [s.xaxis, s.yaxis],
|
167
|
+
radius = s.points.radius,
|
168
|
+
err = [s.points.xerr, s.points.yerr];
|
169
|
+
|
170
|
+
//sanity check, in case some inverted axis hack is applied to flot
|
171
|
+
var invertX = false;
|
172
|
+
if (ax[0].p2c(ax[0].max) < ax[0].p2c(ax[0].min)) {
|
173
|
+
invertX = true;
|
174
|
+
var tmp = err[0].lowerCap;
|
175
|
+
err[0].lowerCap = err[0].upperCap;
|
176
|
+
err[0].upperCap = tmp;
|
177
|
+
}
|
178
|
+
|
179
|
+
var invertY = false;
|
180
|
+
if (ax[1].p2c(ax[1].min) < ax[1].p2c(ax[1].max)) {
|
181
|
+
invertY = true;
|
182
|
+
var tmp = err[1].lowerCap;
|
183
|
+
err[1].lowerCap = err[1].upperCap;
|
184
|
+
err[1].upperCap = tmp;
|
185
|
+
}
|
186
|
+
|
187
|
+
for (var i = 0; i < s.datapoints.points.length; i += ps) {
|
188
|
+
|
189
|
+
//parse
|
190
|
+
var errRanges = parseErrors(s, i);
|
191
|
+
|
192
|
+
//cycle xerr & yerr
|
193
|
+
for (var e = 0; e < err.length; e++){
|
194
|
+
|
195
|
+
var minmax = [ax[e].min, ax[e].max];
|
196
|
+
|
197
|
+
//draw this error?
|
198
|
+
if (errRanges[e * err.length]){
|
199
|
+
|
200
|
+
//data coordinates
|
201
|
+
var x = points[i],
|
202
|
+
y = points[i + 1];
|
203
|
+
|
204
|
+
//errorbar ranges
|
205
|
+
var upper = [x, y][e] + errRanges[e * err.length + 1],
|
206
|
+
lower = [x, y][e] - errRanges[e * err.length];
|
207
|
+
|
208
|
+
//points outside of the canvas
|
209
|
+
if (err[e].err == 'x')
|
210
|
+
if (y > ax[1].max || y < ax[1].min || upper < ax[0].min || lower > ax[0].max)
|
211
|
+
continue;
|
212
|
+
if (err[e].err == 'y')
|
213
|
+
if (x > ax[0].max || x < ax[0].min || upper < ax[1].min || lower > ax[1].max)
|
214
|
+
continue;
|
215
|
+
|
216
|
+
// prevent errorbars getting out of the canvas
|
217
|
+
var drawUpper = true,
|
218
|
+
drawLower = true;
|
219
|
+
|
220
|
+
if (upper > minmax[1]) {
|
221
|
+
drawUpper = false;
|
222
|
+
upper = minmax[1];
|
223
|
+
}
|
224
|
+
if (lower < minmax[0]) {
|
225
|
+
drawLower = false;
|
226
|
+
lower = minmax[0];
|
227
|
+
}
|
228
|
+
|
229
|
+
//sanity check, in case some inverted axis hack is applied to flot
|
230
|
+
if ((err[e].err == 'x' && invertX) || (err[e].err == 'y' && invertY)) {
|
231
|
+
//swap coordinates
|
232
|
+
var tmp = lower;
|
233
|
+
lower = upper;
|
234
|
+
upper = tmp;
|
235
|
+
tmp = drawLower;
|
236
|
+
drawLower = drawUpper;
|
237
|
+
drawUpper = tmp;
|
238
|
+
tmp = minmax[0];
|
239
|
+
minmax[0] = minmax[1];
|
240
|
+
minmax[1] = tmp;
|
241
|
+
}
|
242
|
+
|
243
|
+
// convert to pixels
|
244
|
+
x = ax[0].p2c(x),
|
245
|
+
y = ax[1].p2c(y),
|
246
|
+
upper = ax[e].p2c(upper);
|
247
|
+
lower = ax[e].p2c(lower);
|
248
|
+
minmax[0] = ax[e].p2c(minmax[0]);
|
249
|
+
minmax[1] = ax[e].p2c(minmax[1]);
|
250
|
+
|
251
|
+
//same style as points by default
|
252
|
+
var lw = err[e].lineWidth ? err[e].lineWidth : s.points.lineWidth,
|
253
|
+
sw = s.points.shadowSize != null ? s.points.shadowSize : s.shadowSize;
|
254
|
+
|
255
|
+
//shadow as for points
|
256
|
+
if (lw > 0 && sw > 0) {
|
257
|
+
var w = sw / 2;
|
258
|
+
ctx.lineWidth = w;
|
259
|
+
ctx.strokeStyle = "rgba(0,0,0,0.1)";
|
260
|
+
drawError(ctx, err[e], x, y, upper, lower, drawUpper, drawLower, radius, w + w/2, minmax);
|
261
|
+
|
262
|
+
ctx.strokeStyle = "rgba(0,0,0,0.2)";
|
263
|
+
drawError(ctx, err[e], x, y, upper, lower, drawUpper, drawLower, radius, w/2, minmax);
|
264
|
+
}
|
265
|
+
|
266
|
+
ctx.strokeStyle = err[e].color? err[e].color: s.color;
|
267
|
+
ctx.lineWidth = lw;
|
268
|
+
//draw it
|
269
|
+
drawError(ctx, err[e], x, y, upper, lower, drawUpper, drawLower, radius, 0, minmax);
|
270
|
+
}
|
271
|
+
}
|
272
|
+
}
|
273
|
+
}
|
274
|
+
|
275
|
+
function drawError(ctx,err,x,y,upper,lower,drawUpper,drawLower,radius,offset,minmax){
|
276
|
+
|
277
|
+
//shadow offset
|
278
|
+
y += offset;
|
279
|
+
upper += offset;
|
280
|
+
lower += offset;
|
281
|
+
|
282
|
+
// error bar - avoid plotting over circles
|
283
|
+
if (err.err == 'x'){
|
284
|
+
if (upper > x + radius) drawPath(ctx, [[upper,y],[Math.max(x + radius,minmax[0]),y]]);
|
285
|
+
else drawUpper = false;
|
286
|
+
if (lower < x - radius) drawPath(ctx, [[Math.min(x - radius,minmax[1]),y],[lower,y]] );
|
287
|
+
else drawLower = false;
|
288
|
+
}
|
289
|
+
else {
|
290
|
+
if (upper < y - radius) drawPath(ctx, [[x,upper],[x,Math.min(y - radius,minmax[0])]] );
|
291
|
+
else drawUpper = false;
|
292
|
+
if (lower > y + radius) drawPath(ctx, [[x,Math.max(y + radius,minmax[1])],[x,lower]] );
|
293
|
+
else drawLower = false;
|
294
|
+
}
|
295
|
+
|
296
|
+
//internal radius value in errorbar, allows to plot radius 0 points and still keep proper sized caps
|
297
|
+
//this is a way to get errorbars on lines without visible connecting dots
|
298
|
+
radius = err.radius != null? err.radius: radius;
|
299
|
+
|
300
|
+
// upper cap
|
301
|
+
if (drawUpper) {
|
302
|
+
if (err.upperCap == '-'){
|
303
|
+
if (err.err=='x') drawPath(ctx, [[upper,y - radius],[upper,y + radius]] );
|
304
|
+
else drawPath(ctx, [[x - radius,upper],[x + radius,upper]] );
|
305
|
+
} else if ($.isFunction(err.upperCap)){
|
306
|
+
if (err.err=='x') err.upperCap(ctx, upper, y, radius);
|
307
|
+
else err.upperCap(ctx, x, upper, radius);
|
308
|
+
}
|
309
|
+
}
|
310
|
+
// lower cap
|
311
|
+
if (drawLower) {
|
312
|
+
if (err.lowerCap == '-'){
|
313
|
+
if (err.err=='x') drawPath(ctx, [[lower,y - radius],[lower,y + radius]] );
|
314
|
+
else drawPath(ctx, [[x - radius,lower],[x + radius,lower]] );
|
315
|
+
} else if ($.isFunction(err.lowerCap)){
|
316
|
+
if (err.err=='x') err.lowerCap(ctx, lower, y, radius);
|
317
|
+
else err.lowerCap(ctx, x, lower, radius);
|
318
|
+
}
|
319
|
+
}
|
320
|
+
}
|
321
|
+
|
322
|
+
function drawPath(ctx, pts){
|
323
|
+
ctx.beginPath();
|
324
|
+
ctx.moveTo(pts[0][0], pts[0][1]);
|
325
|
+
for (var p=1; p < pts.length; p++)
|
326
|
+
ctx.lineTo(pts[p][0], pts[p][1]);
|
327
|
+
ctx.stroke();
|
328
|
+
}
|
329
|
+
|
330
|
+
function draw(plot, ctx){
|
331
|
+
var plotOffset = plot.getPlotOffset();
|
332
|
+
|
333
|
+
ctx.save();
|
334
|
+
ctx.translate(plotOffset.left, plotOffset.top);
|
335
|
+
$.each(plot.getData(), function (i, s) {
|
336
|
+
if (s.points.errorbars && (s.points.xerr.show || s.points.yerr.show))
|
337
|
+
drawSeriesErrors(plot, ctx, s);
|
338
|
+
});
|
339
|
+
ctx.restore();
|
340
|
+
}
|
341
|
+
|
342
|
+
function init(plot) {
|
343
|
+
plot.hooks.processRawData.push(processRawData);
|
344
|
+
plot.hooks.draw.push(draw);
|
345
|
+
}
|
346
|
+
|
347
|
+
$.plot.plugins.push({
|
348
|
+
init: init,
|
349
|
+
options: options,
|
350
|
+
name: 'errorbars',
|
351
|
+
version: '1.0'
|
352
|
+
});
|
353
|
+
})(jQuery);
|