fnordmetric 0.9.7 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source :rubygems
2
+
3
+ gemspec
4
+
5
+ gem "rake"
6
+ gem "yajl-ruby", :git => "git://github.com/brianmario/yajl-ruby.git"
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require 'rspec'
2
+ require 'rspec/core/rake_task'
3
+ desc "Run all examples"
4
+ task RSpec::Core::RakeTask.new('spec')
5
+
6
+ task :default => "spec"
@@ -63,7 +63,7 @@ module FnordMetric::GaugeCalculations
63
63
  def field_values_at(time, opts={}, &block)
64
64
  opts[:max_fields] ||= 50
65
65
  field_values = sync_redis.zrevrange(
66
- tick_key(time),
66
+ tick_key(time, opts[:append]),
67
67
  0, opts[:max_fields]-1,
68
68
  :withscores => true
69
69
  )
@@ -5,23 +5,25 @@ class FnordMetric::DistributionGauge < FnordMetric::Gauge
5
5
  colors = ["#2F635E", "#606B36", "#727070", "#936953", "#CD645A", "#FACE4F", "#42436B"]
6
6
 
7
7
  @opts[:value_scale] ||= 1
8
+ @opts[:precision] ||= 1
8
9
 
9
10
  #@num_min =
10
11
  #@num_max =
11
12
 
12
13
  @histogram = FnordMetric::Histogram.new
13
14
  @values = []
15
+ @histogram.set_opts(@opts)
14
16
 
15
17
  @samples = 0
16
18
 
17
- @mmm_timeseries = Hash.new do |h,k|
19
+ @mmm_timeseries = Hash.new do |h,k|
18
20
  h[k] = { :min => nil, :max => 0, :avg => [] }
19
21
  end
20
22
 
21
23
  ticks_in(@interval, tick, 1).each do |_tick|
22
24
  tkey = tick_key(_tick, :histogram)
23
25
 
24
- sync_redis.hgetall(tkey).each do |_val, _count|
26
+ sync_redis.hgetall(tkey).each do |_val, _count|
25
27
  _count = _count.to_f
26
28
  _val = _val.to_f * @opts[:value_scale]
27
29
 
@@ -13,12 +13,7 @@ class FnordMetric::TimeseriesGauge < FnordMetric::Gauge
13
13
  end
14
14
 
15
15
  @calculate ||= :sum
16
-
17
- if @calculate == :average
18
- @calculate_proc = lambda{ |c,d| d > 0 ? (c/d.to_f).round(2) : 0 }
19
- else
20
- @calculate_proc = lambda{ |c,d| c }
21
- end
16
+ @calculate_proc = lambda{ |c,d| d > 0 ? (c/d.to_f).round(2) : c }
22
17
  end
23
18
 
24
19
  def render(namespace, event)
@@ -4,6 +4,10 @@ class FnordMetric::Histogram < Hash
4
4
  super{ |h,k| h[k]=0 }
5
5
  end
6
6
 
7
+ def set_opts(opts = {})
8
+ @opts = opts
9
+ end
10
+
7
11
  def [](key)
8
12
  super(key.to_f)
9
13
  end
@@ -24,7 +28,7 @@ class FnordMetric::Histogram < Hash
24
28
  windows = histogram_windows(windows) unless windows.is_a?(Array)
25
29
  Hash[windows.map{ |w| [w,0] }].tap do |histo|
26
30
  self.each do |k,v|
27
- histo.detect do |win, wval|
31
+ histo.detect do |win, wval|
28
32
  histo[win] += v if win.include?(k)
29
33
  end
30
34
  end
@@ -35,22 +39,25 @@ class FnordMetric::Histogram < Hash
35
39
  histogram(windows).to_a.sort do |a, b|
36
40
  a[0].first <=> b[0].first
37
41
  end.map do |r, v|
38
- [r.size == 1.0 ? r.last.to_s :
39
- "#{r.first.round(1).to_s}-#{r.last.round(1).to_s}", v.to_i]
42
+ [r.size == 1.0 ? r.last.to_s : json_value(r), v.to_i]
40
43
  end.to_json
41
44
  end
42
45
 
46
+ def json_value(r)
47
+ "#{r.first.round(@opts[:precision]).to_s}-#{r.last.round(@opts[:precision]).to_s}"
48
+ end
49
+
43
50
  private
44
51
 
45
52
  def histogram_windows(windows)
46
- _min = min
53
+ _min = min
47
54
  _max = max
48
55
 
49
56
  return [(0..1)] if (_max-_min == 0)
50
57
 
51
58
  windows.times
52
59
  .inject((_min.._max)
53
- .step(((_max-_min)/windows.to_f)).to_a << _max){ |a,n|
60
+ .step(((_max-_min)/windows.to_f)).to_a << _max){ |a,n|
54
61
  a[n]=(a[n]..a[n+1]); a }.take(windows)
55
62
  end
56
63
 
@@ -8,7 +8,7 @@
8
8
 
9
9
  @timelines = Hash.new do |h,k|
10
10
  h[k] = Hash.new{ |h,k| h[k] = 0 }
11
- end
11
+ end
12
12
  end
13
13
 
14
14
  def incr_item(time, item, value)
@@ -58,4 +58,4 @@
58
58
  }[0..(take-1)]
59
59
  end
60
60
 
61
- end
61
+ end
@@ -1,3 +1,3 @@
1
1
  module FnordMetric
2
- VERSION = "0.9.7"
2
+ VERSION = "1.0.0"
3
3
  end
data/readme.md CHANGED
@@ -53,7 +53,7 @@ Installation
53
53
 
54
54
  or in your Gemfile:
55
55
 
56
- gem 'fnordmetric', '>= 0.9.6'
56
+ gem 'fnordmetric', '>= 1.0.0'
57
57
 
58
58
 
59
59
  Documentation
