@kevinburke/flot 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1814 -0
- package/LICENSE.txt +22 -0
- package/README.md +119 -0
- package/dist/flot.js +9830 -0
- package/dist/flot.min.js +2 -0
- package/dist/flot.min.js.map +1 -0
- package/dist/flot.mjs +9805 -0
- package/dist/jquery.flot.js +9869 -0
- package/dist/jquery.flot.min.js +2 -0
- package/dist/jquery.flot.min.js.map +1 -0
- package/dist/plugins/jquery.flot.crosshair.js +207 -0
- package/dist/plugins/jquery.flot.crosshair.min.js +2 -0
- package/dist/plugins/jquery.flot.crosshair.min.js.map +1 -0
- package/dist/plugins/jquery.flot.image.js +261 -0
- package/dist/plugins/jquery.flot.image.min.js +2 -0
- package/dist/plugins/jquery.flot.image.min.js.map +1 -0
- package/dist/plugins/jquery.flot.pie.js +815 -0
- package/dist/plugins/jquery.flot.pie.min.js +2 -0
- package/dist/plugins/jquery.flot.pie.min.js.map +1 -0
- package/dist/plugins/jquery.flot.resize.js +62 -0
- package/dist/plugins/jquery.flot.resize.min.js +2 -0
- package/dist/plugins/jquery.flot.resize.min.js.map +1 -0
- package/dist/plugins/jquery.flot.threshold.js +148 -0
- package/dist/plugins/jquery.flot.threshold.min.js +2 -0
- package/dist/plugins/jquery.flot.threshold.min.js.map +1 -0
- package/docs/API.md +1767 -0
- package/docs/PLUGINS.md +143 -0
- package/docs/absRelTime.md +42 -0
- package/docs/browser.md +24 -0
- package/docs/canvaswrapper.md +116 -0
- package/docs/composeImages.md +32 -0
- package/docs/drawSeries.md +35 -0
- package/docs/hover.md +21 -0
- package/docs/interactions.md +57 -0
- package/docs/logaxis.md +27 -0
- package/docs/navigate.md +110 -0
- package/package.json +53 -0
- package/source/helpers.js +168 -0
- package/source/index.js +70 -0
- package/source/jquery-adapter.js +83 -0
- package/source/jquery.canvaswrapper.js +546 -0
- package/source/jquery.colorhelpers.js +198 -0
- package/source/jquery.flot.axislabels.js +214 -0
- package/source/jquery.flot.browser.js +53 -0
- package/source/jquery.flot.categories.js +202 -0
- package/source/jquery.flot.composeImages.js +327 -0
- package/source/jquery.flot.crosshair.js +203 -0
- package/source/jquery.flot.drawSeries.js +699 -0
- package/source/jquery.flot.errorbars.js +375 -0
- package/source/jquery.flot.fillbetween.js +254 -0
- package/source/jquery.flot.flatdata.js +47 -0
- package/source/jquery.flot.hover.js +354 -0
- package/source/jquery.flot.image.js +252 -0
- package/source/jquery.flot.js +2814 -0
- package/source/jquery.flot.legend.js +444 -0
- package/source/jquery.flot.logaxis.js +299 -0
- package/source/jquery.flot.navigate.js +842 -0
- package/source/jquery.flot.pie.js +811 -0
- package/source/jquery.flot.resize.js +57 -0
- package/source/jquery.flot.saturated.js +40 -0
- package/source/jquery.flot.selection.js +552 -0
- package/source/jquery.flot.stack.js +220 -0
- package/source/jquery.flot.symbol.js +98 -0
- package/source/jquery.flot.threshold.js +144 -0
- package/source/jquery.flot.time.js +584 -0
- package/source/jquery.flot.touch.js +320 -0
- package/source/jquery.flot.touchNavigate.js +357 -0
- package/source/jquery.flot.uiConstants.js +9 -0
- package/source/jquery.js +9473 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/* Plugin for working with colors.
|
|
2
|
+
*
|
|
3
|
+
* Version 1.1.
|
|
4
|
+
*
|
|
5
|
+
* Inspiration from jQuery color animation plugin by John Resig.
|
|
6
|
+
*
|
|
7
|
+
* Released under the MIT license by Ole Laursen, October 2009.
|
|
8
|
+
*
|
|
9
|
+
* Examples:
|
|
10
|
+
*
|
|
11
|
+
* color.parse("#fff").scale('rgb', 0.25).add('a', -0.5).toString()
|
|
12
|
+
* var c = color.extract($("#mydiv"), 'background-color');
|
|
13
|
+
* console.log(c.r, c.g, c.b, c.a);
|
|
14
|
+
* color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)"
|
|
15
|
+
*
|
|
16
|
+
* Note that .scale() and .add() return the same modified object
|
|
17
|
+
* instead of making a new one.
|
|
18
|
+
*
|
|
19
|
+
* V. 1.1: Fix error handling so e.g. parsing an empty string does
|
|
20
|
+
* produce a color rather than just crashing.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
export var color = {};
|
|
24
|
+
|
|
25
|
+
// construct color object with some convenient chainable helpers
|
|
26
|
+
color.make = function (r, g, b, a) {
|
|
27
|
+
var o = {};
|
|
28
|
+
o.r = r || 0;
|
|
29
|
+
o.g = g || 0;
|
|
30
|
+
o.b = b || 0;
|
|
31
|
+
o.a = a != null ? a : 1;
|
|
32
|
+
|
|
33
|
+
o.add = function (c, d) {
|
|
34
|
+
for (var i = 0; i < c.length; ++i) {
|
|
35
|
+
o[c.charAt(i)] += d;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return o.normalize();
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
o.scale = function (c, f) {
|
|
42
|
+
for (var i = 0; i < c.length; ++i) {
|
|
43
|
+
o[c.charAt(i)] *= f;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return o.normalize();
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
o.toString = function () {
|
|
50
|
+
if (o.a >= 1.0) {
|
|
51
|
+
return "rgb(" + [o.r, o.g, o.b].join(",") + ")";
|
|
52
|
+
} else {
|
|
53
|
+
return "rgba(" + [o.r, o.g, o.b, o.a].join(",") + ")";
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
o.normalize = function () {
|
|
58
|
+
function clamp(min, value, max) {
|
|
59
|
+
return value < min ? min : (value > max ? max : value);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
o.r = clamp(0, parseInt(o.r), 255);
|
|
63
|
+
o.g = clamp(0, parseInt(o.g), 255);
|
|
64
|
+
o.b = clamp(0, parseInt(o.b), 255);
|
|
65
|
+
o.a = clamp(0, o.a, 1);
|
|
66
|
+
return o;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
o.clone = function () {
|
|
70
|
+
return color.make(o.r, o.b, o.g, o.a);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
return o.normalize();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// extract CSS color property from element, going up in the DOM
|
|
77
|
+
// if it's "transparent". Takes a raw DOM element.
|
|
78
|
+
color.extract = function (elem, css) {
|
|
79
|
+
var c;
|
|
80
|
+
|
|
81
|
+
do {
|
|
82
|
+
var camel = css.replace(/-([a-z])/g, function(_, ch) { return ch.toUpperCase(); });
|
|
83
|
+
c = (elem.style[camel] || getComputedStyle(elem)[css] || '').toLowerCase();
|
|
84
|
+
// keep going until we find an element that has color, or
|
|
85
|
+
// we hit the body or root (have no parent)
|
|
86
|
+
if (c !== '' && c !== 'transparent') {
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
elem = elem.parentElement;
|
|
91
|
+
} while (elem != null && elem.nodeName.toLowerCase() !== "body");
|
|
92
|
+
|
|
93
|
+
// catch Safari's way of signalling transparent
|
|
94
|
+
if (c === "rgba(0, 0, 0, 0)") {
|
|
95
|
+
c = "transparent";
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return color.parse(c);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// parse CSS color string (like "rgb(10, 32, 43)" or "#fff"),
|
|
102
|
+
// returns color object, if parsing failed, you get black (0, 0,
|
|
103
|
+
// 0) out
|
|
104
|
+
color.parse = function (str) {
|
|
105
|
+
var res, m = color.make;
|
|
106
|
+
|
|
107
|
+
// Look for rgb(num,num,num)
|
|
108
|
+
res = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(str);
|
|
109
|
+
if (res) {
|
|
110
|
+
return m(parseInt(res[1], 10), parseInt(res[2], 10), parseInt(res[3], 10));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Look for rgba(num,num,num,num)
|
|
114
|
+
res = /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str)
|
|
115
|
+
if (res) {
|
|
116
|
+
return m(parseInt(res[1], 10), parseInt(res[2], 10), parseInt(res[3], 10), parseFloat(res[4]));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Look for rgb(num%,num%,num%)
|
|
120
|
+
res = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)%\s*,\s*([0-9]+(?:\.[0-9]+)?)%\s*,\s*([0-9]+(?:\.[0-9]+)?)%\s*\)/.exec(str);
|
|
121
|
+
if (res) {
|
|
122
|
+
return m(parseFloat(res[1]) * 2.55, parseFloat(res[2]) * 2.55, parseFloat(res[3]) * 2.55);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Look for rgba(num%,num%,num%,num)
|
|
126
|
+
res = /rgba\(\s*([0-9]+(?:\.[0-9]+)?)%\s*,\s*([0-9]+(?:\.[0-9]+)?)%\s*,\s*([0-9]+(?:\.[0-9]+)?)%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str);
|
|
127
|
+
if (res) {
|
|
128
|
+
return m(parseFloat(res[1]) * 2.55, parseFloat(res[2]) * 2.55, parseFloat(res[3]) * 2.55, parseFloat(res[4]));
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Look for #a0b1c2
|
|
132
|
+
res = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(str);
|
|
133
|
+
if (res) {
|
|
134
|
+
return m(parseInt(res[1], 16), parseInt(res[2], 16), parseInt(res[3], 16));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Look for #fff
|
|
138
|
+
res = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(str);
|
|
139
|
+
if (res) {
|
|
140
|
+
return m(parseInt(res[1] + res[1], 16), parseInt(res[2] + res[2], 16), parseInt(res[3] + res[3], 16));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Otherwise, we're most likely dealing with a named color
|
|
144
|
+
var name = (str || '').trim().toLowerCase();
|
|
145
|
+
if (name === "transparent") {
|
|
146
|
+
return m(255, 255, 255, 0);
|
|
147
|
+
} else {
|
|
148
|
+
// default to black
|
|
149
|
+
res = lookupColors[name] || [0, 0, 0];
|
|
150
|
+
return m(res[0], res[1], res[2]);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
var lookupColors = {
|
|
155
|
+
aqua: [0, 255, 255],
|
|
156
|
+
azure: [240, 255, 255],
|
|
157
|
+
beige: [245, 245, 220],
|
|
158
|
+
black: [0, 0, 0],
|
|
159
|
+
blue: [0, 0, 255],
|
|
160
|
+
brown: [165, 42, 42],
|
|
161
|
+
cyan: [0, 255, 255],
|
|
162
|
+
darkblue: [0, 0, 139],
|
|
163
|
+
darkcyan: [0, 139, 139],
|
|
164
|
+
darkgrey: [169, 169, 169],
|
|
165
|
+
darkgreen: [0, 100, 0],
|
|
166
|
+
darkkhaki: [189, 183, 107],
|
|
167
|
+
darkmagenta: [139, 0, 139],
|
|
168
|
+
darkolivegreen: [85, 107, 47],
|
|
169
|
+
darkorange: [255, 140, 0],
|
|
170
|
+
darkorchid: [153, 50, 204],
|
|
171
|
+
darkred: [139, 0, 0],
|
|
172
|
+
darksalmon: [233, 150, 122],
|
|
173
|
+
darkviolet: [148, 0, 211],
|
|
174
|
+
fuchsia: [255, 0, 255],
|
|
175
|
+
gold: [255, 215, 0],
|
|
176
|
+
green: [0, 128, 0],
|
|
177
|
+
indigo: [75, 0, 130],
|
|
178
|
+
khaki: [240, 230, 140],
|
|
179
|
+
lightblue: [173, 216, 230],
|
|
180
|
+
lightcyan: [224, 255, 255],
|
|
181
|
+
lightgreen: [144, 238, 144],
|
|
182
|
+
lightgrey: [211, 211, 211],
|
|
183
|
+
lightpink: [255, 182, 193],
|
|
184
|
+
lightyellow: [255, 255, 224],
|
|
185
|
+
lime: [0, 255, 0],
|
|
186
|
+
magenta: [255, 0, 255],
|
|
187
|
+
maroon: [128, 0, 0],
|
|
188
|
+
navy: [0, 0, 128],
|
|
189
|
+
olive: [128, 128, 0],
|
|
190
|
+
orange: [255, 165, 0],
|
|
191
|
+
pink: [255, 192, 203],
|
|
192
|
+
purple: [128, 0, 128],
|
|
193
|
+
violet: [128, 0, 128],
|
|
194
|
+
red: [255, 0, 0],
|
|
195
|
+
silver: [192, 192, 192],
|
|
196
|
+
white: [255, 255, 255],
|
|
197
|
+
yellow: [255, 255, 0]
|
|
198
|
+
};
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Axis label plugin for flot
|
|
3
|
+
|
|
4
|
+
Derived from:
|
|
5
|
+
Axis Labels Plugin for flot.
|
|
6
|
+
http://github.com/markrcote/flot-axislabels
|
|
7
|
+
|
|
8
|
+
Original code is Copyright (c) 2010 Xuan Luo.
|
|
9
|
+
Original code was released under the GPLv3 license by Xuan Luo, September 2010.
|
|
10
|
+
Original code was rereleased under the MIT license by Xuan Luo, April 2012.
|
|
11
|
+
|
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
13
|
+
a copy of this software and associated documentation files (the
|
|
14
|
+
"Software"), to deal in the Software without restriction, including
|
|
15
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
16
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
17
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
18
|
+
the following conditions:
|
|
19
|
+
|
|
20
|
+
The above copyright notice and this permission notice shall be
|
|
21
|
+
included in all copies or substantial portions of the Software.
|
|
22
|
+
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
24
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
25
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
26
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
27
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
28
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
29
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
import { plugins } from './jquery.flot.js';
|
|
33
|
+
|
|
34
|
+
"use strict";
|
|
35
|
+
|
|
36
|
+
var options = {
|
|
37
|
+
axisLabels: {
|
|
38
|
+
show: true
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
function AxisLabel(axisName, position, padding, placeholder, axisLabel, surface) {
|
|
43
|
+
this.axisName = axisName;
|
|
44
|
+
this.position = position;
|
|
45
|
+
this.padding = padding;
|
|
46
|
+
this.placeholder = placeholder;
|
|
47
|
+
this.axisLabel = axisLabel;
|
|
48
|
+
this.surface = surface;
|
|
49
|
+
this.width = 0;
|
|
50
|
+
this.height = 0;
|
|
51
|
+
this.elem = null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
AxisLabel.prototype.calculateSize = function() {
|
|
55
|
+
var axisId = this.axisName + 'Label',
|
|
56
|
+
layerId = axisId + 'Layer',
|
|
57
|
+
className = axisId + ' axisLabels';
|
|
58
|
+
|
|
59
|
+
var info = this.surface.getTextInfo(layerId, this.axisLabel, className);
|
|
60
|
+
this.labelWidth = info.width;
|
|
61
|
+
this.labelHeight = info.height;
|
|
62
|
+
|
|
63
|
+
if (this.position === 'left' || this.position === 'right') {
|
|
64
|
+
this.width = this.labelHeight + this.padding;
|
|
65
|
+
this.height = 0;
|
|
66
|
+
} else {
|
|
67
|
+
this.width = 0;
|
|
68
|
+
this.height = this.labelHeight + this.padding;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
AxisLabel.prototype.transforms = function(degrees, x, y, svgLayer) {
|
|
73
|
+
var transforms = [], translate, rotate;
|
|
74
|
+
if (x !== 0 || y !== 0) {
|
|
75
|
+
translate = svgLayer.createSVGTransform();
|
|
76
|
+
translate.setTranslate(x, y);
|
|
77
|
+
transforms.push(translate);
|
|
78
|
+
}
|
|
79
|
+
if (degrees !== 0) {
|
|
80
|
+
rotate = svgLayer.createSVGTransform();
|
|
81
|
+
var centerX = Math.round(this.labelWidth / 2),
|
|
82
|
+
centerY = 0;
|
|
83
|
+
rotate.setRotate(degrees, centerX, centerY);
|
|
84
|
+
transforms.push(rotate);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return transforms;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
AxisLabel.prototype.calculateOffsets = function(box) {
|
|
91
|
+
var offsets = {
|
|
92
|
+
x: 0,
|
|
93
|
+
y: 0,
|
|
94
|
+
degrees: 0
|
|
95
|
+
};
|
|
96
|
+
if (this.position === 'bottom') {
|
|
97
|
+
offsets.x = box.left + box.width / 2 - this.labelWidth / 2;
|
|
98
|
+
offsets.y = box.top + box.height - this.labelHeight;
|
|
99
|
+
} else if (this.position === 'top') {
|
|
100
|
+
offsets.x = box.left + box.width / 2 - this.labelWidth / 2;
|
|
101
|
+
offsets.y = box.top;
|
|
102
|
+
} else if (this.position === 'left') {
|
|
103
|
+
offsets.degrees = -90;
|
|
104
|
+
offsets.x = box.left - this.labelWidth / 2;
|
|
105
|
+
offsets.y = box.height / 2 + box.top;
|
|
106
|
+
} else if (this.position === 'right') {
|
|
107
|
+
offsets.degrees = 90;
|
|
108
|
+
offsets.x = box.left + box.width - this.labelWidth / 2;
|
|
109
|
+
offsets.y = box.height / 2 + box.top;
|
|
110
|
+
}
|
|
111
|
+
offsets.x = Math.round(offsets.x);
|
|
112
|
+
offsets.y = Math.round(offsets.y);
|
|
113
|
+
|
|
114
|
+
return offsets;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
AxisLabel.prototype.cleanup = function() {
|
|
118
|
+
var axisId = this.axisName + 'Label',
|
|
119
|
+
layerId = axisId + 'Layer',
|
|
120
|
+
className = axisId + ' axisLabels';
|
|
121
|
+
this.surface.removeText(layerId, 0, 0, this.axisLabel, className);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
AxisLabel.prototype.draw = function(box) {
|
|
125
|
+
var axisId = this.axisName + 'Label',
|
|
126
|
+
layerId = axisId + 'Layer',
|
|
127
|
+
className = axisId + ' axisLabels',
|
|
128
|
+
offsets = this.calculateOffsets(box),
|
|
129
|
+
style = {
|
|
130
|
+
position: 'absolute',
|
|
131
|
+
bottom: '',
|
|
132
|
+
right: '',
|
|
133
|
+
display: 'inline-block',
|
|
134
|
+
'white-space': 'nowrap'
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
var layer = this.surface.getSVGLayer(layerId);
|
|
138
|
+
var transforms = this.transforms(offsets.degrees, offsets.x, offsets.y, layer.parentNode);
|
|
139
|
+
|
|
140
|
+
this.surface.addText(layerId, 0, 0, this.axisLabel, className, undefined, undefined, undefined, undefined, transforms);
|
|
141
|
+
this.surface.render();
|
|
142
|
+
Object.keys(style).forEach(function(key) {
|
|
143
|
+
layer.style[key] = style[key];
|
|
144
|
+
});
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
function init(plot) {
|
|
148
|
+
plot.hooks.processOptions.push(function(plot, options) {
|
|
149
|
+
if (!options.axisLabels.show) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
var axisLabels = {};
|
|
154
|
+
var defaultPadding = 2; // padding between axis and tick labels
|
|
155
|
+
|
|
156
|
+
plot.hooks.axisReserveSpace.push(function(plot, axis) {
|
|
157
|
+
var opts = axis.options;
|
|
158
|
+
var axisName = axis.direction + axis.n;
|
|
159
|
+
|
|
160
|
+
axis.labelHeight += axis.boxPosition.centerY;
|
|
161
|
+
axis.labelWidth += axis.boxPosition.centerX;
|
|
162
|
+
|
|
163
|
+
if (!opts || !opts.axisLabel || !axis.show) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
var padding = opts.axisLabelPadding === undefined
|
|
168
|
+
? defaultPadding
|
|
169
|
+
: opts.axisLabelPadding;
|
|
170
|
+
|
|
171
|
+
var axisLabel = axisLabels[axisName];
|
|
172
|
+
if (!axisLabel) {
|
|
173
|
+
axisLabel = new AxisLabel(axisName,
|
|
174
|
+
opts.position, padding,
|
|
175
|
+
plot.getPlaceholder(), opts.axisLabel, plot.getSurface());
|
|
176
|
+
axisLabels[axisName] = axisLabel;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
axisLabel.calculateSize();
|
|
180
|
+
|
|
181
|
+
// Incrementing the sizes of the tick labels.
|
|
182
|
+
axis.labelHeight += axisLabel.height;
|
|
183
|
+
axis.labelWidth += axisLabel.width;
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// TODO - use the drawAxis hook
|
|
187
|
+
plot.hooks.draw.push(function(plot, ctx) {
|
|
188
|
+
var axes = plot.getAxes();
|
|
189
|
+
Object.keys(axes).forEach(function(flotAxisName) {
|
|
190
|
+
var axis = axes[flotAxisName];
|
|
191
|
+
var opts = axis.options;
|
|
192
|
+
if (!opts || !opts.axisLabel || !axis.show) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
var axisName = axis.direction + axis.n;
|
|
197
|
+
axisLabels[axisName].draw(axis.box);
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
plot.hooks.shutdown.push(function(plot, eventHolder) {
|
|
202
|
+
for (var axisName in axisLabels) {
|
|
203
|
+
axisLabels[axisName].cleanup();
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
plugins.push({
|
|
210
|
+
init: init,
|
|
211
|
+
options: options,
|
|
212
|
+
name: 'axisLabels',
|
|
213
|
+
version: '3.0'
|
|
214
|
+
});
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
export var browser = {
|
|
4
|
+
getPageXY: function (e) {
|
|
5
|
+
var doc = document.documentElement,
|
|
6
|
+
pageX = e.clientX + (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0),
|
|
7
|
+
pageY = e.clientY + (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
|
|
8
|
+
return { X: pageX, Y: pageY };
|
|
9
|
+
},
|
|
10
|
+
|
|
11
|
+
getPixelRatio: function(context) {
|
|
12
|
+
var devicePixelRatio = window.devicePixelRatio || 1,
|
|
13
|
+
backingStoreRatio =
|
|
14
|
+
context.webkitBackingStorePixelRatio ||
|
|
15
|
+
context.mozBackingStorePixelRatio ||
|
|
16
|
+
context.msBackingStorePixelRatio ||
|
|
17
|
+
context.oBackingStorePixelRatio ||
|
|
18
|
+
context.backingStorePixelRatio || 1;
|
|
19
|
+
return devicePixelRatio / backingStoreRatio;
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
isSafari: function() {
|
|
23
|
+
return /constructor/i.test(window.top.HTMLElement) || (function (p) { return p.toString() === "[object SafariRemoteNotification]"; })(!window.top['safari'] || (typeof window.top.safari !== 'undefined' && window.top.safari.pushNotification));
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
isMobileSafari: function() {
|
|
27
|
+
return navigator.userAgent.match(/(iPod|iPhone|iPad)/) && navigator.userAgent.match(/AppleWebKit/);
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
isOpera: function() {
|
|
31
|
+
return (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
isFirefox: function() {
|
|
35
|
+
return typeof InstallTrigger !== 'undefined';
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
isIE: function() {
|
|
39
|
+
return /*@cc_on!@*/false || !!document.documentMode;
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
isEdge: function() {
|
|
43
|
+
return !browser.isIE() && !!window.StyleMedia;
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
isChrome: function() {
|
|
47
|
+
return !!window.chrome && !!window.chrome.webstore;
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
isBlink: function() {
|
|
51
|
+
return (browser.isChrome() || browser.isOpera()) && !!window.CSS;
|
|
52
|
+
}
|
|
53
|
+
};
|
|
@@ -0,0 +1,202 @@
|
|
|
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
|
+
import { plugins } from './jquery.flot.js';
|
|
47
|
+
|
|
48
|
+
var options = {
|
|
49
|
+
xaxis: {
|
|
50
|
+
categories: null
|
|
51
|
+
},
|
|
52
|
+
yaxis: {
|
|
53
|
+
categories: null
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
function processRawData(plot, series, data, datapoints) {
|
|
58
|
+
// if categories are enabled, we need to disable
|
|
59
|
+
// auto-transformation to numbers so the strings are intact
|
|
60
|
+
// for later processing
|
|
61
|
+
|
|
62
|
+
var xCategories = series.xaxis.options.mode === "categories",
|
|
63
|
+
yCategories = series.yaxis.options.mode === "categories";
|
|
64
|
+
|
|
65
|
+
if (!(xCategories || yCategories)) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
var format = datapoints.format;
|
|
70
|
+
|
|
71
|
+
if (!format) {
|
|
72
|
+
// FIXME: auto-detection should really not be defined here
|
|
73
|
+
var s = series;
|
|
74
|
+
format = [];
|
|
75
|
+
format.push({ x: true, number: true, required: true, computeRange: true});
|
|
76
|
+
format.push({ y: true, number: true, required: true, computeRange: true });
|
|
77
|
+
|
|
78
|
+
if (s.bars.show || (s.lines.show && s.lines.fill)) {
|
|
79
|
+
var autoScale = !!((s.bars.show && s.bars.zero) || (s.lines.show && s.lines.zero));
|
|
80
|
+
format.push({ y: true, number: true, required: false, defaultValue: 0, computeRange: autoScale });
|
|
81
|
+
if (s.bars.horizontal) {
|
|
82
|
+
delete format[format.length - 1].y;
|
|
83
|
+
format[format.length - 1].x = true;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
datapoints.format = format;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
for (var m = 0; m < format.length; ++m) {
|
|
91
|
+
if (format[m].x && xCategories) {
|
|
92
|
+
format[m].number = false;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (format[m].y && yCategories) {
|
|
96
|
+
format[m].number = false;
|
|
97
|
+
format[m].computeRange = false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function getNextIndex(categories) {
|
|
103
|
+
var index = -1;
|
|
104
|
+
|
|
105
|
+
for (var v in categories) {
|
|
106
|
+
if (categories[v] > index) {
|
|
107
|
+
index = categories[v];
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return index + 1;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function categoriesTickGenerator(axis) {
|
|
115
|
+
var res = [];
|
|
116
|
+
for (var label in axis.categories) {
|
|
117
|
+
var v = axis.categories[label];
|
|
118
|
+
if (v >= axis.min && v <= axis.max) {
|
|
119
|
+
res.push([v, label]);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
res.sort(function (a, b) { return a[0] - b[0]; });
|
|
124
|
+
|
|
125
|
+
return res;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function setupCategoriesForAxis(series, axis, datapoints) {
|
|
129
|
+
if (series[axis].options.mode !== "categories") {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (!series[axis].categories) {
|
|
134
|
+
// parse options
|
|
135
|
+
var c = {}, o = series[axis].options.categories || {};
|
|
136
|
+
if (Array.isArray(o)) {
|
|
137
|
+
for (var i = 0; i < o.length; ++i) {
|
|
138
|
+
c[o[i]] = i;
|
|
139
|
+
}
|
|
140
|
+
} else {
|
|
141
|
+
for (var v in o) {
|
|
142
|
+
c[v] = o[v];
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
series[axis].categories = c;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// fix ticks
|
|
150
|
+
if (!series[axis].options.ticks) {
|
|
151
|
+
series[axis].options.ticks = categoriesTickGenerator;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
transformPointsOnAxis(datapoints, axis, series[axis].categories);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function transformPointsOnAxis(datapoints, axis, categories) {
|
|
158
|
+
// go through the points, transforming them
|
|
159
|
+
var points = datapoints.points,
|
|
160
|
+
ps = datapoints.pointsize,
|
|
161
|
+
format = datapoints.format,
|
|
162
|
+
formatColumn = axis.charAt(0),
|
|
163
|
+
index = getNextIndex(categories);
|
|
164
|
+
|
|
165
|
+
for (var i = 0; i < points.length; i += ps) {
|
|
166
|
+
if (points[i] == null) {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
for (var m = 0; m < ps; ++m) {
|
|
171
|
+
var val = points[i + m];
|
|
172
|
+
|
|
173
|
+
if (val == null || !format[m][formatColumn]) {
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (!(val in categories)) {
|
|
178
|
+
categories[val] = index;
|
|
179
|
+
++index;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
points[i + m] = categories[val];
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function processDatapoints(plot, series, datapoints) {
|
|
188
|
+
setupCategoriesForAxis(series, "xaxis", datapoints);
|
|
189
|
+
setupCategoriesForAxis(series, "yaxis", datapoints);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function init(plot) {
|
|
193
|
+
plot.hooks.processRawData.push(processRawData);
|
|
194
|
+
plot.hooks.processDatapoints.push(processDatapoints);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
plugins.push({
|
|
198
|
+
init: init,
|
|
199
|
+
options: options,
|
|
200
|
+
name: 'categories',
|
|
201
|
+
version: '1.0'
|
|
202
|
+
});
|