fnordmetric 1.0.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/Rakefile +1 -1
  2. data/fnordmetric.gemspec +1 -0
  3. data/lib/fnordmetric.rb +6 -13
  4. data/lib/fnordmetric/acceptors/acceptor.rb +20 -7
  5. data/lib/fnordmetric/acceptors/amqp_acceptor.rb +56 -0
  6. data/lib/fnordmetric/acceptors/fyrehose_acceptor.rb +43 -0
  7. data/lib/fnordmetric/acceptors/stomp_acceptor.rb +71 -0
  8. data/lib/fnordmetric/acceptors/tcp_acceptor.rb +1 -0
  9. data/lib/fnordmetric/acceptors/udp_acceptor.rb +2 -1
  10. data/lib/fnordmetric/context.rb +21 -9
  11. data/lib/fnordmetric/defaults.rb +16 -3
  12. data/lib/fnordmetric/gauge.rb +8 -3
  13. data/lib/fnordmetric/gauge_calculations.rb +8 -2
  14. data/lib/fnordmetric/gauge_modifiers.rb +5 -4
  15. data/lib/fnordmetric/gauges/server_health_gauge.rb +13 -0
  16. data/lib/fnordmetric/namespace.rb +53 -17
  17. data/lib/fnordmetric/util.rb +25 -0
  18. data/lib/fnordmetric/version.rb +1 -1
  19. data/lib/fnordmetric/web/app.rb +7 -66
  20. data/lib/fnordmetric/web/reactor.rb +32 -2
  21. data/lib/fnordmetric/web/websocket.rb +1 -1
  22. data/lib/fnordmetric/widgets/bars_widget.rb +1 -1
  23. data/lib/fnordmetric/widgets/numbers_widget.rb +28 -4
  24. data/lib/fnordmetric/widgets/timeseries_widget.rb +19 -9
  25. data/lib/fnordmetric/widgets/toplist_widget.rb +8 -4
  26. data/lib/fnordmetric/worker.rb +5 -1
  27. data/lib/fnordmetric/zero_config_gauge.rb +138 -0
  28. data/spec/context_spec.rb +4 -4
  29. data/spec/event_spec.rb +11 -11
  30. data/spec/gauge_modifiers_spec.rb +135 -29
  31. data/spec/gauge_spec.rb +7 -2
  32. data/spec/namespace_spec.rb +8 -19
  33. data/spec/util_spec.rb +46 -0
  34. data/web/.gitignore +4 -0
  35. data/web/build.sh +34 -0
  36. data/web/{fnordmetric.css → css/fnordmetric.core.css} +121 -58
  37. data/web/haml/app.haml +4 -22
  38. data/web/{loader.gif → img/loader.gif} +0 -0
  39. data/web/js/fnordmetric.bars_widget.js +3 -3
  40. data/web/js/fnordmetric.dashboard_view.js +1 -1
  41. data/web/js/fnordmetric.gauge_explorer.js +173 -0
  42. data/web/js/fnordmetric.js +93 -33
  43. data/web/js/fnordmetric.numbers_widget.js +15 -14
  44. data/web/js/fnordmetric.session_view.js +0 -1
  45. data/web/js/fnordmetric.timeline_widget.js +3 -3
  46. data/web/js/fnordmetric.timeseries_widget.js +46 -29
  47. data/web/js/fnordmetric.toplist_widget.js +23 -16
  48. data/web/js/fnordmetric.util.js +12 -8
  49. data/web/vendor/font-awesome/css/font-awesome-ie7.min.css +22 -0
  50. data/web/vendor/font-awesome/css/font-awesome.css +522 -221
  51. data/web/vendor/font-awesome/css/font-awesome.min.css +33 -0
  52. data/web/vendor/font-awesome/font/FontAwesome.otf +0 -0
  53. data/web/vendor/font-awesome/font/fontawesome-webfont.eot +0 -0
  54. data/web/vendor/font-awesome/font/fontawesome-webfont.svg +278 -169
  55. data/web/vendor/font-awesome/font/fontawesome-webfont.ttf +0 -0
  56. data/web/vendor/font-awesome/font/fontawesome-webfont.woff +0 -0
  57. data/web/vendor/jquery-ui.min.js +6 -413
  58. data/web/vendor/jquery.combobox.js +129 -0
  59. metadata +55 -48
  60. data/doc/V1.0-ROADMAP +0 -97
  61. data/doc/full_example.rb +0 -224
  62. data/doc/legacy_example.rb +0 -640
  63. data/doc/minimal_example.rb +0 -26
  64. data/doc/preview1.png +0 -0
  65. data/doc/preview2.png +0 -0
  66. data/doc/preview3.png +0 -0
  67. data/readme.md +0 -365
  68. data/web/vendor/d3.v2.js +0 -9382
  69. data/web/vendor/font-awesome/font/fontawesome-webfont.svgz +0 -0
  70. data/web/vendor/rickshaw.css +0 -286
  71. data/web/vendor/rickshaw.fnordmetric.js +0 -2700