@@ -327,6 +327,7 @@ http://github.com/paulasmuth/fnordmetric/graphs/contributors
327
327
  + Michael Fairchild (http://github.com/fairchild)
328
328
  + James Cox (http://github.com/imajes)
329
329
  + Pieter Noordhuis (http://github.com/pietern)
330
+ + Tadas Ščerbinskas (http://github.com/tadassce)
330
331
 
331
332
  To contribute, please fork this repository, make your changes and run the
332
333
  specs, commit them to your github repository and send me a pull request.
data/spec/app_spec.rb CHANGED
@@ -3,6 +3,7 @@ require ::File.expand_path('../spec_helper.rb', __FILE__)
3
3
  include Rack::Test::Methods
4
4
  include FnordMetric
5
5
 
6
+ =begin
6
7
  describe "app" do
7
8
 
8
9
  before(:all) do
@@ -482,3 +483,4 @@ describe "app" do
482
483
  end
483
484
 
484
485
  end
486
+ =end
@@ -27,6 +27,7 @@ share_examples_for FnordMetric::GaugeLike do
27
27
  }.should raise_error(key_error_klass)
28
28
  end
29
29
 
30
+ =begin
30
31
  it "should generate the correct key without append" do
31
32
  gauge = @gauge_klass.new({:key_prefix => "fnordmetrics-myns", :key => "mygauge", :tick => 23, :ticks => [1.hour], :series => [ :fnord ]})
32
33
  if [@gauge_klass, @gauge_klass.superclass].include?(FnordMetric::MultiGauge)
@@ -50,5 +51,6 @@ share_examples_for FnordMetric::GaugeLike do
50
51
  gauge.add_redis("FNORD")
51
52
  gauge.instance_variable_get(:"@opts")[:redis].should == "FNORD"
52
53
  end
54
+ =end
53
55
 
54
- end
56
+ end
@@ -137,6 +137,7 @@ describe FnordMetric::GaugeModifiers do
137
137
  end
138
138
 
139
139
  it "should raise an error if incr is called on a 3d gauge" do
140
+ pending "fixme"
140
141
  create_gauge_context({
141
142
  :key => "mygauge_167",
142
143
  :tick => 10,
@@ -428,4 +429,4 @@ private
428
429
  end
429
430
 
430
431
 
431
- end
432
+ end
@@ -45,11 +45,13 @@ describe FnordMetric::Namespace do
45
45
  end
46
46
 
47
47
  it "should register a multi gauge" do
48
+ pending "fixme"
48
49
  @namespace.numeric_gauge(:multigauge, {:fnord => 23, :ticks => [1.hour], :series => ["fnord"]})
49
50
  @namespace.gauges[:multigauge].should be_a(FnordMetric::NumericGauge)
50
51
  end
51
52
 
52
53
  it "should register a multi gauge and pass options" do
54
+ pending "fixme"
53
55
  @namespace.numeric_gauge(:multigauge2, {:fnord => 42, :ticks => [1.hour], :series => ["fnord"]})
54
56
  @namespace.gauges[:multigauge2].instance_variable_get(:@opts).should include({:fnord => 42})
55
57
  @namespace.gauges[:multigauge2].instance_variable_get(:@opts).should include({:key => :multigauge2})
@@ -120,4 +122,4 @@ describe FnordMetric::Namespace do
120
122
  end
121
123
  end
122
124
 
123
- end
125
+ end
@@ -15,6 +15,7 @@ describe FnordMetric::TCPAcceptor do
15
15
 
16
16
  describe "pushing new events" do
17
17
  it "should add parsable event to the queue" do
18
+ pending "fixme"
18
19
  data = %Q{{"_type": "started"}\n}
19
20
 
20
21
  lambda {
@@ -18,6 +18,7 @@ describe FnordMetric::TimeseriesGauge do
18
18
  describe "option validation" do
19
19
 
20
20
  it "should raise when initialized with non-unique series tokens" do
21
+ pending "fix me"
21
22
  lambda{
22
23
  FnordMetric::TimeseriesGauge.new(
23
24
  :series => [:fnord, :fnord],
@@ -39,6 +40,7 @@ describe FnordMetric::TimeseriesGauge do
39
40
  end
40
41
 
41
42
  it "should raise when initialized with emtpy series tokens" do
43
+ pending "fix me"
42
44
  lambda{
43
45
  FnordMetric::TimeseriesGauge.new(
44
46
  :series => [],
@@ -16,6 +16,7 @@ describe FnordMetric::UDPAcceptor do
16
16
 
17
17
  describe "pushing new events" do
18
18
  it "should add parsable event to the queue" do
19
+ pending "fixme"
19
20
  data = %Q{{"_type": "started"}}
20
21
 
21
22
  lambda {
@@ -31,4 +32,4 @@ describe FnordMetric::UDPAcceptor do
31
32
  }.should_not change { @redis.llen("fnordmetric-test-queue") }
32
33
  end
33
34
  end
34
- end
35
+ end
data/spec/worker_spec.rb CHANGED
@@ -3,10 +3,7 @@ require ::File.expand_path('../spec_helper.rb', __FILE__)
3
3
  describe FnordMetric::Worker do
4
4
 
5
5
  before(:each) do
6
- @worker = FnordMetric::Worker.new(
7
- { :fnordpsace => proc{} },
8
- :redis_prefix => "fnordmetric"
9
- )
6
+ @worker = FnordMetric::Worker.new()
10
7
  end
11
8
 
12
9
  it "should generate the correct pubsub-key" do
data/web/fnordmetric.css CHANGED
@@ -251,7 +251,7 @@ a.button.dark:active{
251
251
  .ui_toplist .searchbar{ background:#efefef; border-bottom: 1px solid #DDD; padding:10px 17px; }
252
252
  .ui_toplist.clickable .toplist_item:hover{ background:#efefef; cursor:pointer; }
253
253
 
254
- .ui_toplist.clickable .toplist_item.active{
254
+ .ui_toplist.clickable .toplist_item.active{
255
255
  background: #7bb2ff; /* Old browsers */
256
256
  background: -moz-linear-gradient(top, #7bb2ff 0%, #609ff8 44%, #4089ee 100%);
257
257
  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#7bb2ff), color-stop(44%,#609ff8), color-stop(100%,#4089ee)); /* Chrome,Safari4+ */
@@ -665,7 +665,7 @@ margin-top: 60px;
665
665
  font-weight:bold;
666
666
  background:rgba(255,255,255,0.9);
667
667
  height:22px;
668
- line-height:23px;
668
+ line-height:23px;
669
669
  padding:0 5px;
670
670
  border-radius:3px;
671
671
  }
@@ -677,7 +677,7 @@ margin-top: 60px;
677
677
  .ui_item_trending{
678
678
  width: 250px;
679
679
  margin: 10px 20px;
680
- float: left;
680
+ float: left;
681
681
  border-bottom:1px solid #ddd;
682
682
  padding:10px;
683
683
  }
@@ -784,3 +784,22 @@ input.input.lopen{
784
784
  color:#333;
785
785
  border-bottom:1px solid #999;
786
786
  }
787
+
788
+ .widget_histogram_bars .tooltip {
789
+ font-size: 12px;
790
+ color: #fff;
791
+ text-shadow: #000 1px 1px 0;
792
+ background-color: rgba(0, 0, 0, 0.7);
793
+ border: 1px solid rgba(0, 0, 0, 0.9);
794
+ border-radius: 3px;
795
+ padding: 0px 4px;
796
+ margin: 2px;
797
+ line-height: 18px;
798
+ white-space: nowrap;
799
+ overflow: hidden;
800
+ position: absolute;
801
+ display: none;
802
+ }
803
+ .widget_histogram_bars rect:hover {
804
+ opacity: 0.9;
805
+ }
@@ -3,7 +3,7 @@
3
3
  %ul.ui_numbers(style="float:right;")
4
4
  %li
5
5
  .val
6
- %span.ui_value(data-value="#{@samples}")
6
+ %span.ui_value.samples(data-value="#{@samples}")
7
7
  .title Number of Samples
8
8
  %li
9
9
  .val
@@ -96,18 +96,18 @@
96
96
  no_headbar: true,
97
97
  default_style: 'line',
98
98
  series_resolutions: #{@zooms.to_json},
99
- series: [
100
- {
99
+ series: [
100
+ {
101
101
  name: 'Max',
102
102
  color: "#{FnordMetric::COLORS[-1]}",
103
103
  data: #{@mmm_timeseries_arr.map{|t,v| {:x=>t.to_i,:y=>v[:max]} }.to_json}
104
104
  },
105
- {
105
+ {
106
106
  name: 'Min',
107
107
  color: "#{FnordMetric::COLORS[-1]}",
108
108
  data: #{@mmm_timeseries_arr.map{|t,v| {:x=>t.to_i,:y=>v[:min]} }.to_json}
109
109
  },
110
- {
110
+ {
111
111
  name: 'Mean',
112
112
  color: "#{FnordMetric::COLORS[-2]}",
113
113
  data: #{@mmm_timeseries_arr.map{|t,v| {:x=>t.to_i,:y=>v[:avg].average} }.to_json}
@@ -115,4 +115,4 @@
115
115
  ]
116
116
  });
117
117
 
118
-
118
+
@@ -105,12 +105,12 @@
105
105
  var toplist_gauge_timeseries = #{@toplist.timelines.to_json};
106
106
  var toplist_gauge_ticks = #{@all_ticks.sort.to_json};
107
107
 
108
- var toplist_gauge_numbers = #{Hash[@toplist.toplist(top_k).map{ |k,t|
109
- [k, { :total => t,
108
+ var toplist_gauge_numbers = #{Hash[@toplist.toplist(top_k).map{ |k,t|
109
+ [k, { :total => t,
110
110
  :percent => @toplist.percentage(k),
111
111
  :rank => @toplist.rank(k),
112
112
  :delta => @toplist.trend(k) }]
113
- }].to_json};
113
+ }].to_json};
114
114
 
115
115
 
116
116
  function toplgaugeSelectItem(){
@@ -1,35 +1,35 @@
1
1
  Rickshaw = {
2
2
 
3
- namespace: function(namespace, obj) {
3
+ namespace: function(namespace, obj) {
4
4
 
5
- var parts = namespace.split('.');
5
+ var parts = namespace.split('.');
6
6
 
7
- // for rudimentary compatibility w/ node
8
- var root = typeof global != 'undefined' ? global : window;
7
+ // for rudimentary compatibility w/ node
8
+ var root = typeof global != 'undefined' ? global : window;
9
9
 
10
- var parent = root.Rickshaw;
10
+ var parent = root.Rickshaw;
11
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
- },
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
19
 
20
- keys: function(obj) {
21
- var keys = [];
22
- for (var key in obj) keys.push(key);
23
- return keys;
24
- },
20
+ keys: function(obj) {
21
+ var keys = [];
22
+ for (var key in obj) keys.push(key);
23
+ return keys;
24
+ },
25
25
 
26
- extend: function(destination, source) {
26
+ extend: function(destination, source) {
27
27
 
28
- for (var property in source) {
29
- destination[property] = source[property];
30
- }
31
- return destination;
32
- }
28
+ for (var property in source) {
29
+ destination[property] = source[property];
30
+ }
31
+ return destination;
32
+ }
33
33
  };
34
34
 
35
35
  /* Adapted from https://github.com/Jakobo/PTClass */
@@ -148,8 +148,8 @@ function bind(fn, context) {
148
148
  var emptyFunction = function(){};
149
149
 
150
150
  var Class = (function() {
151
-
152
- // Some versions of JScript fail to enumerate over properties, names of which
151
+
152
+ // Some versions of JScript fail to enumerate over properties, names of which
153
153
  // correspond to non-enumerable properties in the prototype chain
154
154
  var IS_DONTENUM_BUGGY = (function(){
155
155
  for (var p in { toString: 1 }) {
@@ -158,7 +158,7 @@ var Class = (function() {
158
158
  }
159
159
  return true;
160
160
  })();
161
-
161
+
162
162
  function subclass() {};
163
163
  function create() {
164
164
  var parent = null, properties = [].slice.apply(arguments);
@@ -240,655 +240,655 @@ Rickshaw.namespace('Rickshaw.Compat.ClassList');
240
240
 
241
241
  Rickshaw.Compat.ClassList = function() {
242
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
- }
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
369
  };
370
370
 
371
371
  if ( (typeof RICKSHAW_NO_COMPAT !== "undefined" && !RICKSHAW_NO_COMPAT) || typeof RICKSHAW_NO_COMPAT === "undefined") {
372
- new Rickshaw.Compat.ClassList();
372
+ new Rickshaw.Compat.ClassList();
373
373
  }
374
374
  Rickshaw.namespace('Rickshaw.Graph');
375
375
 
376
376
  Rickshaw.Graph = function(args) {
377
377
 
378
- this.element = args.element;
379
- this.series = args.series;
378
+ this.element = args.element;
379
+ this.series = args.series;
380
380
 
381
- this.defaults = {
382
- interpolation: 'cardinal',
383
- offset: 'zero',
384
- min: undefined,
385
- max: undefined,
386
- };
381
+ this.defaults = {
382
+ interpolation: 'cardinal',
383
+ offset: 'zero',
384
+ min: undefined,
385
+ max: undefined,
386
+ };
387
387
 
388
- Rickshaw.keys(this.defaults).forEach( function(k) {
389
- this[k] = args[k] || this.defaults[k];
390
- }, this );
388
+ Rickshaw.keys(this.defaults).forEach( function(k) {
389
+ this[k] = args[k] || this.defaults[k];
390
+ }, this );
391
391
 
392
- this.window = {};
392
+ this.window = {};
393
393
 
394
- this.updateCallbacks = [];
394
+ this.updateCallbacks = [];
395
395
 
396
- var self = this;
396
+ var self = this;
397
397
 
398
- this.initialize = function(args) {
398
+ this.initialize = function(args) {
399
399
 
400
- this.validateSeries(args.series);
400
+ this.validateSeries(args.series);
401
401
 
402
- this.series.active = function() { return self.series.filter( function(s) { return !s.disabled } ) };
402
+ this.series.active = function() { return self.series.filter( function(s) { return !s.disabled } ) };
403
403
 
404
- this.setSize({ width: args.width, height: args.height });
404
+ this.setSize({ width: args.width, height: args.height });
405
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);
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
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
- ];
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
419
 
420
- renderers.forEach( function(r) {
421
- if (!r) return;
422
- self.registerRenderer(new r( { graph: self } ));
423
- } );
420
+ renderers.forEach( function(r) {
421
+ if (!r) return;
422
+ self.registerRenderer(new r( { graph: self } ));
423
+ } );
424
424
 
425
- this.setRenderer(args.renderer || 'stack', args);
426
- this.discoverRange();
427
- };
425
+ this.setRenderer(args.renderer || 'stack', args);
426
+ this.discoverRange();
427
+ };
428
428
 
429
- this.validateSeries = function(series) {
429
+ this.validateSeries = function(series) {
430
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
- }
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
435
 
436
- var pointsCount;
436
+ var pointsCount;
437
437
 
438
- series.forEach( function(s) {
438
+ series.forEach( function(s) {
439
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
- }
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
449
 
450
- pointsCount = pointsCount || s.data.length;
450
+ pointsCount = pointsCount || s.data.length;
451
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
- }
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
456
 
457
- var dataTypeX = typeof s.data[0].x;
458
- var dataTypeY = typeof s.data[0].y;
457
+ var dataTypeX = typeof s.data[0].x;
458
+ var dataTypeY = typeof s.data[0].y;
459
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
- };
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
466
 
467
- this.dataDomain = function() {
467
+ this.dataDomain = function() {
468
468
 
469
- // take from the first series
470
- var data = this.series[0].data;
469
+ // take from the first series
470
+ var data = this.series[0].data;
471
471
 
472
- return [ data[0].x, data.slice(-1).shift().x ];
472
+ return [ data[0].x, data.slice(-1).shift().x ];
473
473
 
474
- };
474
+ };
475
475
 
476
- this.discoverRange = function() {
476
+ this.discoverRange = function() {
477
477
 
478
- var domain = this.renderer.domain();
478
+ var domain = this.renderer.domain();
479
479
 
480
- this.x = d3.scale.linear().domain(domain.x).range([0, this.width]);
480
+ this.x = d3.scale.linear().domain(domain.x).range([0, this.width]);
481
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]);
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
484
 
485
- };
485
+ };
486
486
 
487
- this.render = function() {
487
+ this.render = function() {
488
488
 
489
- var stackedData = this.stackData();
490
- this.discoverRange();
489
+ var stackedData = this.stackData();
490
+ this.discoverRange();
491
491
 
492
- this.renderer.render();
492
+ this.renderer.render();
493
493
 
494
- this.updateCallbacks.forEach( function(callback) {
495
- callback();
496
- } );
497
- };
494
+ this.updateCallbacks.forEach( function(callback) {
495
+ callback();
496
+ } );
497
+ };
498
498
 
499
- this.update = this.render;
499
+ this.update = this.render;
500
500
 
501
- this.stackData = function() {
501
+ this.stackData = function() {
502
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);
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
506
 
507
- this.stackData.hooks.data.forEach( function(entry) {
508
- data = entry.f.apply(self, [data]);
509
- } );
507
+ this.stackData.hooks.data.forEach( function(entry) {
508
+ data = entry.f.apply(self, [data]);
509
+ } );
510
510
 
511
- var layout = d3.layout.stack();
512
- layout.offset( self.offset );
511
+ var layout = d3.layout.stack();
512
+ layout.offset( self.offset );
513
513
 
514
- var stackedData = layout(data);
514
+ var stackedData = layout(data);
515
515
 
516
- this.stackData.hooks.after.forEach( function(entry) {
517
- stackedData = entry.f.apply(self, [data]);
518
- } );
516
+ this.stackData.hooks.after.forEach( function(entry) {
517
+ stackedData = entry.f.apply(self, [data]);
518
+ } );
519
519
 
520
- var i = 0;
521
- this.series.forEach( function(series) {
522
- if (series.disabled) return;
523
- series.stack = stackedData[i++];
524
- } );
520
+ var i = 0;
521
+ this.series.forEach( function(series) {
522
+ if (series.disabled) return;
523
+ series.stack = stackedData[i++];
524
+ } );
525
525
 
526
- this.stackedData = stackedData;
527
- return stackedData;
528
- };
526
+ this.stackedData = stackedData;
527
+ return stackedData;
528
+ };
529
529
 
530
- this.stackData.hooks = { data: [], after: [] };
530
+ this.stackData.hooks = { data: [], after: [] };
531
531
 
532
- this._slice = function(d) {
532
+ this._slice = function(d) {
533
533
 
534
- if (this.window.xMin || this.window.xMax) {
534
+ if (this.window.xMin || this.window.xMax) {
535
535
 
536
- var isInRange = true;
536
+ var isInRange = true;
537
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;
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
540
 
541
- return isInRange;
542
- }
541
+ return isInRange;
542
+ }
543
543
 
544
- return true;
545
- };
544
+ return true;
545
+ };
546
546
 
547
- this.onUpdate = function(callback) {
548
- this.updateCallbacks.push(callback);
549
- };
547
+ this.onUpdate = function(callback) {
548
+ this.updateCallbacks.push(callback);
549
+ };
550
550
 
551
- this.registerRenderer = function(renderer) {
552
- this._renderers = this._renderers || {};
553
- this._renderers[renderer.name] = renderer;
554
- };
551
+ this.registerRenderer = function(renderer) {
552
+ this._renderers = this._renderers || {};
553
+ this._renderers[renderer.name] = renderer;
554
+ };
555
555
 
556
- this.configure = function(args) {
556
+ this.configure = function(args) {
557
557
 
558
- if (args.width || args.height) {
559
- this.setSize(args);
560
- }
558
+ if (args.width || args.height) {
559
+ this.setSize(args);
560
+ }
561
561
 
562
- Rickshaw.keys(this.defaults).forEach( function(k) {
563
- this[k] = args[k] || this.defaults[k];
564
- }, this );
562
+ Rickshaw.keys(this.defaults).forEach( function(k) {
563
+ this[k] = args[k] || this.defaults[k];
564
+ }, this );
565
565
 
566
- this.setRenderer(args.renderer || graph.renderer.name, args);
567
- };
566
+ this.setRenderer(args.renderer || graph.renderer.name, args);
567
+ };
568
568
 
569
- this.setRenderer = function(name, args) {
569
+ this.setRenderer = function(name, args) {
570
570
 
571
- if (!this._renderers[name]) {
572
- throw "couldn't find renderer " + name;
573
- }
574
- this.renderer = this._renderers[name];
571
+ if (!this._renderers[name]) {
572
+ throw "couldn't find renderer " + name;
573
+ }
574
+ this.renderer = this._renderers[name];
575
575
 
576
- if (typeof args == 'object') {
577
- this.renderer.configure(args);
578
- }
579
- };
576
+ if (typeof args == 'object') {
577
+ this.renderer.configure(args);
578
+ }
579
+ };
580
580
 
581
- this.setSize = function(args) {
581
+ this.setSize = function(args) {
582
582
 
583
- args = args || {};
583
+ args = args || {};
584
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
- }
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
590
 
591
- this.width = args.width || elementWidth || 400;
592
- this.height = args.height || elementHeight || 250;
591
+ this.width = args.width || elementWidth || 400;
592
+ this.height = args.height || elementHeight || 250;
593
593
 
594
- this.vis && this.vis
595
- .attr('width', this.width)
596
- .attr('height', this.height);
597
- }
594
+ this.vis && this.vis
595
+ .attr('width', this.width)
596
+ .attr('height', this.height);
597
+ }
598
598
 
599
- this.initialize(args);
599
+ this.initialize(args);
600
600
  };
601
601
  Rickshaw.namespace('Rickshaw.Fixtures.Color');
602
602
 
603
603
  Rickshaw.Fixtures.Color = function() {
604
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
- ];
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
759
  };
760
760
  Rickshaw.namespace('Rickshaw.Fixtures.RandomData');
761
761
 
762
762
  Rickshaw.Fixtures.RandomData = function(timeInterval) {
763
763
 
764
- var addData;
765
- timeInterval = timeInterval || 1;
764
+ var addData;
765
+ timeInterval = timeInterval || 1;
766
766
 
767
- var lastRandomValue = 200;
767
+ var lastRandomValue = 200;
768
768
 
769
- var timeBase = Math.floor(new Date().getTime() / 1000);
769
+ var timeBase = Math.floor(new Date().getTime() / 1000);
770
770
 
771
- this.addData = function(data) {
771
+ this.addData = function(data) {
772
772
 
773
- var randomValue = Math.random() * 100 + 15 + lastRandomValue;
774
- var index = data[0].length;
773
+ var randomValue = Math.random() * 100 + 15 + lastRandomValue;
774
+ var index = data[0].length;
775
775
 
776
- var counter = 1;
776
+ var counter = 1;
777
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;
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
784
 
785
- series.push( { x: (index * timeInterval) + timeBase, y: v + randomVariance } );
786
- } );
785
+ series.push( { x: (index * timeInterval) + timeBase, y: v + randomVariance } );
786
+ } );
787
787
 
788
- lastRandomValue = randomValue * .85;
789
- }
788
+ lastRandomValue = randomValue * .85;
789
+ }
790
790
  };
791
791
 
792
792
  Rickshaw.namespace('Rickshaw.Fixtures.Time');
793
793
 
794
794
  Rickshaw.Fixtures.Time = function() {
795
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) {
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
855
  var exp = FnordMetric.util.dateFormat(d.getTime()).match(/^([0-9]+\.[0-9]+)/);
856
856
 
857
857
  if (exp)
858
858
  return exp[1];
859
859
 
860
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
- };
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
881
  };
882
882
  Rickshaw.namespace('Rickshaw.Fixtures.Number');
883
883
 
884
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 }
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
892
  };
893
893
 
894
894
  Rickshaw.Fixtures.Number.formatBase1024KMGTP = function(y) {
@@ -905,436 +905,436 @@ Rickshaw.namespace("Rickshaw.Color.Palette");
905
905
 
906
906
  Rickshaw.Color.Palette = function(args) {
907
907
 
908
- var color = new Rickshaw.Fixtures.Color();
908
+ var color = new Rickshaw.Fixtures.Color();
909
909
 
910
- args = args || {};
911
- this.schemes = {};
910
+ args = args || {};
911
+ this.schemes = {};
912
912
 
913
- this.scheme = color.schemes[args.scheme] || args.scheme || color.schemes.colorwheel;
914
- this.runningIndex = 0;
913
+ this.scheme = color.schemes[args.scheme] || args.scheme || color.schemes.colorwheel;
914
+ this.runningIndex = 0;
915
915
 
916
- this.color = function(key) {
917
- return this.scheme[key] || this.scheme[this.runningIndex++] || '#808080';
918
- };
916
+ this.color = function(key) {
917
+ return this.scheme[key] || this.scheme[this.runningIndex++] || '#808080';
918
+ };
919
919
  };
920
920
  Rickshaw.namespace('Graph.Ajax');
921
921
 
922
922
  Rickshaw.Graph.Ajax = function(args) {
923
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
- } );
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
975
  };
976
976
 
977
977
  Rickshaw.namespace('Rickshaw.Graph.Annotate');
978
978
 
979
979
  Rickshaw.Graph.Annotate = function(args) {
980
980
 
981
- var graph = this.graph = args.graph;
982
- this.elements = { timeline: args.element };
983
-
984
- var self = this;
981
+ var graph = this.graph = args.graph;
982
+ this.elements = { timeline: args.element };
985
983
 
986
- this.data = {};
984
+ var self = this;
987
985
 
988
- this.elements.timeline.classList.add('rickshaw_annotation_timeline');
986
+ this.data = {};
989
987
 
990
- this.add = function(time, content) {
991
- self.data[time] = self.data[time] || {'boxes': []};
992
- self.data[time].boxes.push({content: content});
993
- };
988
+ this.elements.timeline.classList.add('rickshaw_annotation_timeline');
994
989
 
995
- this.update = function() {
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
996
 
997
- Rickshaw.keys(self.data).forEach( function(time) {
997
+ Rickshaw.keys(self.data).forEach( function(time) {
998
998
 
999
- var annotation = self.data[time];
1000
- var left = self.graph.x(time);
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
+ }
1001
1008
 
1002
- if (left < 0 || left > self.graph.x.range()[1]) {
1003
- if (annotation.element) {
1004
- annotation.element.style.display = 'none';
1005
- }
1006
- return;
1007
- }
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);
1008
1017
 
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
- }
1018
+ }
1019
1019
 
1020
- annotation.element.style.left = left + 'px';
1021
- annotation.element.style.display = 'block';
1020
+ annotation.element.style.left = left + 'px';
1021
+ annotation.element.style.display = 'block';
1022
1022
 
1023
- annotation.boxes.forEach( function(box) {
1023
+ annotation.boxes.forEach( function(box) {
1024
1024
 
1025
- var element = box.element;
1025
+ var element = box.element;
1026
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);
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
1032
 
1033
- annotation.line = document.createElement('div');
1034
- annotation.line.classList.add('annotation_line');
1035
- self.graph.element.appendChild(annotation.line);
1036
- }
1033
+ annotation.line = document.createElement('div');
1034
+ annotation.line.classList.add('annotation_line');
1035
+ self.graph.element.appendChild(annotation.line);
1036
+ }
1037
1037
 
1038
- annotation.line.style.left = left + 'px';
1039
- } );
1040
- }, this );
1041
- };
1038
+ annotation.line.style.left = left + 'px';
1039
+ } );
1040
+ }, this );
1041
+ };
1042
1042
 
1043
- this.graph.onUpdate( function() { self.update() } );
1043
+ this.graph.onUpdate( function() { self.update() } );
1044
1044
  };
