fnordmetric 0.7.5 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. data/doc/V1.0-ROADMAP +97 -0
  2. data/doc/full_example.rb +95 -511
  3. data/doc/legacy_example.rb +640 -0
  4. data/doc/minimal_example.rb +26 -0
  5. data/doc/preview3.png +0 -0
  6. data/fnordmetric.gemspec +3 -2
  7. data/lib/fnordmetric/acceptors/acceptor.rb +29 -0
  8. data/lib/fnordmetric/{inbound_stream.rb → acceptors/tcp_acceptor.rb} +8 -5
  9. data/lib/fnordmetric/{inbound_datagram.rb → acceptors/udp_acceptor.rb} +9 -8
  10. data/lib/fnordmetric/api.rb +2 -2
  11. data/lib/fnordmetric/context.rb +37 -18
  12. data/lib/fnordmetric/defaults.rb +9 -0
  13. data/lib/fnordmetric/ext.rb +72 -0
  14. data/lib/fnordmetric/gauge.rb +37 -10
  15. data/lib/fnordmetric/gauge_calculations.rb +38 -16
  16. data/lib/fnordmetric/gauge_modifiers.rb +67 -0
  17. data/lib/fnordmetric/gauge_rendering.rb +40 -0
  18. data/lib/fnordmetric/gauge_validations.rb +15 -0
  19. data/lib/fnordmetric/gauges/distribution_gauge.rb +85 -0
  20. data/lib/fnordmetric/gauges/timeseries_gauge.rb +143 -0
  21. data/lib/fnordmetric/gauges/toplist_gauge.rb +44 -0
  22. data/lib/fnordmetric/histogram.rb +57 -0
  23. data/lib/fnordmetric/logger.rb +42 -36
  24. data/lib/fnordmetric/namespace.rb +47 -23
  25. data/lib/fnordmetric/session.rb +6 -6
  26. data/lib/fnordmetric/standalone.rb +15 -35
  27. data/lib/fnordmetric/timeseries.rb +79 -0
  28. data/lib/fnordmetric/toplist.rb +61 -0
  29. data/lib/fnordmetric/version.rb +1 -1
  30. data/lib/fnordmetric/web/app.rb +122 -0
  31. data/lib/fnordmetric/web/app_helpers.rb +42 -0
  32. data/lib/fnordmetric/{dashboard.rb → web/dashboard.rb} +4 -0
  33. data/lib/fnordmetric/{event.rb → web/event.rb} +7 -2
  34. data/lib/fnordmetric/web/reactor.rb +87 -0
  35. data/lib/fnordmetric/web/web.rb +53 -0
  36. data/lib/fnordmetric/web/websocket.rb +38 -0
  37. data/lib/fnordmetric/widgets/bars_widget.rb +44 -0
  38. data/lib/fnordmetric/{html_widget.rb → widgets/html_widget.rb} +0 -0
  39. data/lib/fnordmetric/widgets/numbers_widget.rb +56 -0
  40. data/lib/fnordmetric/{pie_widget.rb → widgets/pie_widget.rb} +0 -0
  41. data/lib/fnordmetric/widgets/timeseries_widget.rb +55 -0
  42. data/lib/fnordmetric/widgets/toplist_widget.rb +64 -0
  43. data/lib/fnordmetric/worker.rb +26 -25
  44. data/lib/fnordmetric.rb +85 -115
  45. data/readme.md +362 -0
  46. data/spec/gauge_like_shared.rb +54 -0
  47. data/spec/gauge_spec.rb +2 -36
  48. data/spec/namespace_spec.rb +25 -11
  49. data/spec/spec_helper.rb +4 -0
  50. data/spec/{inbound_stream_spec.rb → tcp_acceptor_spec.rb} +3 -3
  51. data/spec/timeseries_gauge_spec.rb +54 -0
  52. data/spec/{inbound_datagram_spec.rb → udp_acceptor_spec.rb} +3 -3
  53. data/web/fnordmetric.css +786 -0
  54. data/web/haml/app.haml +38 -0
  55. data/web/haml/distribution_gauge.haml +118 -0
  56. data/web/haml/timeseries_gauge.haml +80 -0
  57. data/web/haml/toplist_gauge.haml +194 -0
  58. data/web/img/head.png +0 -0
  59. data/web/img/list.png +0 -0
  60. data/web/img/list_active.png +0 -0
  61. data/web/img/list_hover.png +0 -0
  62. data/web/img/loader_white.gif +0 -0
  63. data/web/img/navbar.png +0 -0
  64. data/web/img/navbar_btn.png +0 -0
  65. data/web/img/picto_gauge.png +0 -0
  66. data/web/js/fnordmetric.bars_widget.js +178 -0
  67. data/web/js/fnordmetric.dashboard_view.js +99 -0
  68. data/web/js/fnordmetric.gauge_view.js +260 -0
  69. data/web/js/fnordmetric.html_widget.js +21 -0
  70. data/web/js/fnordmetric.js +255 -0
  71. data/web/js/fnordmetric.numbers_widget.js +121 -0
  72. data/web/js/fnordmetric.overview_view.js +35 -0
  73. data/web/js/fnordmetric.pie_widget.js +118 -0
  74. data/web/js/fnordmetric.realtime_timeline_widget.js +175 -0
  75. data/web/js/fnordmetric.session_view.js +343 -0
  76. data/web/js/fnordmetric.timeline_widget.js +333 -0
  77. data/web/js/fnordmetric.timeseries_widget.js +388 -0
  78. data/web/js/fnordmetric.toplist_widget.js +112 -0
  79. data/web/js/fnordmetric.ui.js +91 -0
  80. data/web/js/fnordmetric.util.js +244 -0
  81. data/{pub → web}/loader.gif +0 -0
  82. data/web/vendor/d3.v2.js +9382 -0
  83. data/web/vendor/font-awesome/css/font-awesome.css +239 -0
  84. data/web/vendor/font-awesome/font/fontawesome-webfont.eot +0 -0
  85. data/web/vendor/font-awesome/font/fontawesome-webfont.svg +175 -0
  86. data/web/vendor/font-awesome/font/fontawesome-webfont.svgz +0 -0
  87. data/web/vendor/font-awesome/font/fontawesome-webfont.ttf +0 -0
  88. data/web/vendor/font-awesome/font/fontawesome-webfont.woff +0 -0
  89. data/web/vendor/jquery-1.6.2.min.js +18 -0
  90. data/web/vendor/jquery-ui.min.js +413 -0
  91. data/web/vendor/jquery.maskedinput.js +252 -0
  92. data/web/vendor/rickshaw.css +286 -0
  93. data/web/vendor/rickshaw.fnordmetric.js +2676 -0
  94. metadata +129 -79
  95. data/Gemfile +0 -6
  96. data/README.md +0 -404
  97. data/Rakefile +0 -6
  98. data/doc/version +0 -1
  99. data/haml/app.haml +0 -79
  100. data/haml/widget.haml +0 -9
  101. data/lib/fnordmetric/app.rb +0 -163
  102. data/lib/fnordmetric/average_metric.rb +0 -7
  103. data/lib/fnordmetric/bars_widget.rb +0 -26
  104. data/lib/fnordmetric/combine_metric.rb +0 -7
  105. data/lib/fnordmetric/count_metric.rb +0 -13
  106. data/lib/fnordmetric/funnel_widget.rb +0 -2
  107. data/lib/fnordmetric/metric.rb +0 -80
  108. data/lib/fnordmetric/metric_api.rb +0 -37
  109. data/lib/fnordmetric/numbers_widget.rb +0 -26
  110. data/lib/fnordmetric/report.rb +0 -29
  111. data/lib/fnordmetric/sum_metric.rb +0 -13
  112. data/lib/fnordmetric/timeline_widget.rb +0 -30
  113. data/lib/fnordmetric/toplist_widget.rb +0 -25
  114. data/pub/fnordmetric.css +0 -145
  115. data/pub/fnordmetric.js +0 -1179
  116. data/pub/vendor/highcharts.js +0 -170
  117. data/pub/vendor/jquery-1.6.1.min.js +0 -18
