if(group_count < 1) group_count = 1;
// if(group_count > st->entries / 20) group_count = st->entries / 20;
- size_t printed = 0; // the lines of JSON data we have generated so far
+ long printed = 0; // the lines of JSON data we have generated so far
- size_t current_entry = st->current_entry;
- size_t t, lt; // t = the current entry, lt = the lest entry of data
+ long stop_entry, current_entry = st->current_entry;
- RRD_DIMENSION *rd;
- size_t c = 0; // counter for dimension loops
- size_t dimensions = 0; // the total number of dimensions present
+ int c = 0; // counter for dimension loops
+ int dimensions = 0; // the total number of dimensions present
unsigned long long usec = 0;// usec between the entries
char dtm[201]; // temp variable for storing dates
int we_need_totals = 0; // if set, we should calculate totals for all dimensions
// find how many dimensions we have
+ RRD_DIMENSION *rd;
for( rd = st->dimensions ; rd ; rd = rd->next) {
dimensions++;
if(rd->type == RRD_DIMENSION_PCENT_OVER_DIFF_TOTAL || rd->type == RRD_DIMENSION_PCENT_OVER_ROW_TOTAL) we_need_totals++;
for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++)
group_values[c] = group_counts[c] = 0;
+ // print the labels
wb->bytes += sprintf(&wb->buffer[wb->bytes], "{\n %scols%s:\n [\n", kq, kq);
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);
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);
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);
+ // print the header for each dimension
+ // and update the print_hidden array for the dimensions that should be hidden
for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
if(rd->hidden)
print_hidden[c] = 1;
}
}
+ // print the begin of row data
wb->bytes += sprintf(&wb->buffer[wb->bytes], "\n ],\n %srows%s:\n [\n", kq, kq);
// make sure current_entry is within limits
if(before == 0) before = st->times[current_entry].tv_sec;
// find the oldest entry of the round-robin
- t = rrd_stats_first_entry(st);
- lt = t;
- size_t stop_entry = t;
+ stop_entry = rrd_stats_first_entry(st);
// skip the oldest, to have incremental data
- t++;
- if(t >= st->entries) t = 0;
- if(after == 0) after = st->times[t].tv_sec;
+ if(after == 0) after = st->times[stop_entry].tv_sec;
// the minimum line length we expect
int line_size = 4096 + (dimensions * 200);
int normal_annotation_len = snprintf(normal_annotation, 200, ",{%sv%s:null},{%sv%s:null}", kq, kq, kq, kq);
normal_annotation[200] = '\0';
- // count down of the entries examined so far
- long count = ((before - after) / update_every) + 1;
-
// to allow grouping on the same values, we need a pad
long pad = before % group_count;
// checks for debuging
if(before < after)
- error("WARNING: The newest value in the database (%lu) is earlier than the oldest (%lu)", before, after);
+ debug(D_RRD_STATS, "WARNING: %s The newest value in the database (%lu) is earlier than the oldest (%lu)", st->name, before, after);
if((before - after) > st->entries * update_every)
- 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);
-
- // we need these at the end for debugging
- long count_start = count;
- size_t t_start = t;
+ 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);
- // the loop in dimension data
+ // loop in dimension data
int annotate_reset = 0;
- for ( ; t != stop_entry && count >= 0 ; lt = t++) {
+ long t = current_entry, lt = current_entry - 1, count; // t = the current entry, lt = the last entry of data
+ if(lt < 0) lt = st->entries - 1;
+ for (count = printed = 0; t != stop_entry ; t = lt--) {
int print_this = 0;
- if(t >= st->entries) t = 0;
+ if(lt < 0) lt = st->entries - 1;
// make sure we return data in the proper time range
if(st->times[t].tv_sec < after || st->times[t].tv_sec > before) continue;
- count--;
-
- // check if we may exceed the buffer provided
- web_buffer_increase(wb, line_size);
-
- // prefer the most recent last entries
- if(((count - pad) / group_count) >= entries_to_show) continue;
+ count++;
// ok. we will use this entry!
// find how much usec since the previous entry
-
usec = usecdiff(&st->times[t], &st->times[lt]);
if(((count - pad) % group_count) == 0) {
break;
}
+ // check if we may exceed the buffer provided
+ web_buffer_increase(wb, line_size);
+
// generate the local date time
struct tm *tm = localtime(&st->times[t].tv_sec);
if(!tm) { error("localtime() failed."); continue; }
if(printed) wb->bytes += sprintf(&wb->buffer[wb->bytes], "]}");
wb->bytes += sprintf(&wb->buffer[wb->bytes], "\n ]\n}\n");
- if(!printed)
- 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);
+ debug(D_RRD_STATS, "RRD_STATS_JSON: %s Generated %ld rows, total %ld bytes", st->name, printed, wb->bytes);
pthread_mutex_unlock(&st->mutex);
return last_timestamp;
// Set a callback to run when the Google Visualization API is loaded.
google.setOnLoadCallback(initCharts);
- var TARGET_THUMB_GRAPH_WIDTH = 500; // chart width will range from 0.5 to 1.5 of that
- var MINIMUM_THUMB_GRAPH_WIDTH = 400; // chart will generally try to be wider than that
- var TARGET_THUMB_GRAPH_HEIGHT = 220;
- var MAINCHART_MAX_TIME_TO_SHOW = 600;
- var THUMBS_MAX_TIME_TO_SHOW = 600;
- var MAINCHART_CONTROL_HEIGHT = 100;
- var MAINCHART_CONTROL_DIVISOR = 1;
- var MAINCHART_POINTS_DIVISOR = 5;
+ var TARGET_THUMB_GRAPH_WIDTH = 500; // thumb charts width will range from 0.5 to 1.5 of that
+ var MINIMUM_THUMB_GRAPH_WIDTH = 400; // thumb chart will generally try to be wider than that
+ var TARGET_THUMB_GRAPH_HEIGHT = 220; // the height of the thumb charts
+ var THUMBS_MAX_TIME_TO_SHOW = 600; // how much time the thumb charts will present?
+
+ var MAINCHART_MAX_TIME_TO_SHOW = 600; // how much time the main chart will present by default?
+ var MAINCHART_POINTS_DIVISOR = 10; // how much detailed will the main chart be by default? 1 = finest, higher is faster
+ var MAINCHART_CONTROL_HEIGHT = 75; // how tall the control chart will be
+ var MAINCHART_CONTROL_DIVISOR = 2; // how much detailed will the control chart be? 1 = finest, higher is faster
var MODE_THUMBS = 1;
var MODE_MAIN = 2;
// ------------------------------------------------------------------------
// common HTML generation
- 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>"; }
+ 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>"; }
- function showChartIsLoading(id, width, height) {
+ function showChartIsLoading(id, name, width, height) {
//mylog('adding loading chart html in div with id ' + id);
- document.getElementById(id).innerHTML = chartIsLoadingHTML(width, height);
+ document.getElementById(id).innerHTML = chartIsLoadingHTML(name, width, height);
}
function thumbChartActions(i, c, nogroup) {
var dt = before - after;
if(dt > c.entries * c.update_every) dt = c.entries * c.update_every;
- if(maxtime && dt > maxtime) dt = maxtime;
+ if(maxtime) dt = maxtime;
- var data_points = dt / c.update_every;
+ var data_points = Math.round(dt / c.update_every);
var screen_points = Math.round(c.chartOptions.width / divisor);
+ //mylog('screen = ' + screen_points + ', data = ' + data_points + ', divisor = ' + divisor);
- if(!group) {
+ if(group <= 0) {
if(screen_points > data_points) {
c.group = 1;
c.points_to_show = data_points;
+ //mylog("rendering at full detail");
}
else {
c.group = Math.round(data_points / screen_points);
- if(c.group > 60) c.group = 60;
- else if(c.group > 45) c.group = 45;
- else if(c.group > 30) c.group = 30;
- else if(c.group > 20) c.group = 20;
- else if(c.group > 15) c.group = 15;
- else if(c.group > 10) c.group = 10;
- else if(c.group > 5) c.group = 5;
- else if(c.group > 2) c.group = 2;
- else c.group = 1;
+ if(group >= 0) {
+ if(c.group > 60) c.group = 60;
+ else if(c.group > 45) c.group = 45;
+ else if(c.group > 30) c.group = 30;
+ else if(c.group > 20) c.group = 20;
+ else if(c.group > 15) c.group = 15;
+ else if(c.group > 10) c.group = 10;
+ else if(c.group > 5) c.group = 5;
+ else if(c.group > 2) c.group = 2;
+ else c.group = 1;
+ }
c.points_to_show = Math.round(data_points / c.group);
+ //mylog("rendering adaptive");
}
}
else {
c.group = group;
c.points_to_show = Math.round(data_points / group);
+ //mylog("rendering with given group");
}
+ //mylog('group = ' + c.group + ', points = ' + c.points_to_show);
if(mainchart.chartType == 'LineChart') {
if(mainchart.group <= 2) mainchart.chartOptions.lineWidth = 1;
if(mainchart) cleanThisChart(mainchart);
mainchart = $.extend(true, {}, c);
- var tempchart = $.extend(true, {}, mainchart);
-
+ mainchart.refreshCount = 0;
+ mainchart.last_updated = 0;
+ mainchart.chartOptions.explorer = null;
mainchart.chart = null;
+
mainchart.chartOptions.width = screenWidth();
mainchart.chartOptions.height = $(window).height() - 150 - MAINCHART_CONTROL_HEIGHT;
if(mainchart.chartOptions.height < 300) mainchart.chartOptions.height = 300;
+ //mainchart.chartOptions.chartArea = {'width': '80%'};
mainchart.div = 'maingraph';
- mainchart.last_updated = 0;
-
calculateChartGroup(mainchart, MAINCHART_POINTS_DIVISOR, MAINCHART_MAX_TIME_TO_SHOW, 0);
- mainchart.chartOptions.explorer = null;
+
+ // copy it to the hidden chart
+ mainchart.hiddenchart = $.extend(true, {}, mainchart);
+ mainchart.hiddenchart.chartOptions.height = MAINCHART_CONTROL_HEIGHT;
+ mainchart.hiddenchart.div = 'maingraph_control';
// initialize the div
- showChartIsLoading(mainchart.div, mainchart.chartOptions.width, mainchart.chartOptions.height);
+ showChartIsLoading(mainchart.div, mainchart.name, mainchart.chartOptions.width, mainchart.chartOptions.height);
// set the radio buttons
setMainChartGroupMethod(mainchart.group_method, 'no-refresh');
$('#group' + mainchart.group).trigger('click');
setMainChartGroup(mainchart.group, 'no-refresh');
- var controlopts = $.extend(true, {}, mainchart.chartOptions, {
- lineWidth: 1,
- height: MAINCHART_CONTROL_HEIGHT,
- chartArea: {'width': '90%'},
- hAxis: {'baselineColor': 'none'},
- vAxis: {'title': null},
- });
+ switchToMainGraph();
+ }
- mainchart.dashboard = new google.visualization.Dashboard(document.getElementById('maingraph_dashboard'));
- mainchart.control = new google.visualization.ControlWrapper({
- controlType: 'ChartRangeFilter',
- containerId: 'maingraph_control',
- options: {
- filterColumnIndex: 0,
- ui: {
- chartType: mainchart.chartType,
- chartOptions: controlopts,
- minRangeSize: MAINCHART_MAX_TIME_TO_SHOW * mainchart.update_every / MAINCHART_POINTS_DIVISOR * 1000,
- }
- },
- });
- mainchart.hiddenchart = new google.visualization.ChartWrapper({
- chartType: mainchart.chartType,
- containerId: 'maingraph_hidden',
- options: {
- isStacked: mainchart.chartOptions.isStacked,
- width: mainchart.chartOptions.width,
- height: mainchart.chartOptions.height,
- //chartArea: {'height': '80%', 'width': '100%'},
- //hAxis: {'slantedText': false},
- //legend: {'position': 'none'}
- },
- });
+ function refreshHiddenChart(doNext) {
+ if(refresh_mode == REFRESH_PAUSED && mainchart.hiddenchart.last_updated != 0) {
+ if(typeof doNext == "function") doNext();
+ return;
+ }
+
+ // is it too soon for a refresh?
+ var now = new Date().getTime();
+ if((now - mainchart.hiddenchart.last_updated) < (mainchart.hiddenchart.group * mainchart.hiddenchart.update_every * 1000)) {
+ if(typeof doNext == "function") doNext();
+ return;
+ }
- // load the data for the control and the hidden chart
- calculateChartGroup(tempchart, MAINCHART_CONTROL_DIVISOR, 0, 0);
- // alert("diff = " + (tempchart.before - tempchart.after) + ", group = " + tempchart.group);
+ if(mainchart.dashboard && mainchart.hiddenchart.refreshCount > 50) {
+ mainchart.dashboard.clear();
+ mainchart.control_wrapper.clear();
+ mainchart.hidden_wrapper.clear();
- switchToMainGraph();
+ mainchart.dashboard = null;
+ mainchart.control_wrapper = null;
+ mainchart.hidden_wrapper = null;
+ }
+
+ if(!mainchart.dashboard) {
+ var controlopts = $.extend(true, {}, mainchart.chartOptions, {
+ lineWidth: 1,
+ height: mainchart.hiddenchart.chartOptions.height,
+ chartArea: {'width': '98%'},
+ hAxis: {'baselineColor': 'none'},
+ vAxis: {'title': null},
+ });
+
+ mainchart.dashboard = new google.visualization.Dashboard(document.getElementById('maingraph_dashboard'));
+ mainchart.control_wrapper = new google.visualization.ControlWrapper({
+ controlType: 'ChartRangeFilter',
+ containerId: 'maingraph_control',
+ options: {
+ filterColumnIndex: 0,
+ ui: {
+ chartType: mainchart.chartType,
+ chartOptions: controlopts,
+ minRangeSize: (MAINCHART_MAX_TIME_TO_SHOW * 1000 * mainchart.update_every) / MAINCHART_POINTS_DIVISOR,
+ }
+ },
+ });
+ mainchart.hidden_wrapper = new google.visualization.ChartWrapper({
+ chartType: mainchart.chartType,
+ containerId: 'maingraph_hidden',
+ options: {
+ isStacked: mainchart.chartOptions.isStacked,
+ width: mainchart.hiddenchart.chartOptions.width,
+ height: mainchart.hiddenchart.chartOptions.height,
+ //chartArea: {'height': '80%', 'width': '100%'},
+ //hAxis: {'slantedText': false},
+ //legend: {'position': 'none'}
+ },
+ });
+
+ mainchart.hiddenchart.refreshCount = 0;
+ }
+
+ // load the data for the control and the hidden wrappers
+ // calculate the group and points to show for the control chart
+ calculateChartGroup(mainchart.hiddenchart, MAINCHART_CONTROL_DIVISOR, 0, -1);
$.ajax({
- url: generateChartURL(tempchart),
+ url: generateChartURL(mainchart.hiddenchart),
dataType:"json",
cache: false
})
mainchart.control_data = new google.visualization.DataTable(jsondata);
- google.visualization.events.addListener(mainchart.control, 'ready', mainchartControlReadyEvent);
- mainchart.dashboard.bind(mainchart.control, mainchart.hiddenchart);
+ if(mainchart.hiddenchart.last_updated == 0) {
+ google.visualization.events.addListener(mainchart.control_wrapper, 'ready', mainchartControlReadyEvent);
+ mainchart.dashboard.bind(mainchart.control_wrapper, mainchart.hidden_wrapper);
+ }
+ if(refresh_mode != REFRESH_PAUSED)
+ mainchart.control_wrapper.setState({range: {
+ start: new Date((Math.round(new Date().getTime() / 1000) - MAINCHART_MAX_TIME_TO_SHOW) * 1000),
+ end: new Date()
+ }});
+
mainchart.dashboard.draw(mainchart.control_data);
+ mainchart.hiddenchart.last_updated = new Date().getTime();
+ mainchart.hiddenchart.refreshCount++;
+ })
+ .always(function() {
+ if(typeof doNext == "function") doNext();
});
}
function mainchartControlReadyEvent() {
- google.visualization.events.addListener(mainchart.control, 'statechange', mainchartControlStateHandler);
+ google.visualization.events.addListener(mainchart.control_wrapper, 'statechange', mainchartControlStateHandler);
+ //mylog(mainchart);
}
function mainchartControlStateHandler() {
// setMainChartPlay('pause');
- var state = mainchart.control.getState();
+ var state = mainchart.control_wrapper.getState();
mainchart.after = Math.round(state.range.start.getTime() / 1000);
mainchart.before = Math.round(state.range.end.getTime() / 1000);
calculateChartGroup(mainchart, MAINCHART_POINTS_DIVISOR, 0, 0);
- console.log('group = ' + mainchart.group + ', points_to_show = ' + mainchart.points_to_show + ', dt = ' + (mainchart.before - mainchart.after));
+ //mylog('group = ' + mainchart.group + ', points_to_show = ' + mainchart.points_to_show + ', dt = ' + (mainchart.before - mainchart.after));
$('#group' + mainchart.group).trigger('click');
mainchart.last_updated = 0;
- if(refresh_mode != REFRESH_ZOOMED) zoomGraphs();
+ if(refresh_mode != REFRESH_PAUSED) pauseGraphs();
}
function initMainChartIndex(i) {
if(!norefresh) {
mainchart.last_updated = 0;
- if(refresh_mode == REFRESH_PAUSED) playGraphs();
}
}
if(!norefresh) {
mainchart.last_updated = 0;
- if(refresh_mode == REFRESH_PAUSED) playGraphs();
}
last_main_chart_avg = g;
if(mainchart) {
mainchart.chartOptions.width = width;
- mainchart.chartOptions.height = $(window).height() - 200;
+ mainchart.chartOptions.height = $(window).height() - 150 - MAINCHART_CONTROL_HEIGHT;
mainchart.last_updated = 0;
+
+ mainchart.hidden_wrapper.setOption('width', width);
+ mainchart.control_wrapper.setOption('ui.chartOptions.width', width);
+ mainchart.hiddenchart.chartOptions.width = width;
+ mainchart.hiddenchart.last_updated = 0;
}
width = thumbWidth();
if(c.enabled && c.chartOptions.width != width) {
cleanThisChart(c);
c.chartOptions.width = width;
- showChartIsLoading(c.div, c.chartOptions.width, c.chartOptions.height);
+ showChartIsLoading(c.div, c.name, c.chartOptions.width, c.chartOptions.height);
c.last_updated = 0;
}
});
cleanThisChart(c);
c.chartOptions.width = sizes.width;
c.chartOptions.height = sizes.height;
- showChartIsLoading(c.div, c.chartOptions.width, c.chartOptions.height);
+ showChartIsLoading(c.div, c.name, c.chartOptions.width, c.chartOptions.height);
c.last_updated = 0;
}
});
var REFRESH_PAUSED = 0;
var REFRESH_ALWAYS = 1;
- var REFRESH_ZOOMED = 2;
var refresh_mode = REFRESH_PAUSED;
var last_refresh = 0;
function playGraphs() {
- if(refresh_mode != REFRESH_PAUSED) {
- // check if the thread died due to a javascript error
- var now = new Date().getTime();
- if((now - last_refresh) > 5000) {
- // it died!
- //mylog('It seems the refresh thread died. Restarting it.');
- chartsRefresh();
- }
- return;
- }
+ if(refresh_mode == REFRESH_ALWAYS) return;
+ //mylog('PlayGraphs()');
refresh_mode = REFRESH_ALWAYS;
$('.mainchart_play_button').button('play');
- chartsRefresh();
+
+ // check if the thread died due to a javascript error
+ var now = new Date().getTime();
+ if((now - last_refresh) > 5000) {
+ // it died or never started
+ //mylog('It seems the refresh thread died. Restarting it.');
+ chartsRefresh();
+ }
}
function pauseGraphs() {
if(refresh_mode == REFRESH_PAUSED) return;
+ //mylog('PauseGraphs()');
refresh_mode = REFRESH_PAUSED;
$('.mainchart_play_button').button('pause');
}
- function zoomGraphs() {
- if(refresh_mode == REFRESH_ZOOMED) return;
-
- refresh_mode = REFRESH_ZOOMED;
- $('.mainchart_play_button').button('pause');
- }
-
// refresh the proper chart
// this is an internal function.
// never call it directly, or new javascript threads will be spawn
var timeout;
- var refresh_count = 0;
function chartsRefresh() {
- refresh_count++;
-
if(resize_request) {
resizeCharts();
resize_request = false;
- refresh_mode = REFRESH_ALWAYS;
+ // refresh_mode = REFRESH_ALWAYS;
}
+ last_refresh = new Date().getTime();
+
if(refresh_mode == REFRESH_PAUSED) {
- //mylog("stop refresh");
+ if(mode == MODE_MAIN && mainchart.last_updated == 0)
+ mainChartRefresh();
+ else
+ timeout = setTimeout(chartsRefresh, 500);
+
return;
}
- last_refresh = new Date().getTime();
-
if(mode == MODE_THUMBS) thumbChartsRefresh();
else if(mode == MODE_GROUP_THUMBS) groupChartsRefresh();
else if(mode == MODE_MAIN) mainChartRefresh();
// this is an internal function.
// never call it directly, or new javascript threads will be spawn
function triggerRefresh() {
- //mylog('triggerRefresh(' + refresh_count + ')');
+ //mylog('triggerRefresh()');
// cleanup has to take place when the charts are not refreshed
// since the refreshing thread is in this function, it means
return;
}
- if(!refreshChart(mainchart, triggerRefresh))
- triggerRefresh();
+ if(!refreshChart(mainchart, hiddenChartRefresh))
+ hiddenChartRefresh();
+ }
+
+ function hiddenChartRefresh() {
+ refreshHiddenChart(triggerRefresh);
}
function roundRobinRefresh(charts, startat) {
function cleanThisChart(chart, emptydivs) {
//mylog('cleanThisChart(' + chart.name + ', ' + emptydivs +')');
+ if(chart.dashboard) {
+ chart.dashboard.clear();
+ chart.dashboard = null;
+
+ if(chart.control_wrapper) {
+ chart.control_wrapper.clear();
+ chart.control_wrapper = null;
+ }
+
+ if(chart.hidden_wrapper) {
+ chart.hidden_wrapper.clear();
+ chart.hidden_wrapper = null;
+ }
+
+ chart.control_data = null;
+ }
+
if(chart.chart) chart.chart.clearChart();
chart.chart = null;
c.chartOptions.width = sizes.width;
c.chartOptions.height = sizes.height;
- 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>";
+ 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>";
});
groupbody += "";
if(c.enabled) {
var j;
- 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\">"
+ 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\">"
+ thumbChartActions(i, c)
+ "</td></tr></table></div>";