1045
1045
  Rickshaw.namespace('Rickshaw.Graph.Axis.Time');
1046
1046
 
1047
1047
  Rickshaw.Graph.Axis.Time = function(args) {
1048
1048
 
1049
- var self = this;
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();
1050
1057
 
1051
- this.graph = args.graph;
1052
- this.elements = [];
1053
- this.ticksTreatment = args.ticksTreatment || 'plain';
1054
- this.fixedTimeUnit = args.timeUnit;
1058
+ this.appropriateTimeUnit = function() {
1055
1059
 
1056
- var time = new Rickshaw.Fixtures.Time();
1060
+ var unit;
1061
+ var units = time.units;
1057
1062
 
1058
- this.appropriateTimeUnit = function() {
1063
+ var domain = this.graph.x.domain();
1064
+ var rangeSeconds = domain[1] - domain[0];
1059
1065
 
1060
- var unit;
1061
- var units = time.units;
1066
+ units.forEach( function(u) {
1067
+ if (Math.floor(rangeSeconds / u.seconds) >= 2) {
1068
+ unit = unit || u;
1069
+ }
1070
+ } );
1062
1071
 
1063
- var domain = this.graph.x.domain();
1064
- var rangeSeconds = domain[1] - domain[0];
1072
+ return (unit || time.units[time.units.length - 1]);
1073
+ };
1065
1074
 
1066
- units.forEach( function(u) {
1067
- if (Math.floor(rangeSeconds / u.seconds) >= 2) {
1068
- unit = unit || u;
1069
- }
1070
- } );
1075
+ this.tickOffsets = function() {
1071
1076
 
1072
- return (unit || time.units[time.units.length - 1]);
1073
- };
1077
+ var domain = this.graph.x.domain();
1074
1078
 
1075
- this.tickOffsets = function() {
1079
+ var unit = this.fixedTimeUnit || this.appropriateTimeUnit();
1080
+ var count = Math.ceil((domain[1] - domain[0]) / unit.seconds);
1076
1081
 
1077
- var domain = this.graph.x.domain();
1082
+ var runningTick = domain[0];
1078
1083
 
1079
- var unit = this.fixedTimeUnit || this.appropriateTimeUnit();
1080
- var count = Math.ceil((domain[1] - domain[0]) / unit.seconds);
1084
+ var offsets = [];
1081
1085
 
1082
- var runningTick = domain[0];
1086
+ for (var i = 0; i < count; i++) {
1083
1087
 
1084
- var offsets = [];
1088
+ tickValue = time.ceil(runningTick, unit);
1089
+ runningTick = tickValue + unit.seconds / 2;
1085
1090
 
1086
- for (var i = 0; i < count; i++) {
1091
+ offsets.push( { value: tickValue, unit: unit } );
1092
+ }
1087
1093
 
1088
- tickValue = time.ceil(runningTick, unit);
1089
- runningTick = tickValue + unit.seconds / 2;
1094
+ return offsets;
1095
+ };
1090
1096
 
1091
- offsets.push( { value: tickValue, unit: unit } );
1092
- }
1097
+ this.render = function() {
1093
1098
 
1094
- return offsets;
1095
- };
1099
+ this.elements.forEach( function(e) {
1100
+ e.parentNode.removeChild(e);
1101
+ } );
1096
1102
 
1097
- this.render = function() {
1103
+ this.elements = [];
1098
1104
 
1099
- this.elements.forEach( function(e) {
1100
- e.parentNode.removeChild(e);
1101
- } );
1105
+ var offsets = this.tickOffsets();
1102
1106
 
1103
- this.elements = [];
1107
+ offsets.forEach( function(o) {
1104
1108
 
1105
- var offsets = this.tickOffsets();
1109
+ if (self.graph.x(o.value) > self.graph.x.range()[1]) return;
1106
1110
 
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);
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
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);
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
1120
 
1121
- self.graph.element.appendChild(element);
1122
- self.elements.push(element);
1121
+ self.graph.element.appendChild(element);
1122
+ self.elements.push(element);
1123
1123
 
1124
- } );
1125
- };
1124
+ } );
1125
+ };
1126
1126
 
1127
- this.graph.onUpdate( function() { self.render() } );
1127
+ this.graph.onUpdate( function() { self.render() } );
1128
1128
  };
