finalized new main chart with adaptive explorer on the chart
Costa Tsaousis (ktsaou) committed
Apr 24, 2014 at 02:18 UTC
8d1f0c2a1127b6eed0add0186417503fd18828bf
2 files changed
+203
-142
netdata.c
+23
-34
@@ -1103,14 +1103,12 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1103
if(group_count < 1) group_count = 1;
1104
// if(group_count > st->entries / 20) group_count = st->entries / 20;
1105
1106
- size_t printed = 0; // the lines of JSON data we have generated so far
1106
+ long printed = 0; // the lines of JSON data we have generated so far
1107
1108
- size_t current_entry = st->current_entry;
1109
- size_t t, lt; // t = the current entry, lt = the lest entry of data
1108
+ long stop_entry, current_entry = st->current_entry;
1109
1111
- RRD_DIMENSION *rd;
1112
- size_t c = 0; // counter for dimension loops
1113
- size_t dimensions = 0; // the total number of dimensions present
1110
+ int c = 0; // counter for dimension loops
1111
+ int dimensions = 0; // the total number of dimensions present
1112
1113
unsigned long long usec = 0;// usec between the entries
1114
char dtm[201]; // temp variable for storing dates
@@ -1118,6 +1116,7 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1116
int we_need_totals = 0; // if set, we should calculate totals for all dimensions
1117
1118
// find how many dimensions we have
1119
+ RRD_DIMENSION *rd;
1120
for( rd = st->dimensions ; rd ; rd = rd->next) {
1121
dimensions++;
1122
if(rd->type == RRD_DIMENSION_PCENT_OVER_DIFF_TOTAL || rd->type == RRD_DIMENSION_PCENT_OVER_ROW_TOTAL) we_need_totals++;
@@ -1141,11 +1140,14 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1140
for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++)
1141
group_values[c] = group_counts[c] = 0;
1142
1143
+ // print the labels
1144
wb->bytes += sprintf(&wb->buffer[wb->bytes], "{\n %scols%s:\n [\n", kq, kq);
1145
wb->bytes += sprintf(&wb->buffer[wb->bytes], " {%sid%s:%s%s,%slabel%s:%stime%s,%spattern%s:%s%s,%stype%s:%sdatetime%s},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq);
1146
wb->bytes += sprintf(&wb->buffer[wb->bytes], " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotation%s}},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
1147
wb->bytes += sprintf(&wb->buffer[wb->bytes], " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotationText%s}}", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
1148
1149
+ // print the header for each dimension
1150
+ // and update the print_hidden array for the dimensions that should be hidden
1151
for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
1152
if(rd->hidden)
1153
print_hidden[c] = 1;
@@ -1155,6 +1157,7 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1157
}
1158
}
1159
1160
+ // print the begin of row data
1161
wb->bytes += sprintf(&wb->buffer[wb->bytes], "\n ],\n %srows%s:\n [\n", kq, kq);
1162
1163
// make sure current_entry is within limits
@@ -1162,14 +1165,10 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1165
if(before == 0) before = st->times[current_entry].tv_sec;
1166
1167
// find the oldest entry of the round-robin
1165
- t = rrd_stats_first_entry(st);
1166
- lt = t;
1167
- size_t stop_entry = t;
1168
+ stop_entry = rrd_stats_first_entry(st);
1169
1170
// skip the oldest, to have incremental data
1170
- t++;
1171
- if(t >= st->entries) t = 0;
1172
- if(after == 0) after = st->times[t].tv_sec;
1171
+ if(after == 0) after = st->times[stop_entry].tv_sec;
1172
1173
// the minimum line length we expect
1174
int line_size = 4096 + (dimensions * 200);
@@ -1182,43 +1181,31 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1181
int normal_annotation_len = snprintf(normal_annotation, 200, ",{%sv%s:null},{%sv%s:null}", kq, kq, kq, kq);
1182
normal_annotation[200] = '\0';
1183
1185
- // count down of the entries examined so far
1186
- long count = ((before - after) / update_every) + 1;
1187
-
1184
// to allow grouping on the same values, we need a pad
1185
long pad = before % group_count;
1186
1187
// checks for debuging
1188
if(before < after)
1193
- error("WARNING: The newest value in the database (%lu) is earlier than the oldest (%lu)", before, after);
1189
+ debug(D_RRD_STATS, "WARNING: %s The newest value in the database (%lu) is earlier than the oldest (%lu)", st->name, before, after);
1190
1191
if((before - after) > st->entries * update_every)
1196
- error("WARNING: The time difference between the oldest and the newest entries (%lu) is higher than the capacity of the database (%lu)", before - after, st->entries * update_every);
1197
-
1198
- // we need these at the end for debugging
1199
- long count_start = count;
1200
- size_t t_start = t;
1192
+ debug(D_RRD_STATS, "WARNING: %s The time difference between the oldest and the newest entries (%lu) is higher than the capacity of the database (%lu)", st->name, before - after, st->entries * update_every);
1193
1202
- // the loop in dimension data
1194
+ // loop in dimension data
1195
int annotate_reset = 0;
1204
- for ( ; t != stop_entry && count >= 0 ; lt = t++) {
1196
+ long t = current_entry, lt = current_entry - 1, count; // t = the current entry, lt = the last entry of data
1197
+ if(lt < 0) lt = st->entries - 1;
1198
+ for (count = printed = 0; t != stop_entry ; t = lt--) {
1199
int print_this = 0;
1200
1207
- if(t >= st->entries) t = 0;
1201
+ if(lt < 0) lt = st->entries - 1;
1202
1203
// make sure we return data in the proper time range
1204
if(st->times[t].tv_sec < after || st->times[t].tv_sec > before) continue;
1211
- count--;
1212
-
1213
- // check if we may exceed the buffer provided
1214
- web_buffer_increase(wb, line_size);
1215
-
1216
- // prefer the most recent last entries
1217
- if(((count - pad) / group_count) >= entries_to_show) continue;
1205
+ count++;
1206
1207
// ok. we will use this entry!
1208
// find how much usec since the previous entry
1221
-
1209
usec = usecdiff(&st->times[t], &st->times[lt]);
1210
1211
if(((count - pad) % group_count) == 0) {
@@ -1227,6 +1214,9 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1214
break;
1215
}
1216
1217
+ // check if we may exceed the buffer provided
1218
+ web_buffer_increase(wb, line_size);
1219
+
1220
// generate the local date time
1221
struct tm *tm = localtime(&st->times[t].tv_sec);
1222
if(!tm) { error("localtime() failed."); continue; }
@@ -1327,8 +1317,7 @@ unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, siz
1317
if(printed) wb->bytes += sprintf(&wb->buffer[wb->bytes], "]}");
1318
wb->bytes += sprintf(&wb->buffer[wb->bytes], "\n ]\n}\n");
1319
1330
- if(!printed)
1331
- error("WARNING: NOTHING PRINTED: %s, after = %lu, before = %lu, diff = %lu, pad = %ld, count = %ld, entries_to_show = %lu, group_count = %lu, current_entry = %lu, t = %lu", st->name, after, before, before - after, pad, count_start, entries_to_show, group_count, current_entry, t_start);
1320
+ debug(D_RRD_STATS, "RRD_STATS_JSON: %s Generated %ld rows, total %ld bytes", st->name, printed, wb->bytes);
1321
1322
pthread_mutex_unlock(&st->mutex);
1323
return last_timestamp;
web/index.html
+180
-108
@@ -30,14 +30,15 @@
30
// Set a callback to run when the Google Visualization API is loaded.
31
google.setOnLoadCallback(initCharts);
32
33
- var TARGET_THUMB_GRAPH_WIDTH = 500; // chart width will range from 0.5 to 1.5 of that
34
- var MINIMUM_THUMB_GRAPH_WIDTH = 400; // chart will generally try to be wider than that
35
- var TARGET_THUMB_GRAPH_HEIGHT = 220;
36
- var MAINCHART_MAX_TIME_TO_SHOW = 600;
37
- var THUMBS_MAX_TIME_TO_SHOW = 600;
38
- var MAINCHART_CONTROL_HEIGHT = 100;
39
- var MAINCHART_CONTROL_DIVISOR = 1;
40
- var MAINCHART_POINTS_DIVISOR = 5;
33
+ var TARGET_THUMB_GRAPH_WIDTH = 500; // thumb charts width will range from 0.5 to 1.5 of that
34
+ var MINIMUM_THUMB_GRAPH_WIDTH = 400; // thumb chart will generally try to be wider than that
35
+ var TARGET_THUMB_GRAPH_HEIGHT = 220; // the height of the thumb charts
36
+ var THUMBS_MAX_TIME_TO_SHOW = 600; // how much time the thumb charts will present?
37
+
38
+ var MAINCHART_MAX_TIME_TO_SHOW = 600; // how much time the main chart will present by default?
39
+ var MAINCHART_POINTS_DIVISOR = 10; // how much detailed will the main chart be by default? 1 = finest, higher is faster
40
+ var MAINCHART_CONTROL_HEIGHT = 75; // how tall the control chart will be
41
+ var MAINCHART_CONTROL_DIVISOR = 2; // how much detailed will the control chart be? 1 = finest, higher is faster
42
43
var MODE_THUMBS = 1;
44
var MODE_MAIN = 2;
@@ -54,11 +55,11 @@
55
// ------------------------------------------------------------------------
56
// common HTML generation
57
57
- function chartIsLoadingHTML(width, height) { return "<table><tr><td align=\"center\" width=\"" + width + "\" height=\"" + height + "\" style=\"vertical-align:middle\"><h4><span class=\"glyphicon glyphicon-refresh\"></span><br/><br/>loading chart<br/><br/><span class=\"label label-default\">Please wait...</span></h4></td></tr></table>"; }
58
+ function chartIsLoadingHTML(name, width, height) { return "<table><tr><td align=\"center\" width=\"" + width + "\" height=\"" + height + "\" style=\"vertical-align:middle\"><h4><span class=\"glyphicon glyphicon-refresh\"></span><br/><br/>loading " + name + "<br/><br/><span class=\"label label-default\">Please wait...</span></h4></td></tr></table>"; }
59
59
- function showChartIsLoading(id, width, height) {
60
+ function showChartIsLoading(id, name, width, height) {
61
//mylog('adding loading chart html in div with id ' + id);
61
- document.getElementById(id).innerHTML = chartIsLoadingHTML(width, height);
62
+ document.getElementById(id).innerHTML = chartIsLoadingHTML(name, width, height);
63
}
64
65
function thumbChartActions(i, c, nogroup) {
@@ -119,36 +120,43 @@
120
var dt = before - after;
121
if(dt > c.entries * c.update_every) dt = c.entries * c.update_every;
122
122
- if(maxtime && dt > maxtime) dt = maxtime;
123
+ if(maxtime) dt = maxtime;
124
124
- var data_points = dt / c.update_every;
125
+ var data_points = Math.round(dt / c.update_every);
126
var screen_points = Math.round(c.chartOptions.width / divisor);
127
+ //mylog('screen = ' + screen_points + ', data = ' + data_points + ', divisor = ' + divisor);
128
127
- if(!group) {
129
+ if(group <= 0) {
130
if(screen_points > data_points) {
131
c.group = 1;
132
c.points_to_show = data_points;
133
+ //mylog("rendering at full detail");
134
}
135
else {
136
c.group = Math.round(data_points / screen_points);
137
135
- if(c.group > 60) c.group = 60;
136
- else if(c.group > 45) c.group = 45;
137
- else if(c.group > 30) c.group = 30;
138
- else if(c.group > 20) c.group = 20;
139
- else if(c.group > 15) c.group = 15;
140
- else if(c.group > 10) c.group = 10;
141
- else if(c.group > 5) c.group = 5;
142
- else if(c.group > 2) c.group = 2;
143
- else c.group = 1;
138
+ if(group >= 0) {
139
+ if(c.group > 60) c.group = 60;
140
+ else if(c.group > 45) c.group = 45;
141
+ else if(c.group > 30) c.group = 30;
142
+ else if(c.group > 20) c.group = 20;
143
+ else if(c.group > 15) c.group = 15;
144
+ else if(c.group > 10) c.group = 10;
145
+ else if(c.group > 5) c.group = 5;
146
+ else if(c.group > 2) c.group = 2;
147
+ else c.group = 1;
148
+ }
149
150
c.points_to_show = Math.round(data_points / c.group);
151
+ //mylog("rendering adaptive");
152
}
153
}
154
else {
155
c.group = group;
156
c.points_to_show = Math.round(data_points / group);
157
+ //mylog("rendering with given group");
158
}
159
+ //mylog('group = ' + c.group + ', points = ' + c.points_to_show);
160
161
if(mainchart.chartType == 'LineChart') {
162
if(mainchart.group <= 2) mainchart.chartOptions.lineWidth = 1;
@@ -162,21 +170,26 @@
170
if(mainchart) cleanThisChart(mainchart);
171
172
mainchart = $.extend(true, {}, c);
165
- var tempchart = $.extend(true, {}, mainchart);
166
-
173
+ mainchart.refreshCount = 0;
174
+ mainchart.last_updated = 0;
175
+ mainchart.chartOptions.explorer = null;
176
mainchart.chart = null;
177
+
178
mainchart.chartOptions.width = screenWidth();
179
mainchart.chartOptions.height = $(window).height() - 150 - MAINCHART_CONTROL_HEIGHT;
180
if(mainchart.chartOptions.height < 300) mainchart.chartOptions.height = 300;
181
+ //mainchart.chartOptions.chartArea = {'width': '80%'};
182
183
mainchart.div = 'maingraph';
173
- mainchart.last_updated = 0;
174
-
184
calculateChartGroup(mainchart, MAINCHART_POINTS_DIVISOR, MAINCHART_MAX_TIME_TO_SHOW, 0);
176
- mainchart.chartOptions.explorer = null;
185
+
186
+ // copy it to the hidden chart
187
+ mainchart.hiddenchart = $.extend(true, {}, mainchart);
188
+ mainchart.hiddenchart.chartOptions.height = MAINCHART_CONTROL_HEIGHT;
189
+ mainchart.hiddenchart.div = 'maingraph_control';
190
191
// initialize the div
179
- showChartIsLoading(mainchart.div, mainchart.chartOptions.width, mainchart.chartOptions.height);
192
+ showChartIsLoading(mainchart.div, mainchart.name, mainchart.chartOptions.width, mainchart.chartOptions.height);
193
194
// set the radio buttons
195
setMainChartGroupMethod(mainchart.group_method, 'no-refresh');
@@ -185,48 +198,76 @@
198
$('#group' + mainchart.group).trigger('click');
199
setMainChartGroup(mainchart.group, 'no-refresh');
200
188
- var controlopts = $.extend(true, {}, mainchart.chartOptions, {
189
- lineWidth: 1,
190
- height: MAINCHART_CONTROL_HEIGHT,
191
- chartArea: {'width': '90%'},
192
- hAxis: {'baselineColor': 'none'},
193
- vAxis: {'title': null},
194
- });
201
+ switchToMainGraph();
202
+ }
203
196
- mainchart.dashboard = new google.visualization.Dashboard(document.getElementById('maingraph_dashboard'));
197
- mainchart.control = new google.visualization.ControlWrapper({
198
- controlType: 'ChartRangeFilter',
199
- containerId: 'maingraph_control',
200
- options: {
201
- filterColumnIndex: 0,
202
- ui: {
203
- chartType: mainchart.chartType,
204
- chartOptions: controlopts,
205
- minRangeSize: MAINCHART_MAX_TIME_TO_SHOW * mainchart.update_every / MAINCHART_POINTS_DIVISOR * 1000,
206
- }
207
- },
208
- });
209
- mainchart.hiddenchart = new google.visualization.ChartWrapper({
210
- chartType: mainchart.chartType,
211
- containerId: 'maingraph_hidden',
212
- options: {
213
- isStacked: mainchart.chartOptions.isStacked,
214
- width: mainchart.chartOptions.width,
215
- height: mainchart.chartOptions.height,
216
- //chartArea: {'height': '80%', 'width': '100%'},
217
- //hAxis: {'slantedText': false},
218
- //legend: {'position': 'none'}
219
- },
220
- });
204
+ function refreshHiddenChart(doNext) {
205
+ if(refresh_mode == REFRESH_PAUSED && mainchart.hiddenchart.last_updated != 0) {
206
+ if(typeof doNext == "function") doNext();
207
+ return;
208
+ }
209
+
210
+ // is it too soon for a refresh?
211
+ var now = new Date().getTime();
212
+ if((now - mainchart.hiddenchart.last_updated) < (mainchart.hiddenchart.group * mainchart.hiddenchart.update_every * 1000)) {
213
+ if(typeof doNext == "function") doNext();
214
+ return;
215
+ }
216
222
- // load the data for the control and the hidden chart
223
- calculateChartGroup(tempchart, MAINCHART_CONTROL_DIVISOR, 0, 0);
224
- // alert("diff = " + (tempchart.before - tempchart.after) + ", group = " + tempchart.group);
217
+ if(mainchart.dashboard && mainchart.hiddenchart.refreshCount > 50) {
218
+ mainchart.dashboard.clear();
219
+ mainchart.control_wrapper.clear();
220
+ mainchart.hidden_wrapper.clear();
221
226
- switchToMainGraph();
222
+ mainchart.dashboard = null;
223
+ mainchart.control_wrapper = null;
224
+ mainchart.hidden_wrapper = null;
225
+ }
226
+
227
+ if(!mainchart.dashboard) {
228
+ var controlopts = $.extend(true, {}, mainchart.chartOptions, {
229
+ lineWidth: 1,
230
+ height: mainchart.hiddenchart.chartOptions.height,
231
+ chartArea: {'width': '98%'},
232
+ hAxis: {'baselineColor': 'none'},
233
+ vAxis: {'title': null},
234
+ });
235
+
236
+ mainchart.dashboard = new google.visualization.Dashboard(document.getElementById('maingraph_dashboard'));
237
+ mainchart.control_wrapper = new google.visualization.ControlWrapper({
238
+ controlType: 'ChartRangeFilter',
239
+ containerId: 'maingraph_control',
240
+ options: {
241
+ filterColumnIndex: 0,
242
+ ui: {
243
+ chartType: mainchart.chartType,
244
+ chartOptions: controlopts,
245
+ minRangeSize: (MAINCHART_MAX_TIME_TO_SHOW * 1000 * mainchart.update_every) / MAINCHART_POINTS_DIVISOR,
246
+ }
247
+ },
248
+ });
249
+ mainchart.hidden_wrapper = new google.visualization.ChartWrapper({
250
+ chartType: mainchart.chartType,
251
+ containerId: 'maingraph_hidden',
252
+ options: {
253
+ isStacked: mainchart.chartOptions.isStacked,
254
+ width: mainchart.hiddenchart.chartOptions.width,
255
+ height: mainchart.hiddenchart.chartOptions.height,
256
+ //chartArea: {'height': '80%', 'width': '100%'},
257
+ //hAxis: {'slantedText': false},
258
+ //legend: {'position': 'none'}
259
+ },
260
+ });
261
+
262
+ mainchart.hiddenchart.refreshCount = 0;
263
+ }
264
+
265
+ // load the data for the control and the hidden wrappers
266
+ // calculate the group and points to show for the control chart
267
+ calculateChartGroup(mainchart.hiddenchart, MAINCHART_CONTROL_DIVISOR, 0, -1);
268
269
$.ajax({
229
- url: generateChartURL(tempchart),
270
+ url: generateChartURL(mainchart.hiddenchart),
271
dataType:"json",
272
cache: false
273
})
@@ -235,30 +276,44 @@
276
277
mainchart.control_data = new google.visualization.DataTable(jsondata);
278
238
- google.visualization.events.addListener(mainchart.control, 'ready', mainchartControlReadyEvent);
239
- mainchart.dashboard.bind(mainchart.control, mainchart.hiddenchart);
279
+ if(mainchart.hiddenchart.last_updated == 0) {
280
+ google.visualization.events.addListener(mainchart.control_wrapper, 'ready', mainchartControlReadyEvent);
281
+ mainchart.dashboard.bind(mainchart.control_wrapper, mainchart.hidden_wrapper);
282
+ }
283
+ if(refresh_mode != REFRESH_PAUSED)
284
+ mainchart.control_wrapper.setState({range: {
285
+ start: new Date((Math.round(new Date().getTime() / 1000) - MAINCHART_MAX_TIME_TO_SHOW) * 1000),
286
+ end: new Date()
287
+ }});
288
+
289
mainchart.dashboard.draw(mainchart.control_data);
290
+ mainchart.hiddenchart.last_updated = new Date().getTime();
291
+ mainchart.hiddenchart.refreshCount++;
292
+ })
293
+ .always(function() {
294
+ if(typeof doNext == "function") doNext();
295
});
296
}
297
298
function mainchartControlReadyEvent() {
245
- google.visualization.events.addListener(mainchart.control, 'statechange', mainchartControlStateHandler);
299
+ google.visualization.events.addListener(mainchart.control_wrapper, 'statechange', mainchartControlStateHandler);
300
+ //mylog(mainchart);
301
}
302
303
function mainchartControlStateHandler() {
304
// setMainChartPlay('pause');
305
251
- var state = mainchart.control.getState();
306
+ var state = mainchart.control_wrapper.getState();
307
mainchart.after = Math.round(state.range.start.getTime() / 1000);
308
mainchart.before = Math.round(state.range.end.getTime() / 1000);
309
310
calculateChartGroup(mainchart, MAINCHART_POINTS_DIVISOR, 0, 0);
256
- console.log('group = ' + mainchart.group + ', points_to_show = ' + mainchart.points_to_show + ', dt = ' + (mainchart.before - mainchart.after));
311
+ //mylog('group = ' + mainchart.group + ', points_to_show = ' + mainchart.points_to_show + ', dt = ' + (mainchart.before - mainchart.after));
312
313
$('#group' + mainchart.group).trigger('click');
314
mainchart.last_updated = 0;
315
261
- if(refresh_mode != REFRESH_ZOOMED) zoomGraphs();
316
+ if(refresh_mode != REFRESH_PAUSED) pauseGraphs();
317
}
318
319
function initMainChartIndex(i) {
@@ -308,7 +363,6 @@
363
364
if(!norefresh) {
365
mainchart.last_updated = 0;
311
- if(refresh_mode == REFRESH_PAUSED) playGraphs();
366
}
367
}
368
@@ -327,7 +381,6 @@
381
382
if(!norefresh) {
383
mainchart.last_updated = 0;
330
- if(refresh_mode == REFRESH_PAUSED) playGraphs();
384
}
385
386
last_main_chart_avg = g;
@@ -415,8 +468,13 @@
468
469
if(mainchart) {
470
mainchart.chartOptions.width = width;
418
- mainchart.chartOptions.height = $(window).height() - 200;
471
+ mainchart.chartOptions.height = $(window).height() - 150 - MAINCHART_CONTROL_HEIGHT;
472
mainchart.last_updated = 0;
473
+
474
+ mainchart.hidden_wrapper.setOption('width', width);
475
+ mainchart.control_wrapper.setOption('ui.chartOptions.width', width);
476
+ mainchart.hiddenchart.chartOptions.width = width;
477
+ mainchart.hiddenchart.last_updated = 0;
478
}
479
480
width = thumbWidth();
@@ -424,7 +482,7 @@
482
if(c.enabled && c.chartOptions.width != width) {
483
cleanThisChart(c);
484
c.chartOptions.width = width;
427
- showChartIsLoading(c.div, c.chartOptions.width, c.chartOptions.height);
485
+ showChartIsLoading(c.div, c.name, c.chartOptions.width, c.chartOptions.height);
486
c.last_updated = 0;
487
}
488
});
@@ -436,7 +494,7 @@
494
cleanThisChart(c);
495
c.chartOptions.width = sizes.width;
496
c.chartOptions.height = sizes.height;
439
- showChartIsLoading(c.div, c.chartOptions.width, c.chartOptions.height);
497
+ showChartIsLoading(c.div, c.name, c.chartOptions.width, c.chartOptions.height);
498
c.last_updated = 0;
499
}
500
});
@@ -453,62 +511,55 @@
511
512
var REFRESH_PAUSED = 0;
513
var REFRESH_ALWAYS = 1;
456
- var REFRESH_ZOOMED = 2;
514
515
var refresh_mode = REFRESH_PAUSED;
516
var last_refresh = 0;
517
function playGraphs() {
461
- if(refresh_mode != REFRESH_PAUSED) {
462
- // check if the thread died due to a javascript error
463
- var now = new Date().getTime();
464
- if((now - last_refresh) > 5000) {
465
- // it died!
466
- //mylog('It seems the refresh thread died. Restarting it.');
467
- chartsRefresh();
468
- }
469
- return;
470
- }
518
+ if(refresh_mode == REFRESH_ALWAYS) return;
519
520
+ //mylog('PlayGraphs()');
521
refresh_mode = REFRESH_ALWAYS;
522
$('.mainchart_play_button').button('play');
474
- chartsRefresh();
523
+
524
+ // check if the thread died due to a javascript error
525
+ var now = new Date().getTime();
526
+ if((now - last_refresh) > 5000) {
527
+ // it died or never started
528
+ //mylog('It seems the refresh thread died. Restarting it.');
529
+ chartsRefresh();
530
+ }
531
}
532
533
function pauseGraphs() {
534
if(refresh_mode == REFRESH_PAUSED) return;
535
536
+ //mylog('PauseGraphs()');
537
refresh_mode = REFRESH_PAUSED;
538
$('.mainchart_play_button').button('pause');
539
}
540
484
- function zoomGraphs() {
485
- if(refresh_mode == REFRESH_ZOOMED) return;
486
-
487
- refresh_mode = REFRESH_ZOOMED;
488
- $('.mainchart_play_button').button('pause');
489
- }
490
-
541
// refresh the proper chart
542
// this is an internal function.
543
// never call it directly, or new javascript threads will be spawn
544
var timeout;
495
- var refresh_count = 0;
545
function chartsRefresh() {
497
- refresh_count++;
498
-
546
if(resize_request) {
547
resizeCharts();
548
resize_request = false;
502
- refresh_mode = REFRESH_ALWAYS;
549
+ // refresh_mode = REFRESH_ALWAYS;
550
}
551
552
+ last_refresh = new Date().getTime();
553
+
554
if(refresh_mode == REFRESH_PAUSED) {
506
- //mylog("stop refresh");
555
+ if(mode == MODE_MAIN && mainchart.last_updated == 0)
556
+ mainChartRefresh();
557
+ else
558
+ timeout = setTimeout(chartsRefresh, 500);
559
+
560
return;
561
}
562
510
- last_refresh = new Date().getTime();
511
-
563
if(mode == MODE_THUMBS) thumbChartsRefresh();
564
else if(mode == MODE_GROUP_THUMBS) groupChartsRefresh();
565
else if(mode == MODE_MAIN) mainChartRefresh();
@@ -519,7 +570,7 @@
570
// this is an internal function.
571
// never call it directly, or new javascript threads will be spawn
572
function triggerRefresh() {
522
- //mylog('triggerRefresh(' + refresh_count + ')');
573
+ //mylog('triggerRefresh()');
574
575
// cleanup has to take place when the charts are not refreshed
576
// since the refreshing thread is in this function, it means
@@ -542,8 +593,12 @@
593
return;
594
}
595
545
- if(!refreshChart(mainchart, triggerRefresh))
546
- triggerRefresh();
596
+ if(!refreshChart(mainchart, hiddenChartRefresh))
597
+ hiddenChartRefresh();
598
+ }
599
+
600
+ function hiddenChartRefresh() {
601
+ refreshHiddenChart(triggerRefresh);
602
}
603
604
function roundRobinRefresh(charts, startat) {
@@ -639,6 +694,23 @@
694
function cleanThisChart(chart, emptydivs) {
695
//mylog('cleanThisChart(' + chart.name + ', ' + emptydivs +')');
696
697
+ if(chart.dashboard) {
698
+ chart.dashboard.clear();
699
+ chart.dashboard = null;
700
+
701
+ if(chart.control_wrapper) {
702
+ chart.control_wrapper.clear();
703
+ chart.control_wrapper = null;
704
+ }
705
+
706
+ if(chart.hidden_wrapper) {
707
+ chart.hidden_wrapper.clear();
708
+ chart.hidden_wrapper = null;
709
+ }
710
+
711
+ chart.control_data = null;
712
+ }
713
+
714
if(chart.chart) chart.chart.clearChart();
715
chart.chart = null;
716
@@ -794,7 +866,7 @@
866
c.chartOptions.width = sizes.width;
867
c.chartOptions.height = sizes.height;
868
797
- groupbody += "<div class=\"thumbgraph\" id=\"" + c.div + "_parent\"><table><tr><td><div class=\"thumbgraph\" id=\"" + c.div + "\">" + chartIsLoadingHTML(c.chartOptions.width, c.chartOptions.height) + "</div></td></tr><tr><td align=\"center\">" + thumbChartActions(i, c, 'nogroup') + "</td></tr></table></div>";
869
+ groupbody += "<div class=\"thumbgraph\" id=\"" + c.div + "_parent\"><table><tr><td><div class=\"thumbgraph\" id=\"" + c.div + "\">" + chartIsLoadingHTML(c.name, c.chartOptions.width, c.chartOptions.height) + "</div></td></tr><tr><td align=\"center\">" + thumbChartActions(i, c, 'nogroup') + "</td></tr></table></div>";
870
});
871
groupbody += "";
872
@@ -858,7 +930,7 @@
930
931
if(c.enabled) {
932
var j;
861
- var h = "<div class=\"thumbgraph\" id=\"" + c.div + "_parent\"><table><tr><td><div class=\"thumbgraph\" id=\"" + c.div + "\">" + chartIsLoadingHTML(c.chartOptions.width, c.chartOptions.height) + "</div></td></tr><tr><td align=\"center\">"
933
+ var h = "<div class=\"thumbgraph\" id=\"" + c.div + "_parent\"><table><tr><td><div class=\"thumbgraph\" id=\"" + c.div + "\">" + chartIsLoadingHTML(c.name, c.chartOptions.width, c.chartOptions.height) + "</div></td></tr><tr><td align=\"center\">"
934
+ thumbChartActions(i, c)
935
+ "</td></tr></table></div>";
936