@@ -0,0 +1,252 @@
1
+ /// <reference path="../../../lib/jquery-1.2.6.js" />
2
+ /*
3
+ Masked Input plugin for jQuery
4
+ Copyright (c) 2007-2009 Josh Bush (digitalbush.com)
5
+ Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license)
6
+ Version: 1.2.2 (03/09/2009 22:39:06)
7
+ */
8
+ (function($) {
9
+ var pasteEventName = ($.browser.msie ? 'paste' : 'input') + ".mask";
10
+ var iPhone = (window.orientation != undefined);
11
+
12
+ $.mask = {
13
+ //Predefined character definitions
14
+ definitions: {
15
+ '9': "[0-9]",
16
+ 'a': "[A-Za-z]",
17
+ '*': "[A-Za-z0-9]"
18
+ }
19
+ };
20
+
21
+ $.fn.extend({
22
+ //Helper Function for Caret positioning
23
+ caret: function(begin, end) {
24
+ if (this.length == 0) return;
25
+ if (typeof begin == 'number') {
26
+ end = (typeof end == 'number') ? end : begin;
27
+ return this.each(function() {
28
+ if (this.setSelectionRange) {
29
+ this.focus();
30
+ this.setSelectionRange(begin, end);
31
+ } else if (this.createTextRange) {
32
+ var range = this.createTextRange();
33
+ range.collapse(true);
34
+ range.moveEnd('character', end);
35
+ range.moveStart('character', begin);
36
+ range.select();
37
+ }
38
+ });
39
+ } else {
40
+ if (this[0].setSelectionRange) {
41
+ begin = this[0].selectionStart;
42
+ end = this[0].selectionEnd;
43
+ } else if (document.selection && document.selection.createRange) {
44
+ var range = document.selection.createRange();
45
+ begin = 0 - range.duplicate().moveStart('character', -100000);
46
+ end = begin + range.text.length;
47
+ }
48
+ return { begin: begin, end: end };
49
+ }
50
+ },
51
+ unmask: function() { return this.trigger("unmask"); },
52
+ mask: function(mask, settings) {
53
+ if (!mask && this.length > 0) {
54
+ var input = $(this[0]);
55
+ var tests = input.data("tests");
56
+ return $.map(input.data("buffer"), function(c, i) {
57
+ return tests[i] ? c : null;
58
+ }).join('');
59
+ }
60
+ settings = $.extend({
61
+ placeholder: "_",
62
+ completed: null
63
+ }, settings);
64
+
65
+ var defs = $.mask.definitions;
66
+ var tests = [];
67
+ var partialPosition = mask.length;
68
+ var firstNonMaskPos = null;
69
+ var len = mask.length;
70
+
71
+ $.each(mask.split(""), function(i, c) {
72
+ if (c == '?') {
73
+ len--;
74
+ partialPosition = i;
75
+ } else if (defs[c]) {
76
+ tests.push(new RegExp(defs[c]));
77
+ if(firstNonMaskPos==null)
78
+ firstNonMaskPos = tests.length - 1;
79
+ } else {
80
+ tests.push(null);
81
+ }
82
+ });
83
+
84
+ return this.each(function() {
85
+ var input = $(this);
86
+ var buffer = $.map(mask.split(""), function(c, i) { if (c != '?') return defs[c] ? settings.placeholder : c });
87
+ var ignore = false; //Variable for ignoring control keys
88
+ var focusText = input.val();
89
+
90
+ input.data("buffer", buffer).data("tests", tests);
91
+
92
+ function seekNext(pos) {
93
+ while (++pos <= len && !tests[pos]);
94
+ return pos;
95
+ };
96
+
97
+ function shiftL(pos) {
98
+ while (!tests[pos] && --pos >= 0);
99
+ for (var i = pos; i < len; i++) {
100
+ if (tests[i]) {
101
+ buffer[i] = settings.placeholder;
102
+ var j = seekNext(i);
103
+ if (j < len && tests[i].test(buffer[j])) {
104
+ buffer[i] = buffer[j];
105
+ } else
106
+ break;
107
+ }
108
+ }
109
+ writeBuffer();
110
+ input.caret(Math.max(firstNonMaskPos, pos));
111
+ };
112
+
113
+ function shiftR(pos) {
114
+ for (var i = pos, c = settings.placeholder; i < len; i++) {
115
+ if (tests[i]) {
116
+ var j = seekNext(i);
117
+ var t = buffer[i];
118
+ buffer[i] = c;
119
+ if (j < len && tests[j].test(t))
120
+ c = t;
121
+ else
122
+ break;
123
+ }
124
+ }
125
+ };
126
+
127
+ function keydownEvent(e) {
128
+ var pos = $(this).caret();
129
+ var k = e.keyCode;
130
+ ignore = (k < 16 || (k > 16 && k < 32) || (k > 32 && k < 41));
131
+
132
+ //delete selection before proceeding
133
+ if ((pos.begin - pos.end) != 0 && (!ignore || k == 8 || k == 46))
134
+ clearBuffer(pos.begin, pos.end);
135
+
136
+ //backspace, delete, and escape get special treatment
137
+ if (k == 8 || k == 46 || (iPhone && k == 127)) {//backspace/delete
138
+ shiftL(pos.begin + (k == 46 ? 0 : -1));
139
+ return false;
140
+ } else if (k == 27) {//escape
141
+ input.val(focusText);
142
+ input.caret(0, checkVal());
143
+ return false;
144
+ }
145
+ };
146
+
147
+ function keypressEvent(e) {
148
+ if (ignore) {
149
+ ignore = false;
150
+ //Fixes Mac FF bug on backspace
151
+ return (e.keyCode == 8) ? false : null;
152
+ }
153
+ e = e || window.event;
154
+ var k = e.charCode || e.keyCode || e.which;
155
+ var pos = $(this).caret();
156
+
157
+ if (e.ctrlKey || e.altKey || e.metaKey) {//Ignore
158
+ return true;
159
+ } else if ((k >= 32 && k <= 125) || k > 186) {//typeable characters
160
+ var p = seekNext(pos.begin - 1);
161
+ if (p < len) {
162
+ var c = String.fromCharCode(k);
163
+ if (tests[p].test(c)) {
164
+ shiftR(p);
165
+ buffer[p] = c;
166
+ writeBuffer();
167
+ var next = seekNext(p);
168
+ $(this).caret(next);
169
+ if (settings.completed && next == len)
170
+ settings.completed.call(input);
171
+ }
172
+ }
173
+ }
174
+ return false;
175
+ };
176
+
177
+ function clearBuffer(start, end) {
178
+ for (var i = start; i < end && i < len; i++) {
179
+ if (tests[i])
180
+ buffer[i] = settings.placeholder;
181
+ }
182
+ };
183
+
184
+ function writeBuffer() { return input.val(buffer.join('')).val(); };
185
+
186
+ function checkVal(allow) {
187
+ //try to place characters where they belong
188
+ var test = input.val();
189
+ var lastMatch = -1;
190
+ for (var i = 0, pos = 0; i < len; i++) {
191
+ if (tests[i]) {
192
+ buffer[i] = settings.placeholder;
193
+ while (pos++ < test.length) {
194
+ var c = test.charAt(pos - 1);
195
+ if (tests[i].test(c)) {
196
+ buffer[i] = c;
197
+ lastMatch = i;
198
+ break;
199
+ }
200
+ }
201
+ if (pos > test.length)
202
+ break;
203
+ } else if (buffer[i] == test[pos] && i!=partialPosition) {
204
+ pos++;
205
+ lastMatch = i;
206
+ }
207
+ }
208
+ if (!allow && lastMatch + 1 < partialPosition) {
209
+ input.val("");
210
+ clearBuffer(0, len);
211
+ } else if (allow || lastMatch + 1 >= partialPosition) {
212
+ writeBuffer();
213
+ if (!allow) input.val(input.val().substring(0, lastMatch + 1));
214
+ }
215
+ return (partialPosition ? i : firstNonMaskPos);
216
+ };
217
+
218
+ if (!input.attr("readonly"))
219
+ input
220
+ .one("unmask", function() {
221
+ input
222
+ .unbind(".mask")
223
+ .removeData("buffer")
224
+ .removeData("tests");
225
+ })
226
+ .bind("focus.mask", function() {
227
+ focusText = input.val();
228
+ var pos = checkVal();
229
+ writeBuffer();
230
+ setTimeout(function() {
231
+ if (pos == mask.length)
232
+ input.caret(0, pos);
233
+ else
234
+ input.caret(pos);
235
+ }, 0);
236
+ })
237
+ .bind("blur.mask", function() {
238
+ checkVal();
239
+ if (input.val() != focusText)
240
+ input.change();
241
+ })
242
+ .bind("keydown.mask", keydownEvent)
243
+ .bind("keypress.mask", keypressEvent)
244
+ .bind(pasteEventName, function() {
245
+ setTimeout(function() { input.caret(checkVal(true)); }, 0);
246
+ });
247
+
248
+ checkVal(); //Perform initial check for existing values
249
+ });
250
+ }
251
+ });
252
+ })(jQuery);
@@ -0,0 +1,286 @@
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
+ }