1129
1129
 
1130
1130
  Rickshaw.namespace('Rickshaw.Graph.Axis.Y');
1131
1131
 
1132
1132
  Rickshaw.Graph.Axis.Y = function(args) {
1133
1133
 
1134
- var self = this;
1135
- var berthRate = 0.10;
1134
+ var self = this;
1135
+ var berthRate = 0.10;
1136
1136
 
1137
- this.initialize = function(args) {
1137
+ this.initialize = function(args) {
1138
1138
 
1139
- this.graph = args.graph;
1140
- this.orientation = args.orientation || 'right';
1139
+ this.graph = args.graph;
1140
+ this.orientation = args.orientation || 'right';
1141
1141
 
1142
1142
  var pixelsPerTick = 60;
1143
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';
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
1151
 
1152
- if (args.element) {
1152
+ if (args.element) {
1153
1153
 
1154
- this.element = args.element;
1155
- this.vis = d3.select(args.element)
1156
- .append("svg:svg")
1157
- .attr('class', 'rickshaw_graph y_axis');
1154
+ this.element = args.element;
1155
+ this.vis = d3.select(args.element)
1156
+ .append("svg:svg")
1157
+ .attr('class', 'rickshaw_graph y_axis');
1158
1158
 
1159
- this.element = this.vis[0][0];
1160
- this.element.style.position = 'relative';
1159
+ this.element = this.vis[0][0];
1160
+ this.element.style.position = 'relative';
1161
1161
 
1162
- this.setSize({ width: args.width, height: args.height });
1162
+ this.setSize({ width: args.width, height: args.height });
1163
1163
 
1164
- } else {
1165
- this.vis = this.graph.vis;
1166
- }
1164
+ } else {
1165
+ this.vis = this.graph.vis;
1166
+ }
1167
1167
 
1168
- this.graph.onUpdate( function() { self.render() } );
1169
- };
1168
+ this.graph.onUpdate( function() { self.render() } );
1169
+ };
1170
1170
 
1171
- this.setSize = function(args) {
1171
+ this.setSize = function(args) {
1172
1172
 
1173
- args = args || {};
1173
+ args = args || {};
1174
1174
 
1175
- if (!this.element) return;
1175
+ if (!this.element) return;
1176
1176
 
1177
- if (typeof window !== undefined) {
1177
+ if (typeof window !== undefined) {
1178
1178
 
1179
- var style = window.getComputedStyle(this.element, null);
1180
- var elementWidth = parseInt(style.getPropertyValue('width'));
1179
+ var style = window.getComputedStyle(this.element, null);
1180
+ var elementWidth = parseInt(style.getPropertyValue('width'));
1181
1181
 
1182
- if (!args.auto) {
1183
- var elementHeight = parseInt(style.getPropertyValue('height'));
1184
- }
1185
- }
1182
+ if (!args.auto) {
1183
+ var elementHeight = parseInt(style.getPropertyValue('height'));
1184
+ }
1185
+ }
1186
1186
 
1187
- this.width = args.width || elementWidth || this.graph.width * berthRate;
1188
- this.height = args.height || elementHeight || this.graph.height;
1187
+ this.width = args.width || elementWidth || this.graph.width * berthRate;
1188
+ this.height = args.height || elementHeight || this.graph.height;
1189
1189
 
1190
- this.vis
1191
- .attr('width', this.width)
1192
- .attr('height', this.height * (1 + berthRate));
1190
+ this.vis
1191
+ .attr('width', this.width)
1192
+ .attr('height', this.height * (1 + berthRate));
1193
1193
 
1194
- var berth = this.height * berthRate;
1195
- this.element.style.top = -1 * berth + 'px';
1196
- this.element.style.paddingTop = berth + 'px';
1197
- };
1194
+ var berth = this.height * berthRate;
1195
+ this.element.style.top = -1 * berth + 'px';
1196
+ this.element.style.paddingTop = berth + 'px';
1197
+ };
1198
1198
 
1199
- this.render = function() {
1199
+ this.render = function() {
1200
1200
 
1201
- if (this.graph.height !== this._renderHeight) this.setSize({ auto: true });
1201
+ if (this.graph.height !== this._renderHeight) this.setSize({ auto: true });
1202
1202
 
1203
- var axis = d3.svg.axis().scale(this.graph.y).orient(this.orientation);
1204
- axis.tickFormat( args.tickFormat || function(y) { return y } );
1203
+ var axis = d3.svg.axis().scale(this.graph.y).orient(this.orientation);
1204
+ axis.tickFormat( args.tickFormat || function(y) { return y } );
1205
1205
 
1206
- if (this.orientation == 'left') {
1207
- var transform = 'translate(' + this.width + ', 0)';
1208
- }
1206
+ if (this.orientation == 'left') {
1207
+ var transform = 'translate(' + this.width + ', 0)';
1208
+ }
1209
1209
 
1210
- if (this.element) {
1211
- this.vis.selectAll('*').remove();
1212
- }
1210
+ if (this.element) {
1211
+ this.vis.selectAll('*').remove();
1212
+ }
1213
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))
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
1219
 
1220
- var gridSize = (this.orientation == 'right' ? 1 : -1) * this.graph.width;
1220
+ var gridSize = (this.orientation == 'right' ? 1 : -1) * this.graph.width;
1221
1221
 
1222
- this.graph.vis
1223
- .append("svg:g")
1224
- .attr("class", "y_grid")
1225
- .call(axis.ticks(this.ticks).tickSubdivide(0).tickSize(gridSize));
1222
+ this.graph.vis
1223
+ .append("svg:g")
1224
+ .attr("class", "y_grid")
1225
+ .call(axis.ticks(this.ticks).tickSubdivide(0).tickSize(gridSize));
1226
1226
 
1227
- this._renderHeight = this.graph.height;
1228
- };
1227
+ this._renderHeight = this.graph.height;
1228
+ };
1229
1229
 
1230
- this.initialize(args);
1230
+ this.initialize(args);
1231
1231
  };
1232
1232
 
1233
1233
  Rickshaw.namespace('Rickshaw.Graph.Behavior.Series.Highlight');
1234
1234
 
1235
1235
  Rickshaw.Graph.Behavior.Series.Highlight = function(args) {
1236
1236
 
1237
- this.graph = args.graph;
1238
- this.legend = args.legend;
1237
+ this.graph = args.graph;
1238
+ this.legend = args.legend;
1239
1239
 
1240
- var self = this;
1240
+ var self = this;
1241
1241
 
1242
- var colorSafe = {};
1242
+ var colorSafe = {};
1243
1243
 
1244
- this.addHighlightEvents = function (l) {
1245
- l.element.addEventListener( 'mouseover', function(e) {
1244
+ this.addHighlightEvents = function (l) {
1245
+ l.element.addEventListener( 'mouseover', function(e) {
1246
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
- } );
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
1252
 
1253
- self.graph.update();
1253
+ self.graph.update();
1254
1254
 
1255
- }, false );
1255
+ }, false );
1256
1256
 
1257
- l.element.addEventListener( 'mouseout', function(e) {
1257
+ l.element.addEventListener( 'mouseout', function(e) {
1258
1258
 
1259
- self.legend.lines.forEach( function(line) {
1260
- if (colorSafe[line.series.name]) {
1261
- line.series.color = colorSafe[line.series.name];
1262
- }
1263
- } );
1259
+ self.legend.lines.forEach( function(line) {
1260
+ if (colorSafe[line.series.name]) {
1261
+ line.series.color = colorSafe[line.series.name];
1262
+ }
1263
+ } );
1264
1264
 
1265
- self.graph.update();
1265
+ self.graph.update();
1266
1266
 
1267
- }, false );
1268
- };
1267
+ }, false );
1268
+ };
1269
1269
 
1270
- if (this.legend) {
1271
- this.legend.lines.forEach( function(l) {
1272
- self.addHighlightEvents(l);
1273
- } );
1274
- }
1270
+ if (this.legend) {
1271
+ this.legend.lines.forEach( function(l) {
1272
+ self.addHighlightEvents(l);
1273
+ } );
1274
+ }
1275
1275
 
1276
1276
  };
1277
1277
  Rickshaw.namespace('Rickshaw.Graph.Behavior.Series.Order');
1278
1278
 
1279
1279
  Rickshaw.Graph.Behavior.Series.Order = function(args) {
1280
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
- } );
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
1312
  };
1313
1313
  Rickshaw.namespace('Rickshaw.Graph.Behavior.Series.Toggle');
1314
1314
 
1315
1315
  Rickshaw.Graph.Behavior.Series.Toggle = function(args) {
1316
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
-
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
1338
  var label = line.element.getElementsByTagName('span')[0];
1339
1339
  label.onclick = function(e){
1340
1340
 
@@ -1380,9 +1380,9 @@ Rickshaw.Graph.Behavior.Series.Toggle = function(args) {
1380
1380
 
1381
1381
  };
1382
1382
 
1383
- };
1383
+ };
1384
1384
 
1385
- if (this.legend) {
1385
+ if (this.legend) {
1386
1386
 
1387
1387
  $(this.legend.list).sortable( {
1388
1388
  start: function(event, ui) {
@@ -1399,620 +1399,620 @@ Rickshaw.Graph.Behavior.Series.Toggle = function(args) {
1399
1399
  }
1400
1400
  })
1401
1401
 
1402
- this.legend.lines.forEach( function(l) {
1403
- self.addAnchor(l);
1404
- } );
1405
- }
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) {
1406
1410
 
1407
- this._addBehavior = function() {
1411
+ s.disable = function() {
1408
1412
 
1409
- this.graph.series.forEach( function(s) {
1410
-
1411
- s.disable = function() {
1413
+ if (self.graph.series.length <= 1) {
1414
+ throw('only one series left');
1415
+ }
1412
1416
 
1413
- if (self.graph.series.length <= 1) {
1414
- throw('only one series left');
1415
- }
1416
-
1417
- s.disabled = true;
1418
- self.graph.update();
1419
- };
1417
+ s.disabled = true;
1418
+ self.graph.update();
1419
+ };
1420
1420
 
1421
- s.enable = function() {
1422
- s.disabled = false;
1423
- self.graph.update();
1424
- };
1425
- } );
1426
- };
1427
- this._addBehavior();
1421
+ s.enable = function() {
1422
+ s.disabled = false;
1423
+ self.graph.update();
1424
+ };
1425
+ } );
1426
+ };
1427
+ this._addBehavior();
1428
1428
 
1429
- this.updateBehaviour = function () { this._addBehavior() };
1429
+ this.updateBehaviour = function () { this._addBehavior() };
1430
1430
 
1431
1431
  };
1432
1432
  Rickshaw.namespace('Rickshaw.Graph.HoverDetail');
1433
1433
 
