diff options
-rw-r--r-- | docs/examples/index.html | 152 | ||||
-rw-r--r-- | docs/examples/jarmon_example_recipes.js | 8 | ||||
-rw-r--r-- | jarmon/jarmon.js | 158 |
3 files changed, 170 insertions, 148 deletions
diff --git a/docs/examples/index.html b/docs/examples/index.html index ec5143d..e561b9e 100644 --- a/docs/examples/index.html +++ b/docs/examples/index.html @@ -16,154 +16,15 @@ <script type="text/javascript" src="../../jarmon/jarmon.js"></script> <script type="text/javascript" src="jarmon_example_recipes.js"></script> <script type="text/javascript"> - // Recipes for the charts on this page - - var application_recipe = { - title: 'Jarmon Webserver TCP Stats', - data: [ - ['data/tcpconns-8080-local/tcp_connections-CLOSE_WAIT.rrd', 0, 'CLOSE_WAIT', ''], - ['data/tcpconns-8080-local/tcp_connections-SYN_RECV.rrd', 0, 'SYN_RECV', ''], - ['data/tcpconns-8080-local/tcp_connections-TIME_WAIT.rrd', 0, 'TIME_WAIT', ''], - ['data/tcpconns-8080-local/tcp_connections-CLOSED.rrd', 0, 'CLOSED', ''], - ['data/tcpconns-8080-local/tcp_connections-FIN_WAIT2.rrd', 0, 'FIN_WAIT2', ''], - ['data/tcpconns-8080-local/tcp_connections-FIN_WAIT1.rrd', 0, 'FIN_WAIT1', ''], - ['data/tcpconns-8080-local/tcp_connections-ESTABLISHED.rrd', 0, 'ESTABLISHED', ''], - ['data/tcpconns-8080-local/tcp_connections-LAST_ACK.rrd', 0, 'LAST_ACK', ''], - ['data/tcpconns-8080-local/tcp_connections-LISTEN.rrd', 0, 'LISTEN', ''], - ['data/tcpconns-8080-local/tcp_connections-SYN_SENT.rrd', 0, 'SYN_SENT', ''], - ['data/tcpconns-8080-local/tcp_connections-CLOSING.rrd', 0, 'CLOSING', ''] - ], - options: jQuery.extend(true, {yaxis: {tickDecimals: 0}}, jarmon.Chart.BASE_OPTIONS, jarmon.Chart.STACKED_OPTIONS) - }; - - - function initialiseCharts() { - /** - * Setup chart date range controls and all charts - **/ - var cc = new jarmon.ChartCoordinator($('.chartRangeControl')); - - var TABS = [ - ['System', ['cpu', 'memory','load']], - ['Network', ['interface']], - ['DNS', ['dns_query_types', 'dns_return_codes']] - ]; - - var p = new jarmon.Parallimiter(1); - function serialDownloader(url) { - return p.addCallable(jarmon.downloadBinary, [url]); - } - - // Extract the chart template from the page - var $chartTemplate = $('.chart-container').remove(); - - var $tabs = $('<ul/>', {'class': 'css-tabs'}).appendTo('.tabbed-chart-interface'); - var $tabPanels = $('<div/>', {'class': 'css-panes charts'}).appendTo('.tabbed-chart-interface'); - var tabName, $tabPanel, chartNames; - for(var i=0; i<TABS.length; i++) { - tabName = TABS[i][0]; - chartNames = TABS[i][1]; - // Add a tab - $('<li/>').append( - $('<a/>', {href: ['#', tabName].join('')}).text(tabName) - ).appendTo($tabs); - - // Add tab panel - $tabPanel = $('<div/>').appendTo($tabPanels); - - for(var j=0; j<chartNames.length; j++) { - cc.charts.push( - new jarmon.Chart( - $chartTemplate.clone().appendTo($tabPanel), - jarmon.COLLECTD_RECIPES[chartNames[j]], - serialDownloader - ) - ); - } - } - - // Setup dhtml tabs - $(".css-tabs").tabs(".css-panes > div", {history: true}); - - var t; - // Initialise tabs and update charts when tab is clicked - $(".css-tabs:first").bind('click', function(i) { - // XXX: Hack to give the tab just enough time to become visible - // so that flot can calculate chart dimensions. - window.clearTimeout(t); - t = window.setTimeout(function() { cc.update(); }, 100); - }); - - // Initialise all the charts - cc.init(); - } $(function() { - // Add dhtml calendars to the date input fields - $(".timerange_control img") - .dateinput({ - 'format': 'dd mmm yyyy 00:00:00', - 'max': +1, - 'css': {'input': 'jquerytools_date'}}) - .bind('onBeforeShow', function(e) { - var classes = $(this).attr('class').split(' '); - var currentDate, input_selector; - for(var i=0; i<=classes.length; i++) { - input_selector = '[name="' + classes[i] + '"]'; - // Look for a neighboring input element whose name matches the - // class name of this calendar - // Parse the value as a date if the returned date.getTime - // returns NaN we know it's an invalid date - // XXX: is there a better way to check for valid date? - currentDate = new Date($(this).siblings(input_selector).val()); - if(currentDate.getTime() != NaN) { - $(this).data('dateinput')._input_selector = input_selector; - $(this).data('dateinput')._initial_val = currentDate.getTime(); - $(this).data('dateinput').setValue(currentDate); - break; - } - } - }) - .bind('onHide', function(e) { - // Called after a calendar date has been chosen by the user. - - // Use the sibling selector that we generated above before opening - // the calendar - var input_selector = $(this).data('dateinput')._input_selector; - var oldStamp = $(this).data('dateinput')._initial_val; - var newDate = $(this).data('dateinput').getValue(); - // Only update the form field if the date has changed. - if(oldStamp != newDate.getTime()) { - $(this).siblings(input_selector).val( - newDate.toString().split(' ').slice(1,5).join(' ')); - // Trigger a change event which should automatically update the - // graphs and change the timerange drop down selector to - // "custom" - $(this).siblings(input_selector).trigger('change'); - } - }); - - // Avoid overlaps between the calendars - // XXX: This is a bit of hack, what if there's more than one set of calendar - // controls on a page? - $(".timerange_control img.from_custom").bind('onBeforeShow', - function() { - var otherVal = new Date( - $('.timerange_control [name="to_custom"]').val()); - - $(this).data('dateinput').setMax(otherVal); - } + jarmon.buildTabbedChartUi( + $('.chart-container').remove(), + jarmon.CHART_RECIPES_COLLECTD, + $('.tabbed-chart-interface'), + jarmon.TAB_RECIPES_STANDARD, + $('.chartRangeControl') ); - $(".timerange_control img.to_custom").bind('onBeforeShow', - function() { - var otherVal = new Date( - $('.timerange_control [name="from_custom"]').val()); - - $(this).data('dateinput').setMin(otherVal); - } - ); - - initialiseCharts(); }); </script> </head> @@ -205,5 +66,6 @@ <div class="graph-legend"></div> </div> </div> + </body> </html> diff --git a/docs/examples/jarmon_example_recipes.js b/docs/examples/jarmon_example_recipes.js index e2e42b9..610ecb2 100644 --- a/docs/examples/jarmon_example_recipes.js +++ b/docs/examples/jarmon_example_recipes.js @@ -9,7 +9,13 @@ if(typeof jarmon == 'undefined') { var jarmon = {}; } -jarmon.COLLECTD_RECIPES = { +jarmon.TAB_RECIPES_STANDARD = [ + ['System', ['cpu', 'memory','load']], + ['Network', ['interface']], + ['DNS', ['dns_query_types', 'dns_return_codes']] +]; + +jarmon.CHART_RECIPES_COLLECTD = { 'cpu': { title: 'CPU Usage', data: [ diff --git a/jarmon/jarmon.js b/jarmon/jarmon.js index 0919915..a2c862d 100644 --- a/jarmon/jarmon.js +++ b/jarmon/jarmon.js @@ -972,6 +972,89 @@ jarmon.ChartEditor.prototype._addDatasourceRow = function(record) { }; +jarmon.TabbedInterface = function($tpl, recipe) { + this.$tpl = $tpl; + this.recipe = recipe; + this.placeholders = []; + + var $tabBar = $('<ul/>', {'class': 'css-tabs'}).appendTo($tpl); + var $tabPanels = $('<div/>', {'class': 'css-panes charts'}).appendTo($tpl); + var tabName, $tabPanel, placeNames; + for(var i=0; i<recipe.length; i++) { + tabName = recipe[i][0]; + placeNames = recipe[i][1]; + // Add a tab + $('<li/>').append( + $('<a/>', {href: ['#', tabName].join('')}).text(tabName) + ).appendTo($tabBar); + + // Add tab panel + $tabPanel = $('<div/>').appendTo($tabPanels); + + for(var j=0; j<placeNames.length; j++) { + this.placeholders.push([ + placeNames[j], $('<div/>').appendTo($tabPanel)]); + } + } + + // Setup dhtml tabs + $tabBar.tabs($tabPanels.children('div'), {history: true}); + +}; + +jarmon.TabbedInterface.prototype.draw = function() { + +}; + + +jarmon.buildTabbedChartUi = function ($chartTemplate, chartRecipes, + $tabTemplate, tabRecipes, + $controlPanelTemplate) { + /** + * Setup chart date range controls and all charts + **/ + var p = new jarmon.Parallimiter(1); + function serialDownloader(url) { + return p.addCallable(jarmon.downloadBinary, [url]); + } + + var ti = new jarmon.TabbedInterface($tabTemplate, tabRecipes); + + var charts = jQuery.map( + ti.placeholders, + function(el, i) { + return new jarmon.Chart( + $chartTemplate.clone().replaceAll(el[1]), + chartRecipes[el[0]], + serialDownloader + ) + } + ); + + var cc = new jarmon.ChartCoordinator($controlPanelTemplate, charts); + // Update charts when tab is clicked + ti.$tpl.find(".css-tabs:first").bind( + 'click', + {'cc': cc}, + function(e) { + var cc = e.data.cc; + // XXX: Hack to give the tab just enough time to become visible + // so that flot can calculate chart dimensions. + window.clearTimeout(cc.t); + cc.t = window.setTimeout( + function() { + cc.update(); + }, 100); + } + ); + + // Initialise all the charts + cc.init(); + + return [charts, ti, cc]; +}; + + // Options common to all the chart on this page jarmon.Chart.BASE_OPTIONS = { grid: { @@ -1038,10 +1121,10 @@ jarmon.timeRangeShortcuts = [ * @param ui {Object} A one element jQuery containing an input form and * placeholders for the timeline and for the series of charts. **/ -jarmon.ChartCoordinator = function(ui) { +jarmon.ChartCoordinator = function(ui, charts) { var self = this; this.ui = ui; - this.charts = []; + this.charts = charts; // Style and configuration of the range timeline this.rangePreviewOptions = { @@ -1140,6 +1223,77 @@ jarmon.ChartCoordinator = function(ui) { self.setTimeRange(ranges.xaxis.from, ranges.xaxis.to); self.update(); }); + + // Add dhtml calendars to the date input fields + this.ui.find(".timerange_control img") + .dateinput({ + 'format': 'dd mmm yyyy 00:00:00', + 'max': +1, + 'css': {'input': 'jquerytools_date'}}) + .bind('onBeforeShow', function(e) { + var classes = $(this).attr('class').split(' '); + var currentDate, input_selector; + for(var i=0; i<=classes.length; i++) { + input_selector = '[name="' + classes[i] + '"]'; + // Look for a neighboring input element whose name matches the + // class name of this calendar + // Parse the value as a date if the returned date.getTime + // returns NaN we know it's an invalid date + // XXX: is there a better way to check for valid date? + currentDate = new Date($(this).siblings(input_selector).val()); + if(currentDate.getTime() != NaN) { + $(this).data('dateinput')._input_selector = input_selector; + $(this).data('dateinput')._initial_val = currentDate.getTime(); + $(this).data('dateinput').setValue(currentDate); + break; + } + } + }) + .bind('onHide', function(e) { + // Called after a calendar date has been chosen by the user. + + // Use the sibling selector that we generated above before opening + // the calendar + var input_selector = $(this).data('dateinput')._input_selector; + var oldStamp = $(this).data('dateinput')._initial_val; + var newDate = $(this).data('dateinput').getValue(); + // Only update the form field if the date has changed. + if(oldStamp != newDate.getTime()) { + $(this).siblings(input_selector).val( + newDate.toString().split(' ').slice(1,5).join(' ')); + // Trigger a change event which should automatically update the + // graphs and change the timerange drop down selector to + // "custom" + $(this).siblings(input_selector).trigger('change'); + } + }); + + // Avoid overlaps between the calendars + // XXX: This is a bit of hack, what if there's more than one set of calendar + // controls on a page? + this.ui.find(".timerange_control img.from_custom").bind( + 'onBeforeShow', + {self: this}, + function(e) { + var self = e.data.self; + var otherVal = new Date( + self.ui.find('.timerange_control [name="to_custom"]').val()); + + $(this).data('dateinput').setMax(otherVal); + } + ); + this.ui.find(".timerange_control img.to_custom").bind( + 'onBeforeShow', + {self: this}, + function(e) { + var self = e.data.self; + var otherVal = new Date( + self.ui.find('.timerange_control [name="from_custom"]').val()); + + $(this).data('dateinput').setMin(otherVal); + } + ); + }; |