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