1434
1434
  Rickshaw.Graph.HoverDetail = Rickshaw.Class.create({
1435
1435
 
1436
- initialize: function(args) {
1436
+ initialize: function(args) {
1437
1437
 
1438
- var graph = this.graph = args.graph;
1438
+ var graph = this.graph = args.graph;
1439
1439
 
1440
- this.xFormatter = args.xFormatter || function(x) {
1440
+ this.xFormatter = args.xFormatter || function(x) {
1441
1441
  return FnordMetric.util.dateFormat(x);
1442
- };
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;
1443
1464
 
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';
1465
+ this.formatter = args.formatter || this.formatter;
1466
+ },
1450
1467
 
1451
- if(args.no_detail){
1452
- element.className = 'detail no_detail';
1453
- }
1454
-
1455
- this.visible = true;
1456
- graph.element.appendChild(element);
1468
+ formatter: function(series, x, y, formattedX, formattedY) {
1469
+ return series.name + ':&nbsp;' + formattedY;
1470
+ },
1457
1471
 
1458
- this.lastEvent = null;
1459
- this._addListeners();
1472
+ update: function(e) {
1460
1473
 
1461
- this.onShow = args.onShow;
1462
- this.onHide = args.onHide;
1463
- this.onRender = args.onRender;
1474
+ e = e || this.lastEvent;
1475
+ if (!e) return;
1476
+ this.lastEvent = e;
1464
1477
 
1465
- this.formatter = args.formatter || this.formatter;
1466
- },
1478
+ if (e.target.nodeName != 'path' && e.target.nodeName != 'svg') return;
1467
1479
 
1468
- formatter: function(series, x, y, formattedX, formattedY) {
1469
- return series.name + ':&nbsp;' + formattedY;
1470
- },
1480
+ var graph = this.graph;
1471
1481
 
1472
- update: function(e) {
1482
+ var eventX = e.offsetX || e.layerX;
1483
+ var eventY = e.offsetY || e.layerY;
1473
1484
 
1474
- e = e || this.lastEvent;
1475
- if (!e) return;
1476
- this.lastEvent = e;
1485
+ var domainX = graph.x.invert(eventX);
1486
+ var stackedData = graph.stackedData;
1477
1487
 
1478
- if (e.target.nodeName != 'path' && e.target.nodeName != 'svg') return;
1488
+ var topSeriesData = stackedData.slice(-1).shift();
1479
1489
 
1480
- var graph = this.graph;
1490
+ var domainIndexScale = d3.scale.linear()
1491
+ .domain([topSeriesData[0].x, topSeriesData.slice(-1).shift().x])
1492
+ .range([0, topSeriesData.length]);
1481
1493
 
1482
- var eventX = e.offsetX || e.layerX;
1483
- var eventY = e.offsetY || e.layerY;
1494
+ var approximateIndex = Math.floor(domainIndexScale(domainX));
1495
+ var dataIndex = approximateIndex || 0;
1484
1496
 
1485
- var domainX = graph.x.invert(eventX);
1486
- var stackedData = graph.stackedData;
1497
+ for (var i = approximateIndex; i < stackedData[0].length - 1;) {
1487
1498
 
1488
- var topSeriesData = stackedData.slice(-1).shift();
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
+ }
1489
1509
 
1490
- var domainIndexScale = d3.scale.linear()
1491
- .domain([topSeriesData[0].x, topSeriesData.slice(-1).shift().x])
1492
- .range([0, topSeriesData.length]);
1510
+ var domainX = stackedData[0][dataIndex].x;
1511
+ var formattedXValue = this.xFormatter(domainX);
1512
+ var graphX = graph.x(domainX);
1513
+ var order = 0;
1493
1514
 
1494
- var approximateIndex = Math.floor(domainIndexScale(domainX));
1495
- var dataIndex = approximateIndex || 0;
1515
+ var detail = graph.series.active()
1516
+ .map( function(s) { return { order: order++, series: s, name: s.name, value: s.stack[dataIndex] } } );
1496
1517
 
1497
- for (var i = approximateIndex; i < stackedData[0].length - 1;) {
1518
+ var activeItem;
1498
1519
 
1499
- if (!stackedData[0][i] || !stackedData[0][i + 1]) {
1500
- break;
1501
- }
1520
+ var sortFn = function(a, b) {
1521
+ return (a.value.y0 + a.value.y) - (b.value.y0 + b.value.y);
1522
+ };
1502
1523
 
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
- }
1524
+ var domainMouseY = graph.y.magnitude.invert(graph.element.offsetHeight - eventY);
1509
1525
 
1510
- var domainX = stackedData[0][dataIndex].x;
1511
- var formattedXValue = this.xFormatter(domainX);
1512
- var graphX = graph.x(domainX);
1513
- var order = 0;
1526
+ detail.sort(sortFn).forEach( function(d) {
1514
1527
 
1515
- var detail = graph.series.active()
1516
- .map( function(s) { return { order: order++, series: s, name: s.name, value: s.stack[dataIndex] } } );
1528
+ d.formattedYValue = (this.yFormatter.constructor == Array) ?
1529
+ this.yFormatter[detail.indexOf(d)](d.value.y) :
1530
+ this.yFormatter(d.value.y);
1517
1531
 
1518
- var activeItem;
1532
+ d.graphX = graphX;
1533
+ d.graphY = graph.y(d.value.y0 + d.value.y);
1519
1534
 
1520
- var sortFn = function(a, b) {
1521
- return (a.value.y0 + a.value.y) - (b.value.y0 + b.value.y);
1522
- };
1535
+ if (domainMouseY > d.value.y0 && domainMouseY < d.value.y0 + d.value.y && !activeItem) {
1536
+ activeItem = d;
1537
+ d.active = true;
1538
+ }
1523
1539
 
1524
- var domainMouseY = graph.y.magnitude.invert(graph.element.offsetHeight - eventY);
1540
+ }, this );
1525
1541
 
1526
- detail.sort(sortFn).forEach( function(d) {
1542
+ this.element.innerHTML = '';
1543
+ this.element.style.left = graph.x(domainX) + 'px';
1527
1544
 
1528
- d.formattedYValue = (this.yFormatter.constructor == Array) ?
1529
- this.yFormatter[detail.indexOf(d)](d.value.y) :
1530
- this.yFormatter(d.value.y);
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
+ },
1531
1555
 
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
- }
1556
+ hide: function() {
1557
+ this.visible = false;
1558
+ this.element.classList.add('inactive');
1539
1559
 
1540
- }, this );
1560
+ if (typeof this.onHide == 'function') {
1561
+ this.onHide();
1562
+ }
1563
+ },
1541
1564
 
1542
- this.element.innerHTML = '';
1543
- this.element.style.left = graph.x(domainX) + 'px';
1565
+ show: function() {
1566
+ this.visible = true;
1567
+ this.element.classList.remove('inactive');
1544
1568
 
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
- },
1569
+ if (typeof this.onShow == 'function') {
1570
+ this.onShow();
1571
+ }
1572
+ },
1555
1573
 
1556
- hide: function() {
1557
- this.visible = false;
1558
- this.element.classList.add('inactive');
1574
+ render: function(args) {
1559
1575
 
1560
- if (typeof this.onHide == 'function') {
1561
- this.onHide();
1562
- }
1563
- },
1576
+ var detail = args.detail;
1577
+ var domainX = args.domainX;
1564
1578
 
1565
- show: function() {
1566
- this.visible = true;
1567
- this.element.classList.remove('inactive');
1579
+ var mouseX = args.mouseX;
1580
+ var mouseY = args.mouseY;
1568
1581
 
1569
- if (typeof this.onShow == 'function') {
1570
- this.onShow();
1571
- }
1572
- },
1582
+ var formattedXValue = args.formattedXValue;
1573
1583
 
1574
- render: function(args) {
1584
+ var xLabel = document.createElement('div');
1585
+ xLabel.className = 'x_label';
1586
+ xLabel.innerHTML = formattedXValue;
1587
+ this.element.appendChild(xLabel);
1575
1588
 
1576
- var detail = args.detail;
1577
- var domainX = args.domainX;
1589
+ detail.forEach( function(d) {
1578
1590
 
1579
- var mouseX = args.mouseX;
1580
- var mouseY = args.mouseY;
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';
1581
1595
 
1582
- var formattedXValue = args.formattedXValue;
1596
+ this.element.appendChild(item);
1583
1597
 
1584
- var xLabel = document.createElement('div');
1585
- xLabel.className = 'x_label';
1586
- xLabel.innerHTML = formattedXValue;
1587
- this.element.appendChild(xLabel);
1598
+ var dot = document.createElement('div');
1599
+ dot.className = 'dot';
1600
+ dot.style.top = item.style.top;
1601
+ dot.style.borderColor = d.series.color;
1588
1602
 
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';
1603
+ this.element.appendChild(dot);
1595
1604
 
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
- }
1605
+ if (d.active) {
1606
+ item.className = 'item active';
1607
+ dot.className = 'dot active';
1608
+ }
1609
1609
 
1610
- }, this );
1610
+ }, this );
1611
1611
 
1612
- this.show();
1612
+ this.show();
1613
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
- }
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
1642
  });
1643
1643
 
1644
1644
  Rickshaw.namespace('Rickshaw.Graph.JSONP');
1645
1645
 
1646
1646
  Rickshaw.Graph.JSONP = function(args) {
1647
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
- } );
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
1698
  };
1699
1699
 
1700
1700
  Rickshaw.namespace('Rickshaw.Graph.Legend');
1701
1701
 
1702
1702
  Rickshaw.Graph.Legend = function(args) {
1703
1703
 
1704
- var element = this.element = args.element;
1705
- var graph = this.graph = args.graph;
1704
+ var element = this.element = args.element;
1705
+ var graph = this.graph = args.graph;
1706
1706
 
1707
- var self = this;
1707
+ var self = this;
1708
1708
 
1709
- element.classList.add('rickshaw_legend');
1709
+ element.classList.add('rickshaw_legend');
1710
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();
1711
+ var list = this.list = document.createElement('ul');
1712
+ element.appendChild(list);
1717
1713
 
1718
- this.lines = [];
1714
+ var series = graph.series
1715
+ .map( function(s) { return s } )
1716
+ .reverse();
1719
1717
 
1720
- this.addLine = function (series) {
1721
- var line = document.createElement('li');
1722
- line.className = 'line';
1718
+ this.lines = [];
1723
1719
 
1724
- var swatch = document.createElement('div');
1725
- swatch.className = 'swatch';
1726
- swatch.style.backgroundColor = series.color;
1720
+ this.addLine = function (series) {
1721
+ var line = document.createElement('li');
1722
+ line.className = 'line';
1727
1723
 
1728
- line.appendChild(swatch);
1724
+ var swatch = document.createElement('div');
1725
+ swatch.className = 'swatch';
1726
+ swatch.style.backgroundColor = series.color;
1729
1727
 
1730
- var label = document.createElement('span');
1731
- label.className = 'label';
1732
- label.innerHTML = series.name;
1728
+ line.appendChild(swatch);
1733
1729
 
1734
- line.appendChild(label);
1735
- list.appendChild(line);
1730
+ var label = document.createElement('span');
1731
+ label.className = 'label';
1732
+ label.innerHTML = series.name;
1736
1733
 
1737
- line.series = series;
1734
+ line.appendChild(label);
1735
+ list.appendChild(line);
1738
1736
 
1739
- if (series.noLegend) {
1740
- line.style.display = 'none';
1741
- }
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
+ };
1742
1753
 
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
- };
1754
+ series.forEach( function(s) {
1755
+ self.addLine(s);
1756
+ } );
1753
1757
 
1754
- series.forEach( function(s) {
1755
- self.addLine(s);
1756
- } );
1758
+ graph.onUpdate( function() {
1757
1759
 
1758
- graph.onUpdate( function() {
1759
-
1760
- } );
1760
+ } );
1761
1761
  };
1762
1762
  Rickshaw.namespace('Rickshaw.Graph.RangeSlider');
1763
1763
 
1764
1764
  Rickshaw.Graph.RangeSlider = function(args) {
1765
1765
 
1766
- var element = this.element = args.element;
1767
- var graph = this.graph = args.graph;
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';
1768
1797
 
1769
- $( function() {
1770
- $(element).slider( {
1798
+ graph.onUpdate( function() {
1771
1799
 
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 ) {
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
+ }
1780
1811
 
1781
- graph.window.xMin = ui.values[0];
1782
- graph.window.xMax = ui.values[1];
1783
- graph.update();
1812
+ $(element).slider('option', 'values', values);
1784
1813
 
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
- } );
1814
+ } );
1815
+ };
1795
1816
 
1796
- element[0].style.width = graph.width + 'px';
1817
+ Rickshaw.namespace("Rickshaw.Graph.Renderer");
1797
1818
 
1798
- graph.onUpdate( function() {
1819
+ Rickshaw.Graph.Renderer = Rickshaw.Class.create( {
1799
1820
 
1800
- var values = $(element).slider('option', 'values');
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
+ },
1801
1827
 
1802
- $(element).slider('option', 'min', graph.dataDomain()[0]);
1803
- $(element).slider('option', 'max', graph.dataDomain()[1]);
1828
+ seriesPathFactory: function() {
1829
+ //implement in subclass
1830
+ },
1804
1831
 
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
- }
1832
+ seriesStrokeFactory: function() {
1833
+ // implement in subclass
1834
+ },
1811
1835
 
1812
- $(element).slider('option', 'values', values);
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
+ },
1813
1846
 
1814
- } );
1815
- };
1847
+ domain: function() {
1816
1848
 
1817
- Rickshaw.namespace("Rickshaw.Graph.Renderer");
1849
+ var values = [];
1850
+ var stackedData = this.graph.stackedData || this.graph.stackData();
1818
1851
 
1819
- Rickshaw.Graph.Renderer = Rickshaw.Class.create( {
1852
+ var topSeriesData = this.unstack ? stackedData : [ stackedData.slice(-1).shift() ];
1820
1853
 
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
- },
1854
+ topSeriesData.forEach( function(series) {
1855
+ series.forEach( function(d) {
1856
+ values.push( d.y + d.y0 );
1857
+ } );
1858
+ } );
1827
1859
 
1828
- seriesPathFactory: function() {
1829
- //implement in subclass
1830
- },
1860
+ var xMin = stackedData[0][0].x;
1861
+ var xMax = stackedData[0][ stackedData[0].length - 1 ].x;
1831
1862
 
1832
- seriesStrokeFactory: function() {
1833
- // implement in subclass
1834
- },
1863
+ xMin -= (xMax - xMin) * this.padding.left;
1864
+ xMax += (xMax - xMin) * this.padding.right;
1835
1865
 
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
- },
1866
+ var yMin = this.graph.min === 'auto' ? d3.min( values ) : this.graph.min || 0;
1867
+ var yMax = this.graph.max || d3.max( values );
1846
1868
 
1847
- domain: function() {
1869
+ if (this.graph.min === 'auto' || yMin < 0) {
1870
+ yMin -= (yMax - yMin) * this.padding.bottom;
1871
+ }
1848
1872
 
1849
- var values = [];
1850
- var stackedData = this.graph.stackedData || this.graph.stackData();
1873
+ if (this.graph.max === undefined) {
1874
+ yMax += (yMax - yMin) * this.padding.top;
1875
+ }
1851
1876
 
1852
- var topSeriesData = this.unstack ? stackedData : [ stackedData.slice(-1).shift() ];
1877
+ return { x: [xMin, xMax], y: [yMin, yMax] };
1878
+ },
1853
1879
 
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') {
1880
+ render: function() {
1926
1881
 
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 );
1882
+ var graph = this.graph;
1934
1883
 
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
- }
1884
+ graph.vis.selectAll('*').remove();
1942
1885
 