@@ -1,286 +0,0 @@
1
- .rickshaw_graph .detail {
2
- pointer-events: none;
3
- position: absolute;
4
- top: 0;
5
- z-index: 2;
6
- background: rgba(0, 0, 0, 0.1);
7
- bottom: 0;
8
- width: 1px;
9
- transition: opacity 0.25s linear;
10
- -moz-transition: opacity 0.25s linear;
11
- -o-transition: opacity 0.25s linear;
12
- -webkit-transition: opacity 0.25s linear;
13
- }
14
- .rickshaw_graph .detail.inactive {
15
- opacity: 0;
16
- }
17
- .rickshaw_graph .detail .item.active {
18
- opacity: 1;
19
- }
20
- .rickshaw_graph .detail .x_label {
21
- font-family: "Gotham Narrow", Helvetica, Arial, sans-serif;
22
- border-radius: 3px;
23
- padding: 6px;
24
- opacity: 0.5;
25
- border: 1px solid #e0e0e0;
26
- font-size: 12px;
27
- position: absolute;
28
- background: white;
29
- white-space: nowrap;
30
- }
31
- .rickshaw_graph .detail .item {
32
- position: absolute;
33
- z-index: 2;
34
- border-radius: 3px;
35
- padding: 0.25em;
36
- font-size: 12px;
37
- font-family: "Gotham Narrow", Helvetica, Arial, sans-serif;
38
- opacity: 0;
39
- background: rgba(0, 0, 0, 0.4);
40
- color: white;
41
- border: 1px solid rgba(0, 0, 0, 0.4);
42
- margin-left: 1em;
43
- margin-top: -1em;
44
- white-space: nowrap;
45
- }
46
- .rickshaw_graph .detail .item.active {
47
- opacity: 1;
48
- background: rgba(0, 0, 0, 0.8);
49
- }
50
- .rickshaw_graph .detail .item:before {
51
- content: "\25c2";
52
- position: absolute;
53
- left: -0.5em;
54
- color: rgba(0, 0, 0, 0.7);
55
- width: 0;
56
- }
57
- .rickshaw_graph .detail .dot {
58
- width: 4px;
59
- height: 4px;
60
- margin-left: -4px;
61
- margin-top: -3px;
62
- border-radius: 5px;
63
- position: absolute;
64
- box-shadow: 0 0 2px rgba(0, 0, 0, 0.6);
65
- background: white;
66
- border-width: 2px;
67
- border-style: solid;
68
- display: none;
69
- background-clip: padding-box;
70
- }
71
- .rickshaw_graph .detail .dot.active {
72
- display: block;
73
- }
74
- /* graph */
75
-
76
- .rickshaw_graph {
77
- position: relative;
78
- }
79
- .rickshaw_graph svg {
80
- display: block;
81
- overflow: hidden;
82
- }
83
-
84
- /* ticks */
85
-
86
- .rickshaw_graph .x_tick {
87
- position: absolute;
88
- top: 0;
89
- bottom: 0;
90
- width: 0px;
91
- border-left: 1px dotted rgba(0, 0, 0, 0.2);
92
- pointer-events: none;
93
- }
94
- .rickshaw_graph .x_tick .title {
95
- position: absolute;
96
- font-size: 12px;
97
- font-family: "Gotham Narrow", Helvetica, Arial, sans-serif;
98
- opacity: 0.5;
99
- white-space: nowrap;
100
- margin-left: 3px;
101
- bottom: 1px;
102
- }
103
-
104
- /* annotations */
105
-
106
- .rickshaw_annotation_timeline {
107
- height: 1px;
108
- border-top: 1px solid #e0e0e0;
109
- margin-top: 10px;
110
- position: relative;
111
- }
112
- .rickshaw_annotation_timeline .annotation {
113
- position: absolute;
114
- height: 6px;
115
- width: 6px;
116
- margin-left: -2px;
117
- top: -3px;
118
- border-radius: 5px;
119
- background-color: rgba(0, 0, 0, 0.25);
120
- }
121
- .rickshaw_graph .annotation_line {
122
- position: absolute;
123
- top: 0;
124
- bottom: -6px;
125
- width: 0px;
126
- border-left: 2px solid rgba(0, 0, 0, 0.3);
127
- display: none;
128
- }
129
- .rickshaw_graph .annotation_line.active {
130
- display: block;
131
- }
132
- .rickshaw_annotation_timeline .annotation .content {
133
- background: white;
134
- color: black;
135
- opacity: 0.9;
136
- padding: 5px 5px;
137
- box-shadow: 0 0 2px rgba(0, 0, 0, 0.8);
138
- border-radius: 3px;
139
- position: relative;
140
- z-index: 20;
141
- font-size: 12px;
142
- padding: 6px 8px 8px;
143
- top: 18px;
144
- left: -11px;
145
- width: 160px;
146
- display: none;
147
- cursor: pointer;
148
- }
149
- .rickshaw_annotation_timeline .annotation .content:before {
150
- content: "\25b2";
151
- position: absolute;
152
- top: -11px;
153
- color: white;
154
- text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.8);
155
- }
156
- .rickshaw_annotation_timeline .annotation.active,
157
- .rickshaw_annotation_timeline .annotation:hover {
158
- background-color: rgba(0, 0, 0, 0.8);
159
- cursor: none;
160
- }
161
- .rickshaw_annotation_timeline .annotation .content:hover {
162
- z-index: 50;
163
- }
164
- .rickshaw_annotation_timeline .annotation.active .content {
165
- display: block;
166
- }
167
- .rickshaw_annotation_timeline .annotation:hover .content {
168
- display: block;
169
- z-index: 50;
170
- }
171
- .rickshaw_graph .y_axis {
172
- fill: none;
173
- }
174
- .rickshaw_graph .y_ticks .tick {
175
- stroke: rgba(0, 0, 0, 0.16);
176
- stroke-width: 2px;
177
- shape-rendering: crisp-edges;
178
- pointer-events: none;
179
- }
180
- .rickshaw_graph .y_grid .tick {
181
- z-index: -1;
182
- stroke: rgba(0, 0, 0, 0.20);
183
- stroke-width: 1px;
184
- stroke-dasharray: 1 1;
185
- }
186
- .rickshaw_graph .y_grid path {
187
- fill: none;
188
- stroke: none;
189
- }
190
- .rickshaw_graph .y_ticks path {
191
- fill: none;
192
- stroke: #808080;
193
- }
194
- .rickshaw_graph .y_ticks text {
195
- opacity: 0.5;
196
- font-size: 12px;
197
- pointer-events: none;
198
- }
199
- .rickshaw_graph .x_tick.glow .title,
200
- .rickshaw_graph .y_ticks.glow text {
201
- fill: black;
202
- color: black;
203
- text-shadow:
204
- -1px 1px 0 rgba(255, 255, 255, 0.1),
205
- 1px -1px 0 rgba(255, 255, 255, 0.1),
206
- 1px 1px 0 rgba(255, 255, 255, 0.1),
207
- 0px 1px 0 rgba(255, 255, 255, 0.1),
208
- 0px -1px 0 rgba(255, 255, 255, 0.1),
209
- 1px 0px 0 rgba(255, 255, 255, 0.1),
210
- -1px 0px 0 rgba(255, 255, 255, 0.1),
211
- -1px -1px 0 rgba(255, 255, 255, 0.1);
212
- }
213
- .rickshaw_graph .x_tick.inverse .title,
214
- .rickshaw_graph .y_ticks.inverse text {
215
- fill: white;
216
- color: white;
217
- text-shadow:
218
- -1px 1px 0 rgba(0, 0, 0, 0.8),
219
- 1px -1px 0 rgba(0, 0, 0, 0.8),
220
- 1px 1px 0 rgba(0, 0, 0, 0.8),
221
- 0px 1px 0 rgba(0, 0, 0, 0.8),
222
- 0px -1px 0 rgba(0, 0, 0, 0.8),
223
- 1px 0px 0 rgba(0, 0, 0, 0.8),
224
- -1px 0px 0 rgba(0, 0, 0, 0.8),
225
- -1px -1px 0 rgba(0, 0, 0, 0.8);
226
- }
227
- .rickshaw_legend {
228
- font-family: "Gotham Narrow", Helvetica, Arial;
229
- font-size: 12px;
230
- color: white;
231
- background: #404040;
232
- display: inline-block;
233
- padding: 12px 5px;
234
- border-radius: 2px;
235
- position: relative;
236
- }
237
- .rickshaw_legend:hover {
238
- z-index: 10;
239
- }
240
- .rickshaw_legend .line {
241
- clear: both;
242
- line-height: 140%;
243
- padding-right: 15px;
244
- }
245
- .rickshaw_legend .line .swatch {
246
- display: inline-block;
247
- margin-right: 3px;
248
- border-radius: 2px;
249
- }
250
- .rickshaw_legend .label {
251
- white-space: nowrap;
252
- display: inline;
253
- }
254
- .rickshaw_legend .action:hover {
255
- opacity: 0.6;
256
- }
257
- .rickshaw_legend .action {
258
- margin-right: 0.2em;
259
- font-size: 10px;
260
- opacity: 0.2;
261
- cursor: pointer;
262
- font-size: 14px;
263
- }
264
- .rickshaw_legend .line.disabled {
265
- opacity: 0.4;
266
- }
267
- .rickshaw_legend ul {
268
- list-style-type: none;
269
- margin: 0;
270
- padding: 0;
271
- margin: 2px;
272
- cursor: pointer;
273
- }
274
- .rickshaw_legend li {
275
- padding: 0 0 0 2px;
276
- min-width: 80px;
277
- white-space: nowrap;
278
- }
279
- .rickshaw_legend li:hover {
280
- background: rgba(255, 255, 255, 0.08);
281
- border-radius: 3px;
282
- }
283
- .rickshaw_legend li:active {
284
- background: rgba(255, 255, 255, 0.2);
285
- border-radius: 3px;
286
- }
@@ -1,2700 +0,0 @@
1
- Rickshaw = {
2
-
3
- namespace: function(namespace, obj) {
4
-
5
- var parts = namespace.split('.');
6
-
7
- // for rudimentary compatibility w/ node
8
- var root = typeof global != 'undefined' ? global : window;
9
-
10
- var parent = root.Rickshaw;
11
-
12
- for(var i = 1, length = parts.length; i < length; i++) {
13
- currentPart = parts[i];
14
- parent[currentPart] = parent[currentPart] || {};
15
- parent = parent[currentPart];
16
- }
17
- return parent;
18
- },
19
-
20
- keys: function(obj) {
21
- var keys = [];
22
- for (var key in obj) keys.push(key);
23
- return keys;
24
- },
25
-
26
- extend: function(destination, source) {
27
-
28
- for (var property in source) {
29
- destination[property] = source[property];
30
- }
31
- return destination;
32
- }
33
- };
34
-
35
- /* Adapted from https://github.com/Jakobo/PTClass */
36
-
37
- /*
38
- Copyright (c) 2005-2010 Sam Stephenson
39
-
40
- Permission is hereby granted, free of charge, to any person obtaining a copy
41
- of this software and associated documentation files (the "Software"), to deal
42
- in the Software without restriction, including without limitation the rights
43
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
44
- copies of the Software, and to permit persons to whom the Software is
45
- furnished to do so, subject to the following conditions:
46
-
47
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
48
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
49
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
50
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
51
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
52
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
53
- SOFTWARE.
54
- */
55
- /* Based on Alex Arnell's inheritance implementation. */
56
- /** section: Language
57
- * class Class
58
- *
59
- * Manages Prototype's class-based OOP system.
60
- *
61
- * Refer to Prototype's web site for a [tutorial on classes and
62
- * inheritance](http://prototypejs.org/learn/class-inheritance).
63
- **/
64
- (function(globalContext) {
65
- /* ------------------------------------ */
66
- /* Import from object.js */
67
- /* ------------------------------------ */
68
- var _toString = Object.prototype.toString,
69
- NULL_TYPE = 'Null',
70
- UNDEFINED_TYPE = 'Undefined',
71
- BOOLEAN_TYPE = 'Boolean',
72
- NUMBER_TYPE = 'Number',
73
- STRING_TYPE = 'String',
74
- OBJECT_TYPE = 'Object',
75
- FUNCTION_CLASS = '[object Function]';
76
- function isFunction(object) {
77
- return _toString.call(object) === FUNCTION_CLASS;
78
- }
79
- function extend(destination, source) {
80
- for (var property in source) if (source.hasOwnProperty(property)) // modify protect primitive slaughter
81
- destination[property] = source[property];
82
- return destination;
83
- }
84
- function keys(object) {
85
- if (Type(object) !== OBJECT_TYPE) { throw new TypeError(); }
86
- var results = [];
87
- for (var property in object) {
88
- if (object.hasOwnProperty(property)) {
89
- results.push(property);
90
- }
91
- }
92
- return results;
93
- }
94
- function Type(o) {
95
- switch(o) {
96
- case null: return NULL_TYPE;
97
- case (void 0): return UNDEFINED_TYPE;
98
- }
99
- var type = typeof o;
100
- switch(type) {
101
- case 'boolean': return BOOLEAN_TYPE;
102
- case 'number': return NUMBER_TYPE;
103
- case 'string': return STRING_TYPE;
104
- }
105
- return OBJECT_TYPE;
106
- }
107
- function isUndefined(object) {
108
- return typeof object === "undefined";
109
- }
110
- /* ------------------------------------ */
111
- /* Import from Function.js */
112
- /* ------------------------------------ */
113
- var slice = Array.prototype.slice;
114
- function argumentNames(fn) {
115
- var names = fn.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1]
116
- .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '')
117
- .replace(/\s+/g, '').split(',');
118
- return names.length == 1 && !names[0] ? [] : names;
119
- }
120
- function wrap(fn, wrapper) {
121
- var __method = fn;
122
- return function() {
123
- var a = update([bind(__method, this)], arguments);
124
- return wrapper.apply(this, a);
125
- }
126
- }
127
- function update(array, args) {
128
- var arrayLength = array.length, length = args.length;
129
- while (length--) array[arrayLength + length] = args[length];
130
- return array;
131
- }
132
- function merge(array, args) {
133
- array = slice.call(array, 0);
134
- return update(array, args);
135
- }
136
- function bind(fn, context) {
137
- if (arguments.length < 2 && isUndefined(arguments[0])) return this;
138
- var __method = fn, args = slice.call(arguments, 2);
139
- return function() {
140
- var a = merge(args, arguments);
141
- return __method.apply(context, a);
142
- }
143
- }
144
-
145
- /* ------------------------------------ */
146
- /* Import from Prototype.js */
147
- /* ------------------------------------ */
148
- var emptyFunction = function(){};
149
-
150
- var Class = (function() {
151
-
152
- // Some versions of JScript fail to enumerate over properties, names of which
153
- // correspond to non-enumerable properties in the prototype chain
154
- var IS_DONTENUM_BUGGY = (function(){
155
- for (var p in { toString: 1 }) {
156
- // check actual property name, so that it works with augmented Object.prototype
157
- if (p === 'toString') return false;
158
- }
159
- return true;
160
- })();
161
-
162
- function subclass() {};
163
- function create() {
164
- var parent = null, properties = [].slice.apply(arguments);
165
- if (isFunction(properties[0]))
166
- parent = properties.shift();
167
-
168
- function klass() {
169
- this.initialize.apply(this, arguments);
170
- }
171
-
172
- extend(klass, Class.Methods);
173
- klass.superclass = parent;
174
- klass.subclasses = [];
175
-
176
- if (parent) {
177
- subclass.prototype = parent.prototype;
178
- klass.prototype = new subclass;
179
- try { parent.subclasses.push(klass) } catch(e) {}
180
- }
181
-
182
- for (var i = 0, length = properties.length; i < length; i++)
183
- klass.addMethods(properties[i]);
184
-
185
- if (!klass.prototype.initialize)
186
- klass.prototype.initialize = emptyFunction;
187
-
188
- klass.prototype.constructor = klass;
189
- return klass;
190
- }
191
-
192
- function addMethods(source) {
193
- var ancestor = this.superclass && this.superclass.prototype,
194
- properties = keys(source);
195
-
196
- // IE6 doesn't enumerate `toString` and `valueOf` (among other built-in `Object.prototype`) properties,
197
- // Force copy if they're not Object.prototype ones.
198
- // Do not copy other Object.prototype.* for performance reasons
199
- if (IS_DONTENUM_BUGGY) {
200
- if (source.toString != Object.prototype.toString)
201
- properties.push("toString");
202
- if (source.valueOf != Object.prototype.valueOf)
203
- properties.push("valueOf");
204
- }
205
-
206
- for (var i = 0, length = properties.length; i < length; i++) {
207
- var property = properties[i], value = source[property];
208
- if (ancestor && isFunction(value) &&
209
- argumentNames(value)[0] == "$super") {
210
- var method = value;
211
- value = wrap((function(m) {
212
- return function() { return ancestor[m].apply(this, arguments); };
213
- })(property), method);
214
-
215
- value.valueOf = bind(method.valueOf, method);
216
- value.toString = bind(method.toString, method);
217
- }
218
- this.prototype[property] = value;
219
- }
220
-
221
- return this;
222
- }
223
-
224
- return {
225
- create: create,
226
- Methods: {
227
- addMethods: addMethods
228
- }
229
- };
230
- })();
231
-
232
- if (globalContext.exports) {
233
- globalContext.exports.Class = Class;
234
- }
235
- else {
236
- globalContext.Class = Class;
237
- }
238
- })(Rickshaw);
239
- Rickshaw.namespace('Rickshaw.Compat.ClassList');
240
-
241
- Rickshaw.Compat.ClassList = function() {
242
-
243
- /* adapted from http://purl.eligrey.com/github/classList.js/blob/master/classList.js */
244
-
245
- if (typeof document !== "undefined" && !("classList" in document.createElement("a"))) {
246
-
247
- (function (view) {
248
-
249
- "use strict";
250
-
251
- var
252
- classListProp = "classList"
253
- , protoProp = "prototype"
254
- , elemCtrProto = (view.HTMLElement || view.Element)[protoProp]
255
- , objCtr = Object
256
- , strTrim = String[protoProp].trim || function () {
257
- return this.replace(/^\s+|\s+$/g, "");
258
- }
259
- , arrIndexOf = Array[protoProp].indexOf || function (item) {
260
- var
261
- i = 0
262
- , len = this.length
263
- ;
264
- for (; i < len; i++) {
265
- if (i in this && this[i] === item) {
266
- return i;
267
- }
268
- }
269
- return -1;
270
- }
271
- // Vendors: please allow content code to instantiate DOMExceptions
272
- , DOMEx = function (type, message) {
273
- this.name = type;
274
- this.code = DOMException[type];
275
- this.message = message;
276
- }
277
- , checkTokenAndGetIndex = function (classList, token) {
278
- if (token === "") {
279
- throw new DOMEx(
280
- "SYNTAX_ERR"
281
- , "An invalid or illegal string was specified"
282
- );
283
- }
284
- if (/\s/.test(token)) {
285
- throw new DOMEx(
286
- "INVALID_CHARACTER_ERR"
287
- , "String contains an invalid character"
288
- );
289
- }
290
- return arrIndexOf.call(classList, token);
291
- }
292
- , ClassList = function (elem) {
293
- var
294
- trimmedClasses = strTrim.call(elem.className)
295
- , classes = trimmedClasses ? trimmedClasses.split(/\s+/) : []
296
- , i = 0
297
- , len = classes.length
298
- ;
299
- for (; i < len; i++) {
300
- this.push(classes[i]);
301
- }
302
- this._updateClassName = function () {
303
- elem.className = this.toString();
304
- };
305
- }
306
- , classListProto = ClassList[protoProp] = []
307
- , classListGetter = function () {
308
- return new ClassList(this);
309
- }
310
- ;
311
- // Most DOMException implementations don't allow calling DOMException's toString()
312
- // on non-DOMExceptions. Error's toString() is sufficient here.
313
- DOMEx[protoProp] = Error[protoProp];
314
- classListProto.item = function (i) {
315
- return this[i] || null;
316
- };
317
- classListProto.contains = function (token) {
318
- token += "";
319
- return checkTokenAndGetIndex(this, token) !== -1;
320
- };
321
- classListProto.add = function (token) {
322
- token += "";
323
- if (checkTokenAndGetIndex(this, token) === -1) {
324
- this.push(token);
325
- this._updateClassName();
326
- }
327
- };
328
- classListProto.remove = function (token) {
329
- token += "";
330
- var index = checkTokenAndGetIndex(this, token);
331
- if (index !== -1) {
332
- this.splice(index, 1);
333
- this._updateClassName();
334
- }
335
- };
336
- classListProto.toggle = function (token) {
337
- token += "";
338
- if (checkTokenAndGetIndex(this, token) === -1) {
339
- this.add(token);
340
- } else {
341
- this.remove(token);
342
- }
343
- };
344
- classListProto.toString = function () {
345
- return this.join(" ");
346
- };
347
-
348
- if (objCtr.defineProperty) {
349
- var classListPropDesc = {
350
- get: classListGetter
351
- , enumerable: true
352
- , configurable: true
353
- };
354
- try {
355
- objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
356
- } catch (ex) { // IE 8 doesn't support enumerable:true
357
- if (ex.number === -0x7FF5EC54) {
358
- classListPropDesc.enumerable = false;
359
- objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc);
360
- }
361
- }
362
- } else if (objCtr[protoProp].__defineGetter__) {
363
- elemCtrProto.__defineGetter__(classListProp, classListGetter);
364
- }
365
-
366
- }(self));
367
-
368
- }
369
- };
370
-
371
- if ( (typeof RICKSHAW_NO_COMPAT !== "undefined" && !RICKSHAW_NO_COMPAT) || typeof RICKSHAW_NO_COMPAT === "undefined") {
372
- new Rickshaw.Compat.ClassList();
373
- }
374
- Rickshaw.namespace('Rickshaw.Graph');
375
-
376
- Rickshaw.Graph = function(args) {
377
-
378
- this.element = args.element;
379
- this.series = args.series;
380
-
381
- this.defaults = {
382
- interpolation: 'cardinal',
383
- offset: 'zero',
384
- min: undefined,
385
- max: undefined,
386
- };
387
-
388
- Rickshaw.keys(this.defaults).forEach( function(k) {
389
- this[k] = args[k] || this.defaults[k];
390
- }, this );
391
-
392
- this.window = {};
393
-
394
- this.updateCallbacks = [];
395
-
396
- var self = this;
397
-
398
- this.initialize = function(args) {
399
-
400
- this.validateSeries(args.series);
401
-
402
- this.series.active = function() { return self.series.filter( function(s) { return !s.disabled } ) };
403
-
404
- this.setSize({ width: args.width, height: args.height });
405
-
406
- this.element.classList.add('rickshaw_graph');
407
- this.vis = d3.select(this.element)
408
- .append("svg:svg")
409
- .attr('width', this.width)
410
- .attr('height', this.height);
411
-
412
- var renderers = [
413
- Rickshaw.Graph.Renderer.Stack,
414
- Rickshaw.Graph.Renderer.Line,
415
- Rickshaw.Graph.Renderer.Bar,
416
- Rickshaw.Graph.Renderer.Area,
417
- Rickshaw.Graph.Renderer.ScatterPlot
418
- ];
419
-
420
- renderers.forEach( function(r) {
421
- if (!r) return;
422
- self.registerRenderer(new r( { graph: self } ));
423
- } );
424
-
425
- this.setRenderer(args.renderer || 'stack', args);
426
- this.discoverRange();
427
- };
428
-
429
- this.validateSeries = function(series) {
430
-
431
- if (!(series instanceof Array) && !(series instanceof Rickshaw.Series)) {
432
- var seriesSignature = Object.prototype.toString.apply(series);
433
- throw "series is not an array: " + seriesSignature;
434
- }
435
-
436
- var pointsCount;
437
-
438
- series.forEach( function(s) {
439
-
440
- if (!(s instanceof Object)) {
441
- throw "series element is not an object: " + s;
442
- }
443
- if (!(s.data)) {
444
- throw "series has no data: " + JSON.stringify(s);
445
- }
446
- if (!(s.data instanceof Array)) {
447
- throw "series data is not an array: " + JSON.stringify(s.data);
448
- }
449
-
450
- pointsCount = pointsCount || s.data.length;
451
-
452
- if (pointsCount && s.data.length != pointsCount) {
453
- throw "series cannot have differing numbers of points: " +
454
- pointsCount + " vs " + s.data.length + "; see Rickshaw.Series.zeroFill()";
455
- }
456
-
457
- var dataTypeX = typeof s.data[0].x;
458
- var dataTypeY = typeof s.data[0].y;
459
-
460
- if (dataTypeX != 'number' || dataTypeY != 'number') {
461
- throw "x and y properties of points should be numbers instead of " +
462
- dataTypeX + " and " + dataTypeY;
463
- }
464
- } );
465
- };
466
-
467
- this.dataDomain = function() {
468
-
469
- // take from the first series
470
- var data = this.series[0].data;
471
-
472
- return [ data[0].x, data.slice(-1).shift().x ];
473
-
474
- };
475
-
476
- this.discoverRange = function() {
477
-
478
- var domain = this.renderer.domain();
479
-
480
- this.x = d3.scale.linear().domain(domain.x).range([0, this.width]);
481
-
482
- this.y = d3.scale.linear().domain(domain.y).range([this.height, 0]);
483
- this.y.magnitude = d3.scale.linear().domain(domain.y).range([0, this.height]);
484
-
485
- };
486
-
487
- this.render = function() {
488
-
489
- var stackedData = this.stackData();
490
- this.discoverRange();
491
-
492
- this.renderer.render();
493
-
494
- this.updateCallbacks.forEach( function(callback) {
495
- callback();
496
- } );
497
- };
498
-
499
- this.update = this.render;
500
-
501
- this.stackData = function() {
502
-
503
- var data = this.series.active()
504
- .map( function(d) { return d.data } )
505
- .map( function(d) { return d.filter( function(d) { return this._slice(d) }, this ) }, this);
506
-
507
- this.stackData.hooks.data.forEach( function(entry) {
508
- data = entry.f.apply(self, [data]);
509
- } );
510
-
511
- var layout = d3.layout.stack();
512
- layout.offset( self.offset );
513
-
514
- var stackedData = layout(data);
515
-
516
- this.stackData.hooks.after.forEach( function(entry) {
517
- stackedData = entry.f.apply(self, [data]);
518
- } );
519
-
520
- var i = 0;
521
- this.series.forEach( function(series) {
522
- if (series.disabled) return;
523
- series.stack = stackedData[i++];
524
- } );
525
-
526
- this.stackedData = stackedData;
527
- return stackedData;
528
- };
529
-
530
- this.stackData.hooks = { data: [], after: [] };
531
-
532
- this._slice = function(d) {
533
-
534
- if (this.window.xMin || this.window.xMax) {
535
-
536
- var isInRange = true;
537
-
538
- if (this.window.xMin && d.x < this.window.xMin) isInRange = false;
539
- if (this.window.xMax && d.x > this.window.xMax) isInRange = false;
540
-
541
- return isInRange;
542
- }
543
-
544
- return true;
545
- };
546
-
547
- this.onUpdate = function(callback) {
548
- this.updateCallbacks.push(callback);
549
- };
550
-
551
- this.registerRenderer = function(renderer) {
552
- this._renderers = this._renderers || {};
553
- this._renderers[renderer.name] = renderer;
554
- };
555
-
556
- this.configure = function(args) {
557
-
558
- if (args.width || args.height) {
559
- this.setSize(args);
560
- }
561
-
562
- Rickshaw.keys(this.defaults).forEach( function(k) {
563
- this[k] = args[k] || this.defaults[k];
564
- }, this );
565
-
566
- this.setRenderer(args.renderer || graph.renderer.name, args);
567
- };
568
-
569
- this.setRenderer = function(name, args) {
570
-
571
- if (!this._renderers[name]) {
572
- throw "couldn't find renderer " + name;
573
- }
574
- this.renderer = this._renderers[name];
575
-
576
- if (typeof args == 'object') {
577
- this.renderer.configure(args);
578
- }
579
- };
580
-
581
- this.setSize = function(args) {
582
-
583
- args = args || {};
584
-
585
- if (typeof window !== undefined) {
586
- var style = window.getComputedStyle(this.element, null);
587
- var elementWidth = parseInt(style.getPropertyValue('width'));
588
- var elementHeight = parseInt(style.getPropertyValue('height'));
589
- }
590
-
591
- this.width = args.width || elementWidth || 400;
592
- this.height = args.height || elementHeight || 250;
593
-
594
- this.vis && this.vis
595
- .attr('width', this.width)
596
- .attr('height', this.height);
597
- }
598
-
599
- this.initialize(args);
600
- };
601
- Rickshaw.namespace('Rickshaw.Fixtures.Color');
602
-
603
- Rickshaw.Fixtures.Color = function() {
604
-
605
- this.schemes = {};
606
-
607
- this.schemes.spectrum14 = [
608
- '#ecb796',
609
- '#dc8f70',
610
- '#b2a470',
611
- '#92875a',
612
- '#716c49',
613
- '#d2ed82',
614
- '#bbe468',
615
- '#a1d05d',
616
- '#e7cbe6',
617
- '#d8aad6',
618
- '#a888c2',
619
- '#9dc2d3',
620
- '#649eb9',
621
- '#387aa3'
622
- ].reverse();
623
-
624
- this.schemes.spectrum2000 = [
625
- '#57306f',
626
- '#514c76',
627
- '#646583',
628
- '#738394',
629
- '#6b9c7d',
630
- '#84b665',
631
- '#a7ca50',
632
- '#bfe746',
633
- '#e2f528',
634
- '#fff726',
635
- '#ecdd00',
636
- '#d4b11d',
637
- '#de8800',
638
- '#de4800',
639
- '#c91515',
640
- '#9a0000',
641
- '#7b0429',
642
- '#580839',
643
- '#31082b'
644
- ];
645
-
646
- this.schemes.spectrum2001 = [
647
- '#2f243f',
648
- '#3c2c55',
649
- '#4a3768',
650
- '#565270',
651
- '#6b6b7c',
652
- '#72957f',
653
- '#86ad6e',
654
- '#a1bc5e',
655
- '#b8d954',
656
- '#d3e04e',
657
- '#ccad2a',
658
- '#cc8412',
659
- '#c1521d',
660
- '#ad3821',
661
- '#8a1010',
662
- '#681717',
663
- '#531e1e',
664
- '#3d1818',
665
- '#320a1b'
666
- ];
667
-
668
- this.schemes.classic9 = [
669
- '#423d4f',
670
- '#4a6860',
671
- '#848f39',
672
- '#a2b73c',
673
- '#ddcb53',
674
- '#c5a32f',
675
- '#7d5836',
676
- '#963b20',
677
- '#7c2626',
678
- '#491d37',
679
- '#2f254a'
680
- ].reverse();
681
-
682
- this.schemes.httpStatus = {
683
- 503: '#ea5029',
684
- 502: '#d23f14',
685
- 500: '#bf3613',
686
- 410: '#efacea',
687
- 409: '#e291dc',
688
- 403: '#f457e8',
689
- 408: '#e121d2',
690
- 401: '#b92dae',
691
- 405: '#f47ceb',
692
- 404: '#a82a9f',
693
- 400: '#b263c6',
694
- 301: '#6fa024',
695
- 302: '#87c32b',
696
- 307: '#a0d84c',
697
- 304: '#28b55c',
698
- 200: '#1a4f74',
699
- 206: '#27839f',
700
- 201: '#52adc9',
701
- 202: '#7c979f',
702
- 203: '#a5b8bd',
703
- 204: '#c1cdd1'
704
- };
705
-
706
- this.schemes.colorwheel = [
707
- '#b5b6a9',
708
- '#858772',
709
- '#785f43',
710
- '#96557e',
711
- '#4682b4',
712
- '#65b9ac',
713
- '#73c03a',
714
- '#cb513a'
715
- ].reverse();
716
-
717
- this.schemes.cool = [
718
- '#5e9d2f',
719
- '#73c03a',
720
- '#4682b4',
721
- '#7bc3b8',
722
- '#a9884e',
723
- '#c1b266',
724
- '#a47493',
725
- '#c09fb5'
726
- ];
727
-
728
- this.schemes.munin = [
729
- '#00cc00',
730
- '#0066b3',
731
- '#ff8000',
732
- '#ffcc00',
733
- '#330099',
734
- '#990099',
735
- '#ccff00',
736
- '#ff0000',
737
- '#808080',
738
- '#008f00',
739
- '#00487d',
740
- '#b35a00',
741
- '#b38f00',
742
- '#6b006b',
743
- '#8fb300',
744
- '#b30000',
745
- '#bebebe',
746
- '#80ff80',
747
- '#80c9ff',
748
- '#ffc080',
749
- '#ffe680',
750
- '#aa80ff',
751
- '#ee00cc',
752
- '#ff8080',
753
- '#666600',
754
- '#ffbfff',
755
- '#00ffcc',
756
- '#cc6699',
757
- '#999900'
758
- ];
759
- };
760
- Rickshaw.namespace('Rickshaw.Fixtures.RandomData');
761
-
762
- Rickshaw.Fixtures.RandomData = function(timeInterval) {
763
-
764
- var addData;
765
- timeInterval = timeInterval || 1;
766
-
767
- var lastRandomValue = 200;
768
-
769
- var timeBase = Math.floor(new Date().getTime() / 1000);
770
-
771
- this.addData = function(data) {
772
-
773
- var randomValue = Math.random() * 100 + 15 + lastRandomValue;
774
- var index = data[0].length;
775
-
776
- var counter = 1;
777
-
778
- data.forEach( function(series) {
779
- var randomVariance = Math.random() * 20;
780
- var v = randomValue / 25 + counter++
781
- + (Math.cos((index * counter * 11) / 960) + 2) * 15
782
- + (Math.cos(index / 7) + 2) * 7
783
- + (Math.cos(index / 17) + 2) * 1;
784
-
785
- series.push( { x: (index * timeInterval) + timeBase, y: v + randomVariance } );
786
- } );
787
-
788
- lastRandomValue = randomValue * .85;
789
- }
790
- };
791
-
792
- Rickshaw.namespace('Rickshaw.Fixtures.Time');
793
-
794
- Rickshaw.Fixtures.Time = function() {
795
-
796
- var tzOffset = new Date().getTimezoneOffset() * 60;
797
-
798
- var self = this;
799
-
800
- this.months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
801
-
802
- this.units = [
803
- {
804
- name: 'decade',
805
- seconds: 86400 * 365.25 * 10,
806
- formatter: function(d) { return (parseInt(d.getUTCFullYear() / 10) * 10) }
807
- }, {
808
- name: 'year',
809
- seconds: 86400 * 365.25,
810
- formatter: function(d) { return d.getUTCFullYear() }
811
- }, {
812
- name: 'month',
813
- seconds: 86400 * 30.5,
814
- formatter: function(d) { return self.months[d.getUTCMonth()] }
815
- }, {
816
- name: 'week',
817
- seconds: 86400 * 7,
818
- formatter: function(d) { return self.formatDate(d) }
819
- }, {
820
- name: 'day',
821
- seconds: 86400,
822
- formatter: function(d) { return d.getUTCDate() }
823
- }, {
824
- name: '6 hour',
825
- seconds: 3600 * 6,
826
- formatter: function(d) { return self.formatTime(d) }
827
- }, {
828
- name: 'hour',
829
- seconds: 3600,
830
- formatter: function(d) { return self.formatTime(d) }
831
- }, {
832
- name: '15 minute',
833
- seconds: 60 * 15,
834
- formatter: function(d) { return self.formatTime(d) }
835
- }, {
836
- name: 'minute',
837
- seconds: 60,
838
- formatter: function(d) { return d.getUTCMinutes() }
839
- }, {
840
- name: '15 second',
841
- seconds: 15,
842
- formatter: function(d) { return d.getUTCSeconds() + 's' }
843
- }, {
844
- name: 'second',
845
- seconds: 1,
846
- formatter: function(d) { return d.getUTCSeconds() + 's' }
847
- }
848
- ];
849
-
850
- this.unit = function(unitName) {
851
- return this.units.filter( function(unit) { return unitName == unit.name } ).shift();
852
- };
853
-
854
- this.formatDate = function(d) {
855
- var exp = FnordMetric.util.dateFormat(d.getTime()).match(/^([0-9]+\.[0-9]+)/);
856
-
857
- if (exp)
858
- return exp[1];
859
-
860
- return 0;
861
- };
862
-
863
- this.formatTime = function(d) {
864
- return d.toLocaleString().match(/(\d+:\d+):/)[1];
865
- };
866
-
867
- this.ceil = function(time, unit) {
868
-
869
- if (unit.name == 'month') {
870
- var nearFuture = new Date((time + unit.seconds - 1) * 1000);
871
- return new Date(nearFuture.getUTCFullYear(), nearFuture.getUTCMonth() + 1, 1, 0, 0, 0, 0).getTime() / 1000;
872
- }
873
-
874
- if (unit.name == 'year') {
875
- var nearFuture = new Date((time + unit.seconds - 1) * 1000);
876
- return new Date(nearFuture.getUTCFullYear(), 1, 1, 0, 0, 0, 0).getTime() / 1000;
877
- }
878
-
879
- return Math.ceil(time / unit.seconds) * unit.seconds;
880
- };
881
- };
882
- Rickshaw.namespace('Rickshaw.Fixtures.Number');
883
-
884
- Rickshaw.Fixtures.Number.formatKMBT = function(y) {
885
- if (y >= 1000000000000) { return y / 1000000000000 + "T" }
886
- else if (y >= 1000000000) { return y / 1000000000 + "B" }
887
- else if (y >= 1000000) { return y / 1000000 + "M" }
888
- else if (y >= 1000) { return y / 1000 + "K" }
889
- else if (y < 1 && y > 0) { return y.toFixed(2) }
890
- else if (y == 0) { return '' }
891
- else { return y }
892
- };
893
-
894
- Rickshaw.Fixtures.Number.formatBase1024KMGTP = function(y) {
895
- if (y >= 1125899906842624) { return y / 1125899906842624 + "P" }
896
- else if (y >= 1099511627776){ return y / 1099511627776 + "T" }
897
- else if (y >= 1073741824) { return y / 1073741824 + "G" }
898
- else if (y >= 1048576) { return y / 1048576 + "M" }
899
- else if (y >= 1024) { return y / 1024 + "K" }
900
- else if (y < 1 && y > 0) { return y.toFixed(2) }
901
- else if (y == 0) { return '' }
902
- else { return y }
903
- };
904
- Rickshaw.namespace("Rickshaw.Color.Palette");
905
-
906
- Rickshaw.Color.Palette = function(args) {
907
-
908
- var color = new Rickshaw.Fixtures.Color();
909
-
910
- args = args || {};
911
- this.schemes = {};
912
-
913
- this.scheme = color.schemes[args.scheme] || args.scheme || color.schemes.colorwheel;
914
- this.runningIndex = 0;
915
-
916
- this.color = function(key) {
917
- return this.scheme[key] || this.scheme[this.runningIndex++] || '#808080';
918
- };
919
- };
920
- Rickshaw.namespace('Graph.Ajax');
921
-
922
- Rickshaw.Graph.Ajax = function(args) {
923
-
924
- var self = this;
925
- this.dataURL = args.dataURL;
926
-
927
- $.ajax( {
928
- url: this.dataURL,
929
- complete: function(response, status) {
930
-
931
- if (status === 'error') {
932
- console.log("error loading dataURL: " + this.dataURL);
933
- }
934
-
935
- var data = JSON.parse(response.responseText);
936
-
937
- if (typeof args.onData === 'function') {
938
- var processedData = args.onData(data);
939
- data = processedData;
940
- }
941
-
942
- if (args.series) {
943
-
944
- args.series.forEach( function(s) {
945
-
946
- var seriesKey = s.key || s.name;
947
- if (!seriesKey) throw "series needs a key or a name";
948
-
949
- data.forEach( function(d) {
950
-
951
- var dataKey = d.key || d.name;
952
- if (!dataKey) throw "data needs a key or a name";
953
-
954
- if (seriesKey == dataKey) {
955
- var properties = ['color', 'name', 'data'];
956
- properties.forEach( function(p) {
957
- s[p] = s[p] || d[p];
958
- } );
959
- }
960
- } );
961
- } );
962
-
963
- } else {
964
- args.series = data;
965
- }
966
-
967
- self.graph = new Rickshaw.Graph(args);
968
- self.graph.render();
969
-
970
- if (typeof args.onComplete == 'function') {
971
- args.onComplete(self);
972
- }
973
- }
974
- } );
975
- };
976
-
977
- Rickshaw.namespace('Rickshaw.Graph.Annotate');
978
-
979
- Rickshaw.Graph.Annotate = function(args) {
980
-
981
- var graph = this.graph = args.graph;
982
- this.elements = { timeline: args.element };
983
-
984
- var self = this;
985
-
986
- this.data = {};
987
-
988
- this.elements.timeline.classList.add('rickshaw_annotation_timeline');
989
-
990
- this.add = function(time, content) {
991
- self.data[time] = self.data[time] || {'boxes': []};
992
- self.data[time].boxes.push({content: content});
993
- };
994
-
995
- this.update = function() {
996
-
997
- Rickshaw.keys(self.data).forEach( function(time) {
998
-
999
- var annotation = self.data[time];
1000
- var left = self.graph.x(time);
1001
-
1002
- if (left < 0 || left > self.graph.x.range()[1]) {
1003
- if (annotation.element) {
1004
- annotation.element.style.display = 'none';
1005
- }
1006
- return;
1007
- }
1008
-
1009
- if (!annotation.element) {
1010
- var element = annotation.element = document.createElement('div');
1011
- element.classList.add('annotation');
1012
- this.elements.timeline.appendChild(element);
1013
- element.addEventListener('click', function(e) {
1014
- element.classList.toggle('active');
1015
- annotation.line.classList.toggle('active');
1016
- }, false);
1017
-
1018
- }
1019
-
1020
- annotation.element.style.left = left + 'px';
1021
- annotation.element.style.display = 'block';
1022
-
1023
- annotation.boxes.forEach( function(box) {
1024
-
1025
- var element = box.element;
1026
-
1027
- if (!element) {
1028
- element = box.element = document.createElement('div');
1029
- element.classList.add('content');
1030
- element.innerHTML = box.content;
1031
- annotation.element.appendChild(element);
1032
-
1033
- annotation.line = document.createElement('div');
1034
- annotation.line.classList.add('annotation_line');
1035
- self.graph.element.appendChild(annotation.line);
1036
- }
1037
-
1038
- annotation.line.style.left = left + 'px';
1039
- } );
1040
- }, this );
1041
- };
1042
-
1043
- this.graph.onUpdate( function() { self.update() } );
1044
- };
1045
- Rickshaw.namespace('Rickshaw.Graph.Axis.Time');
1046
-
1047
- Rickshaw.Graph.Axis.Time = function(args) {
1048
-
1049
- var self = this;
1050
-
1051
- this.graph = args.graph;
1052
- this.elements = [];
1053
- this.ticksTreatment = args.ticksTreatment || 'plain';
1054
- this.fixedTimeUnit = args.timeUnit;
1055
-
1056
- var time = new Rickshaw.Fixtures.Time();
1057
-
1058
- this.appropriateTimeUnit = function() {
1059
-
1060
- var unit;
1061
- var units = time.units;
1062
-
1063
- var domain = this.graph.x.domain();
1064
- var rangeSeconds = domain[1] - domain[0];
1065
-
1066
- units.forEach( function(u) {
1067
- if (Math.floor(rangeSeconds / u.seconds) >= 2) {
1068
- unit = unit || u;
1069
- }
1070
- } );
1071
-
1072
- return (unit || time.units[time.units.length - 1]);
1073
- };
1074
-
1075
- this.tickOffsets = function() {
1076
-
1077
- var domain = this.graph.x.domain();
1078
-
1079
- var unit = this.fixedTimeUnit || this.appropriateTimeUnit();
1080
- var count = Math.ceil((domain[1] - domain[0]) / unit.seconds);
1081
-
1082
- var runningTick = domain[0];
1083
-
1084
- var offsets = [];
1085
-
1086
- for (var i = 0; i < count; i++) {
1087
-
1088
- tickValue = time.ceil(runningTick, unit);
1089
- runningTick = tickValue + unit.seconds / 2;
1090
-
1091
- offsets.push( { value: tickValue, unit: unit } );
1092
- }
1093
-
1094
- return offsets;
1095
- };
1096
-
1097
- this.render = function() {
1098
-
1099
- this.elements.forEach( function(e) {
1100
- e.parentNode.removeChild(e);
1101
- } );
1102
-
1103
- this.elements = [];
1104
-
1105
- var offsets = this.tickOffsets();
1106
-
1107
- offsets.forEach( function(o) {
1108
-
1109
- if (self.graph.x(o.value) > self.graph.x.range()[1]) return;
1110
-
1111
- var element = document.createElement('div');
1112
- element.style.left = self.graph.x(o.value) + 'px';
1113
- element.classList.add('x_tick');
1114
- element.classList.add(self.ticksTreatment);
1115
-
1116
- var title = document.createElement('div');
1117
- title.classList.add('title');
1118
- title.innerHTML = o.unit.formatter(new Date(o.value * 1000));
1119
- element.appendChild(title);
1120
-
1121
- self.graph.element.appendChild(element);
1122
- self.elements.push(element);
1123
-
1124
- } );
1125
- };
1126
-
1127
- this.graph.onUpdate( function() { self.render() } );
1128
- };
1129
-
1130
- Rickshaw.namespace('Rickshaw.Graph.Axis.Y');
1131
-
1132
- Rickshaw.Graph.Axis.Y = function(args) {
1133
-
1134
- var self = this;
1135
- var berthRate = 0.10;
1136
-
1137
- this.initialize = function(args) {
1138
-
1139
- this.graph = args.graph;
1140
- this.orientation = args.orientation || 'right';
1141
-
1142
- var pixelsPerTick = 60;
1143
-
1144
- if(Math.floor(this.graph.height / pixelsPerTick) > 6){
1145
- pixelsPerTick = Math.floor(this.graph.height / 6);
1146
- }
1147
-
1148
- this.ticks = args.ticks || Math.floor(this.graph.height / pixelsPerTick);
1149
- this.tickSize = args.tickSize || 4;
1150
- this.ticksTreatment = args.ticksTreatment || 'plain';
1151
-
1152
- if (args.element) {
1153
-
1154
- this.element = args.element;
1155
- this.vis = d3.select(args.element)
1156
- .append("svg:svg")
1157
- .attr('class', 'rickshaw_graph y_axis');
1158
-
1159
- this.element = this.vis[0][0];
1160
- this.element.style.position = 'relative';
1161
-
1162
- this.setSize({ width: args.width, height: args.height });
1163
-
1164
- } else {
1165
- this.vis = this.graph.vis;
1166
- }
1167
-
1168
- this.graph.onUpdate( function() { self.render() } );
1169
- };
1170
-
1171
- this.setSize = function(args) {
1172
-
1173
- args = args || {};
1174
-
1175
- if (!this.element) return;
1176
-
1177
- if (typeof window !== undefined) {
1178
-
1179
- var style = window.getComputedStyle(this.element, null);
1180
- var elementWidth = parseInt(style.getPropertyValue('width'));
1181
-
1182
- if (!args.auto) {
1183
- var elementHeight = parseInt(style.getPropertyValue('height'));
1184
- }
1185
- }
1186
-
1187
- this.width = args.width || elementWidth || this.graph.width * berthRate;
1188
- this.height = args.height || elementHeight || this.graph.height;
1189
-
1190
- this.vis
1191
- .attr('width', this.width)
1192
- .attr('height', this.height * (1 + berthRate));
1193
-
1194
- var berth = this.height * berthRate;
1195
- this.element.style.top = -1 * berth + 'px';
1196
- this.element.style.paddingTop = berth + 'px';
1197
- };
1198
-
1199
- this.render = function() {
1200
-
1201
- if (this.graph.height !== this._renderHeight) this.setSize({ auto: true });
1202
-
1203
- var axis = d3.svg.axis().scale(this.graph.y).orient(this.orientation);
1204
- axis.tickFormat( args.tickFormat || function(y) { return y } );
1205
-
1206
- if (this.orientation == 'left') {
1207
- var transform = 'translate(' + this.width + ', 0)';
1208
- }
1209
-
1210
- if (this.element) {
1211
- this.vis.selectAll('*').remove();
1212
- }
1213
-
1214
- this.vis
1215
- .append("svg:g")
1216
- .attr("class", ["y_ticks", this.ticksTreatment].join(" "))
1217
- .attr("transform", transform)
1218
- .call(axis.ticks(this.ticks).tickSubdivide(0).tickSize(this.tickSize))
1219
-
1220
- var gridSize = (this.orientation == 'right' ? 1 : -1) * this.graph.width;
1221
-
1222
- this.graph.vis
1223
- .append("svg:g")
1224
- .attr("class", "y_grid")
1225
- .call(axis.ticks(this.ticks).tickSubdivide(0).tickSize(gridSize));
1226
-
1227
- this._renderHeight = this.graph.height;
1228
- };
1229
-
1230
- this.initialize(args);
1231
- };
1232
-
1233
- Rickshaw.namespace('Rickshaw.Graph.Behavior.Series.Highlight');
1234
-
1235
- Rickshaw.Graph.Behavior.Series.Highlight = function(args) {
1236
-
1237
- this.graph = args.graph;
1238
- this.legend = args.legend;
1239
-
1240
- var self = this;
1241
-
1242
- var colorSafe = {};
1243
-
1244
- this.addHighlightEvents = function (l) {
1245
- l.element.addEventListener( 'mouseover', function(e) {
1246
-
1247
- self.legend.lines.forEach( function(line) {
1248
- if (l === line) return;
1249
- colorSafe[line.series.name] = colorSafe[line.series.name] || line.series.color;
1250
- line.series.color = d3.interpolateRgb(line.series.color, d3.rgb('#d8d8d8'))(0.8).toString();
1251
- } );
1252
-
1253
- self.graph.update();
1254
-
1255
- }, false );
1256
-
1257
- l.element.addEventListener( 'mouseout', function(e) {
1258
-
1259
- self.legend.lines.forEach( function(line) {
1260
- if (colorSafe[line.series.name]) {
1261
- line.series.color = colorSafe[line.series.name];
1262
- }
1263
- } );
1264
-
1265
- self.graph.update();
1266
-
1267
- }, false );
1268
- };
1269
-
1270
- if (this.legend) {
1271
- this.legend.lines.forEach( function(l) {
1272
- self.addHighlightEvents(l);
1273
- } );
1274
- }
1275
-
1276
- };
1277
- Rickshaw.namespace('Rickshaw.Graph.Behavior.Series.Order');
1278
-
1279
- Rickshaw.Graph.Behavior.Series.Order = function(args) {
1280
-
1281
- this.graph = args.graph;
1282
- this.legend = args.legend;
1283
-
1284
- var self = this;
1285
-
1286
- $(function() {
1287
- $(self.legend.list).sortable( {
1288
- containment: 'parent',
1289
- tolerance: 'pointer',
1290
- update: function( event, ui ) {
1291
- var series = [];
1292
- $(self.legend.list).find('li').each( function(index, item) {
1293
- if (!item.series) return;
1294
- series.push(item.series);
1295
- } );
1296
-
1297
- for (var i = self.graph.series.length - 1; i >= 0; i--) {
1298
- self.graph.series[i] = series.shift();
1299
- }
1300
-
1301
- self.graph.update();
1302
- }
1303
- } );
1304
- $(self.legend.list).disableSelection();
1305
- });
1306
-
1307
- //hack to make jquery-ui sortable behave
1308
- this.graph.onUpdate( function() {
1309
- var h = window.getComputedStyle(self.legend.element).height;
1310
- self.legend.element.style.height = h;
1311
- } );
1312
- };
1313
- Rickshaw.namespace('Rickshaw.Graph.Behavior.Series.Toggle');
1314
-
1315
- Rickshaw.Graph.Behavior.Series.Toggle = function(args) {
1316
-
1317
- this.graph = args.graph;
1318
- this.legend = args.legend;
1319
-
1320
- var self = this;
1321
-
1322
- this.addAnchor = function(line) {
1323
- var anchor = document.createElement('a');
1324
- anchor.innerHTML = '&#10004;';
1325
- anchor.classList.add('action');
1326
- line.element.insertBefore(anchor, line.element.firstChild);
1327
-
1328
- anchor.onclick = function(e) {
1329
- if (line.series.disabled) {
1330
- line.series.enable();
1331
- line.element.classList.remove('disabled');
1332
- } else {
1333
- line.series.disable();
1334
- line.element.classList.add('disabled');
1335
- }
1336
- }
1337
-
1338
- var label = line.element.getElementsByTagName('span')[0];
1339
- label.onclick = function(e){
1340
-
1341
- var disableAllOtherLines = line.series.disabled;
1342
- if ( ! disableAllOtherLines ) {
1343
- for ( var i = 0; i < self.legend.lines.length; i++ ) {
1344
- var l = self.legend.lines[i];
1345
- if ( line.series === l.series ) {
1346
- // noop
1347
- } else if ( l.series.disabled ) {
1348
- // noop
1349
- } else {
1350
- disableAllOtherLines = true;
1351
- break;
1352
- }
1353
- }
1354
- }
1355
-
1356
- // show all or none
1357
- if ( disableAllOtherLines ) {
1358
-
1359
- // these must happen first or else we try ( and probably fail ) to make a no line graph
1360
- line.series.enable();
1361
- line.element.classList.remove('disabled');
1362
-
1363
- self.legend.lines.forEach(function(l){
1364
- if ( line.series === l.series ) {
1365
- // noop
1366
- } else {
1367
- l.series.disable();
1368
- l.element.classList.add('disabled');
1369
- }
1370
- });
1371
-
1372
- } else {
1373
-
1374
- self.legend.lines.forEach(function(l){
1375
- l.series.enable();
1376
- l.element.classList.remove('disabled');
1377
- });
1378
-
1379
- }
1380
-
1381
- };
1382
-
1383
- };
1384
-
1385
- if (this.legend) {
1386
-
1387
- $(this.legend.list).sortable( {
1388
- start: function(event, ui) {
1389
- ui.item.bind('no.onclick',
1390
- function(event) {
1391
- event.preventDefault();
1392
- }
1393
- );
1394
- },
1395
- stop: function(event, ui) {
1396
- setTimeout(function(){
1397
- ui.item.unbind('no.onclick');
1398
- }, 250);
1399
- }
1400
- })
1401
-
1402
- this.legend.lines.forEach( function(l) {
1403
- self.addAnchor(l);
1404
- } );
1405
- }
1406
-
1407
- this._addBehavior = function() {
1408
-
1409
- this.graph.series.forEach( function(s) {
1410
-
1411
- s.disable = function() {
1412
-
1413
- if (self.graph.series.length <= 1) {
1414
- throw('only one series left');
1415
- }
1416
-
1417
- s.disabled = true;
1418
- self.graph.update();
1419
- };
1420
-
1421
- s.enable = function() {
1422
- s.disabled = false;
1423
- self.graph.update();
1424
- };
1425
- } );
1426
- };
1427
- this._addBehavior();
1428
-
1429
- this.updateBehaviour = function () { this._addBehavior() };
1430
-
1431
- };
1432
- Rickshaw.namespace('Rickshaw.Graph.HoverDetail');
1433
-
1434
- Rickshaw.Graph.HoverDetail = Rickshaw.Class.create({
1435
-
1436
- initialize: function(args) {
1437
-
1438
- var graph = this.graph = args.graph;
1439
-
1440
- this.xFormatter = args.xFormatter || function(x) {
1441
- return FnordMetric.util.dateFormat(x);
1442
- };
1443
-
1444
- this.yFormatter = args.yFormatter || function(y) {
1445
- return y.toFixed(2);
1446
- };
1447
-
1448
- var element = this.element = document.createElement('div');
1449
- element.className = 'detail';
1450
-
1451
- if(args.no_detail){
1452
- element.className = 'detail no_detail';
1453
- }
1454
-
1455
- this.visible = true;
1456
- graph.element.appendChild(element);
1457
-
1458
- this.lastEvent = null;
1459
- this._addListeners();
1460
-
1461
- this.onShow = args.onShow;
1462
- this.onHide = args.onHide;
1463
- this.onRender = args.onRender;
1464
-
1465
- this.formatter = args.formatter || this.formatter;
1466
- },
1467
-
1468
- formatter: function(series, x, y, formattedX, formattedY) {
1469
- return series.name + ':&nbsp;' + formattedY;
1470
- },
1471
-
1472
- update: function(e) {
1473
-
1474
- e = e || this.lastEvent;
1475
- if (!e) return;
1476
- this.lastEvent = e;
1477
-
1478
- if (e.target.nodeName != 'path' && e.target.nodeName != 'svg') return;
1479
-
1480
- var graph = this.graph;
1481
-
1482
- var eventX = e.offsetX || e.layerX;
1483
- var eventY = e.offsetY || e.layerY;
1484
-
1485
- var domainX = graph.x.invert(eventX);
1486
- var stackedData = graph.stackedData;
1487
-
1488
- var topSeriesData = stackedData.slice(-1).shift();
1489
-
1490
- var domainIndexScale = d3.scale.linear()
1491
- .domain([topSeriesData[0].x, topSeriesData.slice(-1).shift().x])
1492
- .range([0, topSeriesData.length]);
1493
-
1494
- var approximateIndex = Math.floor(domainIndexScale(domainX));
1495
- var dataIndex = approximateIndex || 0;
1496
-
1497
- for (var i = approximateIndex; i < stackedData[0].length - 1;) {
1498
-
1499
- if (!stackedData[0][i] || !stackedData[0][i + 1]) {
1500
- break;
1501
- }
1502
-
1503
- if (stackedData[0][i].x <= domainX && stackedData[0][i + 1].x > domainX) {
1504
- dataIndex = i;
1505
- break;
1506
- }
1507
- if (stackedData[0][i + 1] < domainX) { i++ } else { i-- }
1508
- }
1509
-
1510
- var domainX = stackedData[0][dataIndex].x;
1511
- var formattedXValue = this.xFormatter(domainX);
1512
- var graphX = graph.x(domainX);
1513
- var order = 0;
1514
-
1515
- var detail = graph.series.active()
1516
- .map( function(s) { return { order: order++, series: s, name: s.name, value: s.stack[dataIndex] } } );
1517
-
1518
- var activeItem;
1519
-
1520
- var sortFn = function(a, b) {
1521
- return (a.value.y0 + a.value.y) - (b.value.y0 + b.value.y);
1522
- };
1523
-
1524
- var domainMouseY = graph.y.magnitude.invert(graph.element.offsetHeight - eventY);
1525
-
1526
- detail.sort(sortFn).forEach( function(d) {
1527
-
1528
- d.formattedYValue = (this.yFormatter.constructor == Array) ?
1529
- this.yFormatter[detail.indexOf(d)](d.value.y) :
1530
- this.yFormatter(d.value.y);
1531
-
1532
- d.graphX = graphX;
1533
- d.graphY = graph.y(d.value.y0 + d.value.y);
1534
-
1535
- if (domainMouseY > d.value.y0 && domainMouseY < d.value.y0 + d.value.y && !activeItem) {
1536
- activeItem = d;
1537
- d.active = true;
1538
- }
1539
-
1540
- }, this );
1541
-
1542
- this.element.innerHTML = '';
1543
- this.element.style.left = graph.x(domainX) + 'px';
1544
-
1545
- if (this.visible) {
1546
- this.render( {
1547
- detail: detail,
1548
- domainX: domainX,
1549
- formattedXValue: formattedXValue,
1550
- mouseX: eventX,
1551
- mouseY: eventY
1552
- } );
1553
- }
1554
- },
1555
-
1556
- hide: function() {
1557
- this.visible = false;
1558
- this.element.classList.add('inactive');
1559
-
1560
- if (typeof this.onHide == 'function') {
1561
- this.onHide();
1562
- }
1563
- },
1564
-
1565
- show: function() {
1566
- this.visible = true;
1567
- this.element.classList.remove('inactive');
1568
-
1569
- if (typeof this.onShow == 'function') {
1570
- this.onShow();
1571
- }
1572
- },
1573
-
1574
- render: function(args) {
1575
-
1576
- var detail = args.detail;
1577
- var domainX = args.domainX;
1578
-
1579
- var mouseX = args.mouseX;
1580
- var mouseY = args.mouseY;
1581
-
1582
- var formattedXValue = args.formattedXValue;
1583
-
1584
- var xLabel = document.createElement('div');
1585
- xLabel.className = 'x_label';
1586
- xLabel.innerHTML = formattedXValue;
1587
- this.element.appendChild(xLabel);
1588
-
1589
- detail.forEach( function(d) {
1590
-
1591
- var item = document.createElement('div');
1592
- item.className = 'item';
1593
- item.innerHTML = this.formatter(d.series, domainX, d.value.y, formattedXValue, d.formattedYValue);
1594
- item.style.top = this.graph.y(d.value.y0 + d.value.y) + 'px';
1595
-
1596
- this.element.appendChild(item);
1597
-
1598
- var dot = document.createElement('div');
1599
- dot.className = 'dot';
1600
- dot.style.top = item.style.top;
1601
- dot.style.borderColor = d.series.color;
1602
-
1603
- this.element.appendChild(dot);
1604
-
1605
- if (d.active) {
1606
- item.className = 'item active';
1607
- dot.className = 'dot active';
1608
- }
1609
-
1610
- }, this );
1611
-
1612
- this.show();
1613
-
1614
- if (typeof this.onRender == 'function') {
1615
- this.onRender(args);
1616
- }
1617
- },
1618
-
1619
- _addListeners: function() {
1620
-
1621
- this.graph.element.addEventListener(
1622
- 'mousemove',
1623
- function(e) {
1624
- this.visible = true;
1625
- this.update(e)
1626
- }.bind(this),
1627
- false
1628
- );
1629
-
1630
- this.graph.onUpdate( function() { this.update() }.bind(this) );
1631
-
1632
- this.graph.element.addEventListener(
1633
- 'mouseout',
1634
- function(e) {
1635
- if (e.relatedTarget && !(e.relatedTarget.compareDocumentPosition(this.graph.element) & Node.DOCUMENT_POSITION_CONTAINS)) {
1636
- this.hide();
1637
- }
1638
- }.bind(this),
1639
- false
1640
- );
1641
- }
1642
- });
1643
-
1644
- Rickshaw.namespace('Rickshaw.Graph.JSONP');
1645
-
1646
- Rickshaw.Graph.JSONP = function(args) {
1647
-
1648
- var self = this;
1649
- this.dataURL = args.dataURL;
1650
-
1651
- $.ajax( {
1652
- url: this.dataURL,
1653
- dataType: 'jsonp',
1654
- success: function(data, status, response) {
1655
-
1656
- if (status === 'error') {
1657
- console.log("error loading dataURL: " + this.dataURL);
1658
- }
1659
-
1660
- if (typeof args.onData === 'function') {
1661
- var processedData = args.onData(data);
1662
- data = processedData;
1663
- }
1664
-
1665
- if (args.series) {
1666
-
1667
- args.series.forEach( function(s) {
1668
-
1669
- var seriesKey = s.key || s.name;
1670
- if (!seriesKey) throw "series needs a key or a name";
1671
-
1672
- data.forEach( function(d) {
1673
-
1674
- var dataKey = d.key || d.name;
1675
- if (!dataKey) throw "data needs a key or a name";
1676
-
1677
- if (seriesKey == dataKey) {
1678
- var properties = ['color', 'name', 'data'];
1679
- properties.forEach( function(p) {
1680
- s[p] = s[p] || d[p];
1681
- } );
1682
- }
1683
- } );
1684
- } );
1685
-
1686
- } else {
1687
- args.series = data;
1688
- }
1689
-
1690
- self.graph = new Rickshaw.Graph(args);
1691
- self.graph.render();
1692
-
1693
- if (typeof args.onComplete == 'function') {
1694
- args.onComplete(self);
1695
- }
1696
- }
1697
- } );
1698
- };
1699
-
1700
- Rickshaw.namespace('Rickshaw.Graph.Legend');
1701
-
1702
- Rickshaw.Graph.Legend = function(args) {
1703
-
1704
- var element = this.element = args.element;
1705
- var graph = this.graph = args.graph;
1706
-
1707
- var self = this;
1708
-
1709
- element.classList.add('rickshaw_legend');
1710
-
1711
- var list = this.list = document.createElement('ul');
1712
- element.appendChild(list);
1713
-
1714
- var series = graph.series
1715
- .map( function(s) { return s } )
1716
- .reverse();
1717
-
1718
- this.lines = [];
1719
-
1720
- this.addLine = function (series) {
1721
- var line = document.createElement('li');
1722
- line.className = 'line';
1723
-
1724
- var swatch = document.createElement('div');
1725
- swatch.className = 'swatch';
1726
- swatch.style.backgroundColor = series.color;
1727
-
1728
- line.appendChild(swatch);
1729
-
1730
- var label = document.createElement('span');
1731
- label.className = 'label';
1732
- label.innerHTML = series.name;
1733
-
1734
- line.appendChild(label);
1735
- list.appendChild(line);
1736
-
1737
- line.series = series;
1738
-
1739
- if (series.noLegend) {
1740
- line.style.display = 'none';
1741
- }
1742
-
1743
- var _line = { element: line, series: series };
1744
- if (self.shelving) {
1745
- self.shelving.addAnchor(_line);
1746
- self.shelving.updateBehaviour();
1747
- }
1748
- if (self.highlighter) {
1749
- self.highlighter.addHighlightEvents(_line);
1750
- }
1751
- self.lines.push(_line);
1752
- };
1753
-
1754
- series.forEach( function(s) {
1755
- self.addLine(s);
1756
- } );
1757
-
1758
- graph.onUpdate( function() {
1759
-
1760
- } );
1761
- };
1762
- Rickshaw.namespace('Rickshaw.Graph.RangeSlider');
1763
-
1764
- Rickshaw.Graph.RangeSlider = function(args) {
1765
-
1766
- var element = this.element = args.element;
1767
- var graph = this.graph = args.graph;
1768
-
1769
- $( function() {
1770
- $(element).slider( {
1771
-
1772
- range: true,
1773
- min: graph.dataDomain()[0],
1774
- max: graph.dataDomain()[1],
1775
- values: [
1776
- graph.dataDomain()[0],
1777
- graph.dataDomain()[1],
1778
- ],
1779
- slide: function( event, ui ) {
1780
-
1781
- graph.window.xMin = ui.values[0];
1782
- graph.window.xMax = ui.values[1];
1783
- graph.update();
1784
-
1785
- // if we're at an extreme, stick there
1786
- if (graph.dataDomain()[0] == ui.values[0]) {
1787
- graph.window.xMin = undefined;
1788
- }
1789
- if (graph.dataDomain()[1] == ui.values[1]) {
1790
- graph.window.xMax = undefined;
1791
- }
1792
- }
1793
- } );
1794
- } );
1795
-
1796
- element[0].style.width = graph.width + 'px';
1797
-
1798
- graph.onUpdate( function() {
1799
-
1800
- var values = $(element).slider('option', 'values');
1801
-
1802
- $(element).slider('option', 'min', graph.dataDomain()[0]);
1803
- $(element).slider('option', 'max', graph.dataDomain()[1]);
1804
-
1805
- if (graph.window.xMin == undefined) {
1806
- values[0] = graph.dataDomain()[0];
1807
- }
1808
- if (graph.window.xMax == undefined) {
1809
- values[1] = graph.dataDomain()[1];
1810
- }
1811
-
1812
- $(element).slider('option', 'values', values);
1813
-
1814
- } );
1815
- };
1816
-
1817
- Rickshaw.namespace("Rickshaw.Graph.Renderer");
1818
-
1819
- Rickshaw.Graph.Renderer = Rickshaw.Class.create( {
1820
-
1821
- initialize: function(args) {
1822
- this.graph = args.graph;
1823
- this.tension = args.tension || this.tension;
1824
- this.graph.unstacker = this.graph.unstacker || new Rickshaw.Graph.Unstacker( { graph: this.graph } );
1825
- this.configure(args);
1826
- },
1827
-
1828
- seriesPathFactory: function() {
1829
- //implement in subclass
1830
- },
1831
-
1832
- seriesStrokeFactory: function() {
1833
- // implement in subclass
1834
- },
1835
-
1836
- defaults: function() {
1837
- return {
1838
- tension: 0.8,
1839
- strokeWidth: 2,
1840
- unstack: true,
1841
- padding: { top: 0.01, right: 0, bottom: 0.01, left: 0 },
1842
- stroke: false,
1843
- fill: false
1844
- };
1845
- },
1846
-
1847
- domain: function() {
1848
-
1849
- var values = [];
1850
- var stackedData = this.graph.stackedData || this.graph.stackData();
1851
-
1852
- var topSeriesData = this.unstack ? stackedData : [ stackedData.slice(-1).shift() ];
1853
-
1854
- topSeriesData.forEach( function(series) {
1855
- series.forEach( function(d) {
1856
- values.push( d.y + d.y0 );
1857
- } );
1858
- } );
1859
-
1860
- var xMin = stackedData[0][0].x;
1861
- var xMax = stackedData[0][ stackedData[0].length - 1 ].x;
1862
-
1863
- xMin -= (xMax - xMin) * this.padding.left;
1864
- xMax += (xMax - xMin) * this.padding.right;
1865
-
1866
- var yMin = this.graph.min === 'auto' ? d3.min( values ) : this.graph.min || 0;
1867
- var yMax = this.graph.max || d3.max( values );
1868
-
1869
- if (this.graph.min === 'auto' || yMin < 0) {
1870
- yMin -= (yMax - yMin) * this.padding.bottom;
1871
- }
1872
-
1873
- if (this.graph.max === undefined) {
1874
- yMax += (yMax - yMin) * this.padding.top;
1875
- }
1876
-
1877
- return { x: [xMin, xMax], y: [yMin, yMax] };
1878
- },
1879
-
1880
- render: function() {
1881
-
1882
- var graph = this.graph;
1883
-
1884
- graph.vis.selectAll('*').remove();
1885
-
1886
- var nodes = graph.vis.selectAll("path")
1887
- .data(this.graph.stackedData)
1888
- .enter().append("svg:path")
1889
- .attr("d", this.seriesPathFactory());
1890
-
1891
- var i = 0;
1892
- graph.series.forEach( function(series) {
1893
- if (series.disabled) return;
1894
- series.path = nodes[0][i++];
1895
- this._styleSeries(series);
1896
- }, this );
1897
- },
1898
-
1899
- _styleSeries: function(series, fm_opts) {
1900
-
1901
- var fill = this.fill ? series.color : 'none';
1902
- var stroke = this.stroke ? series.color : 'none';
1903
-
1904
- series.path.setAttribute('fill', fill);
1905
- series.path.setAttribute('stroke', stroke);
1906
- if (fm_opts){
1907
- series.path.setAttribute('stroke-width', fm_opts.stroke_width);
1908
- } else {
1909
- series.path.setAttribute('stroke-width', this.strokeWidth);
1910
- }
1911
- series.path.setAttribute('class', series.className);
1912
- },
1913
-
1914
- configure: function(args) {
1915
-
1916
- args = args || {};
1917
-
1918
- Rickshaw.keys(this.defaults()).forEach( function(key) {
1919
-
1920
- if (!args.hasOwnProperty(key)) {
1921
- this[key] = this[key] || this.graph[key] || this.defaults()[key];
1922
- return;
1923
- }
1924
-
1925
- if (typeof this.defaults()[key] == 'object') {
1926
-
1927
- Rickshaw.keys(this.defaults()[key]).forEach( function(k) {
1928
-
1929
- this[key][k] =
1930
- args[key][k] !== undefined ? args[key][k] :
1931
- this[key][k] !== undefined ? this[key][k] :
1932
- this.defaults()[key][k];
1933
- }, this );
1934
-
1935
- } else {
1936
- this[key] =
1937
- args[key] !== undefined ? args[key] :
1938
- this[key] !== undefined ? this[key] :
1939
- this.graph[key] !== undefined ? this.graph[key] :
1940
- this.defaults()[key];
1941
- }
1942
-
1943
- }, this );
1944
- },
1945
-
1946
- setStrokeWidth: function(strokeWidth) {
1947
- if (strokeWidth !== undefined) {
1948
- this.strokeWidth = strokeWidth;
1949
- }
1950
- },
1951
-
1952
- setTension: function(tension) {
1953
- if (tension !== undefined) {
1954
- this.tension = tension;
1955
- }
1956
- }
1957
- } );
1958
-
1959
- Rickshaw.namespace('Rickshaw.Graph.Renderer.Line');
1960
-
1961
- Rickshaw.Graph.Renderer.Line = Rickshaw.Class.create( Rickshaw.Graph.Renderer, {
1962
-
1963
- name: 'line',
1964
-
1965
- defaults: function($super) {
1966
-
1967
- return Rickshaw.extend( $super(), {
1968
- unstack: true,
1969
- fill: false,
1970
- stroke: true
1971
- } );
1972
- },
1973
-
1974
- seriesPathFactory: function() {
1975
-
1976
- var graph = this.graph;
1977
-
1978
- return d3.svg.line()
1979
- .x( function(d) { return graph.x(d.x) } )
1980
- .y( function(d) { return graph.y(d.y) } )
1981
- .interpolate(this.graph.interpolation).tension(this.tension);
1982
- },
1983
-
1984
-
1985
- render: function() {
1986
-
1987
- if(this.graph.stackedData[0].length < 42){
1988
- var fm_opts = { stroke_width: 3, draw_points: true };
1989
- } else if(this.graph.stackedData[0].length < 99){
1990
- var fm_opts = { stroke_width: 2, draw_points: false };
1991
- } else {
1992
- var fm_opts = { stroke_width: 1, draw_points: false };
1993
- }
1994
-
1995
- var graph = this.graph;
1996
-
1997
- graph.vis.selectAll('*').remove();
1998
-
1999
- var nodes = graph.vis.selectAll("path")
2000
- .data(this.graph.stackedData)
2001
- .enter().append("svg:path")
2002
- .attr("d", this.seriesPathFactory());
2003
-
2004
- if(fm_opts.draw_points){
2005
- console.log("FIXPAUL: timeseries widget -° draw points!");
2006
- }
2007
-
2008
- var i = 0;
2009
- graph.series.forEach( function(series) {
2010
- if (series.disabled) return;
2011
- series.path = nodes[0][i++];
2012
- this._styleSeries(series, fm_opts);
2013
- }, this );
2014
-
2015
- },
2016
-
2017
- } );
2018
-
2019
- Rickshaw.namespace('Rickshaw.Graph.Renderer.Stack');
2020
-
2021
- Rickshaw.Graph.Renderer.Stack = Rickshaw.Class.create( Rickshaw.Graph.Renderer, {
2022
-
2023
- name: 'stack',
2024
-
2025
- defaults: function($super) {
2026
-
2027
- return Rickshaw.extend( $super(), {
2028
- fill: true,
2029
- stroke: false,
2030
- unstack: false,
2031
- } );
2032
- },
2033
-
2034
- seriesPathFactory: function() {
2035
-
2036
- var graph = this.graph;
2037
-
2038
- return d3.svg.area()
2039
- .x( function(d) { return graph.x(d.x) } )
2040
- .y0( function(d) { return graph.y(d.y0) } )
2041
- .y1( function(d) { return graph.y(d.y + d.y0) } )
2042
- .interpolate(this.graph.interpolation).tension(this.tension);
2043
- },
2044
-
2045
- render: function() {
2046
- var graph = this.graph;
2047
-
2048
- graph.vis.selectAll('*').remove();
2049
-
2050
- var nodes = graph.vis.selectAll("path")
2051
- .data(this.graph.stackedData)
2052
- .enter().append("svg:path")
2053
- .attr("d", this.seriesPathFactory());
2054
-
2055
- var i = 0;
2056
- graph.series.forEach( function(series) {
2057
- if (series.disabled) return;
2058
- series.path = nodes[0][i++];
2059
- this._styleSeries(series);
2060
- }, this );
2061
- },
2062
-
2063
- _styleSeries: function(series, fm_opts) {
2064
-
2065
- var fill = this.fill ? series.color : 'none';
2066
- var stroke = this.stroke ? series.color : 'none';
2067
-
2068
- series.path.setAttribute('fill', d3.interpolateRgb(fill, 'white')(0.125))
2069
- series.path.setAttribute('stroke', stroke);
2070
- if (fm_opts){
2071
- series.path.setAttribute('stroke-width', fm_opts.stroke_width);
2072
- } else {
2073
- series.path.setAttribute('stroke-width', this.strokeWidth);
2074
- }
2075
- series.path.setAttribute('class', series.className);
2076
- },
2077
-
2078
-
2079
- } );
2080
-
2081
- Rickshaw.namespace('Rickshaw.Graph.Renderer.Bar');
2082
-
2083
- Rickshaw.Graph.Renderer.Bar = Rickshaw.Class.create( Rickshaw.Graph.Renderer, {
2084
-
2085
- name: 'bar',
2086
-
2087
- defaults: function($super) {
2088
-
2089
- var defaults = Rickshaw.extend( $super(), {
2090
- gapSize: 0.10,
2091
- unstack: false,
2092
- } );
2093
-
2094
- delete defaults.tension;
2095
- return defaults;
2096
- },
2097
-
2098
- initialize: function($super, args) {
2099
- args = args || {};
2100
- this.gapSize = args.gapSize || this.gapSize;
2101
- this.xPadding = args.xPadding || 50;
2102
- $super(args);
2103
- },
2104
-
2105
- domain: function($super) {
2106
-
2107
- var domain = $super();
2108
-
2109
- var frequentInterval = this._frequentInterval();
2110
- domain.x[1] += parseInt(frequentInterval.magnitude);
2111
-
2112
- return domain;
2113
- },
2114
-
2115
- barWidth: function() {
2116
- var stackedData = this.graph.stackedData || this.graph.stackData();
2117
- var data = stackedData.slice(-1).shift();
2118
-
2119
- var frequentInterval = this._frequentInterval();
2120
- var barWidth = this.graph.x(data[0].x + frequentInterval.magnitude * (1 - this.gapSize));
2121
-
2122
- return ((this.graph.width - (this.xPadding * 2)) / data.length);
2123
- },
2124
-
2125
- render: function() {
2126
-
2127
- var graph = this.graph;
2128
-
2129
- graph.vis.selectAll('*').remove();
2130
-
2131
- var barWidth = this.barWidth();
2132
- var barXOffset = 0;
2133
-
2134
- var activeSeriesCount = graph.series.filter( function(s) { return !s.disabled; } ).length;
2135
- var seriesBarWidth = this.unstack ? barWidth / activeSeriesCount : barWidth;
2136
-
2137
- graph.series.forEach( function(series) {
2138
-
2139
- if (series.disabled) return;
2140
-
2141
- var xpad = this.xPadding;
2142
-
2143
- var seriesBarDrawWidth = Math.min(60,
2144
- parseInt(seriesBarWidth * (1 - this.gapSize)));
2145
-
2146
- if(parseInt(seriesBarWidth) == seriesBarDrawWidth){
2147
- seriesBarDrawWidth -= 1;
2148
- }
2149
-
2150
- var seriesBarDrawPadding = (seriesBarWidth - seriesBarDrawWidth) / 2;
2151
-
2152
- var nodes = graph.vis.selectAll("path")
2153
- .data(series.stack)
2154
- .enter().append("svg:rect")
2155
- .attr("x", function(d) { return xpad + (d.x * seriesBarWidth) + seriesBarDrawPadding })
2156
- .attr("y", function(d) { return graph.y(d.y0 + d.y) })
2157
- .attr("width", seriesBarDrawWidth)
2158
- .attr("stroke", "#000")
2159
- .attr("stroke-width", "1px")
2160
- .attr("stroke-opacity", "0.6")
2161
- .attr("height", function(d) { return graph.y.magnitude(d.y) });
2162
-
2163
-
2164
- var sdata = series.stack;
2165
-
2166
- for(var ind=0; ind < sdata.length; ind++){
2167
- $(graph.element).append(
2168
- $("<div>")
2169
- .css("position", "absolute")
2170
- .css("color", "#666")
2171
- .css("width", seriesBarWidth)
2172
- .css("textAlign", "center")
2173
- .css("marginTop", "5px")
2174
- .css("marginLeft", xpad + (sdata[ind].x * seriesBarWidth))
2175
- .css("y", graph.height)
2176
- .html(sdata[ind].label)
2177
- );
2178
- //
2179
- }
2180
-
2181
- Array.prototype.forEach.call(nodes[0], function(n) {
2182
- n.setAttribute('fill', series.color);
2183
- } );
2184
-
2185
-
2186
- var total = $('.ui_numbers .samples').data('value');
2187
- $('.widget_histogram_bars .tooltip').remove();
2188
- $('.widget_histogram_bars rect').each(function(hist_i) {
2189
- var percentage = Math.round(sdata[hist_i].y * 1000 / total) / 10;
2190
- var left = parseInt($(this).offset().left);
2191
- var top = parseInt($(this).offset().top) - 23;
2192
- var tooltip = '<div class="tooltip" data-hist-id="' + hist_i
2193
- + '" style="left:' + left + 'px; top: ' + top + 'px">'
2194
- + sdata[hist_i].y + ' (' + percentage + '%)' + '</div>';
2195
- $(this).parents('.widget_histogram_bars:first').append(tooltip);
2196
- $(this).attr('data-id', hist_i);
2197
- });
2198
-
2199
- $('.widget_histogram_bars rect').hover(function() {
2200
- $('.widget_histogram_bars .tooltip[data-hist-id=' +
2201
- $(this).attr('data-id') + ']').show();
2202
- }, function() {
2203
- $('.widget_histogram_bars .tooltip[data-hist-id=' +
2204
- $(this).attr('data-id') + ']').fadeOut();
2205
- });
2206
-
2207
-
2208
- }, this );
2209
- },
2210
-
2211
- _frequentInterval: function() {
2212
-
2213
- var stackedData = this.graph.stackedData || this.graph.stackData();
2214
- var data = stackedData.slice(-1).shift();
2215
-
2216
- var intervalCounts = {};
2217
-
2218
- for (var i = 0; i < data.length - 1; i++) {
2219
- var interval = data[i + 1].x - data[i].x;
2220
- intervalCounts[interval] = intervalCounts[interval] || 0;
2221
- intervalCounts[interval]++;
2222
- }
2223
-
2224
- var frequentInterval = { count: 0 };
2225
-
2226
- Rickshaw.keys(intervalCounts).forEach( function(i) {
2227
- if (frequentInterval.count < intervalCounts[i]) {
2228
-
2229
- frequentInterval = {
2230
- count: intervalCounts[i],
2231
- magnitude: i
2232
- };
2233
- }
2234
- } );
2235
-
2236
- this._frequentInterval = function() { return frequentInterval };
2237
-
2238
- return frequentInterval;
2239
- }
2240
- } );
2241
-
2242
- Rickshaw.namespace('Rickshaw.Graph.Renderer.Area');
2243
-
2244
- Rickshaw.Graph.Renderer.Area = Rickshaw.Class.create( Rickshaw.Graph.Renderer, {
2245
-
2246
- name: 'area',
2247
-
2248
- defaults: function($super) {
2249
-
2250
- return Rickshaw.extend( $super(), {
2251
- unstack: false,
2252
- fill: false,
2253
- stroke: false
2254
- } );
2255
- },
2256
-
2257
- seriesPathFactory: function() {
2258
-
2259
- var graph = this.graph;
2260
-
2261
- return d3.svg.area()
2262
- .x( function(d) { return graph.x(d.x) } )
2263
- .y0( function(d) { return graph.y(d.y0) } )
2264
- .y1( function(d) { return graph.y(d.y + d.y0) } )
2265
- .interpolate(graph.interpolation).tension(this.tension);
2266
- },
2267
-
2268
- seriesStrokeFactory: function() {
2269
-
2270
- var graph = this.graph;
2271
-
2272
- return d3.svg.line()
2273
- .x( function(d) { return graph.x(d.x) } )
2274
- .y( function(d) { return graph.y(d.y + d.y0) } )
2275
- .interpolate(graph.interpolation).tension(this.tension);
2276
- },
2277
-
2278
- render: function() {
2279
-
2280
- var graph = this.graph;
2281
-
2282
- graph.vis.selectAll('*').remove();
2283
-
2284
- if(this.graph.stackedData[0].length < 42){
2285
- var fm_opts = { stroke_width: 3 };
2286
- } else {
2287
- var fm_opts = { stroke_width: 1 };
2288
- }
2289
-
2290
- var nodes = graph.vis.selectAll("path")
2291
- .data(this.graph.stackedData)
2292
- .enter().insert("svg:g", 'g');
2293
-
2294
- nodes.append("svg:path")
2295
- .attr("d", this.seriesPathFactory())
2296
- .attr("class", 'area');
2297
-
2298
- if (this.stroke) {
2299
- nodes.append("svg:path")
2300
- .attr("d", this.seriesStrokeFactory())
2301
- .attr("class", 'line');
2302
- }
2303
-
2304
- var i = 0;
2305
- graph.series.forEach( function(series) {
2306
- if (series.disabled) return;
2307
- series.path = nodes[0][i++];
2308
- this._styleSeries(series, fm_opts);
2309
- }, this );
2310
- },
2311
-
2312
- _styleSeries: function(series, fm_opts) {
2313
-
2314
- if (!series.path) return;
2315
-
2316
- d3.select(series.path).select('.area')
2317
- .attr('opacity', '0.65')
2318
- .attr('fill', series.color);
2319
-
2320
- d3.select(series.path).select('.line')
2321
- .attr('fill', 'none')
2322
- .attr('stroke', d3.interpolateRgb(series.color, 'white')(0.125))
2323
- .attr('stroke-width', fm_opts.stroke_width);
2324
-
2325
- if (series.className) {
2326
- series.path.setAttribute('class', series.className);
2327
- }
2328
- }
2329
- } );
2330
-
2331
- Rickshaw.namespace('Rickshaw.Graph.Renderer.ScatterPlot');
2332
-
2333
- Rickshaw.Graph.Renderer.ScatterPlot = Rickshaw.Class.create( Rickshaw.Graph.Renderer, {
2334
-
2335
- name: 'scatterplot',
2336
-
2337
- defaults: function($super) {
2338
-
2339
- return Rickshaw.extend( $super(), {
2340
- unstack: true,
2341
- fill: true,
2342
- stroke: false,
2343
- padding:{ top: 0.01, right: 0.01, bottom: 0.01, left: 0.01 },
2344
- dotSize: 4
2345
- } );
2346
- },
2347
-
2348
- initialize: function($super, args) {
2349
- $super(args);
2350
- },
2351
-
2352
- render: function() {
2353
-
2354
- var graph = this.graph;
2355
-
2356
- graph.vis.selectAll('*').remove();
2357
-
2358
- graph.series.forEach( function(series) {
2359
-
2360
- if (series.disabled) return;
2361
-
2362
- var nodes = graph.vis.selectAll("path")
2363
- .data(series.stack)
2364
- .enter().append("svg:circle")
2365
- .attr("cx", function(d) { return graph.x(d.x) })
2366
- .attr("cy", function(d) { return graph.y(d.y) })
2367
- .attr("r", this.dotSize);
2368
-
2369
- Array.prototype.forEach.call(nodes[0], function(n) {
2370
- n.setAttribute('fill', series.color);
2371
- } );
2372
-
2373
- }, this );
2374
- }
2375
- } );
2376
- Rickshaw.namespace('Rickshaw.Graph.Smoother');
2377
-
2378
- Rickshaw.Graph.Smoother = function(args) {
2379
-
2380
- this.graph = args.graph;
2381
- this.element = args.element;
2382
-
2383
- var self = this;
2384
-
2385
- this.aggregationScale = 1;
2386
-
2387
- if (this.element) {
2388
-
2389
- $( function() {
2390
- $(self.element).slider( {
2391
- min: 1,
2392
- max: 100,
2393
- slide: function( event, ui ) {
2394
- self.setScale(ui.value);
2395
- self.graph.update();
2396
- }
2397
- } );
2398
- } );
2399
- }
2400
-
2401
- self.graph.stackData.hooks.data.push( {
2402
- name: 'smoother',
2403
- orderPosition: 50,
2404
- f: function(data) {
2405
-
2406
- var aggregatedData = [];
2407
-
2408
- data.forEach( function(seriesData) {
2409
-
2410
- var aggregatedSeriesData = [];
2411
-
2412
- while (seriesData.length) {
2413
-
2414
- var avgX = 0, avgY = 0;
2415
- var slice = seriesData.splice(0, self.aggregationScale);
2416
-
2417
- slice.forEach( function(d) {
2418
- avgX += d.x / slice.length;
2419
- avgY += d.y / slice.length;
2420
- } );
2421
-
2422
- aggregatedSeriesData.push( { x: avgX, y: avgY } );
2423
- }
2424
-
2425
- aggregatedData.push(aggregatedSeriesData);
2426
- } );
2427
-
2428
- return aggregatedData;
2429
- }
2430
- } );
2431
-
2432
- this.setScale = function(scale) {
2433
-
2434
- if (scale < 1) {
2435
- throw "scale out of range: " + scale;
2436
- }
2437
-
2438
- this.aggregationScale = scale;
2439
- this.graph.update();
2440
- }
2441
- };
2442
-
2443
- Rickshaw.namespace('Rickshaw.Graph.Unstacker');
2444
-
2445
- Rickshaw.Graph.Unstacker = function(args) {
2446
-
2447
- this.graph = args.graph;
2448
- var self = this;
2449
-
2450
- this.graph.stackData.hooks.after.push( {
2451
- name: 'unstacker',
2452
- f: function(data) {
2453
-
2454
- if (!self.graph.renderer.unstack) return data;
2455
-
2456
- data.forEach( function(seriesData) {
2457
- seriesData.forEach( function(d) {
2458
- d.y0 = 0;
2459
- } );
2460
- } );
2461
-
2462
- return data;
2463
- }
2464
- } );
2465
- };
2466
-
2467
- Rickshaw.namespace('Rickshaw.Series');
2468
-
2469
- Rickshaw.Series = Rickshaw.Class.create( Array, {
2470
-
2471
- initialize: function (data, palette, options) {
2472
-
2473
- options = options || {}
2474
-
2475
- this.palette = new Rickshaw.Color.Palette(palette);
2476
-
2477
- this.timeBase = typeof(options.timeBase) === 'undefined' ?
2478
- Math.floor(new Date().getTime() / 1000) :
2479
- options.timeBase;
2480
-
2481
- if (data && (typeof(data) == "object") && (data instanceof Array)) {
2482
- data.forEach( function(item) { this.addItem(item) }, this );
2483
- }
2484
- },
2485
-
2486
- addItem: function(item) {
2487
-
2488
- if (typeof(item.name) === 'undefined') {
2489
- throw('addItem() needs a name');
2490
- }
2491
-
2492
- item.color = (item.color || this.palette.color(item.name));
2493
- item.data = (item.data || []);
2494
-
2495
- // backfill, if necessary
2496
- if ((item.data.length == 0) && this.length && (this.getIndex() > 0)) {
2497
- this[0].data.forEach( function(plot) {
2498
- item.data.push({ x: plot.x, y: 0 });
2499
- } );
2500
- } else if (item.data.length == 0) {
2501
- item.data.push({ x: this.timeBase - (this.timeInterval || 0), y: 0 });
2502
- }
2503
-
2504
- this.push(item);
2505
-
2506
- if (this.legend) {
2507
- this.legend.addLine(this.itemByName(item.name));
2508
- }
2509
- },
2510
-
2511
- addData: function(data) {
2512
-
2513
- var index = this.getIndex();
2514
-
2515
- Rickshaw.keys(data).forEach( function(name) {
2516
- if (! this.itemByName(name)) {
2517
- this.addItem({ name: name });
2518
- }
2519
- }, this );
2520
-
2521
- this.forEach( function(item) {
2522
- item.data.push({
2523
- x: (index * this.timeInterval || 1) + this.timeBase,
2524
- y: (data[item.name] || 0)
2525
- });
2526
- }, this );
2527
- },
2528
-
2529
- getIndex: function () {
2530
- return (this[0] && this[0].data && this[0].data.length) ? this[0].data.length : 0;
2531
- },
2532
-
2533
- itemByName: function(name) {
2534
-
2535
- for (var i = 0; i < this.length; i++) {
2536
- if (this[i].name == name)
2537
- return this[i];
2538
- }
2539
- },
2540
-
2541
- setTimeInterval: function(iv) {
2542
- this.timeInterval = iv / 1000;
2543
- },
2544
-
2545
- setTimeBase: function (t) {
2546
- this.timeBase = t;
2547
- },
2548
-
2549
- dump: function() {
2550
-
2551
- var data = {
2552
- timeBase: this.timeBase,
2553
- timeInterval: this.timeInterval,
2554
- items: [],
2555
- };
2556
-
2557
- this.forEach( function(item) {
2558
-
2559
- var newItem = {
2560
- color: item.color,
2561
- name: item.name,
2562
- data: []
2563
- };
2564
-
2565
- item.data.forEach( function(plot) {
2566
- newItem.data.push({ x: plot.x, y: plot.y });
2567
- } );
2568
-
2569
- data.items.push(newItem);
2570
- } );
2571
-
2572
- return data;
2573
- },
2574
-
2575
- load: function(data) {
2576
-
2577
- if (data.timeInterval) {
2578
- this.timeInterval = data.timeInterval;
2579
- }
2580
-
2581
- if (data.timeBase) {
2582
- this.timeBase = data.timeBase;
2583
- }
2584
-
2585
- if (data.items) {
2586
- data.items.forEach( function(item) {
2587
- this.push(item);
2588
- if (this.legend) {
2589
- this.legend.addLine(this.itemByName(item.name));
2590
- }
2591
-
2592
- }, this );
2593
- }
2594
- }
2595
- } );
2596
-
2597
- Rickshaw.Series.zeroFill = function(series) {
2598
-
2599
- var x;
2600
- var i = 0;
2601
-
2602
- var data = series.map( function(s) { return s.data } );
2603
-
2604
- while ( i < Math.max.apply(null, data.map( function(d) { return d.length } )) ) {
2605
-
2606
- x = Math.min.apply( null,
2607
- data
2608
- .filter(function(d) { return d[i] })
2609
- .map(function(d) { return d[i].x })
2610
- );
2611
-
2612
- data.forEach( function(d) {
2613
- if (!d[i] || d[i].x != x) {
2614
- d.splice(i, 0, { x: x, y: 0 });
2615
- }
2616
- } );
2617
-
2618
- i++;
2619
- }
2620
- };
2621
- Rickshaw.namespace('Rickshaw.Series.FixedDuration');
2622
-
2623
- Rickshaw.Series.FixedDuration = Rickshaw.Class.create(Rickshaw.Series, {
2624
-
2625
- initialize: function (data, palette, options) {
2626
-
2627
- var options = options || {}
2628
-
2629
- if (typeof(options.timeInterval) === 'undefined') {
2630
- throw new Error('FixedDuration series requires timeInterval');
2631
- }
2632
-
2633
- if (typeof(options.maxDataPoints) === 'undefined') {
2634
- throw new Error('FixedDuration series requires maxDataPoints');
2635
- }
2636
-
2637
- this.palette = new Rickshaw.Color.Palette(palette);
2638
- this.timeBase = typeof(options.timeBase) === 'undefined' ? Math.floor(new Date().getTime() / 1000) : options.timeBase;
2639
- this.setTimeInterval(options.timeInterval);
2640
-
2641
- if (this[0] && this[0].data && this[0].data.length) {
2642
- this.currentSize = this[0].data.length;
2643
- this.currentIndex = this[0].data.length;
2644
- } else {
2645
- this.currentSize = 0;
2646
- this.currentIndex = 0;
2647
- }
2648
-
2649
- this.maxDataPoints = options.maxDataPoints;
2650
-
2651
-
2652
- if (data && (typeof(data) == "object") && (data instanceof Array)) {
2653
- data.forEach( function (item) { this.addItem(item) }, this );
2654
- this.currentSize += 1;
2655
- this.currentIndex += 1;
2656
- }
2657
-
2658
- // reset timeBase for zero-filled values if needed
2659
- this.timeBase -= (this.maxDataPoints - this.currentSize) * this.timeInterval;
2660
-
2661
- // zero-fill up to maxDataPoints size if we don't have that much data yet
2662
- if ((typeof(this.maxDataPoints) !== 'undefined') && (this.currentSize < this.maxDataPoints)) {
2663
- for (var i = this.maxDataPoints - this.currentSize - 1; i > 0; i--) {
2664
- this.currentSize += 1;
2665
- this.currentIndex += 1;
2666
- this.forEach( function (item) {
2667
- item.data.unshift({ x: ((i-1) * this.timeInterval || 1) + this.timeBase, y: 0, i: i });
2668
- }, this );
2669
- }
2670
- }
2671
- },
2672
-
2673
- addData: function($super, data) {
2674
-
2675
- $super(data)
2676
-
2677
- this.currentSize += 1;
2678
- this.currentIndex += 1;
2679
-
2680
- if (this.maxDataPoints !== undefined) {
2681
- while (this.currentSize > this.maxDataPoints) {
2682
- this.dropData();
2683
- }
2684
- }
2685
- },
2686
-
2687
- dropData: function() {
2688
-
2689
- this.forEach(function(item) {
2690
- item.data.splice(0, 1);
2691
- } );
2692
-
2693
- this.currentSize -= 1;
2694
- },
2695
-
2696
- getIndex: function () {
2697
- return this.currentIndex;
2698
- }
2699
- } );
2700
-