Completed LuCI Livestats
[project/luci.git] / applications / luci-livestats / htdocs / luci-static / resources / livestats / GraphRPC.js
1 function Graph(container, id, options, transform, legend) {
2         if( !options ) options = { };
3
4         this.id        = id;
5         this.cols      = 100;
6         this.type      = "line";
7         this.options   = options;
8         this.transform = transform;
9         this.dataset   = {};
10         this.legend    = legend;
11         this.lastvalue = {};
12         
13         var name  = (options.instanceNames && options.instanceNames[id])
14                 ? options.instanceNames[id] : id;
15         var graph = document.createElement('div');
16         var label = document.createElement('h2');
17                 label.innerHTML = options.title
18                         ? options.title.replace("%s", name) : name;
19
20         container.appendChild( label );
21         container.appendChild( graph );
22
23         this.canvas = document.createElement('canvas');
24         graph.appendChild( this.canvas );
25
26         this.canvas.id = id;
27         this.canvas.width  = ( options.width  || graph.offsetWidth - 20 );
28         this.canvas.height = ( options.height || 300 );
29 }
30
31 Graph.prototype.addDataset = function(name, ds) {
32         if( !this.layout ) {
33                 this.layout = new PlotKit.Layout( this.type, this.options );
34         }
35
36         if( !ds ) {
37                 ds = new Array();
38                 for( var i = 0; i < this.cols; i++ )
39                         ds[i] = new Array( i, 0 );
40         }
41
42         this.dataset[name] = ds;
43         this.layout.addDataset(name, ds);
44 }
45
46 Graph.prototype.updateDataset = function(name, value) {
47         if( this.dataset[name] ) {
48                 var ds = this.dataset[name];
49
50                 for( var i = 1; i < this.cols; i++ )
51                         ds[i-1][1] = ds[i][1];
52
53                 value = Math.abs( parseFloat(value) || 0 );
54
55                 if( this.transform ) {
56                         var orgvalue = value;
57                         value = (this.lastvalue[name]) ? this.transform(value, this.lastvalue[name]) : 0;
58                         this.lastvalue[name] = orgvalue;
59                 }
60
61                 ds[this.cols-1][1] = value;
62                 this.layout.addDataset(name, ds);
63         }
64 }
65
66 Graph.prototype.draw = function( options ) {
67         if( this.layout ) {
68                 this.plotter = new PlotKit.CanvasRenderer(
69                         this.canvas, this.layout, this.options || options || {}
70                 );
71
72                 this.layout.evaluate();
73                 this.plotter.render();
74
75                 legend_opt = {
76                         "legendStyle": 'li'
77                 };
78
79                 legend = new LegendRenderer(this.legend, this.layout, legend_opt);
80                 legend.render();
81         }
82 }
83
84 Graph.prototype.redraw = function() {
85         if( this.layout && this.plotter ) {
86                 this.layout.evaluate();
87                 this.plotter.clear();
88                 this.plotter.render();
89         }
90 }
91
92
93 function GraphRPC(container, uri, action, interval, datasources, options, transform, legend) {
94         this.ds        = datasources;
95         this.uri       = uri
96         this.action    = action;
97         this.options   = options || { };
98         this.container = container;
99         this.transform = transform;
100         this.proxy     = new MochiKit.JsonRpc.JsonRpcProxy(uri, [action]);
101         this.graphs    = new Object();
102         this.legend    = legend;
103
104         this.requestData();
105
106         if( interval ) {
107                 var self = this;
108                 window.setInterval(function(){self.requestData()}, interval);
109         }
110 }
111
112 GraphRPC.prototype.requestData = function() {
113         var r = this.proxy[this.action](); var self = this;
114         r.addCallback(function(r){ self.dispatchResponse(r) });
115         r.addErrback(function(e){ throw('Error: ' + e) });
116 }
117
118 GraphRPC.prototype.dispatchResponse = function(response) {
119         var instances;
120         if( this.options.instances ) {
121                 instances = this.options.instances;
122         }
123         else {
124                 instances = new Array();
125                 for( var instance in response ) {
126                         instances[instances.length] = instance;
127                 }
128         }
129
130         for( var j = 0; j < instances.length; j++ ) {
131                 var instance = instances[j];
132
133                 if( this.options.separateDS ) {
134                         for( var i = 0; i < this.ds.length; i += 2 ) {
135                                 var name = this.ds[i+1] || this.ds[i];
136                                 var gid  = instance + '-' + name;
137                                 var otle = this.options.title || instance;
138
139                                 if( !this.graphs[gid] ) {
140                                         this.options.title = otle.replace('%s', instance) + ': ' + name;
141                                         this.graphs[gid] = new Graph(
142                                                 this.container, gid, this.options, this.transform, this.legend
143                                         );
144
145                                         this.graphs[gid].addDataset(name);
146                                         this.graphs[gid].draw();
147                                         this.options.title = otle;
148                                 }
149                                 else
150                                 {
151                                         var datum = null;
152                                         if (typeof (this.ds[i]) == "function") {
153                                                 datum = this.ds[i](
154                                                         instance ? response[instance] : response
155                                                 );
156                                         } else {
157                                                 datum = instance
158                                                         ? response[instance][this.ds[i]]
159                                                         : response[this.ds[i]]
160                                         }
161                                         this.graphs[gid].updateDataset(
162                                                 name, datum
163                                         );
164                                         this.graphs[gid].redraw();
165                                 }
166                         }
167                 }
168                 else {
169                         var gid = instance || 'livegraph';
170                         if( !this.graphs[gid] ) {
171                                 this.graphs[gid] = new Graph(
172                                         this.container, gid, this.options, this.transform, this.legend
173                                 );
174
175                                 for( var i = 0; i < this.ds.length; i += 2 ) {
176                                         var name = this.ds[i+1] || this.ds[i];
177                                         this.graphs[gid].addDataset(name);
178                                 }
179
180                                 this.graphs[gid].draw();
181                         }
182                         else {
183                                 for( var i = 0; i < this.ds.length; i += 2 ) {
184                                         var name = this.ds[i+1] || this.ds[i];
185                                         var datum = null;
186                                         if (typeof (this.ds[i]) == "function") {
187                                                 datum = this.ds[i](
188                                                         instance ? response[instance] : response
189                                                 );
190                                         } else {
191                                                 datum = instance
192                                                         ? response[instance][this.ds[i]]
193                                                         : response[this.ds[i]]
194                                         }
195                                         this.graphs[gid].updateDataset(
196                                                 name, datum
197                                         );
198                                 }
199
200                                 this.graphs[gid].redraw();
201                         }
202                 }
203         }
204 }