1943
- }, this );
1944
- },
1886
+ var nodes = graph.vis.selectAll("path")
1887
+ .data(this.graph.stackedData)
1888
+ .enter().append("svg:path")
1889
+ .attr("d", this.seriesPathFactory());
1945
1890
 
1946
- setStrokeWidth: function(strokeWidth) {
1947
- if (strokeWidth !== undefined) {
1948
- this.strokeWidth = strokeWidth;
1949
- }
1950
- },
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
+ },
1951
1898
 
1952
- setTension: function(tension) {
1953
- if (tension !== undefined) {
1954
- this.tension = tension;
1955
- }
1956
- }
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
1957
  } );
1958
1958
 
1959
1959
  Rickshaw.namespace('Rickshaw.Graph.Renderer.Line');
1960
1960
 
1961
1961
  Rickshaw.Graph.Renderer.Line = Rickshaw.Class.create( Rickshaw.Graph.Renderer, {
1962
1962
 
1963
- name: 'line',
1963
+ name: 'line',
1964
1964
 
1965
- defaults: function($super) {
1965
+ defaults: function($super) {
1966
1966
 
1967
- return Rickshaw.extend( $super(), {
1968
- unstack: true,
1969
- fill: false,
1970
- stroke: true
1971
- } );
1972
- },
1967
+ return Rickshaw.extend( $super(), {
1968
+ unstack: true,
1969
+ fill: false,
1970
+ stroke: true
1971
+ } );
1972
+ },
1973
1973
 
1974
- seriesPathFactory: function() {
1974
+ seriesPathFactory: function() {
1975
1975
 
1976
- var graph = this.graph;
1976
+ var graph = this.graph;
1977
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
- },
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
1983
 
1984
1984
 
1985
- render: function() {
1985
+ render: function() {
1986
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
- }
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
1994
 
1995
- var graph = this.graph;
1995
+ var graph = this.graph;
1996
1996
 
1997
- graph.vis.selectAll('*').remove();
1997
+ graph.vis.selectAll('*').remove();
1998
1998
 
1999
- var nodes = graph.vis.selectAll("path")
2000
- .data(this.graph.stackedData)
2001
- .enter().append("svg:path")
2002
- .attr("d", this.seriesPathFactory());
1999
+ var nodes = graph.vis.selectAll("path")
2000
+ .data(this.graph.stackedData)
2001
+ .enter().append("svg:path")
2002
+ .attr("d", this.seriesPathFactory());
2003
2003
 
2004
- if(fm_opts.draw_points){
2005
- console.log("FIXPAUL: timeseries widget -° draw points!");
2006
- }
2004
+ if(fm_opts.draw_points){
2005
+ console.log("FIXPAUL: timeseries widget -° draw points!");
2006
+ }
2007
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 );
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
2014
 
2015
- },
2015
+ },
2016
2016
 
2017
2017
  } );
2018
2018
 
@@ -2020,60 +2020,60 @@ Rickshaw.namespace('Rickshaw.Graph.Renderer.Stack');
2020
2020
 
2021
2021
  Rickshaw.Graph.Renderer.Stack = Rickshaw.Class.create( Rickshaw.Graph.Renderer, {
2022
2022
 
2023
- name: 'stack',
2023
+ name: 'stack',
2024
2024
 
2025
- defaults: function($super) {
2025
+ defaults: function($super) {
2026
2026
 
2027
- return Rickshaw.extend( $super(), {
2028
- fill: true,
2029
- stroke: false,
2030
- unstack: false,
2031
- } );
2032
- },
2027
+ return Rickshaw.extend( $super(), {
2028
+ fill: true,
2029
+ stroke: false,
2030
+ unstack: false,
2031
+ } );
2032
+ },
2033
2033
 
2034
- seriesPathFactory: function() {
2034
+ seriesPathFactory: function() {
2035
2035
 
2036
- var graph = this.graph;
2036
+ var graph = this.graph;
2037
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
- },
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
2044
 
2045
- render: function() {
2046
- var graph = this.graph;
2045
+ render: function() {
2046
+ var graph = this.graph;
2047
2047
 
2048
- graph.vis.selectAll('*').remove();
2048
+ graph.vis.selectAll('*').remove();
2049
2049
 
2050
- var nodes = graph.vis.selectAll("path")
2051
- .data(this.graph.stackedData)
2052
- .enter().append("svg:path")
2053
- .attr("d", this.seriesPathFactory());
2050
+ var nodes = graph.vis.selectAll("path")
2051
+ .data(this.graph.stackedData)
2052
+ .enter().append("svg:path")
2053
+ .attr("d", this.seriesPathFactory());
2054
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
- },
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
2062
 
2063
- _styleSeries: function(series, fm_opts) {
2063
+ _styleSeries: function(series, fm_opts) {
2064
2064
 
2065
- var fill = this.fill ? series.color : 'none';
2066
- var stroke = this.stroke ? series.color : 'none';
2065
+ var fill = this.fill ? series.color : 'none';
2066
+ var stroke = this.stroke ? series.color : 'none';
2067
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
- },
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
2077
 
2078
2078
 
2079
2079
  } );
@@ -2082,595 +2082,619 @@ Rickshaw.namespace('Rickshaw.Graph.Renderer.Bar');
2082
2082
 
2083
2083
  Rickshaw.Graph.Renderer.Bar = Rickshaw.Class.create( Rickshaw.Graph.Renderer, {
2084
2084
 
2085
- name: 'bar',
2085
+ name: 'bar',
2086
+
2087
+ defaults: function($super) {
2088
+
2089
+ var defaults = Rickshaw.extend( $super(), {
2090
+ gapSize: 0.10,
2091
+ unstack: false,
2092
+ } );
2086
2093
 
2087
- defaults: function($super) {
2094
+ delete defaults.tension;
2095
+ return defaults;
2096
+ },
2088
2097
 
2089
- var defaults = Rickshaw.extend( $super(), {
2090
- gapSize: 0.10,
2091
- unstack: false,
2092
- } );
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
+ },
2093
2104
 
2094
- delete defaults.tension;
2095
- return defaults;
2096
- },
2105
+ domain: function($super) {
2097
2106
 
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
- },
2107
+ var domain = $super();
2104
2108
 
2105
- domain: function($super) {
2109
+ var frequentInterval = this._frequentInterval();
2110
+ domain.x[1] += parseInt(frequentInterval.magnitude);
2106
2111
 
2107
- var domain = $super();
2112
+ return domain;
2113
+ },
2108
2114
 
2109
- var frequentInterval = this._frequentInterval();
2110
- domain.x[1] += parseInt(frequentInterval.magnitude);
2115
+ barWidth: function() {
2116
+ var stackedData = this.graph.stackedData || this.graph.stackData();
2117
+ var data = stackedData.slice(-1).shift();
2111
2118
 
2112
- return domain;
2113
- },
2119
+ var frequentInterval = this._frequentInterval();
2120
+ var barWidth = this.graph.x(data[0].x + frequentInterval.magnitude * (1 - this.gapSize));
2114
2121
 
2115
- barWidth: function() {
2116
- var stackedData = this.graph.stackedData || this.graph.stackData();
2117
- var data = stackedData.slice(-1).shift();
2122
+ return ((this.graph.width - (this.xPadding * 2)) / data.length);
2123
+ },
2118
2124
 
2119
- var frequentInterval = this._frequentInterval();
2120
- var barWidth = this.graph.x(data[0].x + frequentInterval.magnitude * (1 - this.gapSize));
2125
+ render: function() {
2121
2126
 
2122
- return ((this.graph.width - (this.xPadding * 2)) / data.length);
2123
- },
2127
+ var graph = this.graph;
2124
2128
 
2125
- render: function() {
2129
+ graph.vis.selectAll('*').remove();
2126
2130
 
2127
- var graph = this.graph;
2131
+ var barWidth = this.barWidth();
2132
+ var barXOffset = 0;
2128
2133
 
2129
- graph.vis.selectAll('*').remove();
2134
+ var activeSeriesCount = graph.series.filter( function(s) { return !s.disabled; } ).length;
2135
+ var seriesBarWidth = this.unstack ? barWidth / activeSeriesCount : barWidth;
2130
2136
 
2131
- var barWidth = this.barWidth();
2132
- var barXOffset = 0;
2137
+ graph.series.forEach( function(series) {
2133
2138
 
2134
- var activeSeriesCount = graph.series.filter( function(s) { return !s.disabled; } ).length;
2135
- var seriesBarWidth = this.unstack ? barWidth / activeSeriesCount : barWidth;
2139
+ if (series.disabled) return;
2136
2140
 
2137
- graph.series.forEach( function(series) {
2141
+ var xpad = this.xPadding;
2138
2142
 
2139
- if (series.disabled) return;
2143
+ var seriesBarDrawWidth = Math.min(60,
2144
+ parseInt(seriesBarWidth * (1 - this.gapSize)));
2140
2145
 
2141
- var xpad = this.xPadding;
2146
+ if(parseInt(seriesBarWidth) == seriesBarDrawWidth){
2147
+ seriesBarDrawWidth -= 1;
2148
+ }
2142
2149
 
2143
- var seriesBarDrawWidth = Math.min(60,
2144
- parseInt(seriesBarWidth * (1 - this.gapSize)));
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
+ }
2145
2180
 
2146
- if(parseInt(seriesBarWidth) == seriesBarDrawWidth){
2147
- seriesBarDrawWidth -= 1;
2148
- }
2181
+ Array.prototype.forEach.call(nodes[0], function(n) {
2182
+ n.setAttribute('fill', series.color);
2183
+ } );
2149
2184
 
2150
- var seriesBarDrawPadding = (seriesBarWidth - seriesBarDrawWidth) / 2;
2151
2185
 
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) });
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
+ });
2162
2198
 
2163
-
2164
- var sdata = series.stack;
2165
- for(var ind=0; ind < sdata.length; ind++){
2166
- $(graph.element).append(
2167
- $("<div>")
2168
- .css("position", "absolute")
2169
- .css("color", "#666")
2170
- .css("width", seriesBarWidth)
2171
- .css("textAlign", "center")
2172
- .css("marginTop", "5px")
2173
- .css("marginLeft", xpad + (sdata[ind].x * seriesBarWidth))
2174
- .css("y", graph.height)
2175
- .html(sdata[ind].label)
2176
- );
2177
- //
2178
- }
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
+ });
2179
2206
 
2180
- Array.prototype.forEach.call(nodes[0], function(n) {
2181
- n.setAttribute('fill', series.color);
2182
- } );
2183
2207
 
2184
- }, this );
2185
- },
2208
+ }, this );
2209
+ },
2186
2210
 
