<title>NetData</title>
- <!-- Google AJAX API -->
- <script type="text/javascript" src="https://www.google.com/jsapi"></script>
- <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
-
- <!-- Bootstrap -->
+ <!-- Bootstrap CSS -->
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
- <!-- <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap-theme.min.css"> -->
- <script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<link href="/file/theme.css" rel="stylesheet">
-
- <!-- NetData -->
- <script type="text/javascript" src="/file/netdata.js"></script>
- <script type="text/javascript" src="/file/jquery.visible.js"></script>
- <script type="text/javascript">
-
- // Set a callback to run when the Google Visualization API is loaded.
- google.setOnLoadCallback(initCharts);
-
- 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;
- var MODE_GROUP_THUMBS = 3;
- var mode; // one of the MODE_* values
-
- var mycharts = new Array();
- var mainchart;
-
- // html for the main menu
- var mainmenu = "";
-
-
- // ------------------------------------------------------------------------
- // common HTML generation
-
- 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, name, width, height) {
- //mylog('adding loading chart html in div with id ' + id);
- document.getElementById(id).innerHTML = chartIsLoadingHTML(name, width, height);
- }
-
- function thumbChartActions(i, c, nogroup) {
- var name = c.name;
- if(!nogroup) name = c.group_tag;
-
- var refinfo = "the chart is drawing ";
- if(c.group == 1) refinfo += "every single point collected.";
- else refinfo += ((c.group_method == "average")?"the average":"the max") + " value for every " + (c.group * c.update_every) + " seconds of data";
-
- var html = "<div class=\"btn-group btn-group\" data-toggle=\"tooltip\" title=\"" + refinfo + "\">"
- + "<button type=\"button\" class=\"btn btn-default\" onclick=\"javascript: return;\"><span class=\"glyphicon glyphicon-info-sign\"></span></button>"
- + "</div>"
- + "<div class=\"btn-group btn-group\"><button type=\"button\" class=\"btn btn-default disabled\"><small> " + name + "</small></button>";
-
- if(!nogroup) {
- var ingroup = 0;
- var ingroup_detail = 0;
-
- $.each(mycharts, function(i, d) {
- if(d.group_tag == c.group_tag) {
- ingroup++;
- if(d.isdetail) ingroup_detail++;
- }
- });
-
- var hidden = "";
- if(ingroup_detail) hidden = ", including " + ingroup_detail + " charts not shown now";
-
- html += "<button type=\"button\" data-toggle=\"tooltip\" title=\"Show all " + ingroup + " charts in group '" + c.group_tag + "'" + hidden + "\" class=\"btn btn-default\" onclick=\"initGroupGraphs('" + c.group_tag +"');\"><span class=\"glyphicon glyphicon-th-large\"></span></button>";
- }
-
- html += "<button type=\"button\" data-toggle=\"tooltip\" title=\"show chart '" + c.name + "' in fullscreen\" class=\"btn btn-default\" onclick=\"initMainChartIndex(" + i +");\"><span class=\"glyphicon glyphicon-resize-full\"></span></button>"
- + "<button type=\"button\" data-toggle=\"tooltip\" title=\"set options for chart '" + c.name + "'\" class=\"btn btn-default disabled\" onclick=\"alert('Not implemented yet!');\"><span class=\"glyphicon glyphicon-cog\"></span></button>"
- + "<button type=\"button\" data-toggle=\"tooltip\" title=\"ignore chart '" + c.name + "'\" class=\"btn btn-default\" onclick=\"disableChart(" + i + ");\"><span class=\"glyphicon glyphicon-trash\"></span></button>"
- + "</div>";
-
- return html;
- }
-
- function mylog(txt) {
- console.log(txt);
- }
-
- function chartssort(a, b) {
- if(a.userpriority < b.userpriority) return -1;
- return 1;
- }
-
-
- // ------------------------------------------------------------------------
- // MAINGRAPH = fullscreen view of 1 graph
-
- function calculateChartGroup(c, divisor, maxtime, group) {
- var before = c.before?c.before:new Date().getTime() / 1000;
- var after = c.after?c.after:c.first_entry_t;
-
- var dt = before - after;
- if(dt > c.entries * c.update_every) dt = c.entries * c.update_every;
-
- if(maxtime) dt = maxtime;
-
- 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 <= 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(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;
- else mainchart.chartOptions.lineWidth = 2;
- }
- }
-
- // copy the chart c to mainchart
- // switch to main graphs screen
- function initMainChart(c) {
- if(mainchart) cleanThisChart(mainchart);
-
- mainchart = $.extend(true, {}, c);
- 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';
- calculateChartGroup(mainchart, MAINCHART_POINTS_DIVISOR, MAINCHART_MAX_TIME_TO_SHOW, 0);
-
- // 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.name, mainchart.chartOptions.width, mainchart.chartOptions.height);
-
- // set the radio buttons
- setMainChartGroupMethod(mainchart.group_method, 'no-refresh');
- setMainChartMax('normal');
-
- $('#group' + mainchart.group).trigger('click');
- setMainChartGroup(mainchart.group, 'no-refresh');
-
- switchToMainGraph();
- }
-
- 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;
- }
-
- if(mainchart.dashboard && mainchart.hiddenchart.refreshCount > 50) {
- mainchart.dashboard.clear();
- mainchart.control_wrapper.clear();
- mainchart.hidden_wrapper.clear();
-
- mainchart.dashboard = null;
- mainchart.control_wrapper = null;
- mainchart.hidden_wrapper = null;
- mainchart.hiddenchart.last_updated = 0;
- }
-
- 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(mainchart.hiddenchart),
- dataType:"json",
- cache: false
- })
- .done(function(jsondata) {
- if(!jsondata || jsondata.length == 0) return;
-
- mainchart.control_data = new google.visualization.DataTable(jsondata);
-
- 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_wrapper, 'statechange', mainchartControlStateHandler);
- //mylog(mainchart);
- }
-
- function mainchartControlStateHandler() {
- // setMainChartPlay('pause');
-
- 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);
- //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_PAUSED) pauseGraphs();
- }
-
- function initMainChartIndex(i) {
- if(mode == MODE_GROUP_THUMBS)
- initMainChart(group_charts[i]);
-
- else if(mode == MODE_THUMBS)
- initMainChart(mycharts[i]);
- }
-
- var last_main_chart_max='normal';
- function setMainChartMax(m) {
- if(!mainchart) return;
-
- if(m == 'toggle') {
- if(last_main_chart_max == 'maximized') m = 'normal';
- else m = 'maximized';
- }
-
- if(m == "maximized") {
- mainchart.chartOptions.theme = 'maximized';
- //mainchart.chartOptions.axisTitlesPosition = 'in';
- //mainchart.chartOptions.legend = {position: 'none'};
- //mainchart.chartOptions.hAxis.title = null;
- mainchart.chartOptions.hAxis.viewWindowMode = 'maximized';
- mainchart.chartOptions.vAxis.viewWindowMode = 'maximized';
- }
- else {
- mainchart.chartOptions.theme = null;
- mainchart.chartOptions.hAxis.viewWindowMode = null;
- mainchart.chartOptions.vAxis.viewWindowMode = null;
- }
- $('.mainchart_max_button').button(m);
- last_main_chart_max = m;
- mainchart.last_updated = 0;
- }
-
- function setMainChartGroup(g, norefresh) {
- if(!mainchart) return;
-
- mainchart.group = g;
-
- if(!mainchart.before && !mainchart.after)
- calculateChartGroup(mainchart, MAINCHART_POINTS_DIVISOR, MAINCHART_MAX_TIME_TO_SHOW, mainchart.group);
- else
- calculateChartGroup(mainchart, MAINCHART_POINTS_DIVISOR, 0, mainchart.group);
-
- if(!norefresh) {
- mainchart.last_updated = 0;
- }
- }
-
- var last_main_chart_avg = null;
- function setMainChartGroupMethod(g, norefresh) {
- if(!mainchart) return;
-
- if(g == 'toggle') {
- if(last_main_chart_avg == 'max') g = 'average';
- else g = 'max';
- }
-
- mainchart.group_method = g;
-
- $('.mainchart_avg_button').button(g);
-
- if(!norefresh) {
- mainchart.last_updated = 0;
- }
-
- last_main_chart_avg = g;
- }
-
- function setMainChartPlay(p) {
- if(!mainchart) return;
-
- if(p == 'toggle') {
- if(refresh_mode != REFRESH_ALWAYS) p = 'play';
- else p = 'pause';
- }
-
- if(p == 'play') {
- //mainchart.chartOptions.explorer = null;
- mainchart.after = 0;
- mainchart.before = 0;
- calculateChartGroup(mainchart, MAINCHART_POINTS_DIVISOR, MAINCHART_MAX_TIME_TO_SHOW, 0);
- $('#group' + mainchart.group).trigger('click');
- mainchart.last_updated = 0;
- mainchart.hiddenchart.last_updated = 0;
- playGraphs();
- }
- else {
- //mainchart.chartOptions.explorer = {
- // 'axis': 'horizontal',
- // 'maxZoomOut': 1,
- //};
- //mainchart.last_updated = 0;
-
- //if(!refreshChart(mainchart, pauseGraphs))
- pauseGraphs();
- }
- }
-
-
- // ------------------------------------------------------------------------
- // Chart resizing
-
- function screenWidth() {
- return (($(window).width() * 0.95) - 50);
- }
-
- // calculate the proper width for the thumb charts
- function thumbWidth() {
- var cwidth = screenWidth();
- var items = Math.round(cwidth / TARGET_THUMB_GRAPH_WIDTH);
- if(items < 1) items = 1;
-
- if(items > 1 && (cwidth / items) < MINIMUM_THUMB_GRAPH_WIDTH) items--;
-
- return Math.round(cwidth / items) - 1;
- }
-
- function groupChartSizes() {
- var s = { width: screenWidth() / 2, height: ($(window).height() - 130) / 3 - 10};
- if(s.width < MINIMUM_THUMB_GRAPH_WIDTH * 1.5) s.width = screenWidth();
-
- var count = 0;
- if(group_charts) $.each(group_charts, function(i, c) {
- if(c.enabled) count++;
- });
-
- if(count == 0) {
- s.width = TARGET_THUMB_GRAPH_WIDTH;
- s.height = TARGET_THUMB_GRAPH_HEIGHT;
- }
- if(count < 4) {
- s.width = screenWidth();
- s.height = ($(window).height() - 130) / count - 10;
- }
- else if(count == 4) {
- s.height = ($(window).height() - 130) / 2 - 10;
- }
-
- if(s.height < TARGET_THUMB_GRAPH_HEIGHT * 1.5)
- s.height = TARGET_THUMB_GRAPH_HEIGHT * 1.5;
-
- return s;
- }
-
- // resize all charts
- // if the thumb charts need resize in their width, reset them
- function resizeCharts() {
- var width = screenWidth();
-
- if(mainchart) {
- mainchart.chartOptions.width = width;
- 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();
- $.each(mycharts, function(i, c) {
- if(c.enabled && c.chartOptions.width != width) {
- cleanThisChart(c);
- c.chartOptions.width = width;
- showChartIsLoading(c.div, c.name, c.chartOptions.width, c.chartOptions.height);
- c.last_updated = 0;
- }
- });
-
- if(group_charts) $.each(group_charts, function(i, c) {
- var sizes = groupChartSizes();
-
- if(c.enabled && (c.chartOptions.width != sizes.width || c.chartOptions.height != sizes.height)) {
- cleanThisChart(c);
- c.chartOptions.width = sizes.width;
- c.chartOptions.height = sizes.height;
- showChartIsLoading(c.div, c.name, c.chartOptions.width, c.chartOptions.height);
- c.last_updated = 0;
- }
- });
- }
-
- var resize_request = false;
- window.onresize = function(event) {
- resize_request = true;
- };
-
-
- // ------------------------------------------------------------------------
- // Core of the thread refreshing the charts
-
- var REFRESH_PAUSED = 0;
- var REFRESH_ALWAYS = 1;
-
- var refresh_mode = REFRESH_PAUSED;
- var last_refresh = 0;
- function playGraphs() {
- if(refresh_mode == REFRESH_ALWAYS) return;
-
- //mylog('PlayGraphs()');
- refresh_mode = REFRESH_ALWAYS;
- $('.mainchart_play_button').button('play');
-
- // 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');
- }
-
- // refresh the proper chart
- // this is an internal function.
- // never call it directly, or new javascript threads will be spawn
- var timeout;
- function chartsRefresh() {
- if(resize_request) {
- resizeCharts();
- resize_request = false;
- // refresh_mode = REFRESH_ALWAYS;
- }
-
- last_refresh = new Date().getTime();
-
- if(refresh_mode == REFRESH_PAUSED) {
- if(mode == MODE_MAIN && mainchart.last_updated == 0)
- mainChartRefresh();
- else
- timeout = setTimeout(chartsRefresh, 100);
-
- return;
- }
-
- if(mode == MODE_THUMBS) thumbChartsRefresh();
- else if(mode == MODE_GROUP_THUMBS) groupChartsRefresh();
- else if(mode == MODE_MAIN) mainChartRefresh();
- else timeout = setTimeout(triggerRefresh, 100);
- }
-
- // callback for refreshing the charts later
- // this is an internal function.
- // never call it directly, or new javascript threads will be spawn
- function triggerRefresh() {
- //mylog('triggerRefresh()');
-
- // cleanup has to take place when the charts are not refreshed
- // since the refreshing thread is in this function, it means
- // nothing is being refreshed.
- cleanupCharts();
-
- if(mode == MODE_THUMBS) timeout = setTimeout(chartsRefresh, 200);
- else if(mode == MODE_GROUP_THUMBS) timeout = setTimeout(chartsRefresh, 200);
- else if(mode == MODE_MAIN) timeout = setTimeout(chartsRefresh, 200);
- else timeout = setTimeout(triggerRefresh, 100);
- }
-
- // refresh the main chart
- // make sure we don't loose the refreshing thread
- function mainChartRefresh() {
- //mylog('mainChartRefresh()');
-
- if(mode != MODE_MAIN || !mainchart) {
- triggerRefresh();
- return;
- }
-
- if(!refreshChart(mainchart, hiddenChartRefresh))
- hiddenChartRefresh();
- }
-
- function hiddenChartRefresh() {
- refreshHiddenChart(triggerRefresh);
- }
-
- function roundRobinRefresh(charts, startat) {
- var refreshed = false;
-
- // find a chart to refresh
- var all = charts.length;
- var cur = startat;
- var count = 0;
-
- for(count = 0; count < all ; count++, cur++) {
- if(cur >= all) cur = 0;
-
- if(charts[cur].enabled) {
- //mylog('going to refresh chart ' + charts[cur].name);
- refreshed = refreshChart(charts[cur], chartsRefresh);
- if(refreshed) break;
- }
- }
-
- if(!refreshed) triggerRefresh();
- return cur;
- }
-
- // refresh the thumb charts
- // make sure we don't loose the refreshing thread
- var last_thumb_updated = 0;
- function thumbChartsRefresh() {
- //mylog('thumbChartsRefresh()');
-
- if(mycharts.length == 0 || mode != MODE_THUMBS) {
- triggerRefresh();
- return;
- }
-
- last_thumb_updated = roundRobinRefresh(mycharts, last_thumb_updated);
- }
-
- // refresh the group charts
- // make sure we don't loose the refreshing thread
- var last_group_updated = 0;
- function groupChartsRefresh() {
- //mylog('groupChartsRefresh()');
-
- if(!group_charts || group_charts.length == 0 || mode != MODE_GROUP_THUMBS) {
- //mylog('cannot refresh charts');
- triggerRefresh();
- return;
- }
-
- last_group_updated = roundRobinRefresh(group_charts, last_group_updated);
- }
-
-
- // ------------------------------------------------------------------------
- // switch the screen between views
- // these should be called only from initXXXX()
-
- function disableChart(i) {
- //mylog('disableChart(' + i + ')');
-
- var chart = null;
-
- var count = 0;
- if(mode == MODE_GROUP_THUMBS && group_charts) {
- $.each(group_charts, function(i, c) {
- if(c.enabled) count++;
- });
-
- if(i < group_charts.length) chart = group_charts[i];
- }
- else if(mode == MODE_THUMBS) {
- $.each(mycharts, function(i, c) {
- if(c.enabled) count++;
- });
-
- if(i < mycharts.length) chart = mycharts[i];
- }
-
- if(!chart) return;
-
- if(count <= 1) {
- alert('Cannot close the last chart shown.');
- return;
- }
-
- if(chart) {
- //mylog("disabling chart " + chart.name);
- chart.disablethisplease = true;
- }
- }
-
- 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;
-
- if(emptydivs) {
- var div = document.getElementById(chart.div);
- if(div) {
- div.style.display = 'none';
- div.innerHTML = "";
- }
-
- div = document.getElementById(chart.div + "_parent");
- if(div) {
- div.style.display = 'none';
- div.innerHTML = "";
- }
- }
-
- //mylog("chart " + chart.name + " cleaned with option " + emptydivs);
- }
-
- // cleanup the previously shown charts
- function cleanupCharts() {
- //mylog('cleanupCharts()');
-
- if(mode != MODE_MAIN && mainchart) {
- if(mainchart.chart) cleanThisChart(mainchart);
- mainchart = null;
- }
-
- if(mode != MODE_GROUP_THUMBS && group_charts) {
- clearGroupGraphs();
- }
-
- // cleanup the disabled charts
- $.each(mycharts, function(i, c) {
- if(c.disablethisplease && c.enabled) {
- cleanThisChart(c, 'emptydivs');
- c.disablethisplease = false;
- c.enabled = false;
- resize_request = true;
- //mylog("disabled chart " + c.name + " removed");
- }
- });
-
- if(group_charts) $.each(group_charts, function(i, c) {
- if(c.disablethisplease && c.enabled) {
- cleanThisChart(c, 'emptydivs');
- c.disablethisplease = false;
- c.enabled = false;
- resize_request = true;
- //mylog("disabled chart " + c.name + " removed");
- }
- });
-
- // we never cleanup the thumb charts
- }
-
- function updateUI() {
- $('[data-toggle="tooltip"]').tooltip({'placement': 'top', 'container': 'body', 'html': true});
-
- $('[data-spy="scroll"]').each(function () {
- var $spy = $(this).scrollspy('refresh')
- })
- }
-
- var thumbsScrollPosition = null;
- function switchToMainGraph() {
- //mylog('switchToMainGraph()');
-
- if(!mainchart) return;
-
- if(!group_charts) thumbsScrollPosition = window.pageYOffset;
-
- document.getElementById('maingraph_container').style.display = 'block';
- document.getElementById('thumbgraphs_container').style.display = 'none';
- document.getElementById('groupgraphs_container').style.display = 'none';
-
- document.getElementById("main_menu_div").innerHTML = "<ul class=\"nav navbar-nav\"><li><a href=\"javascript:switchToThumbGraphs();\">Back to Home</a></li><li class=\"active\"><a href=\"#\">" + mainchart.title + "</a></li></ul>";
-
- window.scrollTo(0, 0);
-
- mode = MODE_MAIN;
- playGraphs();
- updateUI();
- }
-
- function switchToThumbGraphs() {
- //mylog('switchToThumbGraphs()');
-
- document.getElementById('maingraph_container').style.display = 'none';
- document.getElementById('thumbgraphs_container').style.display = 'block';
- document.getElementById('groupgraphs_container').style.display = 'none';
-
- document.getElementById("main_menu_div").innerHTML = mainmenu;
-
- if(thumbsScrollPosition) window.scrollTo(0, thumbsScrollPosition);
-
- // switch mode
- mode = MODE_THUMBS;
- playGraphs();
- updateUI();
- }
-
- function switchToGroupGraphs() {
- //mylog('switchToGroupGraphs()');
-
- if(!group_charts) return;
-
- if(!mainchart) thumbsScrollPosition = window.pageYOffset;
-
- document.getElementById('maingraph_container').style.display = 'none';
- document.getElementById('thumbgraphs_container').style.display = 'none';
- document.getElementById('groupgraphs_container').style.display = 'block';
-
- document.getElementById("main_menu_div").innerHTML = "<ul class=\"nav navbar-nav\"><li><a href=\"javascript:switchToThumbGraphs();\">Back to Home</a></li><li class=\"active\"><a href=\"#\">" + group_charts[0].group_tag + " charts</a></li></ul>";
-
- window.scrollTo(0, 0);
-
- mode = MODE_GROUP_THUMBS;
- playGraphs();
- updateUI();
- }
-
-
- // ------------------------------------------------------------------------
- // Group Charts
-
- var group_charts = null;
- function initGroupGraphs(group) {
- var count = 0;
-
- if(group_charts) clearGroupGraphs();
- group_charts = new Array();
-
- var groupbody = "";
- $.each(mycharts, function(i, c) {
- if(c.group_tag == group) {
- group_charts[count] = [];
- group_charts[count] = $.extend(true, {}, c);
- group_charts[count].div += "_group";
- group_charts[count].enabled = true;
- group_charts[count].chart = null;
- group_charts[count].last_updated = 0;
- count++;
- }
- });
- group_charts.sort(chartssort);
-
- var sizes = groupChartSizes();
-
- var groupbody = "";
- $.each(group_charts, function(i, c) {
- 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.name, c.chartOptions.width, c.chartOptions.height) + "</div></td></tr><tr><td align=\"center\">" + thumbChartActions(i, c, 'nogroup') + "</td></tr></table></div>";
- });
- groupbody += "";
-
- document.getElementById("groupgraphs").innerHTML = groupbody;
- switchToGroupGraphs();
- }
-
- function clearGroupGraphs() {
- if(group_charts && group_charts.length) {
- $.each(group_charts, function(i, c) {
- cleanThisChart(c, 'emptydivs');
- });
-
- group_charts = null;
- }
-
- document.getElementById("groupgraphs").innerHTML = "";
- }
-
-
- // ------------------------------------------------------------------------
- // Global entry point
- // initialize the thumb charts
-
- // load the charts from the server
- // generate html for the thumbgraphs to support them
- function initCharts() {
- var width = thumbWidth();
- var height = TARGET_THUMB_GRAPH_HEIGHT;
-
- loadCharts(null, function(c) {
- mycharts = c;
-
- if(mycharts == null || mycharts.length == 0) {
- alert("Cannot load data from server.");
- return;
- }
-
- var thumbsContainer = document.getElementById("thumbgraphs");
- if(!thumbsContainer) {
- alert("Cannot find the thumbsContainer");
- return;
- }
-
- mycharts.sort(chartssort);
-
- document.getElementById('hostname_id').innerHTML = mycharts[0].hostname;
- document.title = mycharts[0].hostname;
-
- // create an array for grouping all same-type graphs together
- var categories = new Array();
- $.each(mycharts, function(i, c) {
- c.chartOptions.width = width;
- c.chartOptions.height = height;
-
- // calculate how many point to show for each chart
- c.points_to_show = Math.round(c.entries / c.group) - 1;
-
- // show max 10 mins of data
- if(c.points_to_show * c.group > THUMBS_MAX_TIME_TO_SHOW) c.points_to_show = THUMBS_MAX_TIME_TO_SHOW / c.group;
-
- 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.name, c.chartOptions.width, c.chartOptions.height) + "</div></td></tr><tr><td align=\"center\">"
- + thumbChartActions(i, c)
- + "</td></tr></table></div>";
-
- // find the categories object for this type
- for(j = 0; j < categories.length ;j++) {
- if(categories[j].name == c.type) {
- categories[j].html += h;
- categories[j].count++;
- break;
- }
- }
-
- if(j == categories.length) {
- categories.push({name: c.type, title: c.category, description: '', priority: 0, count: 1, glyphicon: c.glyphicon, html: h});
- }
- }
- });
-
- $.each(categories, function(i, a) {
- if(a.name == "system") a.priority = 1;
- else if(a.name == "net") a.priority = 2;
- else if(a.name == "tc") a.priority = 3;
- else if(a.name == "conntrack") a.priority = 4;
- else if(a.name == "ipvs") a.priority = 5;
- else if(a.name == "ipv4") a.priority = 6;
- else if(a.name == "cpu") a.priority = 7;
- else if(a.name == "mem") a.priority = 8;
- else if(a.name == "disk") a.priority = 9;
- else a.priority = 99;
-
- a.html = "<tr><td id=\"" + a.name + "\"><ol class=\"breadcrumb graphs\"><li class=\"active\"><span class=\"glyphicon " + a.glyphicon + "\"></span> <a id=\"" + a.name + "\" href=\"#" + a.name + "\"><b>" + a.title + "</b> " + a.description + " </a></li></ol></td></tr><tr><td><div class=\"thumbgraphs\">" + a.html + "</td></tr>";
- });
-
- function categoriessort(a, b) {
- if(a.priority < b.priority) return -1;
- return 1;
- }
- categories.sort(categoriessort);
-
- // combine all the htmls into one
- var allcategories = "<table width=\"100%\">";
- mainmenu = "<ul class=\"nav navbar-nav\"><li><a href=\"#\">Home</a></li>";
- $.each(categories, function(i, a) {
- allcategories += a.html;
- mainmenu += "<li><a href=\"#" + a.name + "\">" + a.title + "</a></li>";
- });
- allcategories += "</table>";
- mainmenu += "</ul>";
-
- thumbsContainer.innerHTML = allcategories;
- switchToThumbGraphs();
- });
- }
-
- </script>
</head>
<body role="document" data-spy="scroll" data-target="#main_menu_div">
<span class="glyphicon glyphicon-signal"></span>
</button>
</div>
-<!-- <div class="btn-group btn-group" data-toggle="buttons">
- <label class="btn btn-primary" data-toggle="tooltip" title="show the MAX point among all points grouped">
- <input type="radio" name="groupmethod" id="groupmax" onChange="setMainChartGroupMethod('max');">
- <span class="glyphicon glyphicon-signal"></span>
- </label>
- <label class="btn btn-primary" data-toggle="tooltip" title="show the AVERAGE of all points grouped">
- <input type="radio" name="groupmethod" id="groupaverage" onChange="setMainChartGroupMethod('average');">
- <span class="glyphicon glyphicon-align-justify"></span>
- </label>
- </div>
---> <div class="btn-group btn-group" data-toggle="buttons" >
+ <div class="btn-group btn-group" data-toggle="buttons" >
<label class="btn btn-primary" data-toggle="tooltip" title="do not group points, show the raw data">
<input type="radio" name="group" id="group1" onChange="setMainChartGroup(1);">1
</label>
<span class="glyphicon glyphicon-fullscreen"></span>
</button>
</div>
-<!-- <div class="btn-group btn-group" data-toggle="buttons" >
- <label class="btn btn-primary" data-toggle="tooltip" title="NORMAL chart size">
- <input type="radio" name="chartmax" id="chartnormal" onChange="setMainChartMax('normal');">
- <span class="glyphicon glyphicon-resize-small"></span>
- </label>
- <label class="btn btn-primary" data-toggle="tooltip" title="MAXIMIZED chart size">
- <input type="radio" name="chartmax" id="chartmax" onChange="setMainChartMax('maximized');">
- <span class="glyphicon glyphicon-fullscreen"></span>
- </label>
- </div>
---> </form>
+ </form>
</div>
</td></tr>
</table>
<br/><br/>
<span class="glyphicon glyphicon-off"></span>
<br/><br/>
- loading charts
+ loading cosmos
<br/><br/>
<span class="label label-default">Please wait...</span>
</h1>
(c) 2014 Costa Tsaousis <a href="mailto:costa@tsaousis.gr">costa@tsaousis.gr</a>
</div>
+ <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
+ <script type='text/javascript'>
+ document.getElementById('splash').height = $(window).height();
+ </script>
+
+ <!-- Bootstrap -->
+ <script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
+
+ <!-- Google AJAX API -->
+ <script type="text/javascript" src="https://www.google.com/jsapi"></script>
+
+ <!-- NetData -->
+ <script type="text/javascript" src="/file/netdata.js"></script>
+ <script type="text/javascript" src="/file/index.js"></script>
+
<script type='text/javascript'>
google.load('visualization', '1.1', {packages: ['controls']});
$(document).ready(function(){
- document.getElementById('splash').height = $(window).height();
$(document).on('click','.navbar-collapse.in',function(e) {
if( $(e.target).is('a') ) {
$(this).collapse('hide');
}
});
-
+
$('body').scrollspy({ target: '#main_menu_div' })
});
-
</script>
</html>
--- /dev/null
+var TARGET_THUMB_GRAPH_WIDTH = 500; // thumb charts width will range from 0.5 to 1.5 of that\r
+var MINIMUM_THUMB_GRAPH_WIDTH = 400; // thumb chart will generally try to be wider than that\r
+var TARGET_THUMB_GRAPH_HEIGHT = 220; // the height of the thumb charts\r
+\r
+var THUMBS_MAX_TIME_TO_SHOW = 600; // how much time the thumb charts will present?\r
+var THUMBS_POINTS_DIVISOR = 4;\r
+var THUMBS_STACKED_POINTS_DIVISOR = 10;\r
+\r
+var GROUPS_MAX_TIME_TO_SHOW = 600; // how much time the thumb charts will present?\r
+var GROUPS_POINTS_DIVISOR = 4;\r
+var GROUPS_STACKED_POINTS_DIVISOR = 10;\r
+\r
+var MAINCHART_MAX_TIME_TO_SHOW = 600; // how much time the main chart will present by default?\r
+var MAINCHART_POINTS_DIVISOR = 10; // how much detailed will the main chart be by default? 1 = finest, higher is faster\r
+var MAINCHART_STACKED_POINTS_DIVISOR = 20; // how much detailed will the main chart be by default? 1 = finest, higher is faster\r
+\r
+var MAINCHART_CONTROL_HEIGHT = 75; // how tall the control chart will be\r
+var MAINCHART_CONTROL_DIVISOR = 2; // how much detailed will the control chart be? 1 = finest, higher is faster\r
+\r
+var MODE_THUMBS = 1;\r
+var MODE_MAIN = 2;\r
+var MODE_GROUP_THUMBS = 3;\r
+var mode; // one of the MODE_* values\r
+\r
+var mycharts = new Array();\r
+var mainchart;\r
+\r
+// html for the main menu\r
+var mainmenu = "";\r
+\r
+\r
+// ------------------------------------------------------------------------\r
+// common HTML generation\r
+\r
+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>"; }\r
+\r
+function showChartIsLoading(id, name, width, height) {\r
+ //mylog('adding loading chart html in div with id ' + id);\r
+ document.getElementById(id).innerHTML = chartIsLoadingHTML(name, width, height);\r
+}\r
+\r
+function thumbChartActions(i, c, nogroup) {\r
+ var name = c.name;\r
+ if(!nogroup) name = c.group_tag;\r
+\r
+ var refinfo = "the chart is drawing ";\r
+ if(c.group == 1) refinfo += "every single point collected.";\r
+ else refinfo += ((c.group_method == "average")?"the average":"the max") + " value for every " + (c.group * c.update_every) + " seconds of data";\r
+\r
+ var html = "<div class=\"btn-group btn-group\" data-toggle=\"tooltip\" title=\"" + refinfo + "\">"\r
+ + "<button type=\"button\" class=\"btn btn-default\" onclick=\"javascript: return;\"><span class=\"glyphicon glyphicon-info-sign\"></span></button>"\r
+ + "</div>"\r
+ + "<div class=\"btn-group btn-group\"><button type=\"button\" class=\"btn btn-default disabled\"><small> " + name + "</small></button>";\r
+\r
+ if(!nogroup) {\r
+ var ingroup = 0;\r
+ var ingroup_detail = 0;\r
+\r
+ $.each(mycharts, function(i, d) {\r
+ if(d.group_tag == c.group_tag) {\r
+ ingroup++;\r
+ if(d.isdetail) ingroup_detail++;\r
+ }\r
+ });\r
+\r
+ var hidden = "";\r
+ if(ingroup_detail) hidden = ", including " + ingroup_detail + " charts not shown now";\r
+\r
+ html += "<button type=\"button\" data-toggle=\"tooltip\" title=\"Show all " + ingroup + " charts in group '" + c.group_tag + "'" + hidden + "\" class=\"btn btn-default\" onclick=\"initGroupGraphs('" + c.group_tag +"');\"><span class=\"glyphicon glyphicon-th-large\"></span></button>";\r
+ }\r
+\r
+ html += "<button type=\"button\" data-toggle=\"tooltip\" title=\"show chart '" + c.name + "' in fullscreen\" class=\"btn btn-default\" onclick=\"initMainChartIndex(" + i +");\"><span class=\"glyphicon glyphicon-resize-full\"></span></button>"\r
+ + "<button type=\"button\" data-toggle=\"tooltip\" title=\"set options for chart '" + c.name + "'\" class=\"btn btn-default disabled\" onclick=\"alert('Not implemented yet!');\"><span class=\"glyphicon glyphicon-cog\"></span></button>"\r
+ + "<button type=\"button\" data-toggle=\"tooltip\" title=\"ignore chart '" + c.name + "'\" class=\"btn btn-default\" onclick=\"disableChart(" + i + ");\"><span class=\"glyphicon glyphicon-trash\"></span></button>"\r
+ + "</div>";\r
+\r
+ return html;\r
+}\r
+\r
+function mylog(txt) {\r
+ console.log(txt);\r
+}\r
+\r
+function chartssort(a, b) {\r
+ if(a.userpriority < b.userpriority) return -1;\r
+ return 1;\r
+}\r
+\r
+\r
+// ------------------------------------------------------------------------\r
+// MAINGRAPH = fullscreen view of 1 graph\r
+\r
+// copy the chart c to mainchart\r
+// switch to main graphs screen\r
+function initMainChart(c) {\r
+ if(mainchart) cleanThisChart(mainchart);\r
+\r
+ mainchart = $.extend(true, {}, c);\r
+ mainchart.refreshCount = 0;\r
+ mainchart.last_updated = 0;\r
+ mainchart.chartOptions.explorer = null;\r
+ mainchart.chart = null;\r
+\r
+ mainchart.chartOptions.width = screenWidth();\r
+ mainchart.chartOptions.height = $(window).height() - 150 - MAINCHART_CONTROL_HEIGHT;\r
+ if(mainchart.chartOptions.height < 300) mainchart.chartOptions.height = 300;\r
+ //mainchart.chartOptions.chartArea = {'width': '80%'};\r
+\r
+ mainchart.div = 'maingraph';\r
+ calculateChartPointsToShow(mainchart, mainchart.chartOptions.isStacked?MAINCHART_STACKED_POINTS_DIVISOR:MAINCHART_POINTS_DIVISOR, MAINCHART_MAX_TIME_TO_SHOW, 0);\r
+\r
+ // copy it to the hidden chart\r
+ mainchart.hiddenchart = $.extend(true, {}, mainchart);\r
+ mainchart.hiddenchart.chartOptions.height = MAINCHART_CONTROL_HEIGHT;\r
+ mainchart.hiddenchart.div = 'maingraph_control';\r
+\r
+ // initialize the div\r
+ showChartIsLoading(mainchart.div, mainchart.name, mainchart.chartOptions.width, mainchart.chartOptions.height);\r
+\r
+ // set the radio buttons\r
+ setMainChartGroupMethod(mainchart.group_method, 'no-refresh');\r
+ setMainChartMax('normal');\r
+\r
+ $('#group' + mainchart.group).trigger('click');\r
+ setMainChartGroup(mainchart.group, 'no-refresh');\r
+\r
+ switchToMainGraph();\r
+}\r
+\r
+function refreshHiddenChart(doNext) {\r
+ if(refresh_mode == REFRESH_PAUSED && mainchart.hiddenchart.last_updated != 0) {\r
+ if(typeof doNext == "function") doNext();\r
+ return;\r
+ }\r
+\r
+ // is it too soon for a refresh?\r
+ var now = new Date().getTime();\r
+ if((now - mainchart.hiddenchart.last_updated) < (mainchart.hiddenchart.group * mainchart.hiddenchart.update_every * 1000)) {\r
+ if(typeof doNext == "function") doNext();\r
+ return;\r
+ }\r
+\r
+ if(mainchart.dashboard && mainchart.hiddenchart.refreshCount > 50) {\r
+ mainchart.dashboard.clear();\r
+ mainchart.control_wrapper.clear();\r
+ mainchart.hidden_wrapper.clear();\r
+\r
+ mainchart.dashboard = null;\r
+ mainchart.control_wrapper = null;\r
+ mainchart.hidden_wrapper = null;\r
+ mainchart.hiddenchart.last_updated = 0;\r
+ }\r
+\r
+ if(!mainchart.dashboard) {\r
+ var controlopts = $.extend(true, {}, mainchart.chartOptions, {\r
+ lineWidth: 1,\r
+ height: mainchart.hiddenchart.chartOptions.height,\r
+ chartArea: {'width': '98%'},\r
+ hAxis: {'baselineColor': 'none'},\r
+ vAxis: {'title': null},\r
+ });\r
+\r
+ mainchart.dashboard = new google.visualization.Dashboard(document.getElementById('maingraph_dashboard'));\r
+ mainchart.control_wrapper = new google.visualization.ControlWrapper({\r
+ controlType: 'ChartRangeFilter',\r
+ containerId: 'maingraph_control',\r
+ options: {\r
+ filterColumnIndex: 0,\r
+ ui: {\r
+ chartType: mainchart.chartType,\r
+ chartOptions: controlopts,\r
+ minRangeSize: (MAINCHART_MAX_TIME_TO_SHOW * 1000 * mainchart.update_every) / MAINCHART_POINTS_DIVISOR,\r
+ }\r
+ },\r
+ });\r
+ mainchart.hidden_wrapper = new google.visualization.ChartWrapper({\r
+ chartType: mainchart.chartType,\r
+ containerId: 'maingraph_hidden',\r
+ options: {\r
+ isStacked: mainchart.chartOptions.isStacked,\r
+ width: mainchart.hiddenchart.chartOptions.width,\r
+ height: mainchart.hiddenchart.chartOptions.height,\r
+ //chartArea: {'height': '80%', 'width': '100%'},\r
+ //hAxis: {'slantedText': false},\r
+ //legend: {'position': 'none'}\r
+ },\r
+ });\r
+\r
+ mainchart.hiddenchart.refreshCount = 0;\r
+ }\r
+\r
+ // load the data for the control and the hidden wrappers\r
+ // calculate the group and points to show for the control chart\r
+ calculateChartPointsToShow(mainchart.hiddenchart, MAINCHART_CONTROL_DIVISOR, 0, -1);\r
+\r
+ $.ajax({\r
+ url: generateChartURL(mainchart.hiddenchart),\r
+ dataType:"json",\r
+ cache: false\r
+ })\r
+ .done(function(jsondata) {\r
+ if(!jsondata || jsondata.length == 0) return;\r
+\r
+ mainchart.control_data = new google.visualization.DataTable(jsondata);\r
+\r
+ if(mainchart.hiddenchart.last_updated == 0) {\r
+ google.visualization.events.addListener(mainchart.control_wrapper, 'ready', mainchartControlReadyEvent);\r
+ mainchart.dashboard.bind(mainchart.control_wrapper, mainchart.hidden_wrapper);\r
+ }\r
+ if(refresh_mode != REFRESH_PAUSED)\r
+ mainchart.control_wrapper.setState({range: {\r
+ start: new Date((Math.round(new Date().getTime() / 1000) - MAINCHART_MAX_TIME_TO_SHOW) * 1000),\r
+ end: new Date()\r
+ }});\r
+\r
+ mainchart.dashboard.draw(mainchart.control_data);\r
+ mainchart.hiddenchart.last_updated = new Date().getTime();\r
+ mainchart.hiddenchart.refreshCount++;\r
+ })\r
+ .always(function() {\r
+ if(typeof doNext == "function") doNext();\r
+ });\r
+}\r
+\r
+function mainchartControlReadyEvent() {\r
+ google.visualization.events.addListener(mainchart.control_wrapper, 'statechange', mainchartControlStateHandler);\r
+ //mylog(mainchart);\r
+}\r
+\r
+function mainchartControlStateHandler() {\r
+ // setMainChartPlay('pause');\r
+\r
+ var state = mainchart.control_wrapper.getState();\r
+ mainchart.after = Math.round(state.range.start.getTime() / 1000);\r
+ mainchart.before = Math.round(state.range.end.getTime() / 1000);\r
+\r
+ calculateChartPointsToShow(mainchart, mainchart.chartOptions.isStacked?MAINCHART_STACKED_POINTS_DIVISOR:MAINCHART_POINTS_DIVISOR, 0, 0);\r
+ //mylog('group = ' + mainchart.group + ', points_to_show = ' + mainchart.points_to_show + ', dt = ' + (mainchart.before - mainchart.after));\r
+\r
+ $('#group' + mainchart.group).trigger('click');\r
+ mainchart.last_updated = 0;\r
+\r
+ if(refresh_mode != REFRESH_PAUSED) pauseGraphs();\r
+}\r
+\r
+function initMainChartIndex(i) {\r
+ if(mode == MODE_GROUP_THUMBS) \r
+ initMainChart(group_charts[i]);\r
+\r
+ else if(mode == MODE_THUMBS)\r
+ initMainChart(mycharts[i]);\r
+}\r
+\r
+var last_main_chart_max='normal';\r
+function setMainChartMax(m) {\r
+ if(!mainchart) return;\r
+\r
+ if(m == 'toggle') {\r
+ if(last_main_chart_max == 'maximized') m = 'normal';\r
+ else m = 'maximized';\r
+ }\r
+\r
+ if(m == "maximized") {\r
+ mainchart.chartOptions.theme = 'maximized';\r
+ //mainchart.chartOptions.axisTitlesPosition = 'in';\r
+ //mainchart.chartOptions.legend = {position: 'none'};\r
+ //mainchart.chartOptions.hAxis.title = null;\r
+ mainchart.chartOptions.hAxis.viewWindowMode = 'maximized';\r
+ mainchart.chartOptions.vAxis.viewWindowMode = 'maximized';\r
+ }\r
+ else {\r
+ mainchart.chartOptions.theme = null;\r
+ mainchart.chartOptions.hAxis.viewWindowMode = null;\r
+ mainchart.chartOptions.vAxis.viewWindowMode = null;\r
+ }\r
+ $('.mainchart_max_button').button(m);\r
+ last_main_chart_max = m;\r
+ mainchart.last_updated = 0;\r
+}\r
+\r
+function setMainChartGroup(g, norefresh) {\r
+ if(!mainchart) return;\r
+\r
+ mainchart.group = g;\r
+\r
+ if(!mainchart.before && !mainchart.after)\r
+ calculateChartPointsToShow(mainchart, mainchart.chartOptions.isStacked?MAINCHART_STACKED_POINTS_DIVISOR:MAINCHART_POINTS_DIVISOR, MAINCHART_MAX_TIME_TO_SHOW, mainchart.group);\r
+ else\r
+ calculateChartPointsToShow(mainchart, mainchart.chartOptions.isStacked?MAINCHART_STACKED_POINTS_DIVISOR:MAINCHART_POINTS_DIVISOR, 0, mainchart.group);\r
+\r
+ if(!norefresh) {\r
+ mainchart.last_updated = 0;\r
+ }\r
+}\r
+\r
+var last_main_chart_avg = null;\r
+function setMainChartGroupMethod(g, norefresh) {\r
+ if(!mainchart) return;\r
+\r
+ if(g == 'toggle') {\r
+ if(last_main_chart_avg == 'max') g = 'average';\r
+ else g = 'max';\r
+ }\r
+\r
+ mainchart.group_method = g;\r
+\r
+ $('.mainchart_avg_button').button(g);\r
+\r
+ if(!norefresh) {\r
+ mainchart.last_updated = 0;\r
+ }\r
+\r
+ last_main_chart_avg = g;\r
+}\r
+\r
+function setMainChartPlay(p) {\r
+ if(!mainchart) return;\r
+\r
+ if(p == 'toggle') {\r
+ if(refresh_mode != REFRESH_ALWAYS) p = 'play';\r
+ else p = 'pause';\r
+ }\r
+\r
+ if(p == 'play') {\r
+ //mainchart.chartOptions.explorer = null;\r
+ mainchart.after = 0;\r
+ mainchart.before = 0;\r
+ calculateChartPointsToShow(mainchart, mainchart.chartOptions.isStacked?MAINCHART_STACKED_POINTS_DIVISOR:MAINCHART_POINTS_DIVISOR, MAINCHART_MAX_TIME_TO_SHOW, 0);\r
+ $('#group' + mainchart.group).trigger('click');\r
+ mainchart.last_updated = 0;\r
+ mainchart.hiddenchart.last_updated = 0;\r
+ playGraphs();\r
+ }\r
+ else {\r
+ //mainchart.chartOptions.explorer = {\r
+ // 'axis': 'horizontal',\r
+ // 'maxZoomOut': 1,\r
+ //};\r
+ //mainchart.last_updated = 0;\r
+ \r
+ //if(!refreshChart(mainchart, pauseGraphs))\r
+ pauseGraphs();\r
+ }\r
+}\r
+\r
+\r
+// ------------------------------------------------------------------------\r
+// Chart resizing\r
+\r
+function screenWidth() {\r
+ return (($(window).width() * 0.95) - 50);\r
+}\r
+\r
+// calculate the proper width for the thumb charts\r
+function thumbWidth() {\r
+ var cwidth = screenWidth();\r
+ var items = Math.round(cwidth / TARGET_THUMB_GRAPH_WIDTH);\r
+ if(items < 1) items = 1;\r
+\r
+ if(items > 1 && (cwidth / items) < MINIMUM_THUMB_GRAPH_WIDTH) items--;\r
+\r
+ return Math.round(cwidth / items) - 1;\r
+}\r
+\r
+function groupChartSizes() {\r
+ var s = { width: screenWidth() / 2, height: ($(window).height() - 130) / 3 - 10};\r
+ if(s.width < MINIMUM_THUMB_GRAPH_WIDTH * 1.5) s.width = screenWidth();\r
+\r
+ var count = 0;\r
+ if(group_charts) $.each(group_charts, function(i, c) {\r
+ if(c.enabled) count++;\r
+ });\r
+\r
+ if(count == 0) {\r
+ s.width = TARGET_THUMB_GRAPH_WIDTH;\r
+ s.height = TARGET_THUMB_GRAPH_HEIGHT;\r
+ }\r
+ if(count < 4) {\r
+ s.width = screenWidth();\r
+ s.height = ($(window).height() - 130) / count - 10;\r
+ }\r
+ else if(count == 4) {\r
+ s.height = ($(window).height() - 130) / 2 - 10;\r
+ }\r
+\r
+ if(s.height < TARGET_THUMB_GRAPH_HEIGHT * 1.5)\r
+ s.height = TARGET_THUMB_GRAPH_HEIGHT * 1.5;\r
+\r
+ return s;\r
+}\r
+\r
+// resize all charts\r
+// if the thumb charts need resize in their width, reset them\r
+function resizeCharts() {\r
+ var width = screenWidth();\r
+\r
+ if(mainchart) {\r
+ mainchart.chartOptions.width = width;\r
+ mainchart.chartOptions.height = $(window).height() - 150 - MAINCHART_CONTROL_HEIGHT;\r
+ mainchart.last_updated = 0;\r
+\r
+ mainchart.hidden_wrapper.setOption('width', width);\r
+ mainchart.control_wrapper.setOption('ui.chartOptions.width', width);\r
+ mainchart.hiddenchart.chartOptions.width = width;\r
+ mainchart.hiddenchart.last_updated = 0;\r
+ }\r
+\r
+ width = thumbWidth();\r
+ $.each(mycharts, function(i, c) {\r
+ if(c.enabled && c.chartOptions.width != width) {\r
+ cleanThisChart(c);\r
+ c.chartOptions.width = width;\r
+ calculateChartPointsToShow(c, c.chartOptions.isStacked?THUMBS_STACKED_POINTS_DIVISOR:THUMBS_POINTS_DIVISOR, THUMBS_MAX_TIME_TO_SHOW, -1);\r
+ showChartIsLoading(c.div, c.name, c.chartOptions.width, c.chartOptions.height);\r
+ c.last_updated = 0;\r
+ }\r
+ });\r
+\r
+ if(group_charts) $.each(group_charts, function(i, c) {\r
+ var sizes = groupChartSizes();\r
+\r
+ if(c.enabled && (c.chartOptions.width != sizes.width || c.chartOptions.height != sizes.height)) {\r
+ cleanThisChart(c);\r
+ c.chartOptions.width = sizes.width;\r
+ c.chartOptions.height = sizes.height;\r
+ calculateChartPointsToShow(c, c.chartOptions.isStacked?GROUPS_STACKED_POINTS_DIVISOR:GROUPS_POINTS_DIVISOR, GROUPS_MAX_TIME_TO_SHOW, -1);\r
+ showChartIsLoading(c.div, c.name, c.chartOptions.width, c.chartOptions.height);\r
+ c.last_updated = 0;\r
+ }\r
+ });\r
+}\r
+\r
+var resize_request = false;\r
+window.onresize = function(event) {\r
+ resize_request = true;\r
+};\r
+\r
+\r
+// ------------------------------------------------------------------------\r
+// Core of the thread refreshing the charts\r
+\r
+var REFRESH_PAUSED = 0;\r
+var REFRESH_ALWAYS = 1;\r
+\r
+var refresh_mode = REFRESH_PAUSED;\r
+var last_refresh = 0;\r
+function playGraphs() {\r
+ if(refresh_mode == REFRESH_ALWAYS) return;\r
+\r
+ //mylog('PlayGraphs()');\r
+ refresh_mode = REFRESH_ALWAYS;\r
+ $('.mainchart_play_button').button('play');\r
+\r
+ // check if the thread died due to a javascript error\r
+ var now = new Date().getTime();\r
+ if((now - last_refresh) > 5000) {\r
+ // it died or never started\r
+ //mylog('It seems the refresh thread died. Restarting it.');\r
+ chartsRefresh();\r
+ }\r
+}\r
+\r
+function pauseGraphs() {\r
+ if(refresh_mode == REFRESH_PAUSED) return;\r
+\r
+ //mylog('PauseGraphs()');\r
+ refresh_mode = REFRESH_PAUSED;\r
+ $('.mainchart_play_button').button('pause');\r
+}\r
+\r
+var interval = null;\r
+function checkRefreshThread() {\r
+ if(interval == null) {\r
+ interval = setInterval(checkRefreshThread, 2000);\r
+ return;\r
+ }\r
+\r
+ var now = new Date().getTime();\r
+ if(now - last_refresh > 10000) {\r
+ mylog('Refresh thread died. Restarting it.');\r
+ chartsRefresh();\r
+ }\r
+}\r
+\r
+// refresh the proper chart\r
+// this is an internal function.\r
+// never call it directly, or new javascript threads will be spawn\r
+var timeout = null;\r
+function chartsRefresh() {\r
+ if(resize_request) {\r
+ resizeCharts();\r
+ resize_request = false;\r
+ // refresh_mode = REFRESH_ALWAYS;\r
+ }\r
+\r
+ last_refresh = new Date().getTime();\r
+\r
+ if(refresh_mode == REFRESH_PAUSED) {\r
+ if(mode == MODE_MAIN && mainchart.last_updated == 0) {\r
+ mainChartRefresh();\r
+ return;\r
+ }\r
+ }\r
+\r
+ if(mode == MODE_THUMBS) thumbChartsRefresh();\r
+ else if(mode == MODE_GROUP_THUMBS) groupChartsRefresh();\r
+ else if(mode == MODE_MAIN) mainChartRefresh();\r
+ else timeout = setTimeout(triggerRefresh, 100);\r
+}\r
+\r
+// callback for refreshing the charts later\r
+// this is an internal function.\r
+// never call it directly, or new javascript threads will be spawn\r
+function triggerRefresh() {\r
+ //mylog('triggerRefresh()');\r
+\r
+ // cleanup has to take place when the charts are not refreshed\r
+ // since the refreshing thread is in this function, it means\r
+ // nothing is being refreshed.\r
+ cleanupCharts();\r
+\r
+ if(mode == MODE_THUMBS) timeout = setTimeout(chartsRefresh, 200);\r
+ else if(mode == MODE_GROUP_THUMBS) timeout = setTimeout(chartsRefresh, 200);\r
+ else if(mode == MODE_MAIN) timeout = setTimeout(chartsRefresh, 200);\r
+ else timeout = setTimeout(triggerRefresh, 100);\r
+}\r
+\r
+// refresh the main chart\r
+// make sure we don't loose the refreshing thread\r
+function mainChartRefresh() {\r
+ //mylog('mainChartRefresh()');\r
+\r
+ if(mode != MODE_MAIN || !mainchart) {\r
+ triggerRefresh();\r
+ return;\r
+ }\r
+\r
+ if(!refreshChart(mainchart, hiddenChartRefresh))\r
+ hiddenChartRefresh();\r
+}\r
+\r
+function hiddenChartRefresh() {\r
+ refreshHiddenChart(triggerRefresh);\r
+}\r
+\r
+function roundRobinRefresh(charts, startat) {\r
+ var refreshed = false;\r
+\r
+ // find a chart to refresh\r
+ var all = charts.length;\r
+ var cur = startat;\r
+ var count = 0;\r
+\r
+ for(count = 0; count < all ; count++, cur++) {\r
+ if(cur >= all) cur = 0;\r
+\r
+ if(charts[cur].enabled) {\r
+ //mylog('going to refresh chart ' + charts[cur].name);\r
+ refreshed = refreshChart(charts[cur], chartsRefresh);\r
+ if(refreshed) break;\r
+ }\r
+ }\r
+\r
+ if(!refreshed) triggerRefresh();\r
+ return cur;\r
+}\r
+\r
+// refresh the thumb charts\r
+// make sure we don't loose the refreshing thread\r
+var last_thumb_updated = 0;\r
+function thumbChartsRefresh() {\r
+ //mylog('thumbChartsRefresh()');\r
+\r
+ if(mycharts.length == 0 || mode != MODE_THUMBS) {\r
+ triggerRefresh();\r
+ return;\r
+ }\r
+\r
+ last_thumb_updated = roundRobinRefresh(mycharts, last_thumb_updated);\r
+}\r
+\r
+// refresh the group charts\r
+// make sure we don't loose the refreshing thread\r
+var last_group_updated = 0;\r
+function groupChartsRefresh() {\r
+ //mylog('groupChartsRefresh()');\r
+\r
+ if(!group_charts || group_charts.length == 0 || mode != MODE_GROUP_THUMBS) {\r
+ //mylog('cannot refresh charts');\r
+ triggerRefresh();\r
+ return;\r
+ }\r
+\r
+ last_group_updated = roundRobinRefresh(group_charts, last_group_updated);\r
+}\r
+\r
+\r
+// ------------------------------------------------------------------------\r
+// switch the screen between views\r
+// these should be called only from initXXXX()\r
+\r
+function disableChart(i) {\r
+ //mylog('disableChart(' + i + ')');\r
+\r
+ var chart = null;\r
+\r
+ var count = 0;\r
+ if(mode == MODE_GROUP_THUMBS && group_charts) {\r
+ $.each(group_charts, function(i, c) {\r
+ if(c.enabled) count++;\r
+ });\r
+\r
+ if(i < group_charts.length) chart = group_charts[i];\r
+ }\r
+ else if(mode == MODE_THUMBS) {\r
+ $.each(mycharts, function(i, c) {\r
+ if(c.enabled) count++;\r
+ });\r
+\r
+ if(i < mycharts.length) chart = mycharts[i];\r
+ }\r
+\r
+ if(!chart) return;\r
+\r
+ if(count <= 1) {\r
+ alert('Cannot close the last chart shown.');\r
+ return;\r
+ }\r
+\r
+ if(chart) {\r
+ //mylog("disabling chart " + chart.name);\r
+ chart.disablethisplease = true;\r
+ }\r
+}\r
+\r
+function cleanThisChart(chart, emptydivs) {\r
+ //mylog('cleanThisChart(' + chart.name + ', ' + emptydivs +')');\r
+\r
+ if(chart.dashboard) {\r
+ chart.dashboard.clear();\r
+ chart.dashboard = null;\r
+\r
+ if(chart.control_wrapper) {\r
+ chart.control_wrapper.clear();\r
+ chart.control_wrapper = null;\r
+ }\r
+\r
+ if(chart.hidden_wrapper) {\r
+ chart.hidden_wrapper.clear();\r
+ chart.hidden_wrapper = null;\r
+ }\r
+\r
+ chart.control_data = null;\r
+ }\r
+\r
+ if(chart.chart) chart.chart.clearChart();\r
+ chart.chart = null;\r
+\r
+ if(emptydivs) {\r
+ var div = document.getElementById(chart.div);\r
+ if(div) {\r
+ div.style.display = 'none';\r
+ div.innerHTML = "";\r
+ }\r
+\r
+ div = document.getElementById(chart.div + "_parent");\r
+ if(div) {\r
+ div.style.display = 'none';\r
+ div.innerHTML = "";\r
+ }\r
+ }\r
+\r
+ //mylog("chart " + chart.name + " cleaned with option " + emptydivs);\r
+}\r
+\r
+// cleanup the previously shown charts\r
+function cleanupCharts() {\r
+ //mylog('cleanupCharts()');\r
+\r
+ if(mode != MODE_MAIN && mainchart) {\r
+ if(mainchart.chart) cleanThisChart(mainchart);\r
+ mainchart = null;\r
+ }\r
+\r
+ if(mode != MODE_GROUP_THUMBS && group_charts) {\r
+ clearGroupGraphs();\r
+ }\r
+\r
+ // cleanup the disabled charts\r
+ $.each(mycharts, function(i, c) {\r
+ if(c.disablethisplease && c.enabled) {\r
+ cleanThisChart(c, 'emptydivs');\r
+ c.disablethisplease = false;\r
+ c.enabled = false;\r
+ resize_request = true;\r
+ //mylog("disabled chart " + c.name + " removed");\r
+ }\r
+ });\r
+\r
+ if(group_charts) $.each(group_charts, function(i, c) {\r
+ if(c.disablethisplease && c.enabled) {\r
+ cleanThisChart(c, 'emptydivs');\r
+ c.disablethisplease = false;\r
+ c.enabled = false;\r
+ resize_request = true;\r
+ //mylog("disabled chart " + c.name + " removed");\r
+ }\r
+ });\r
+\r
+ // we never cleanup the thumb charts\r
+}\r
+\r
+function updateUI() {\r
+ $('[data-toggle="tooltip"]').tooltip({'placement': 'top', 'container': 'body', 'html': true});\r
+\r
+ $('[data-spy="scroll"]').each(function () {\r
+ var $spy = $(this).scrollspy('refresh')\r
+ })\r
+}\r
+\r
+var thumbsScrollPosition = null;\r
+function switchToMainGraph() {\r
+ //mylog('switchToMainGraph()');\r
+\r
+ if(!mainchart) return;\r
+\r
+ if(!group_charts) thumbsScrollPosition = window.pageYOffset;\r
+\r
+ document.getElementById('maingraph_container').style.display = 'block';\r
+ document.getElementById('thumbgraphs_container').style.display = 'none';\r
+ document.getElementById('groupgraphs_container').style.display = 'none';\r
+\r
+ document.getElementById("main_menu_div").innerHTML = "<ul class=\"nav navbar-nav\"><li><a href=\"javascript:switchToThumbGraphs();\">Back to Home</a></li><li class=\"active\"><a href=\"#\">" + mainchart.title + "</a></li></ul>";\r
+\r
+ window.scrollTo(0, 0);\r
+\r
+ mode = MODE_MAIN;\r
+ playGraphs();\r
+ updateUI();\r
+}\r
+\r
+function switchToThumbGraphs() {\r
+ //mylog('switchToThumbGraphs()');\r
+\r
+ document.getElementById('maingraph_container').style.display = 'none';\r
+ document.getElementById('thumbgraphs_container').style.display = 'block';\r
+ document.getElementById('groupgraphs_container').style.display = 'none';\r
+\r
+ document.getElementById("main_menu_div").innerHTML = mainmenu;\r
+\r
+ if(thumbsScrollPosition) window.scrollTo(0, thumbsScrollPosition);\r
+\r
+ // switch mode\r
+ mode = MODE_THUMBS;\r
+ playGraphs();\r
+ updateUI();\r
+}\r
+\r
+function switchToGroupGraphs() {\r
+ //mylog('switchToGroupGraphs()');\r
+\r
+ if(!group_charts) return;\r
+\r
+ if(!mainchart) thumbsScrollPosition = window.pageYOffset;\r
+\r
+ document.getElementById('maingraph_container').style.display = 'none';\r
+ document.getElementById('thumbgraphs_container').style.display = 'none';\r
+ document.getElementById('groupgraphs_container').style.display = 'block';\r
+\r
+ document.getElementById("main_menu_div").innerHTML = "<ul class=\"nav navbar-nav\"><li><a href=\"javascript:switchToThumbGraphs();\">Back to Home</a></li><li class=\"active\"><a href=\"#\">" + group_charts[0].group_tag + " charts</a></li></ul>";\r
+\r
+ window.scrollTo(0, 0);\r
+\r
+ mode = MODE_GROUP_THUMBS;\r
+ playGraphs();\r
+ updateUI();\r
+}\r
+\r
+\r
+// ------------------------------------------------------------------------\r
+// Group Charts\r
+\r
+var group_charts = null;\r
+function initGroupGraphs(group) {\r
+ var count = 0;\r
+ \r
+ if(group_charts) clearGroupGraphs();\r
+ group_charts = new Array();\r
+\r
+ var groupbody = "";\r
+ $.each(mycharts, function(i, c) {\r
+ if(c.group_tag == group) {\r
+ group_charts[count] = [];\r
+ group_charts[count] = $.extend(true, {}, c);\r
+ group_charts[count].div += "_group";\r
+ group_charts[count].enabled = true;\r
+ group_charts[count].chart = null;\r
+ group_charts[count].last_updated = 0;\r
+ count++;\r
+ }\r
+ });\r
+ group_charts.sort(chartssort);\r
+\r
+ var sizes = groupChartSizes();\r
+\r
+ var groupbody = "";\r
+ $.each(group_charts, function(i, c) {\r
+ c.chartOptions.width = sizes.width;\r
+ c.chartOptions.height = sizes.height;\r
+\r
+ calculateChartPointsToShow(c, c.chartOptions.isStacked?GROUPS_STACKED_POINTS_DIVISOR:GROUPS_POINTS_DIVISOR, GROUPS_MAX_TIME_TO_SHOW, -1);\r
+\r
+ 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>";\r
+ });\r
+ groupbody += "";\r
+\r
+ document.getElementById("groupgraphs").innerHTML = groupbody;\r
+ switchToGroupGraphs();\r
+}\r
+\r
+function clearGroupGraphs() {\r
+ if(group_charts && group_charts.length) {\r
+ $.each(group_charts, function(i, c) {\r
+ cleanThisChart(c, 'emptydivs');\r
+ });\r
+\r
+ group_charts = null;\r
+ }\r
+\r
+ document.getElementById("groupgraphs").innerHTML = "";\r
+}\r
+\r
+\r
+// ------------------------------------------------------------------------\r
+// Global entry point\r
+// initialize the thumb charts\r
+\r
+// load the charts from the server\r
+// generate html for the thumbgraphs to support them\r
+function initCharts() {\r
+ var width = thumbWidth();\r
+ var height = TARGET_THUMB_GRAPH_HEIGHT;\r
+\r
+ loadCharts(null, function(c) {\r
+ mycharts = c;\r
+\r
+ if(mycharts == null || mycharts.length == 0) {\r
+ alert("Cannot load data from server.");\r
+ return;\r
+ }\r
+\r
+ var thumbsContainer = document.getElementById("thumbgraphs");\r
+ if(!thumbsContainer) {\r
+ alert("Cannot find the thumbsContainer");\r
+ return;\r
+ }\r
+\r
+ mycharts.sort(chartssort);\r
+\r
+ document.getElementById('hostname_id').innerHTML = mycharts[0].hostname;\r
+ document.title = mycharts[0].hostname;\r
+\r
+ // create an array for grouping all same-type graphs together\r
+ var categories = new Array();\r
+ $.each(mycharts, function(i, c) {\r
+ c.chartOptions.width = width;\r
+ c.chartOptions.height = height;\r
+\r
+ // calculate how many point to show for each chart\r
+ //c.points_to_show = Math.round(c.entries / c.group) - 1;\r
+ // show max 10 mins of data\r
+ //if(c.points_to_show * c.group > THUMBS_MAX_TIME_TO_SHOW) c.points_to_show = THUMBS_MAX_TIME_TO_SHOW / c.group;\r
+ calculateChartPointsToShow(c, c.chartOptions.isStacked?THUMBS_STACKED_POINTS_DIVISOR:THUMBS_POINTS_DIVISOR, THUMBS_MAX_TIME_TO_SHOW, -1);\r
+\r
+ if(c.enabled) {\r
+ var j;\r
+ 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\">"\r
+ + thumbChartActions(i, c)\r
+ + "</td></tr></table></div>";\r
+\r
+ // find the categories object for this type\r
+ for(j = 0; j < categories.length ;j++) {\r
+ if(categories[j].name == c.type) {\r
+ categories[j].html += h;\r
+ categories[j].count++;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if(j == categories.length) {\r
+ categories.push({name: c.type, title: c.category, description: '', priority: 0, count: 1, glyphicon: c.glyphicon, html: h});\r
+ }\r
+ }\r
+ });\r
+\r
+ $.each(categories, function(i, a) {\r
+ if(a.name == "system") a.priority = 1;\r
+ else if(a.name == "net") a.priority = 2;\r
+ else if(a.name == "tc") a.priority = 3;\r
+ else if(a.name == "conntrack") a.priority = 4;\r
+ else if(a.name == "ipvs") a.priority = 5;\r
+ else if(a.name == "ipv4") a.priority = 6;\r
+ else if(a.name == "cpu") a.priority = 7;\r
+ else if(a.name == "mem") a.priority = 8;\r
+ else if(a.name == "disk") a.priority = 9;\r
+ else a.priority = 99;\r
+\r
+ a.html = "<tr><td id=\"" + a.name + "\"><ol class=\"breadcrumb graphs\"><li class=\"active\"><span class=\"glyphicon " + a.glyphicon + "\"></span> <a id=\"" + a.name + "\" href=\"#" + a.name + "\"><b>" + a.title + "</b> " + a.description + " </a></li></ol></td></tr><tr><td><div class=\"thumbgraphs\">" + a.html + "</td></tr>";\r
+ });\r
+\r
+ function categoriessort(a, b) {\r
+ if(a.priority < b.priority) return -1;\r
+ return 1;\r
+ }\r
+ categories.sort(categoriessort);\r
+ \r
+ // combine all the htmls into one\r
+ var allcategories = "<table width=\"100%\">";\r
+ mainmenu = "<ul class=\"nav navbar-nav\"><li><a href=\"#\">Home</a></li>";\r
+ $.each(categories, function(i, a) {\r
+ allcategories += a.html;\r
+ mainmenu += "<li><a href=\"#" + a.name + "\">" + a.title + "</a></li>";\r
+ });\r
+ allcategories += "</table>";\r
+ mainmenu += "</ul>";\r
+\r
+ thumbsContainer.innerHTML = allcategories;\r
+ switchToThumbGraphs();\r
+ checkRefreshThread();\r
+ });\r
+}\r
+\r
+// Set a callback to run when the Google Visualization API is loaded.\r
+google.setOnLoadCallback(initCharts);\r
+\r