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