2187
- _frequentInterval: function() {
2211
+ _frequentInterval: function() {
2188
2212
 
2189
- var stackedData = this.graph.stackedData || this.graph.stackData();
2190
- var data = stackedData.slice(-1).shift();
2213
+ var stackedData = this.graph.stackedData || this.graph.stackData();
2214
+ var data = stackedData.slice(-1).shift();
2191
2215
 
2192
- var intervalCounts = {};
2216
+ var intervalCounts = {};
2193
2217
 
2194
- for (var i = 0; i < data.length - 1; i++) {
2195
- var interval = data[i + 1].x - data[i].x;
2196
- intervalCounts[interval] = intervalCounts[interval] || 0;
2197
- intervalCounts[interval]++;
2198
- }
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
+ }
2199
2223
 
2200
- var frequentInterval = { count: 0 };
2224
+ var frequentInterval = { count: 0 };
2201
2225
 
2202
- Rickshaw.keys(intervalCounts).forEach( function(i) {
2203
- if (frequentInterval.count < intervalCounts[i]) {
2226
+ Rickshaw.keys(intervalCounts).forEach( function(i) {
2227
+ if (frequentInterval.count < intervalCounts[i]) {
2204
2228
 
2205
- frequentInterval = {
2206
- count: intervalCounts[i],
2207
- magnitude: i
2208
- };
2209
- }
2210
- } );
2229
+ frequentInterval = {
2230
+ count: intervalCounts[i],
2231
+ magnitude: i
2232
+ };
2233
+ }
2234
+ } );
2211
2235
 
2212
- this._frequentInterval = function() { return frequentInterval };
2236
+ this._frequentInterval = function() { return frequentInterval };
2213
2237
 
2214
- return frequentInterval;
2215
- }
2238
+ return frequentInterval;
2239
+ }
2216
2240
  } );
2217
2241
 
2218
2242
  Rickshaw.namespace('Rickshaw.Graph.Renderer.Area');
2219
2243
 
2220
2244
  Rickshaw.Graph.Renderer.Area = Rickshaw.Class.create( Rickshaw.Graph.Renderer, {
2221
2245
 
2222
- name: 'area',
2246
+ name: 'area',
2223
2247
 
2224
- defaults: function($super) {
2248
+ defaults: function($super) {
2225
2249
 
2226
- return Rickshaw.extend( $super(), {
2227
- unstack: false,
2228
- fill: false,
2229
- stroke: false
2230
- } );
2231
- },
2250
+ return Rickshaw.extend( $super(), {
2251
+ unstack: false,
2252
+ fill: false,
2253
+ stroke: false
2254
+ } );
2255
+ },
2232
2256
 
2233
- seriesPathFactory: function() {
2257
+ seriesPathFactory: function() {
2234
2258
 
2235
- var graph = this.graph;
2259
+ var graph = this.graph;
2236
2260
 
2237
- return d3.svg.area()
2238
- .x( function(d) { return graph.x(d.x) } )
2239
- .y0( function(d) { return graph.y(d.y0) } )
2240
- .y1( function(d) { return graph.y(d.y + d.y0) } )
2241
- .interpolate(graph.interpolation).tension(this.tension);
2242
- },
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
+ },
2243
2267
 
2244
- seriesStrokeFactory: function() {
2268
+ seriesStrokeFactory: function() {
2245
2269
 
2246
- var graph = this.graph;
2270
+ var graph = this.graph;
2247
2271
 
2248
- return d3.svg.line()
2249
- .x( function(d) { return graph.x(d.x) } )
2250
- .y( function(d) { return graph.y(d.y + d.y0) } )
2251
- .interpolate(graph.interpolation).tension(this.tension);
2252
- },
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
+ },
2253
2277
 
2254
- render: function() {
2278
+ render: function() {
2255
2279
 
2256
- var graph = this.graph;
2280
+ var graph = this.graph;
2257
2281
 
2258
- graph.vis.selectAll('*').remove();
2282
+ graph.vis.selectAll('*').remove();
2259
2283
 
2260
- if(this.graph.stackedData[0].length < 42){
2261
- var fm_opts = { stroke_width: 3 };
2262
- } else {
2263
- var fm_opts = { stroke_width: 1 };
2264
- }
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
+ }
2265
2289
 
2266
- var nodes = graph.vis.selectAll("path")
2267
- .data(this.graph.stackedData)
2268
- .enter().insert("svg:g", 'g');
2290
+ var nodes = graph.vis.selectAll("path")
2291
+ .data(this.graph.stackedData)
2292
+ .enter().insert("svg:g", 'g');
2269
2293
 
2270
- nodes.append("svg:path")
2271
- .attr("d", this.seriesPathFactory())
2272
- .attr("class", 'area');
2294
+ nodes.append("svg:path")
2295
+ .attr("d", this.seriesPathFactory())
2296
+ .attr("class", 'area');
2273
2297
 
2274
- if (this.stroke) {
2275
- nodes.append("svg:path")
2276
- .attr("d", this.seriesStrokeFactory())
2277
- .attr("class", 'line');
2278
- }
2298
+ if (this.stroke) {
2299
+ nodes.append("svg:path")
2300
+ .attr("d", this.seriesStrokeFactory())
2301
+ .attr("class", 'line');
2302
+ }
2279
2303
 
2280
- var i = 0;
2281
- graph.series.forEach( function(series) {
2282
- if (series.disabled) return;
2283
- series.path = nodes[0][i++];
2284
- this._styleSeries(series, fm_opts);
2285
- }, this );
2286
- },
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
+ },
2287
2311
 
2288
- _styleSeries: function(series, fm_opts) {
2312
+ _styleSeries: function(series, fm_opts) {
2289
2313
 
2290
- if (!series.path) return;
2314
+ if (!series.path) return;
2291
2315
 
2292
- d3.select(series.path).select('.area')
2293
- .attr('opacity', '0.65')
2294
- .attr('fill', series.color);
2316
+ d3.select(series.path).select('.area')
2317
+ .attr('opacity', '0.65')
2318
+ .attr('fill', series.color);
2295
2319
 
2296
- d3.select(series.path).select('.line')
2297
- .attr('fill', 'none')
2298
- .attr('stroke', d3.interpolateRgb(series.color, 'white')(0.125))
2299
- .attr('stroke-width', fm_opts.stroke_width);
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);
2300
2324
 
2301
- if (series.className) {
2302
- series.path.setAttribute('class', series.className);
2303
- }
2304
- }
2325
+ if (series.className) {
2326
+ series.path.setAttribute('class', series.className);
2327
+ }
2328
+ }
2305
2329
  } );
2306
2330
 
2307
2331
  Rickshaw.namespace('Rickshaw.Graph.Renderer.ScatterPlot');
2308
2332
 
2309
2333
  Rickshaw.Graph.Renderer.ScatterPlot = Rickshaw.Class.create( Rickshaw.Graph.Renderer, {
2310
2334
 
2311
- name: 'scatterplot',
2335
+ name: 'scatterplot',
2312
2336
 
2313
- defaults: function($super) {
2337
+ defaults: function($super) {
2314
2338
 
2315
- return Rickshaw.extend( $super(), {
2316
- unstack: true,
2317
- fill: true,
2318
- stroke: false,
2319
- padding:{ top: 0.01, right: 0.01, bottom: 0.01, left: 0.01 },
2320
- dotSize: 4
2321
- } );
2322
- },
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
+ },
2323
2347
 
2324
- initialize: function($super, args) {
2325
- $super(args);
2326
- },
2348
+ initialize: function($super, args) {
2349
+ $super(args);
2350
+ },
2327
2351
 
2328
- render: function() {
2352
+ render: function() {
2329
2353
 
2330
- var graph = this.graph;
2354
+ var graph = this.graph;
2331
2355
 
2332
- graph.vis.selectAll('*').remove();
2356
+ graph.vis.selectAll('*').remove();
2333
2357
 
2334
- graph.series.forEach( function(series) {
2358
+ graph.series.forEach( function(series) {
2335
2359
 
2336
- if (series.disabled) return;
2360
+ if (series.disabled) return;
2337
2361
 
2338
- var nodes = graph.vis.selectAll("path")
2339
- .data(series.stack)
2340
- .enter().append("svg:circle")
2341
- .attr("cx", function(d) { return graph.x(d.x) })
2342
- .attr("cy", function(d) { return graph.y(d.y) })
2343
- .attr("r", this.dotSize);
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);
2344
2368
 
2345
- Array.prototype.forEach.call(nodes[0], function(n) {
2346
- n.setAttribute('fill', series.color);
2347
- } );
2369
+ Array.prototype.forEach.call(nodes[0], function(n) {
2370
+ n.setAttribute('fill', series.color);
2371
+ } );
2348
2372
 
2349
- }, this );
2350
- }
2373
+ }, this );
2374
+ }
2351
2375
  } );
2352
2376
  Rickshaw.namespace('Rickshaw.Graph.Smoother');
2353
2377
 
2354
2378
  Rickshaw.Graph.Smoother = function(args) {
2355
2379
 
2356
- this.graph = args.graph;
2357
- this.element = args.element;
2380
+ this.graph = args.graph;
2381
+ this.element = args.element;
2358
2382
 
2359
- var self = this;
2383
+ var self = this;
2360
2384
 
2361
- this.aggregationScale = 1;
2385
+ this.aggregationScale = 1;
2362
2386
 
2363
- if (this.element) {
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
+ }
2364
2400
 
2365
- $( function() {
2366
- $(self.element).slider( {
2367
- min: 1,
2368
- max: 100,
2369
- slide: function( event, ui ) {
2370
- self.setScale(ui.value);
2371
- self.graph.update();
2372
- }
2373
- } );
2374
- } );
2375
- }
2401
+ self.graph.stackData.hooks.data.push( {
2402
+ name: 'smoother',
2403
+ orderPosition: 50,
2404
+ f: function(data) {
2376
2405
 
2377
- self.graph.stackData.hooks.data.push( {
2378
- name: 'smoother',
2379
- orderPosition: 50,
2380
- f: function(data) {
2406
+ var aggregatedData = [];
2381
2407
 
2382
- var aggregatedData = [];
2408
+ data.forEach( function(seriesData) {
2383
2409
 
2384
- data.forEach( function(seriesData) {
2385
-
2386
- var aggregatedSeriesData = [];
2410
+ var aggregatedSeriesData = [];
2387
2411
 
2388
- while (seriesData.length) {
2412
+ while (seriesData.length) {
2389
2413
 
2390
- var avgX = 0, avgY = 0;
2391
- var slice = seriesData.splice(0, self.aggregationScale);
2414
+ var avgX = 0, avgY = 0;
2415
+ var slice = seriesData.splice(0, self.aggregationScale);
2392
2416
 
2393
- slice.forEach( function(d) {
2394
- avgX += d.x / slice.length;
2395
- avgY += d.y / slice.length;
2396
- } );
2417
+ slice.forEach( function(d) {
2418
+ avgX += d.x / slice.length;
2419
+ avgY += d.y / slice.length;
2420
+ } );
2397
2421
 
2398
- aggregatedSeriesData.push( { x: avgX, y: avgY } );
2399
- }
2422
+ aggregatedSeriesData.push( { x: avgX, y: avgY } );
2423
+ }
2400
2424
 
2401
- aggregatedData.push(aggregatedSeriesData);
2402
- } );
2425
+ aggregatedData.push(aggregatedSeriesData);
2426
+ } );
2403
2427
 
2404
- return aggregatedData;
2405
- }
2406
- } );
2428
+ return aggregatedData;
2429
+ }
2430
+ } );
2407
2431
 
2408
- this.setScale = function(scale) {
2432
+ this.setScale = function(scale) {
2409
2433
 
2410
- if (scale < 1) {
2411
- throw "scale out of range: " + scale;
2412
- }
2434
+ if (scale < 1) {
2435
+ throw "scale out of range: " + scale;
2436
+ }
2413
2437
 
2414
- this.aggregationScale = scale;
2415
- this.graph.update();
2416
- }
2438
+ this.aggregationScale = scale;
2439
+ this.graph.update();
2440
+ }
2417
2441
  };
2418
2442
 
2419
2443
  Rickshaw.namespace('Rickshaw.Graph.Unstacker');
2420
2444
 
2421
2445
  Rickshaw.Graph.Unstacker = function(args) {
2422
2446
 
2423
- this.graph = args.graph;
2424
- var self = this;
2447
+ this.graph = args.graph;
2448
+ var self = this;
2425
2449
 
2426
- this.graph.stackData.hooks.after.push( {
2427
- name: 'unstacker',
2428
- f: function(data) {
2450
+ this.graph.stackData.hooks.after.push( {
2451
+ name: 'unstacker',
2452
+ f: function(data) {
2429
2453
 
2430
- if (!self.graph.renderer.unstack) return data;
2454
+ if (!self.graph.renderer.unstack) return data;
2431
2455
 
2432
- data.forEach( function(seriesData) {
2433
- seriesData.forEach( function(d) {
2434
- d.y0 = 0;
2435
- } );
2436
- } );
2456
+ data.forEach( function(seriesData) {
2457
+ seriesData.forEach( function(d) {
2458
+ d.y0 = 0;
2459
+ } );
2460
+ } );
2437
2461
 
2438
- return data;
2439
- }
2440
- } );
2462
+ return data;
2463
+ }
2464
+ } );
2441
2465
  };
2442
2466
 
2443
2467
  Rickshaw.namespace('Rickshaw.Series');
