how_are_we_doing 0.0.4 → 0.0.5
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.
- data/app/controllers/reports_controller.rb +1 -52
- data/app/helpers/reports_helper.rb +30 -4
- data/app/models/print.rb +1 -29
- data/app/models/share.rb +3 -29
- data/app/models/total.rb +2 -21
- data/app/models/view.rb +1 -29
- data/app/views/reports/_bar_graph.html.erb +48 -0
- data/app/views/reports/_line_graph.html.erb +40 -0
- data/app/views/reports/_recent_bar_graph.html.erb +41 -0
- data/app/views/reports/index.html.erb +12 -22
- data/config/locales/en.yml +16 -0
- data/lib/generators/how_are_we_doing/install/install_generator.rb +1 -0
- data/lib/generators/how_are_we_doing/install/templates/public/images/hawd/blank.png +0 -0
- data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/API.txt +85 -68
- data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/FAQ.txt +0 -0
- data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/NEWS.txt +12 -32
- data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/PLUGINS.txt +0 -0
- data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/README.txt +3 -3
- data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/excanvas.js +160 -663
- data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/excanvas.min.js +1 -1
- data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/jquery.flot.crosshair.js +12 -51
- data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/jquery.flot.image.js +0 -0
- data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/jquery.flot.js +509 -155
- data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/jquery.flot.navigate.js +0 -1
- data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/jquery.flot.stack.js +0 -0
- data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/jquery.flot.threshold.js +0 -0
- data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/jquery.js +0 -0
- data/lib/generators/how_are_we_doing/install/templates/public/javascripts/how_are_we_doing.js +50 -8
- data/lib/how_are_we_doing/acts_as_analytical.rb +98 -0
- data/lib/{acts_as_printable.rb → how_are_we_doing/acts_as_printable.rb} +0 -0
- data/lib/{acts_as_shareable.rb → how_are_we_doing/acts_as_shareable.rb} +0 -0
- data/lib/{acts_as_totalable.rb → how_are_we_doing/acts_as_totalable.rb} +0 -0
- data/lib/{acts_as_viewable.rb → how_are_we_doing/acts_as_viewable.rb} +0 -0
- data/lib/how_are_we_doing/controllers/reports_helpers.rb +92 -0
- data/lib/how_are_we_doing/version.rb +1 -1
- data/lib/how_are_we_doing.rb +16 -8
- metadata +13 -6
data/lib/generators/how_are_we_doing/install/templates/public/javascripts/flot/jquery.flot.js
CHANGED
@@ -1,33 +1,9 @@
|
|
1
|
-
/* Javascript plotting library for jQuery, v. 0.
|
1
|
+
/* Javascript plotting library for jQuery, v. 0.5.
|
2
2
|
*
|
3
3
|
* Released under the MIT license by IOLA, December 2007.
|
4
4
|
*
|
5
5
|
*/
|
6
6
|
|
7
|
-
// first an inline dependency, jquery.colorhelpers.js, we inline it here
|
8
|
-
// for convenience
|
9
|
-
|
10
|
-
/* Plugin for jQuery for working with colors.
|
11
|
-
*
|
12
|
-
* Version 1.0.
|
13
|
-
*
|
14
|
-
* Inspiration from jQuery color animation plugin by John Resig.
|
15
|
-
*
|
16
|
-
* Released under the MIT license by Ole Laursen, October 2009.
|
17
|
-
*
|
18
|
-
* Examples:
|
19
|
-
*
|
20
|
-
* $.color.parse("#fff").scale('rgb', 0.25).add('a', -0.5).toString()
|
21
|
-
* var c = $.color.extract($("#mydiv"), 'background-color');
|
22
|
-
* console.log(c.r, c.g, c.b, c.a);
|
23
|
-
* $.color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)"
|
24
|
-
*
|
25
|
-
* Note that .scale() and .add() work in-place instead of returning
|
26
|
-
* new objects.
|
27
|
-
*/
|
28
|
-
(function(){jQuery.color={};jQuery.color.make=function(E,D,B,C){var F={};F.r=E||0;F.g=D||0;F.b=B||0;F.a=C!=null?C:1;F.add=function(I,H){for(var G=0;G<I.length;++G){F[I.charAt(G)]+=H}return F.normalize()};F.scale=function(I,H){for(var G=0;G<I.length;++G){F[I.charAt(G)]*=H}return F.normalize()};F.toString=function(){if(F.a>=1){return"rgb("+[F.r,F.g,F.b].join(",")+")"}else{return"rgba("+[F.r,F.g,F.b,F.a].join(",")+")"}};F.normalize=function(){function G(I,J,H){return J<I?I:(J>H?H:J)}F.r=G(0,parseInt(F.r),255);F.g=G(0,parseInt(F.g),255);F.b=G(0,parseInt(F.b),255);F.a=G(0,F.a,1);return F};F.clone=function(){return jQuery.color.make(F.r,F.b,F.g,F.a)};return F.normalize()};jQuery.color.extract=function(C,B){var D;do{D=C.css(B).toLowerCase();if(D!=""&&D!="transparent"){break}C=C.parent()}while(!jQuery.nodeName(C.get(0),"body"));if(D=="rgba(0, 0, 0, 0)"){D="transparent"}return jQuery.color.parse(D)};jQuery.color.parse=function(E){var D,B=jQuery.color.make;if(D=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(E)){return B(parseInt(D[1],10),parseInt(D[2],10),parseInt(D[3],10))}if(D=/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(E)){return B(parseInt(D[1],10),parseInt(D[2],10),parseInt(D[3],10),parseFloat(D[4]))}if(D=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(E)){return B(parseFloat(D[1])*2.55,parseFloat(D[2])*2.55,parseFloat(D[3])*2.55)}if(D=/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(E)){return B(parseFloat(D[1])*2.55,parseFloat(D[2])*2.55,parseFloat(D[3])*2.55,parseFloat(D[4]))}if(D=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(E)){return B(parseInt(D[1],16),parseInt(D[2],16),parseInt(D[3],16))}if(D=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(E)){return B(parseInt(D[1]+D[1],16),parseInt(D[2]+D[2],16),parseInt(D[3]+D[3],16))}var C=jQuery.trim(E).toLowerCase();if(C=="transparent"){return B(255,255,255,0)}else{D=A[C];return B(D[0],D[1],D[2])}};var A={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})();
|
29
|
-
|
30
|
-
// the actual Flot code
|
31
7
|
(function($) {
|
32
8
|
function Plot(placeholder, data_, options_, plugins) {
|
33
9
|
// data is on the form:
|
@@ -52,8 +28,6 @@
|
|
52
28
|
},
|
53
29
|
xaxis: {
|
54
30
|
mode: null, // null or "time"
|
55
|
-
transform: null, // null or f: number -> number to transform axis
|
56
|
-
inverseTransform: null, // if transform is set, this should be the inverse function
|
57
31
|
min: null, // min. value to show, null means set automatically
|
58
32
|
max: null, // max. value to show, null means set automatically
|
59
33
|
autoscaleMargin: null, // margin in % to add if auto-setting min/max
|
@@ -67,8 +41,7 @@
|
|
67
41
|
tickSize: null, // number or [number, "unit"]
|
68
42
|
minTickSize: null, // number or [number, "unit"]
|
69
43
|
monthNames: null, // list of names of months
|
70
|
-
timeformat: null
|
71
|
-
twelveHourClock: false // 12 or 24 time in time mode
|
44
|
+
timeformat: null // format string to use
|
72
45
|
},
|
73
46
|
yaxis: {
|
74
47
|
autoscaleMargin: 0.02
|
@@ -102,7 +75,8 @@
|
|
102
75
|
fill: true,
|
103
76
|
fillColor: null,
|
104
77
|
align: "left", // or "center"
|
105
|
-
horizontal: false // when horizontal, left is now top
|
78
|
+
horizontal: false, // when horizontal, left is now top
|
79
|
+
series_spread: false // display series side by side
|
106
80
|
},
|
107
81
|
shadowSize: 3
|
108
82
|
},
|
@@ -124,7 +98,10 @@
|
|
124
98
|
autoHighlight: true, // highlight in case mouse is near
|
125
99
|
mouseActiveRadius: 10 // how far the mouse can be away to activate an item
|
126
100
|
},
|
127
|
-
|
101
|
+
selection: {
|
102
|
+
mode: null, // one of null, "x", "y" or "xy"
|
103
|
+
color: "#e8cfac"
|
104
|
+
}
|
128
105
|
},
|
129
106
|
canvas = null, // the canvas for the plot itself
|
130
107
|
overlay = null, // canvas for interactive stuff on top of plot
|
@@ -142,17 +119,22 @@
|
|
142
119
|
bindEvents: [],
|
143
120
|
drawOverlay: []
|
144
121
|
},
|
145
|
-
plot = this
|
122
|
+
plot = this,
|
123
|
+
// dedicated to storing data for buggy standard compliance cases
|
124
|
+
workarounds = {};
|
146
125
|
|
147
126
|
// public functions
|
148
127
|
plot.setData = setData;
|
149
128
|
plot.setupGrid = setupGrid;
|
150
129
|
plot.draw = draw;
|
130
|
+
plot.clearSelection = clearSelection;
|
131
|
+
plot.setSelection = setSelection;
|
132
|
+
plot.getSelection = getSelection;
|
151
133
|
plot.getPlaceholder = function() { return placeholder; };
|
152
134
|
plot.getCanvas = function() { return canvas; };
|
153
135
|
plot.getPlotOffset = function() { return plotOffset; };
|
154
|
-
plot.width = function () { return plotWidth; }
|
155
|
-
plot.height = function () { return plotHeight; }
|
136
|
+
plot.width = function () { return plotWidth; }
|
137
|
+
plot.height = function () { return plotHeight; }
|
156
138
|
plot.offset = function () {
|
157
139
|
var o = eventHolder.offset();
|
158
140
|
o.left += plotOffset.left;
|
@@ -168,7 +150,7 @@
|
|
168
150
|
plot.pointOffset = function(point) {
|
169
151
|
return { left: parseInt(axisSpecToRealAxis(point, "xaxis").p2c(+point.x) + plotOffset.left),
|
170
152
|
top: parseInt(axisSpecToRealAxis(point, "yaxis").p2c(+point.y) + plotOffset.top) };
|
171
|
-
}
|
153
|
+
}
|
172
154
|
|
173
155
|
|
174
156
|
// public attributes
|
@@ -202,7 +184,7 @@
|
|
202
184
|
function parseOptions(opts) {
|
203
185
|
$.extend(true, options, opts);
|
204
186
|
if (options.grid.borderColor == null)
|
205
|
-
options.grid.borderColor = options.grid.color
|
187
|
+
options.grid.borderColor = options.grid.color
|
206
188
|
// backwards compatibility, to be removed in future
|
207
189
|
if (options.xaxis.noTicks && options.xaxis.ticks == null)
|
208
190
|
options.xaxis.ticks = options.xaxis.noTicks;
|
@@ -221,10 +203,6 @@
|
|
221
203
|
if (options.shadowSize)
|
222
204
|
options.series.shadowSize = options.shadowSize;
|
223
205
|
|
224
|
-
for (var n in hooks)
|
225
|
-
if (options.hooks[n] && options.hooks[n].length)
|
226
|
-
hooks[n] = hooks[n].concat(options.hooks[n]);
|
227
|
-
|
228
206
|
executeHooks(hooks.processOptions, [options]);
|
229
207
|
}
|
230
208
|
|
@@ -278,7 +256,7 @@
|
|
278
256
|
if (typeof sc == "number")
|
279
257
|
assignedColors.push(sc);
|
280
258
|
else
|
281
|
-
usedColors.push(
|
259
|
+
usedColors.push(parseColor(series[i].color));
|
282
260
|
}
|
283
261
|
}
|
284
262
|
|
@@ -294,13 +272,14 @@
|
|
294
272
|
while (colors.length < neededColors) {
|
295
273
|
var c;
|
296
274
|
if (options.colors.length == i) // check degenerate case
|
297
|
-
c =
|
275
|
+
c = new Color(100, 100, 100);
|
298
276
|
else
|
299
|
-
c =
|
277
|
+
c = parseColor(options.colors[i]);
|
300
278
|
|
301
279
|
// vary color if needed
|
302
280
|
var sign = variation % 2 == 1 ? -1 : 1;
|
303
|
-
|
281
|
+
var factor = 1 + sign * Math.ceil(variation / 2) * 0.2;
|
282
|
+
c.scale(factor, factor, factor);
|
304
283
|
|
305
284
|
// FIXME: if we're getting to close to something else,
|
306
285
|
// we should probably skip this one
|
@@ -329,7 +308,7 @@
|
|
329
308
|
// turn on lines automatically in case nothing is set
|
330
309
|
if (s.lines.show == null) {
|
331
310
|
var v, show = true;
|
332
|
-
for (v in s)
|
311
|
+
for (var v in s)
|
333
312
|
if (s[v].show) {
|
334
313
|
show = false;
|
335
314
|
break;
|
@@ -353,6 +332,8 @@
|
|
353
332
|
for (axis in axes) {
|
354
333
|
axes[axis].datamin = topSentry;
|
355
334
|
axes[axis].datamax = bottomSentry;
|
335
|
+
axes[axis].min = options[axis].min;
|
336
|
+
axes[axis].max = options[axis].max;
|
356
337
|
axes[axis].used = false;
|
357
338
|
}
|
358
339
|
|
@@ -377,10 +358,10 @@
|
|
377
358
|
var data = s.data, format = s.datapoints.format;
|
378
359
|
|
379
360
|
if (!format) {
|
380
|
-
format = []
|
361
|
+
format = []
|
381
362
|
// find out how to copy
|
382
|
-
format.push({ x: true, number: true, required: true })
|
383
|
-
format.push({ y: true, number: true, required: true })
|
363
|
+
format.push({ x: true, number: true, required: true })
|
364
|
+
format.push({ y: true, number: true, required: true })
|
384
365
|
|
385
366
|
if (s.bars.show)
|
386
367
|
format.push({ y: true, number: true, required: false, defaultValue: 0 });
|
@@ -417,8 +398,15 @@
|
|
417
398
|
}
|
418
399
|
|
419
400
|
if (val == null) {
|
420
|
-
if (f.required)
|
401
|
+
if (f.required) {
|
402
|
+
// extract min/max info before we whack it
|
403
|
+
if (f.x)
|
404
|
+
updateAxis(s.xaxis, val, val)
|
405
|
+
if (f.y)
|
406
|
+
updateAxis(s.yaxis, val, val)
|
407
|
+
val = null;
|
421
408
|
nullify = true;
|
409
|
+
}
|
422
410
|
|
423
411
|
if (f.defaultValue != null)
|
424
412
|
val = f.defaultValue;
|
@@ -430,18 +418,8 @@
|
|
430
418
|
}
|
431
419
|
|
432
420
|
if (nullify) {
|
433
|
-
for (m = 0; m < ps; ++m)
|
434
|
-
val = points[k + m];
|
435
|
-
if (val != null) {
|
436
|
-
f = format[m];
|
437
|
-
// extract min/max info
|
438
|
-
if (f.x)
|
439
|
-
updateAxis(s.xaxis, val, val);
|
440
|
-
if (f.y)
|
441
|
-
updateAxis(s.yaxis, val, val);
|
442
|
-
}
|
421
|
+
for (m = 0; m < ps; ++m)
|
443
422
|
points[k + m] = null;
|
444
|
-
}
|
445
423
|
}
|
446
424
|
else {
|
447
425
|
// a little bit of line specific stuff that
|
@@ -465,7 +443,6 @@
|
|
465
443
|
}
|
466
444
|
}
|
467
445
|
|
468
|
-
// give the hooks a chance to run
|
469
446
|
for (i = 0; i < series.length; ++i) {
|
470
447
|
s = series[i];
|
471
448
|
|
@@ -489,7 +466,7 @@
|
|
489
466
|
val = points[j + m];
|
490
467
|
f = format[m];
|
491
468
|
if (!f)
|
492
|
-
continue
|
469
|
+
continue
|
493
470
|
|
494
471
|
if (f.x) {
|
495
472
|
if (val < xmin)
|
@@ -569,9 +546,13 @@
|
|
569
546
|
eventHolder = $([overlay, canvas]);
|
570
547
|
|
571
548
|
// bind events
|
572
|
-
if (options.
|
549
|
+
if (options.selection.mode != null
|
550
|
+
|| options.grid.hoverable)
|
573
551
|
eventHolder.mousemove(onMouseMove);
|
574
552
|
|
553
|
+
if (options.selection.mode != null)
|
554
|
+
eventHolder.mousedown(onMouseDown);
|
555
|
+
|
575
556
|
if (options.grid.clickable)
|
576
557
|
eventHolder.click(onClick);
|
577
558
|
|
@@ -579,42 +560,27 @@
|
|
579
560
|
}
|
580
561
|
|
581
562
|
function setupGrid() {
|
582
|
-
function setTransformationHelpers(axis
|
583
|
-
|
584
|
-
|
585
|
-
var s, m, t = o.transform || identity,
|
586
|
-
it = o.inverseTransform;
|
563
|
+
function setTransformationHelpers(axis) {
|
564
|
+
var s, m;
|
587
565
|
|
588
566
|
// add transformation helpers
|
589
567
|
if (axis == axes.xaxis || axis == axes.x2axis) {
|
590
568
|
// precompute how much the axis is scaling a point
|
591
569
|
// in canvas space
|
592
|
-
s = axis.scale = plotWidth / (
|
593
|
-
m =
|
594
|
-
|
570
|
+
s = axis.scale = plotWidth / (axis.max - axis.min);
|
571
|
+
m = axis.min;
|
572
|
+
|
595
573
|
// data point to canvas coordinate
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
axis.p2c = function (p) { return (t(p) - m) * s; };
|
600
|
-
// canvas coordinate to data point
|
601
|
-
if (!it)
|
602
|
-
axis.c2p = function (c) { return m + c / s; };
|
603
|
-
else
|
604
|
-
axis.c2p = function (c) { return it(m + c / s); };
|
574
|
+
axis.p2c = function (p) { return (p - m) * s; };
|
575
|
+
// canvas coordinate to data point
|
576
|
+
axis.c2p = function (c) { return m + c / s; };
|
605
577
|
}
|
606
578
|
else {
|
607
|
-
s = axis.scale = plotHeight / (
|
608
|
-
m =
|
579
|
+
s = axis.scale = plotHeight / (axis.max - axis.min)
|
580
|
+
m = axis.max;
|
609
581
|
|
610
|
-
|
611
|
-
|
612
|
-
else
|
613
|
-
axis.p2c = function (p) { return (m - t(p)) * s; };
|
614
|
-
if (!it)
|
615
|
-
axis.c2p = function (c) { return m - c / s; };
|
616
|
-
else
|
617
|
-
axis.c2p = function (c) { return it(m - c / s); };
|
582
|
+
axis.p2c = function (p) { return (m - p) * s; };
|
583
|
+
axis.c2p = function (p) { return m - p / s; };
|
618
584
|
}
|
619
585
|
}
|
620
586
|
|
@@ -630,7 +596,7 @@
|
|
630
596
|
// them, we don't need the exact figures and the
|
631
597
|
// fixed-size box content is easy to center
|
632
598
|
if (axis.labelWidth == null)
|
633
|
-
axis.labelWidth = canvasWidth /
|
599
|
+
axis.labelWidth = canvasWidth / 6;
|
634
600
|
|
635
601
|
// measure x label heights
|
636
602
|
if (axis.labelHeight == null) {
|
@@ -719,7 +685,7 @@
|
|
719
685
|
}
|
720
686
|
|
721
687
|
for (axis in axes)
|
722
|
-
setTransformationHelpers(axes[axis]
|
688
|
+
setTransformationHelpers(axes[axis]);
|
723
689
|
|
724
690
|
if (options.grid.show)
|
725
691
|
insertLabels();
|
@@ -918,15 +884,14 @@
|
|
918
884
|
|
919
885
|
var t = axis.tickSize[0] * timeUnitSize[axis.tickSize[1]];
|
920
886
|
var span = axis.max - axis.min;
|
921
|
-
var suffix = (axisOptions.twelveHourClock) ? " %p" : "";
|
922
887
|
|
923
888
|
if (t < timeUnitSize.minute)
|
924
|
-
fmt = "%h:%M:%S"
|
889
|
+
fmt = "%h:%M:%S";
|
925
890
|
else if (t < timeUnitSize.day) {
|
926
891
|
if (span < 2 * timeUnitSize.day)
|
927
|
-
fmt = "%h:%M"
|
892
|
+
fmt = "%h:%M";
|
928
893
|
else
|
929
|
-
fmt = "%b %d %h:%M"
|
894
|
+
fmt = "%b %d %h:%M";
|
930
895
|
}
|
931
896
|
else if (t < timeUnitSize.month)
|
932
897
|
fmt = "%b %d";
|
@@ -1152,8 +1117,8 @@
|
|
1152
1117
|
|
1153
1118
|
if (xrange.from == xrange.to || yrange.from == yrange.to) {
|
1154
1119
|
// draw line
|
1155
|
-
ctx.beginPath();
|
1156
1120
|
ctx.strokeStyle = m.color || options.grid.markingsColor;
|
1121
|
+
ctx.beginPath();
|
1157
1122
|
ctx.lineWidth = m.lineWidth || options.grid.markingsLineWidth;
|
1158
1123
|
//ctx.moveTo(Math.floor(xrange.from), yrange.from);
|
1159
1124
|
//ctx.lineTo(Math.floor(xrange.to), yrange.to);
|
@@ -1569,7 +1534,7 @@
|
|
1569
1534
|
ctx.restore();
|
1570
1535
|
}
|
1571
1536
|
|
1572
|
-
function drawBar(x, y, b, barLeft, barRight,
|
1537
|
+
function drawBar(x, y, b, barLeft, barRight, yoffset, x_line_adjustment, fillStyleCallback, axisx, axisy, c, horizontal) {
|
1573
1538
|
var left, right, bottom, top,
|
1574
1539
|
drawLeft, drawRight, drawTop, drawBottom,
|
1575
1540
|
tmp;
|
@@ -1649,53 +1614,76 @@
|
|
1649
1614
|
c.fillStyle = fillStyleCallback(bottom, top);
|
1650
1615
|
c.fill();
|
1651
1616
|
}
|
1617
|
+
|
1618
|
+
if (yoffset) {
|
1619
|
+
bottom += yoffset;
|
1620
|
+
top += yoffset;
|
1621
|
+
}
|
1622
|
+
|
1623
|
+
if (x_line_adjustment) {
|
1624
|
+
left += x_line_adjustment;
|
1625
|
+
right -= x_line_adjustment;
|
1626
|
+
}
|
1652
1627
|
|
1653
1628
|
// draw outline
|
1654
1629
|
if (drawLeft || drawRight || drawTop || drawBottom) {
|
1655
1630
|
c.beginPath();
|
1656
1631
|
|
1657
1632
|
// FIXME: inline moveTo is buggy with excanvas
|
1658
|
-
c.moveTo(left, bottom
|
1633
|
+
c.moveTo(left, bottom);
|
1659
1634
|
if (drawLeft)
|
1660
|
-
c.lineTo(left, top
|
1635
|
+
c.lineTo(left, top);
|
1661
1636
|
else
|
1662
|
-
c.moveTo(left, top
|
1637
|
+
c.moveTo(left, top);
|
1663
1638
|
if (drawTop)
|
1664
|
-
c.lineTo(right, top
|
1639
|
+
c.lineTo(right, top);
|
1665
1640
|
else
|
1666
|
-
c.moveTo(right, top
|
1641
|
+
c.moveTo(right, top);
|
1667
1642
|
if (drawRight)
|
1668
|
-
c.lineTo(right, bottom
|
1643
|
+
c.lineTo(right, bottom);
|
1669
1644
|
else
|
1670
|
-
c.moveTo(right, bottom
|
1645
|
+
c.moveTo(right, bottom);
|
1671
1646
|
if (drawBottom)
|
1672
|
-
c.lineTo(left, bottom
|
1647
|
+
c.lineTo(left, bottom);
|
1673
1648
|
else
|
1674
|
-
c.moveTo(left, bottom
|
1649
|
+
c.moveTo(left, bottom);
|
1675
1650
|
c.stroke();
|
1676
1651
|
}
|
1677
1652
|
}
|
1678
1653
|
|
1679
1654
|
function drawSeriesBars(series) {
|
1680
|
-
function plotBars(datapoints, barLeft, barRight,
|
1655
|
+
function plotBars(datapoints, barLeft, barRight, yoffset, x_line_adjustment, fillStyleCallback, axisx, axisy) {
|
1681
1656
|
var points = datapoints.points, ps = datapoints.pointsize;
|
1682
1657
|
|
1683
1658
|
for (var i = 0; i < points.length; i += ps) {
|
1684
1659
|
if (points[i] == null)
|
1685
1660
|
continue;
|
1686
|
-
drawBar(points[i], points[i + 1], points[i + 2], barLeft, barRight,
|
1661
|
+
drawBar(points[i], points[i + 1], points[i + 2], barLeft, barRight, yoffset, x_line_adjustment, fillStyleCallback, axisx, axisy, ctx, series.bars.horizontal);
|
1687
1662
|
}
|
1688
1663
|
}
|
1689
1664
|
|
1690
1665
|
ctx.save();
|
1691
1666
|
ctx.translate(plotOffset.left, plotOffset.top);
|
1692
|
-
|
1667
|
+
|
1693
1668
|
// FIXME: figure out a way to add shadows (for instance along the right edge)
|
1694
1669
|
ctx.lineWidth = series.bars.lineWidth;
|
1695
1670
|
ctx.strokeStyle = series.color;
|
1696
1671
|
var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2;
|
1672
|
+
|
1673
|
+
if (series.bars.series_spread) {
|
1674
|
+
var series_index = indexOfSeries(series);
|
1675
|
+
var series_length = plot.getData().length;
|
1676
|
+
var actualBarWidth = ((1.0/series_length) * (series.bars.barWidth));
|
1677
|
+
barLeft = barLeft + (series_index * actualBarWidth);
|
1678
|
+
}
|
1679
|
+
|
1697
1680
|
var fillStyleCallback = series.bars.fill ? function (bottom, top) { return getFillStyle(series.bars, series.color, bottom, top); } : null;
|
1698
|
-
|
1681
|
+
|
1682
|
+
if (series.bars.series_spread) {
|
1683
|
+
plotBars(series.datapoints, barLeft, barLeft + actualBarWidth, 0, series.bars.lineWidth, fillStyleCallback, series.xaxis, series.yaxis);
|
1684
|
+
} else {
|
1685
|
+
plotBars(series.datapoints, barLeft, barLeft + series.bars.barWidth, 0, 0, fillStyleCallback, series.xaxis, series.yaxis);
|
1686
|
+
}
|
1699
1687
|
ctx.restore();
|
1700
1688
|
}
|
1701
1689
|
|
@@ -1707,7 +1695,7 @@
|
|
1707
1695
|
if (filloptions.fillColor)
|
1708
1696
|
return getColorOrGradient(filloptions.fillColor, bottom, top, seriesColor);
|
1709
1697
|
|
1710
|
-
var c =
|
1698
|
+
var c = parseColor(seriesColor);
|
1711
1699
|
c.a = typeof fill == "number" ? fill : 0.4;
|
1712
1700
|
c.normalize();
|
1713
1701
|
return c.toString();
|
@@ -1771,13 +1759,12 @@
|
|
1771
1759
|
// label boxes
|
1772
1760
|
var c = options.legend.backgroundColor;
|
1773
1761
|
if (c == null) {
|
1774
|
-
|
1775
|
-
if (
|
1776
|
-
|
1762
|
+
var tmp;
|
1763
|
+
if (options.grid.backgroundColor && typeof options.grid.backgroundColor == "string")
|
1764
|
+
tmp = options.grid.backgroundColor;
|
1777
1765
|
else
|
1778
|
-
|
1779
|
-
c
|
1780
|
-
c = c.toString();
|
1766
|
+
tmp = extractColor(legend);
|
1767
|
+
c = parseColor(tmp).adjust(null, null, null, 1).toString();
|
1781
1768
|
}
|
1782
1769
|
var div = legend.children();
|
1783
1770
|
$('<div style="position:absolute;width:' + div.width() + 'px;height:' + div.height() + 'px;' + pos +'background-color:' + c + ';"> </div>').prependTo(legend).css('opacity', options.legend.backgroundOpacity);
|
@@ -1788,16 +1775,24 @@
|
|
1788
1775
|
|
1789
1776
|
// interactive features
|
1790
1777
|
|
1791
|
-
var
|
1792
|
-
|
1778
|
+
var lastMousePos = { pageX: null, pageY: null },
|
1779
|
+
selection = {
|
1780
|
+
first: { x: -1, y: -1}, second: { x: -1, y: -1},
|
1781
|
+
show: false,
|
1782
|
+
active: false
|
1783
|
+
},
|
1784
|
+
highlights = [],
|
1785
|
+
clickIsMouseUp = false,
|
1786
|
+
redrawTimeout = null,
|
1787
|
+
hoverTimeout = null;
|
1793
1788
|
|
1794
1789
|
// returns the data item the mouse is over, or null if none is found
|
1795
1790
|
function findNearbyItem(mouseX, mouseY, seriesFilter) {
|
1796
1791
|
var maxDistance = options.grid.mouseActiveRadius,
|
1797
|
-
|
1792
|
+
lowestDistance = maxDistance * maxDistance + 1,
|
1798
1793
|
item = null, foundPoint = false, i, j;
|
1799
1794
|
|
1800
|
-
for (i = 0; i < series.length; ++i) {
|
1795
|
+
for (var i = 0; i < series.length; ++i) {
|
1801
1796
|
if (!seriesFilter(series[i]))
|
1802
1797
|
continue;
|
1803
1798
|
|
@@ -1827,12 +1822,9 @@
|
|
1827
1822
|
// data units, because the scales of the axes may be different
|
1828
1823
|
var dx = Math.abs(axisx.p2c(x) - mouseX),
|
1829
1824
|
dy = Math.abs(axisy.p2c(y) - mouseY),
|
1830
|
-
dist = dx * dx + dy * dy; //
|
1831
|
-
|
1832
|
-
|
1833
|
-
// (last generally means on top of)
|
1834
|
-
if (dist <= smallestDistance) {
|
1835
|
-
smallestDistance = dist;
|
1825
|
+
dist = dx * dx + dy * dy; // no idea in taking sqrt
|
1826
|
+
if (dist < lowestDistance) {
|
1827
|
+
lowestDistance = dist;
|
1836
1828
|
item = [i, j / ps];
|
1837
1829
|
}
|
1838
1830
|
}
|
@@ -1842,6 +1834,12 @@
|
|
1842
1834
|
var barLeft = s.bars.align == "left" ? 0 : -s.bars.barWidth/2,
|
1843
1835
|
barRight = barLeft + s.bars.barWidth;
|
1844
1836
|
|
1837
|
+
if (s.bars.series_spread) {
|
1838
|
+
var actualBarWidth = ((1.0/series.length) * (s.bars.barWidth));
|
1839
|
+
barLeft = barLeft + (i * actualBarWidth);
|
1840
|
+
barRight = barLeft + actualBarWidth;
|
1841
|
+
}
|
1842
|
+
|
1845
1843
|
for (j = 0; j < points.length; j += ps) {
|
1846
1844
|
var x = points[j], y = points[j + 1], b = points[j + 2];
|
1847
1845
|
if (x == null)
|
@@ -1861,7 +1859,6 @@
|
|
1861
1859
|
if (item) {
|
1862
1860
|
i = item[0];
|
1863
1861
|
j = item[1];
|
1864
|
-
ps = series[i].datapoints.pointsize;
|
1865
1862
|
|
1866
1863
|
return { datapoint: series[i].datapoints.points.slice(j * ps, (j + 1) * ps),
|
1867
1864
|
dataIndex: j,
|
@@ -1873,12 +1870,50 @@
|
|
1873
1870
|
}
|
1874
1871
|
|
1875
1872
|
function onMouseMove(e) {
|
1873
|
+
lastMousePos.pageX = e.pageX;
|
1874
|
+
lastMousePos.pageY = e.pageY;
|
1875
|
+
|
1876
1876
|
if (options.grid.hoverable)
|
1877
|
-
triggerClickHoverEvent("plothover",
|
1877
|
+
triggerClickHoverEvent("plothover", lastMousePos,
|
1878
1878
|
function (s) { return s["hoverable"] != false; });
|
1879
|
+
|
1880
|
+
if (selection.active) {
|
1881
|
+
placeholder.trigger("plotselecting", [ getSelection() ]);
|
1882
|
+
|
1883
|
+
updateSelection(lastMousePos);
|
1884
|
+
}
|
1879
1885
|
}
|
1880
1886
|
|
1887
|
+
function onMouseDown(e) {
|
1888
|
+
if (e.which != 1) // only accept left-click
|
1889
|
+
return;
|
1890
|
+
|
1891
|
+
// cancel out any text selections
|
1892
|
+
document.body.focus();
|
1893
|
+
|
1894
|
+
// prevent text selection and drag in old-school browsers
|
1895
|
+
if (document.onselectstart !== undefined && workarounds.onselectstart == null) {
|
1896
|
+
workarounds.onselectstart = document.onselectstart;
|
1897
|
+
document.onselectstart = function () { return false; };
|
1898
|
+
}
|
1899
|
+
if (document.ondrag !== undefined && workarounds.ondrag == null) {
|
1900
|
+
workarounds.ondrag = document.ondrag;
|
1901
|
+
document.ondrag = function () { return false; };
|
1902
|
+
}
|
1903
|
+
|
1904
|
+
setSelectionPos(selection.first, e);
|
1905
|
+
|
1906
|
+
lastMousePos.pageX = null;
|
1907
|
+
selection.active = true;
|
1908
|
+
$(document).one("mouseup", onSelectionMouseUp);
|
1909
|
+
}
|
1910
|
+
|
1881
1911
|
function onClick(e) {
|
1912
|
+
if (clickIsMouseUp) {
|
1913
|
+
clickIsMouseUp = false;
|
1914
|
+
return;
|
1915
|
+
}
|
1916
|
+
|
1882
1917
|
triggerClickHoverEvent("plotclick", e,
|
1883
1918
|
function (s) { return s["clickable"] != false; });
|
1884
1919
|
}
|
@@ -1946,6 +1981,22 @@
|
|
1946
1981
|
else
|
1947
1982
|
drawPointHighlight(hi.series, hi.point);
|
1948
1983
|
}
|
1984
|
+
|
1985
|
+
// draw selection
|
1986
|
+
if (selection.show && selectionIsSane()) {
|
1987
|
+
octx.strokeStyle = parseColor(options.selection.color).scale(null, null, null, 0.8).toString();
|
1988
|
+
octx.lineWidth = 1;
|
1989
|
+
ctx.lineJoin = "round";
|
1990
|
+
octx.fillStyle = parseColor(options.selection.color).scale(null, null, null, 0.4).toString();
|
1991
|
+
|
1992
|
+
var x = Math.min(selection.first.x, selection.second.x),
|
1993
|
+
y = Math.min(selection.first.y, selection.second.y),
|
1994
|
+
w = Math.abs(selection.second.x - selection.first.x),
|
1995
|
+
h = Math.abs(selection.second.y - selection.first.y);
|
1996
|
+
|
1997
|
+
octx.fillRect(x, y, w, h);
|
1998
|
+
octx.strokeRect(x, y, w, h);
|
1999
|
+
}
|
1949
2000
|
octx.restore();
|
1950
2001
|
|
1951
2002
|
executeHooks(hooks.drawOverlay, [octx]);
|
@@ -1998,6 +2049,15 @@
|
|
1998
2049
|
return -1;
|
1999
2050
|
}
|
2000
2051
|
|
2052
|
+
function indexOfSeries(s) {
|
2053
|
+
for (var i = 0; i < series.length; ++i) {
|
2054
|
+
var os = series[i];
|
2055
|
+
if (os == s)
|
2056
|
+
return i;
|
2057
|
+
}
|
2058
|
+
return -1;
|
2059
|
+
}
|
2060
|
+
|
2001
2061
|
function drawPointHighlight(series, point) {
|
2002
2062
|
var x = point[0], y = point[1],
|
2003
2063
|
axisx = series.xaxis, axisy = series.yaxis;
|
@@ -2007,7 +2067,7 @@
|
|
2007
2067
|
|
2008
2068
|
var pointRadius = series.points.radius + series.points.lineWidth / 2;
|
2009
2069
|
octx.lineWidth = pointRadius;
|
2010
|
-
octx.strokeStyle =
|
2070
|
+
octx.strokeStyle = parseColor(series.color).scale(1, 1, 1, 0.5).toString();
|
2011
2071
|
var radius = 1.5 * pointRadius;
|
2012
2072
|
octx.beginPath();
|
2013
2073
|
octx.arc(axisx.p2c(x), axisy.p2c(y), radius, 0, 2 * Math.PI, false);
|
@@ -2016,13 +2076,161 @@
|
|
2016
2076
|
|
2017
2077
|
function drawBarHighlight(series, point) {
|
2018
2078
|
octx.lineWidth = series.bars.lineWidth;
|
2019
|
-
octx.strokeStyle =
|
2020
|
-
var fillStyle =
|
2079
|
+
octx.strokeStyle = parseColor(series.color).scale(1, 1, 1, 0.5).toString();
|
2080
|
+
var fillStyle = parseColor(series.color).scale(1, 1, 1, 0.5).toString();
|
2021
2081
|
var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2;
|
2022
|
-
|
2023
|
-
|
2082
|
+
|
2083
|
+
|
2084
|
+
if (series.bars.series_spread) {
|
2085
|
+
s = plot.getData();
|
2086
|
+
series_index = indexOfSeries(series);
|
2087
|
+
var actualBarWidth = ((1.0/s.length) * (series.bars.barWidth));
|
2088
|
+
barLeft = barLeft + (series_index * actualBarWidth);
|
2089
|
+
}
|
2090
|
+
|
2091
|
+
if (series.bars.series_spread) {
|
2092
|
+
drawBar(point[0], point[1], point[2] || 0, barLeft, barLeft + actualBarWidth,
|
2093
|
+
0, series.bars.lineWidth, function () { return fillStyle; }, series.xaxis, series.yaxis, octx, series.bars.horizontal);
|
2094
|
+
} else {
|
2095
|
+
drawBar(point[0], point[1], point[2] || 0, barLeft, barLeft + series.bars.barWidth,
|
2096
|
+
0, 0, function () { return fillStyle; }, series.xaxis, series.yaxis, octx, series.bars.horizontal);
|
2097
|
+
}
|
2024
2098
|
}
|
2025
2099
|
|
2100
|
+
function getSelection() {
|
2101
|
+
if (!selectionIsSane())
|
2102
|
+
return null;
|
2103
|
+
|
2104
|
+
var x1 = Math.min(selection.first.x, selection.second.x),
|
2105
|
+
x2 = Math.max(selection.first.x, selection.second.x),
|
2106
|
+
y1 = Math.max(selection.first.y, selection.second.y),
|
2107
|
+
y2 = Math.min(selection.first.y, selection.second.y);
|
2108
|
+
|
2109
|
+
var r = {};
|
2110
|
+
if (axes.xaxis.used)
|
2111
|
+
r.xaxis = { from: axes.xaxis.c2p(x1), to: axes.xaxis.c2p(x2) };
|
2112
|
+
if (axes.x2axis.used)
|
2113
|
+
r.x2axis = { from: axes.x2axis.c2p(x1), to: axes.x2axis.c2p(x2) };
|
2114
|
+
if (axes.yaxis.used)
|
2115
|
+
r.yaxis = { from: axes.yaxis.c2p(y1), to: axes.yaxis.c2p(y2) };
|
2116
|
+
if (axes.y2axis.used)
|
2117
|
+
r.y2axis = { from: axes.y2axis.c2p(y1), to: axes.y2axis.c2p(y2) };
|
2118
|
+
return r;
|
2119
|
+
}
|
2120
|
+
|
2121
|
+
function triggerSelectedEvent() {
|
2122
|
+
var r = getSelection();
|
2123
|
+
|
2124
|
+
placeholder.trigger("plotselected", [ r ]);
|
2125
|
+
|
2126
|
+
// backwards-compat stuff, to be removed in future
|
2127
|
+
if (axes.xaxis.used && axes.yaxis.used)
|
2128
|
+
placeholder.trigger("selected", [ { x1: r.xaxis.from, y1: r.yaxis.from, x2: r.xaxis.to, y2: r.yaxis.to } ]);
|
2129
|
+
}
|
2130
|
+
|
2131
|
+
function onSelectionMouseUp(e) {
|
2132
|
+
// revert drag stuff for old-school browsers
|
2133
|
+
if (document.onselectstart !== undefined)
|
2134
|
+
document.onselectstart = workarounds.onselectstart;
|
2135
|
+
if (document.ondrag !== undefined)
|
2136
|
+
document.ondrag = workarounds.ondrag;
|
2137
|
+
|
2138
|
+
// no more draggy-dee-drag
|
2139
|
+
selection.active = false;
|
2140
|
+
updateSelection(e);
|
2141
|
+
|
2142
|
+
if (selectionIsSane()) {
|
2143
|
+
triggerSelectedEvent();
|
2144
|
+
clickIsMouseUp = true;
|
2145
|
+
}
|
2146
|
+
else {
|
2147
|
+
// this counts as a clear
|
2148
|
+
placeholder.trigger("plotunselected", [ ]);
|
2149
|
+
placeholder.trigger("plotselecting", [ null ]);
|
2150
|
+
}
|
2151
|
+
|
2152
|
+
return false;
|
2153
|
+
}
|
2154
|
+
|
2155
|
+
function setSelectionPos(pos, e) {
|
2156
|
+
var offset = eventHolder.offset();
|
2157
|
+
pos.x = clamp(0, e.pageX - offset.left - plotOffset.left, plotWidth);
|
2158
|
+
pos.y = clamp(0, e.pageY - offset.top - plotOffset.top, plotHeight);
|
2159
|
+
|
2160
|
+
if (options.selection.mode == "y") {
|
2161
|
+
if (pos == selection.first)
|
2162
|
+
pos.x = 0;
|
2163
|
+
else
|
2164
|
+
pos.x = plotWidth;
|
2165
|
+
}
|
2166
|
+
|
2167
|
+
if (options.selection.mode == "x") {
|
2168
|
+
if (pos == selection.first)
|
2169
|
+
pos.y = 0;
|
2170
|
+
else
|
2171
|
+
pos.y = plotHeight;
|
2172
|
+
}
|
2173
|
+
}
|
2174
|
+
|
2175
|
+
function updateSelection(pos) {
|
2176
|
+
if (pos.pageX == null)
|
2177
|
+
return;
|
2178
|
+
|
2179
|
+
setSelectionPos(selection.second, pos);
|
2180
|
+
if (selectionIsSane()) {
|
2181
|
+
selection.show = true;
|
2182
|
+
triggerRedrawOverlay();
|
2183
|
+
}
|
2184
|
+
else
|
2185
|
+
clearSelection(true);
|
2186
|
+
}
|
2187
|
+
|
2188
|
+
function clearSelection(preventEvent) {
|
2189
|
+
if (selection.show) {
|
2190
|
+
selection.show = false;
|
2191
|
+
triggerRedrawOverlay();
|
2192
|
+
if (!preventEvent)
|
2193
|
+
placeholder.trigger("plotunselected", [ ]);
|
2194
|
+
}
|
2195
|
+
}
|
2196
|
+
|
2197
|
+
function setSelection(ranges, preventEvent) {
|
2198
|
+
var range;
|
2199
|
+
|
2200
|
+
if (options.selection.mode == "y") {
|
2201
|
+
selection.first.x = 0;
|
2202
|
+
selection.second.x = plotWidth;
|
2203
|
+
}
|
2204
|
+
else {
|
2205
|
+
range = extractRange(ranges, "x");
|
2206
|
+
|
2207
|
+
selection.first.x = range.axis.p2c(range.from);
|
2208
|
+
selection.second.x = range.axis.p2c(range.to);
|
2209
|
+
}
|
2210
|
+
|
2211
|
+
if (options.selection.mode == "x") {
|
2212
|
+
selection.first.y = 0;
|
2213
|
+
selection.second.y = plotHeight;
|
2214
|
+
}
|
2215
|
+
else {
|
2216
|
+
range = extractRange(ranges, "y");
|
2217
|
+
|
2218
|
+
selection.first.y = range.axis.p2c(range.from);
|
2219
|
+
selection.second.y = range.axis.p2c(range.to);
|
2220
|
+
}
|
2221
|
+
|
2222
|
+
selection.show = true;
|
2223
|
+
triggerRedrawOverlay();
|
2224
|
+
if (!preventEvent)
|
2225
|
+
triggerSelectedEvent();
|
2226
|
+
}
|
2227
|
+
|
2228
|
+
function selectionIsSane() {
|
2229
|
+
var minSize = 5;
|
2230
|
+
return Math.abs(selection.second.x - selection.first.x) >= minSize &&
|
2231
|
+
Math.abs(selection.second.y - selection.first.y) >= minSize;
|
2232
|
+
}
|
2233
|
+
|
2026
2234
|
function getColorOrGradient(spec, bottom, top, defaultColor) {
|
2027
2235
|
if (typeof spec == "string")
|
2028
2236
|
return spec;
|
@@ -2034,12 +2242,7 @@
|
|
2034
2242
|
|
2035
2243
|
for (var i = 0, l = spec.colors.length; i < l; ++i) {
|
2036
2244
|
var c = spec.colors[i];
|
2037
|
-
|
2038
|
-
c = $.color.parse(defaultColor).scale('rgb', c.brightness);
|
2039
|
-
c.a *= c.opacity;
|
2040
|
-
c = c.toString();
|
2041
|
-
}
|
2042
|
-
gradient.addColorStop(i / (l - 1), c);
|
2245
|
+
gradient.addColorStop(i / (l - 1), typeof c == "string" ? c : parseColor(defaultColor).scale(c.brightness, c.brightness, c.brightness, c.opacity));
|
2043
2246
|
}
|
2044
2247
|
|
2045
2248
|
return gradient;
|
@@ -2070,33 +2273,21 @@
|
|
2070
2273
|
|
2071
2274
|
var r = [];
|
2072
2275
|
var escape = false;
|
2073
|
-
var hours = d.getUTCHours();
|
2074
|
-
var isAM = hours < 12;
|
2075
2276
|
if (monthNames == null)
|
2076
2277
|
monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
2077
|
-
|
2078
|
-
if (fmt.search(/%p|%P/) != -1) {
|
2079
|
-
if (hours > 12) {
|
2080
|
-
hours = hours - 12;
|
2081
|
-
} else if (hours == 0) {
|
2082
|
-
hours = 12;
|
2083
|
-
}
|
2084
|
-
}
|
2085
2278
|
for (var i = 0; i < fmt.length; ++i) {
|
2086
2279
|
var c = fmt.charAt(i);
|
2087
2280
|
|
2088
2281
|
if (escape) {
|
2089
2282
|
switch (c) {
|
2090
|
-
case 'h': c = "" +
|
2091
|
-
case 'H': c = leftPad(
|
2283
|
+
case 'h': c = "" + d.getUTCHours(); break;
|
2284
|
+
case 'H': c = leftPad(d.getUTCHours()); break;
|
2092
2285
|
case 'M': c = leftPad(d.getUTCMinutes()); break;
|
2093
2286
|
case 'S': c = leftPad(d.getUTCSeconds()); break;
|
2094
2287
|
case 'd': c = "" + d.getUTCDate(); break;
|
2095
2288
|
case 'm': c = "" + (d.getUTCMonth() + 1); break;
|
2096
2289
|
case 'y': c = "" + d.getUTCFullYear(); break;
|
2097
2290
|
case 'b': c = "" + monthNames[d.getUTCMonth()]; break;
|
2098
|
-
case 'p': c = (isAM) ? ("" + "am") : ("" + "pm"); break;
|
2099
|
-
case 'P': c = (isAM) ? ("" + "AM") : ("" + "PM"); break;
|
2100
2291
|
}
|
2101
2292
|
r.push(c);
|
2102
2293
|
escape = false;
|
@@ -2116,4 +2307,167 @@
|
|
2116
2307
|
return base * Math.floor(n / base);
|
2117
2308
|
}
|
2118
2309
|
|
2310
|
+
function clamp(min, value, max) {
|
2311
|
+
if (value < min)
|
2312
|
+
return min;
|
2313
|
+
else if (value > max)
|
2314
|
+
return max;
|
2315
|
+
else
|
2316
|
+
return value;
|
2317
|
+
}
|
2318
|
+
|
2319
|
+
// color helpers, inspiration from the jquery color animation
|
2320
|
+
// plugin by John Resig
|
2321
|
+
function Color (r, g, b, a) {
|
2322
|
+
|
2323
|
+
var rgba = ['r','g','b','a'];
|
2324
|
+
var x = 4; //rgba.length
|
2325
|
+
|
2326
|
+
while (-1<--x) {
|
2327
|
+
this[rgba[x]] = arguments[x] || ((x==3) ? 1.0 : 0);
|
2328
|
+
}
|
2329
|
+
|
2330
|
+
this.toString = function() {
|
2331
|
+
if (this.a >= 1.0) {
|
2332
|
+
return "rgb("+[this.r,this.g,this.b].join(",")+")";
|
2333
|
+
} else {
|
2334
|
+
return "rgba("+[this.r,this.g,this.b,this.a].join(",")+")";
|
2335
|
+
}
|
2336
|
+
};
|
2337
|
+
|
2338
|
+
this.scale = function(rf, gf, bf, af) {
|
2339
|
+
x = 4; //rgba.length
|
2340
|
+
while (-1<--x) {
|
2341
|
+
if (arguments[x] != null)
|
2342
|
+
this[rgba[x]] *= arguments[x];
|
2343
|
+
}
|
2344
|
+
return this.normalize();
|
2345
|
+
};
|
2346
|
+
|
2347
|
+
this.adjust = function(rd, gd, bd, ad) {
|
2348
|
+
x = 4; //rgba.length
|
2349
|
+
while (-1<--x) {
|
2350
|
+
if (arguments[x] != null)
|
2351
|
+
this[rgba[x]] += arguments[x];
|
2352
|
+
}
|
2353
|
+
return this.normalize();
|
2354
|
+
};
|
2355
|
+
|
2356
|
+
this.clone = function() {
|
2357
|
+
return new Color(this.r, this.b, this.g, this.a);
|
2358
|
+
};
|
2359
|
+
|
2360
|
+
this.normalize = function() {
|
2361
|
+
this.r = clamp(0, parseInt(this.r), 255);
|
2362
|
+
this.g = clamp(0, parseInt(this.g), 255);
|
2363
|
+
this.b = clamp(0, parseInt(this.b), 255);
|
2364
|
+
this.a = clamp(0, this.a, 1);
|
2365
|
+
return this;
|
2366
|
+
};
|
2367
|
+
|
2368
|
+
this.normalize();
|
2369
|
+
}
|
2370
|
+
|
2371
|
+
var lookupColors = {
|
2372
|
+
aqua:[0,255,255],
|
2373
|
+
azure:[240,255,255],
|
2374
|
+
beige:[245,245,220],
|
2375
|
+
black:[0,0,0],
|
2376
|
+
blue:[0,0,255],
|
2377
|
+
brown:[165,42,42],
|
2378
|
+
cyan:[0,255,255],
|
2379
|
+
darkblue:[0,0,139],
|
2380
|
+
darkcyan:[0,139,139],
|
2381
|
+
darkgrey:[169,169,169],
|
2382
|
+
darkgreen:[0,100,0],
|
2383
|
+
darkkhaki:[189,183,107],
|
2384
|
+
darkmagenta:[139,0,139],
|
2385
|
+
darkolivegreen:[85,107,47],
|
2386
|
+
darkorange:[255,140,0],
|
2387
|
+
darkorchid:[153,50,204],
|
2388
|
+
darkred:[139,0,0],
|
2389
|
+
darksalmon:[233,150,122],
|
2390
|
+
darkviolet:[148,0,211],
|
2391
|
+
fuchsia:[255,0,255],
|
2392
|
+
gold:[255,215,0],
|
2393
|
+
green:[0,128,0],
|
2394
|
+
indigo:[75,0,130],
|
2395
|
+
khaki:[240,230,140],
|
2396
|
+
lightblue:[173,216,230],
|
2397
|
+
lightcyan:[224,255,255],
|
2398
|
+
lightgreen:[144,238,144],
|
2399
|
+
lightgrey:[211,211,211],
|
2400
|
+
lightpink:[255,182,193],
|
2401
|
+
lightyellow:[255,255,224],
|
2402
|
+
lime:[0,255,0],
|
2403
|
+
magenta:[255,0,255],
|
2404
|
+
maroon:[128,0,0],
|
2405
|
+
navy:[0,0,128],
|
2406
|
+
olive:[128,128,0],
|
2407
|
+
orange:[255,165,0],
|
2408
|
+
pink:[255,192,203],
|
2409
|
+
purple:[128,0,128],
|
2410
|
+
violet:[128,0,128],
|
2411
|
+
red:[255,0,0],
|
2412
|
+
silver:[192,192,192],
|
2413
|
+
white:[255,255,255],
|
2414
|
+
yellow:[255,255,0]
|
2415
|
+
};
|
2416
|
+
|
2417
|
+
function extractColor(element) {
|
2418
|
+
var color, elem = element;
|
2419
|
+
do {
|
2420
|
+
color = elem.css("background-color").toLowerCase();
|
2421
|
+
// keep going until we find an element that has color, or
|
2422
|
+
// we hit the body
|
2423
|
+
if (color != '' && color != 'transparent')
|
2424
|
+
break;
|
2425
|
+
elem = elem.parent();
|
2426
|
+
} while (!$.nodeName(elem.get(0), "body"));
|
2427
|
+
|
2428
|
+
// catch Safari's way of signalling transparent
|
2429
|
+
if (color == "rgba(0, 0, 0, 0)")
|
2430
|
+
return "transparent";
|
2431
|
+
|
2432
|
+
return color;
|
2433
|
+
}
|
2434
|
+
|
2435
|
+
// parse string, returns Color
|
2436
|
+
function parseColor(str) {
|
2437
|
+
var result;
|
2438
|
+
|
2439
|
+
// Look for rgb(num,num,num)
|
2440
|
+
if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(str))
|
2441
|
+
return new Color(parseInt(result[1], 10), parseInt(result[2], 10), parseInt(result[3], 10));
|
2442
|
+
|
2443
|
+
// Look for rgba(num,num,num,num)
|
2444
|
+
if (result = /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))
|
2445
|
+
return new Color(parseInt(result[1], 10), parseInt(result[2], 10), parseInt(result[3], 10), parseFloat(result[4]));
|
2446
|
+
|
2447
|
+
// Look for rgb(num%,num%,num%)
|
2448
|
+
if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(str))
|
2449
|
+
return new Color(parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55);
|
2450
|
+
|
2451
|
+
// Look for rgba(num%,num%,num%,num)
|
2452
|
+
if (result = /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))
|
2453
|
+
return new Color(parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55, parseFloat(result[4]));
|
2454
|
+
|
2455
|
+
// Look for #a0b1c2
|
2456
|
+
if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(str))
|
2457
|
+
return new Color(parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16));
|
2458
|
+
|
2459
|
+
// Look for #fff
|
2460
|
+
if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(str))
|
2461
|
+
return new Color(parseInt(result[1]+result[1], 16), parseInt(result[2]+result[2], 16), parseInt(result[3]+result[3], 16));
|
2462
|
+
|
2463
|
+
// Otherwise, we're most likely dealing with a named color
|
2464
|
+
var name = $.trim(str).toLowerCase();
|
2465
|
+
if (name == "transparent")
|
2466
|
+
return new Color(255, 255, 255, 0);
|
2467
|
+
else {
|
2468
|
+
result = lookupColors[name];
|
2469
|
+
return new Color(result[0], result[1], result[2]);
|
2470
|
+
}
|
2471
|
+
}
|
2472
|
+
|
2119
2473
|
})(jQuery);
|