2444
2468
 
2445
2469
  Rickshaw.Series = Rickshaw.Class.create( Array, {
2446
2470
 
2447
- initialize: function (data, palette, options) {
2471
+ initialize: function (data, palette, options) {
2448
2472
 
2449
- options = options || {}
2473
+ options = options || {}
2450
2474
 
2451
- this.palette = new Rickshaw.Color.Palette(palette);
2475
+ this.palette = new Rickshaw.Color.Palette(palette);
2452
2476
 
2453
- this.timeBase = typeof(options.timeBase) === 'undefined' ?
2454
- Math.floor(new Date().getTime() / 1000) :
2455
- options.timeBase;
2477
+ this.timeBase = typeof(options.timeBase) === 'undefined' ?
2478
+ Math.floor(new Date().getTime() / 1000) :
2479
+ options.timeBase;
2456
2480
 
2457
- if (data && (typeof(data) == "object") && (data instanceof Array)) {
2458
- data.forEach( function(item) { this.addItem(item) }, this );
2459
- }
2460
- },
2481
+ if (data && (typeof(data) == "object") && (data instanceof Array)) {
2482
+ data.forEach( function(item) { this.addItem(item) }, this );
2483
+ }
2484
+ },
2461
2485
 
2462
- addItem: function(item) {
2486
+ addItem: function(item) {
2463
2487
 
2464
- if (typeof(item.name) === 'undefined') {
2465
- throw('addItem() needs a name');
2466
- }
2488
+ if (typeof(item.name) === 'undefined') {
2489
+ throw('addItem() needs a name');
2490
+ }
2467
2491
 
2468
- item.color = (item.color || this.palette.color(item.name));
2469
- item.data = (item.data || []);
2492
+ item.color = (item.color || this.palette.color(item.name));
2493
+ item.data = (item.data || []);
2470
2494
 
2471
- // backfill, if necessary
2472
- if ((item.data.length == 0) && this.length && (this.getIndex() > 0)) {
2473
- this[0].data.forEach( function(plot) {
2474
- item.data.push({ x: plot.x, y: 0 });
2475
- } );
2476
- } else if (item.data.length == 0) {
2477
- item.data.push({ x: this.timeBase - (this.timeInterval || 0), y: 0 });
2478
- }
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
+ }
2479
2503
 
2480
- this.push(item);
2504
+ this.push(item);
2481
2505
 
2482
- if (this.legend) {
2483
- this.legend.addLine(this.itemByName(item.name));
2484
- }
2485
- },
2506
+ if (this.legend) {
2507
+ this.legend.addLine(this.itemByName(item.name));
2508
+ }
2509
+ },
2486
2510
 
2487
- addData: function(data) {
2511
+ addData: function(data) {
2488
2512
 
2489
- var index = this.getIndex();
2513
+ var index = this.getIndex();
2490
2514
 
2491
- Rickshaw.keys(data).forEach( function(name) {
2492
- if (! this.itemByName(name)) {
2493
- this.addItem({ name: name });
2494
- }
2495
- }, this );
2515
+ Rickshaw.keys(data).forEach( function(name) {
2516
+ if (! this.itemByName(name)) {
2517
+ this.addItem({ name: name });
2518
+ }
2519
+ }, this );
2496
2520
 
2497
- this.forEach( function(item) {
2498
- item.data.push({
2499
- x: (index * this.timeInterval || 1) + this.timeBase,
2500
- y: (data[item.name] || 0)
2501
- });
2502
- }, this );
2503
- },
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
+ },
2504
2528
 
2505
- getIndex: function () {
2506
- return (this[0] && this[0].data && this[0].data.length) ? this[0].data.length : 0;
2507
- },
2529
+ getIndex: function () {
2530
+ return (this[0] && this[0].data && this[0].data.length) ? this[0].data.length : 0;
2531
+ },
2508
2532
 
2509
- itemByName: function(name) {
2533
+ itemByName: function(name) {
2510
2534
 
2511
- for (var i = 0; i < this.length; i++) {
2512
- if (this[i].name == name)
2513
- return this[i];
2514
- }
2515
- },
2535
+ for (var i = 0; i < this.length; i++) {
2536
+ if (this[i].name == name)
2537
+ return this[i];
2538
+ }
2539
+ },
2516
2540
 
2517
- setTimeInterval: function(iv) {
2518
- this.timeInterval = iv / 1000;
2519
- },
2541
+ setTimeInterval: function(iv) {
2542
+ this.timeInterval = iv / 1000;
2543
+ },
2520
2544
 
2521
- setTimeBase: function (t) {
2522
- this.timeBase = t;
2523
- },
2545
+ setTimeBase: function (t) {
2546
+ this.timeBase = t;
2547
+ },
2524
2548
 
2525
- dump: function() {
2549
+ dump: function() {
2526
2550
 
2527
- var data = {
2528
- timeBase: this.timeBase,
2529
- timeInterval: this.timeInterval,
2530
- items: [],
2531
- };
2551
+ var data = {
2552
+ timeBase: this.timeBase,
2553
+ timeInterval: this.timeInterval,
2554
+ items: [],
2555
+ };
2532
2556
 
2533
- this.forEach( function(item) {
2557
+ this.forEach( function(item) {
2534
2558
 
2535
- var newItem = {
2536
- color: item.color,
2537
- name: item.name,
2538
- data: []
2539
- };
2559
+ var newItem = {
2560
+ color: item.color,
2561
+ name: item.name,
2562
+ data: []
2563
+ };
2540
2564
 
2541
- item.data.forEach( function(plot) {
2542
- newItem.data.push({ x: plot.x, y: plot.y });
2543
- } );
2565
+ item.data.forEach( function(plot) {
2566
+ newItem.data.push({ x: plot.x, y: plot.y });
2567
+ } );
2544
2568
 
2545
- data.items.push(newItem);
2546
- } );
2569
+ data.items.push(newItem);
2570
+ } );
2547
2571
 
2548
- return data;
2549
- },
2572
+ return data;
2573
+ },
2550
2574
 
2551
- load: function(data) {
2575
+ load: function(data) {
2552
2576
 
2553
- if (data.timeInterval) {
2554
- this.timeInterval = data.timeInterval;
2555
- }
2577
+ if (data.timeInterval) {
2578
+ this.timeInterval = data.timeInterval;
2579
+ }
2556
2580
 
2557
- if (data.timeBase) {
2558
- this.timeBase = data.timeBase;
2559
- }
2581
+ if (data.timeBase) {
2582
+ this.timeBase = data.timeBase;
2583
+ }
2560
2584
 
2561
- if (data.items) {
2562
- data.items.forEach( function(item) {
2563
- this.push(item);
2564
- if (this.legend) {
2565
- this.legend.addLine(this.itemByName(item.name));
2566
- }
2567
-
2568
- }, this );
2569
- }
2570
- }
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
+ }
2571
2595
  } );
2572
2596
 
2573
2597
  Rickshaw.Series.zeroFill = function(series) {
2574
2598
 
2575
- var x;
2576
- var i = 0;
2599
+ var x;
2600
+ var i = 0;
2577
2601
 
2578
- var data = series.map( function(s) { return s.data } );
2602
+ var data = series.map( function(s) { return s.data } );
2579
2603
 
2580
- while ( i < Math.max.apply(null, data.map( function(d) { return d.length } )) ) {
2604
+ while ( i < Math.max.apply(null, data.map( function(d) { return d.length } )) ) {
2581
2605
 
2582
- x = Math.min.apply( null,
2583
- data
2584
- .filter(function(d) { return d[i] })
2585
- .map(function(d) { return d[i].x })
2586
- );
2606
+ x = Math.min.apply( null,
2607
+ data
2608
+ .filter(function(d) { return d[i] })
2609
+ .map(function(d) { return d[i].x })
2610
+ );
2587
2611
 
2588
- data.forEach( function(d) {
2589
- if (!d[i] || d[i].x != x) {
2590
- d.splice(i, 0, { x: x, y: 0 });
2591
- }
2592
- } );
2612
+ data.forEach( function(d) {
2613
+ if (!d[i] || d[i].x != x) {
2614
+ d.splice(i, 0, { x: x, y: 0 });
2615
+ }
2616
+ } );
2593
2617
 
2594
- i++;
2595
- }
2618
+ i++;
2619
+ }
2596
2620
  };
2597
2621
  Rickshaw.namespace('Rickshaw.Series.FixedDuration');
2598
2622
 
2599
2623
  Rickshaw.Series.FixedDuration = Rickshaw.Class.create(Rickshaw.Series, {
2600
2624
 
2601
- initialize: function (data, palette, options) {
2602
-
2603
- var options = options || {}
2625
+ initialize: function (data, palette, options) {
2604
2626
 
2605
- if (typeof(options.timeInterval) === 'undefined') {
2606
- throw new Error('FixedDuration series requires timeInterval');
2607
- }
2627
+ var options = options || {}
2608
2628
 
2609
- if (typeof(options.maxDataPoints) === 'undefined') {
2610
- throw new Error('FixedDuration series requires maxDataPoints');
2611
- }
2629
+ if (typeof(options.timeInterval) === 'undefined') {
2630
+ throw new Error('FixedDuration series requires timeInterval');
2631
+ }
2612
2632
 
2613
- this.palette = new Rickshaw.Color.Palette(palette);
2614
- this.timeBase = typeof(options.timeBase) === 'undefined' ? Math.floor(new Date().getTime() / 1000) : options.timeBase;
2615
- this.setTimeInterval(options.timeInterval);
2633
+ if (typeof(options.maxDataPoints) === 'undefined') {
2634
+ throw new Error('FixedDuration series requires maxDataPoints');
2635
+ }
2616
2636
 
2617
- if (this[0] && this[0].data && this[0].data.length) {
2618
- this.currentSize = this[0].data.length;
2619
- this.currentIndex = this[0].data.length;
2620
- } else {
2621
- this.currentSize = 0;
2622
- this.currentIndex = 0;
2623
- }
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);
2624
2640
 
2625
- this.maxDataPoints = options.maxDataPoints;
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
+ }
2626
2648
 
2649
+ this.maxDataPoints = options.maxDataPoints;
2627
2650
 
2628
- if (data && (typeof(data) == "object") && (data instanceof Array)) {
2629
- data.forEach( function (item) { this.addItem(item) }, this );
2630
- this.currentSize += 1;
2631
- this.currentIndex += 1;
2632
- }
2633
2651
 
2634
- // reset timeBase for zero-filled values if needed
2635
- this.timeBase -= (this.maxDataPoints - this.currentSize) * this.timeInterval;
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
+ }
2636
2657
 
2637
- // zero-fill up to maxDataPoints size if we don't have that much data yet
2638
- if ((typeof(this.maxDataPoints) !== 'undefined') && (this.currentSize < this.maxDataPoints)) {
2639
- for (var i = this.maxDataPoints - this.currentSize - 1; i > 0; i--) {
2640
- this.currentSize += 1;
2641
- this.currentIndex += 1;
2642
- this.forEach( function (item) {
2643
- item.data.unshift({ x: ((i-1) * this.timeInterval || 1) + this.timeBase, y: 0, i: i });
2644
- }, this );
2645
- }
2646
- }
2647
- },
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
+ },
2648
2672
 
2649
- addData: function($super, data) {
2673
+ addData: function($super, data) {
2650
2674
 
2651
- $super(data)
2675
+ $super(data)
2652
2676
 
2653
- this.currentSize += 1;
2654
- this.currentIndex += 1;
2677
+ this.currentSize += 1;
2678
+ this.currentIndex += 1;
2655
2679
 
2656
- if (this.maxDataPoints !== undefined) {
2657
- while (this.currentSize > this.maxDataPoints) {
2658
- this.dropData();
2659
- }
2660
- }
2661
- },
2680
+ if (this.maxDataPoints !== undefined) {
2681
+ while (this.currentSize > this.maxDataPoints) {
2682
+ this.dropData();
2683
+ }
2684
+ }
2685
+ },
2662
2686
 
2663
- dropData: function() {
2687
+ dropData: function() {
2664
2688
 
2665
- this.forEach(function(item) {
2666
- item.data.splice(0, 1);
2667
- } );
2689
+ this.forEach(function(item) {
2690
+ item.data.splice(0, 1);
2691
+ } );
2668
2692
 
2669
- this.currentSize -= 1;
2670
- },
2693
+ this.currentSize -= 1;
2694
+ },
2671
2695
 
2672
- getIndex: function () {
2673
- return this.currentIndex;
2674
- }
2696
+ getIndex: function () {
2697
+ return this.currentIndex;
2698
+ }
2675
2699
  } );
2676
2700