diff --git a/webroot/css/contrail.elements.css b/webroot/css/contrail.elements.css
index 78cc16bbf..2a3ba704c 100644
--- a/webroot/css/contrail.elements.css
+++ b/webroot/css/contrail.elements.css
@@ -4014,3 +4014,25 @@ td.td-actions a.td-action {
color:#3182bd;
cursor:pointer;
}
+.chart-settings-hide {
+ height: 1px;
+ background-color: #dddddd;
+ margin-left: 70px;
+ margin-right: 20px;
+}
+.chart-settings-expand {
+ margin-left: 70px;
+ margin-right: 20px;
+ border: 1px solid #e5e5e5;
+ background-color: #e5e5e5;
+ border-radius: 3px;
+ padding:2px;
+}
+
+.chart-settings img,.chart-settings-hide img {
+ vertical-align: top;
+ margin-right: auto;
+ margin-left: auto;
+ display: block;
+ cursor:pointer;
+}
diff --git a/webroot/js/chart-utils.js b/webroot/js/chart-utils.js
index a91894378..6f747dad1 100644
--- a/webroot/js/chart-utils.js
+++ b/webroot/js/chart-utils.js
@@ -29,14 +29,11 @@
initScatterChart:function (data) {
var selector = $(this), toFormat = '',
chartOptions = ifNull(data['chartOptions'],{}), chart, yMaxMin, d;
- var hoveredOnTooltip,tooltipTimeoutId;
- var xLbl = ifNull(data['xLbl'], 'CPU (%)'),
- yLbl = ifNull(data['yLbl'], 'Memory (MB)');
-
- var xLblFormat = ifNull(data['xLblFormat'], d3.format()),
- yLblFormat = ifNull(data['yLblFormat'], d3.format());
-
- var yDataType = ifNull(data['yDataType'], '');
+ var hoveredOnTooltip,tooltipTimeoutId,yLbl = ifNull(chartOptions['yLbl'], 'Memory (MB)');
+ var yLblFormat = function(y) {
+ return parseFloat(d3.format('.02f')(y)).toString();
+ }
+ var yDataType = ifNull(chartOptions['yDataType'], '');
if ($.inArray(ifNull(data['title'], ''), ['vRouters', 'Analytic Nodes', 'Config Nodes', 'Control Nodes']) > -1) {
xLblFormat = ifNull(data['xLblFormat'], d3.format('.02f'));
@@ -50,13 +47,6 @@
return obj['values'];
});
dValues = flattenList(dValues);
-
- if(data['yLblFormat'] == null) {
- yLblFormat = function(y) {
- return parseFloat(d3.format('.02f')(y)).toString();
- };
- }
-
//If the axis is bytes, check the max and min and decide the scale KB/MB/GB
//Set size domain
var sizeMinMax = getBubbleSizeRange(dValues);
@@ -71,12 +61,10 @@
}
chartOptions['multiTooltip'] = true;
chartOptions['scatterOverlapBubbles'] = false;
- chartOptions['xLbl'] = xLbl;
+ chartOptions['xLblFormat'] = ifNull(chartOptions['xLblFormat'], d3.format()),
+ chartOptions['yLblFormat'] = ifNull(chartOptions['yLblFormat'], yLblFormat);
+ chartOptions['xLbl'] = ifNull(chartOptions['xLbl'], 'CPU (%)');
chartOptions['yLbl'] = yLbl;
- chartOptions['xLblFormat'] = xLblFormat;
- chartOptions['yLblFormat'] = yLblFormat;
- chartOptions['forceX'] = data['forceX'];
- chartOptions['forceY'] = data['forceY'];
var seriesType = {};
for(var i = 0;i < d.length; i++ ) {
var values = [];
@@ -122,8 +110,13 @@
chartOptions['stateChangeFunction'] = function (e) {
//nv.log('New State:', JSON.stringify(e));
};
-
-
+ var d3Scale = d3.scale.linear().range([1,2]).domain(chartOptions['sizeMinMax']);
+ //Adjust the size domain to have limit on minumum bubble size
+ $.each(d,function(idx,currSeries) {
+ currSeries['values'] = $.each(currSeries['values'],function(idx,obj) {
+ obj['size'] = d3Scale(obj['size']);
+ });
+ });
chartOptions['elementClickFunction'] = function (e) {
if(typeof(chartOptions['clickFn']) == 'function')
chartOptions['clickFn'](e['point']);
@@ -148,16 +141,116 @@
}
if(data['hideLoadingIcon'] != false)
$(this).parents('.widget-box').find('.icon-spinner').hide();
- if(data['loadedDeferredObj'] != null)
- data['loadedDeferredObj'].fail(function(errObj){
- if(errObj['errTxt'] != null && errObj['errTxt'] != 'abort') {
- showMessageInChart({selector:$(selector),chartObj:$(selector).data('chart'),xLbl:chartOptions['xLbl'],yLbl:chartOptions['yLbl'],
- msg:'Error in fetching details',type:'bubblechart'});
- }
- });
- chartOptions['deferredObj'] = data['deferredObj'];
- initScatterBubbleChart(selector, d, chart, chartOptions);
-
+ if(!isScatterChartInitialized("#"+$(selector).attr('id'))) {
+ if(data['loadedDeferredObj'] != null)
+ data['loadedDeferredObj'].fail(function(errObj){
+ if(errObj['errTxt'] != null && errObj['errTxt'] != 'abort') {
+ showMessageInChart({selector:$(selector),chartObj:$(selector).data('chart'),xLbl:chartOptions['xLbl'],yLbl:chartOptions['yLbl'],
+ msg:'Error in fetching details',type:'bubblechart'});
+ }
+ });
+ if(chartOptions['deferredObj'] != null && chartOptions['deferredObj'].state() == 'pending') {
+ chartOptions['deferredObj'].done(function(){
+ var settings = [];
+ if(chartOptions['xAxisParams'] != null) {
+ settings.push({id:'xAxisParams',lbl:'X-Axis parameters'});
+ }
+ if(chartOptions['yAxisParams'] != null) {
+ settings.push({id:'yAxisParams',lbl:'Y-Axis parameters'});
+ }
+ if(chartOptions['showSettings']) {
+ $(selector).parent('div').append(contrail.getTemplate4Id('chart-settings')(settings));
+ showAxisParams(settings);
+ }
+ });
+ }
+ function showAxisParams(settings) {
+ var selParent = $(selector).parent('div');
+ $(selParent).find('div.chart-settings-hide img').bind('click',function(clickEvt){
+ $('div.chart-settings-hide').addClass('hide');
+ $('div.chart-settings-wrapper').removeClass('hide');
+ $(selParent).find('div.chart-settings-wrapper').removeClass('hide');
+ $(selParent).find('div.upArrow img').on('click',function(){
+ $('div.chart-settings-wrapper').addClass('hide');
+ $('div.chart-settings-hide').removeClass('hide');
+ });
+ var chartObj = $.extend(true,{},data);
+ var updateChartParams = chartObj['chartOptions'];
+ $.each(settings,function(idx,setVal){
+ var id = setVal['id'],data = [];
+ var axisType = id.indexOf('xAxis') > -1 ? 'x' : 'y';
+ $("#"+id).contrailDropdown({
+ dataTextField:"text",
+ dataValueField:"value",
+ change:function(e){
+ var chartData = d3.select($(selector).find('svg')[0]).datum();
+ var selValue = $(e['target']).data('contrailDropdown').getSelectedData()[0]['text'];
+ updateChartParams['tooltipFn'] = tooltipFn;
+ $.each(chartData,function(idx,dataItem){
+ $.each(dataItem['values'],function(sIdx,value){
+ $.each(chartOptions[id],function(index,obj){
+ if(obj['lbl'] == selValue) {
+ var values = [],range = [];
+ $.each(chartData,function(idx,data){
+ values = $.merge(values,data['values']);
+ });
+ /* here if type is null, considering it as default data type integer
+ * In case of single point (which mean only one bubble or main bubbles with same x and y value)
+ * minimum and maximum will be same so whole axis will have only two values so we are setting the domain.
+ */
+ if(obj['formatFn'] != null) {
+ value[axisType] = parseInt(obj['formatFn'](value[obj['key']]));
+ } else {
+ if(obj['type'] != null) {
+ updateChartParams[axisType+"LblFormat"] = d3.format('.02f');
+ value[axisType] = parseFloat(value[obj['key']]);
+ } else {
+ updateChartParams[axisType+"LblFormat"] = d3.format('0d');
+ value[axisType] = parseInt(value[obj['key']]);
+ }
+ }
+ range = d3.extent(values,function(item){return item[axisType]});
+ if(obj['type'] == null && range[1] == range[0]) {
+ range[0] = (range[0] - range[0] * 0.05 < 0 ) ? 0 : Math.floor(range[0] - range[0] * 0.05);
+ range[1] = Math.ceil(range[1] + range[1] * 0.05);
+ updateChartParams[axisType+"Domain"] = [range[0],range[1]];
+ }
+ if(obj['dataType'] == 'bytes') {
+ var result = formatByteAxis(chartData);
+ chartData = result['data'];
+ updateChartParams[axisType+'Lbl'] = obj['lbl'] + result[axisType+'Lbl'];
+ } else
+ updateChartParams[axisType+'Lbl'] = obj['lbl'];
+
+ }
+ });
+ });
+ });
+ chartObj['d'] = chartData;
+ chartObj['chartOptions'] = updateChartParams;
+ $(selector).initScatterChart(chartObj);
+ }
+ });
+ $.each(chartOptions[id],function(idx,obj){
+ var obj = {
+ id:obj['lbl'],
+ text:obj['lbl'],
+ value:obj['lbl']
+ };
+ data.push(obj);
+ });
+ $("#"+id).data('contrailDropdown').setData(data);
+ })
+ });
+ }
+ initScatterBubbleChart(selector, d, chart, chartOptions);
+ } else {
+ chart = $(selector).data('chart');
+ var svg = $(selector).find('svg')[0];
+ chart = setChartOptions(chart,chartOptions);
+ d3.select(svg).datum(d);
+ chart.update();
+ }
if(data['widgetBoxId'] != null)
endWidgetLoading(data['widgetBoxId']);
@@ -192,11 +285,9 @@
bubbleDrillDown($(this).find('div.chart-tooltip-title').find('p').text(),result['nodeMap']);
});
$(tooltipContainer).find('div.enabledPointer').on('mouseover',function(e){
- //console.log("Inside the mouse over");
hoveredOnTooltip = true;
});
$(tooltipContainer).find('div.enabledPointer').on('mouseleave',function(e){
- //console.log("Inside the mouseout ");
hoveredOnTooltip = false;
nv.tooltip.cleanup();
});
@@ -209,7 +300,7 @@
var leftPos = 'auto',rightPos = 'auto';
if(result['button'] == 'left') {
if($(tooltipContainer).css('left') == 'auto') {
- leftPos = $(tooltipContainer).position()['left'];
+ leftPos = $(tooltipContainer).offset()['left'];
$(tooltipContainer).css('left',leftPos);
$(tooltipContainer).css('right','auto');
}
@@ -229,7 +320,7 @@
content = data.slice((page-1) * perPage,page * perPage);
} else if (result['button'] == 'right') {
if($(tooltipContainer).css('right') == 'auto') {
- leftPos = $(tooltipContainer).position()['left'];
+ leftPos = $(tooltipContainer).offset()['left'];
rightPos = $(tooltipContainer).offsetParent().width() - $(tooltipContainer).outerWidth() - leftPos;
$(tooltipContainer).css('right', rightPos);
$(tooltipContainer).css('left','auto');
@@ -250,7 +341,7 @@
content = data.slice((data.length - perPage),data.length);
}
}
- leftPos = $(tooltipContainer).position()['left'];
+ leftPos = $(tooltipContainer).offset()['left'];
rightPos = $(tooltipContainer).offsetParent().width() - $(tooltipContainer).outerWidth() - leftPos;
result['content'] = content;
if(result['perPage'] > 1)
@@ -425,7 +516,7 @@ function getMultiTooltipContent(e,tooltipFn,chart) {
});
if(!isEmptyObject(data)) {
//data['point'] = data[0];
- tooltipArray.push(tooltipFn(data[0]));
+ tooltipArray.push(tooltipFn(data[0],null,null));
//Creates a hashMap based on first key/value in tooltipContent
nodeMap[tooltipFn(data[0])[0]['value']] = {point:data[0]};
}
@@ -844,29 +935,42 @@ function updateChartsClass() {
* Re-render the UI widget with updated data
*/
this.updateView = function(obj) {
- if(obj['type'] == 'bubblechart') {
- if(obj['selector'] != null && $(obj['selector']).parent('div.stack-chart') != null) {
- var chart = $(obj['selector']).parent('div.stack-chart').data('chart');
- if(obj['axisFormatFn'] != null) {
- var result = window[obj['axisFormatFn']](obj['data']);
- obj['data'] = result['data'];
- if(obj['yLbl'] != null)
- chart.yAxis.axisLabel(obj['yLbl']+" "+result['yLbl']);
- }
- d3.select(obj['selector']).datum(obj['data']);
- chart.update();
- }
- } else if(obj['type'] == 'infrabubblechart') {
- if(obj['selector'] != null && $(obj['selector']).parent('div') != null) {
- var chart = $(obj['selector']).parent('div').data('chart');
- if(obj['axisformatFn'] != null) {
- var result = window[obj['axisformatFn']](obj['data']);
- obj['data'] = result['data'];
- chart.yAxis.axisLabel(obj['yLbl']+" "+result['yLbl']);
- }
- d3.select(obj['selector']).datum(obj['data']);
- if(chart != null)
- chart.update();
+ if(obj['type'] == 'bubblechart' || obj['type'] == 'infrabubblechart') {
+ var chart = null;
+ if(obj['type'] == 'bubblechart' && obj['selector'] != null && $(obj['selector']).parent('div.stack-chart') != null)
+ chart = $(obj['selector']).parent('div.stack-chart').data('chart');
+ else if (obj['type'] == 'infrabubblechart' && obj['selector'] != null && $(obj['selector']).parent('div') != null)
+ chart = $(obj['selector']).parent('div').data('chart');
+ if(chart != null) {
+ if(obj['axisFormatFn'] != null) {
+ var result = window[obj['axisFormatFn']](obj['data']);
+ obj['data'] = result['data'];
+ if(obj['yLbl'] != null)
+ obj['yLbl'] += result['yLbl'];
+ //chart.yAxis.axisLabel(obj['yLbl']+" "+result['yLbl']);
+ }
+ if(obj['xValueType'] == 'float')
+ chart.xAxis.tickFormat(d3.format('.02f'));
+ else if(obj['xValueType'] == 'integer'){
+ var xDomain = d3.extent(obj['data'][0]['values'],function(item){return item['x']});
+ if(Math.abs(xDomain[1] - xDomain[0]) < 5)
+ chart.xDomain([xDomain[0],xDomain[1] + 5]);
+ chart.xAxis.tickFormat(d3.format('0d'));
+ }
+ if(obj['yValueType'] == 'float')
+ chart.yAxis.tickFormat(d3.format('.02f'));
+ else if(obj['yValueType'] == 'integer'){
+ var yDomain = d3.extent(obj['data'][0]['values'],function(item){return item['y']});
+ if(Math.abs(yDomain[1] - yDomain[0]) < 5)
+ chart.yDomain([yDomain[0],yDomain[1] + 5]);
+ chart.yAxis.tickFormat(d3.format('0d'));
+ }
+ if(obj['xLbl'] != null)
+ chart.xAxis.axisLabel(obj['xLbl']);
+ if(obj['yLbl'] != null)
+ chart.yAxis.axisLabel(obj['yLbl']);
+ d3.select(obj['selector']).datum(obj['data']);
+ chart.update();
}
} else if(obj['type'] == 'timeseriescharts') {
if(obj['selector'] != null && $(obj['selector']).parent('div.ts-chart') != null) {
diff --git a/webroot/js/d3-utils.js b/webroot/js/d3-utils.js
index a834c54e3..34353857a 100644
--- a/webroot/js/d3-utils.js
+++ b/webroot/js/d3-utils.js
@@ -580,13 +580,7 @@ function updateChartOnResize(selector,chart){
}
function initScatterBubbleChart(selector, data, chart, chartOptions) {
- var d3Scale = d3.scale.linear().range([1,2]).domain(chartOptions['sizeMinMax']);
- //Adjust the size domain to have limit on minumum bubble size
- $.each(data,function(idx,currSeries) {
- currSeries['values'] = $.each(currSeries['values'],function(idx,obj) {
- obj['size'] = d3Scale(obj['size']);
- });
- });
+
nv.addGraph(function () {
chart = nv.models.scatterChart()
.showDistX(false)
@@ -596,43 +590,13 @@ function initScatterBubbleChart(selector, data, chart, chartOptions) {
.tooltipYContent(null)
.showTooltipLines(false)
.tooltipContent(chartOptions['tooltipFn']);
-
- if(chartOptions['tooltipRenderedFn'] != null)
- chart.tooltipRenderedFn(chartOptions['tooltipRenderedFn']);
- if (chartOptions['forceX'] != null)
- chart.forceX(chartOptions['forceX']);
- if (chartOptions['forceY'] != null)
- chart.forceY(chartOptions['forceY']);
- if(chartOptions['seriesMap'] != null)
- chart.seriesMap(chartOptions['seriesMap']);
- if(chartOptions['xPositive'] != null && chart.scatter != null)
- chart.scatter.xPositive(chartOptions['xPositive']);
- if(chartOptions['yPositive'] != null && chart.scatter != null)
- chart.scatter.yPositive(chartOptions['yPositive']);
- if(chartOptions['addDomainBuffer'] != null && chart.scatter != null)
- chart.scatter.addDomainBuffer(chartOptions['addDomainBuffer']);
-
- //If more than one category is displayed,enable showLegend
+ chart = setChartOptions(chart,chartOptions);
+ //If more than one category is displayed,enable showLegend
if(data.length == 1) {
chart.showLegend(false);
}
-
- $(selector).data('chart', chart);
-
- chart.xAxis.tickFormat(chartOptions['xLblFormat']);
- chart.yAxis.tickFormat(chartOptions['yLblFormat']);
- chart.xAxis.showMaxMin(false);
- chart.yAxis.showMaxMin(false);
- chart.yAxis.axisLabel(chartOptions['yLbl']);
- chart.xAxis.axisLabel(chartOptions['xLbl']);
- chart.yAxis.ticks(3);
-
$(selector).append('');
-
- chart.dispatch.on('stateChange', chartOptions['stateChangeFunction']);
- chart.scatter.dispatch.on('elementClick', chartOptions['elementClickFunction']);
- chart.scatter.dispatch.on('elementMouseout',chartOptions['elementMouseoutFn']);
- chart.scatter.dispatch.on('elementMouseover',chartOptions['elementMouseoverFn']);
+ $(selector).data('chart', chart);
if(!($(selector).is(':visible'))) {
$(selector).find('svg').bind("refresh", function() {
d3.select($(selector)[0]).select('svg').datum(data).call(chart);
@@ -650,7 +614,32 @@ function initScatterBubbleChart(selector, data, chart, chartOptions) {
return chart;
});
}
-
+function setChartOptions(chart,chartOptions){
+
+ chartOptions = ifNull(chartOptions,{});
+ // In case of dynamic axis while updating the chart with new parameters earlier properties
+ // of the chart object will retain so we are setting to null if any property not exists
+ chart.tooltipRenderedFn(ifNull(chartOptions['tooltipRenderedFn'],null));
+ chart.forceX(ifNull(chartOptions['forceX'],null));
+ chart.forceY(ifNull(chartOptions['forceY'],null));
+ chart.seriesMap(ifNull(chartOptions['seriesMap'],null));
+ chart.scatter.xPositive(ifNull(chartOptions['xPositive'],null));
+ chart.scatter.yPositive(ifNull(chartOptions['yPositive'],null));
+ chart.scatter.addDomainBuffer(ifNull(chartOptions['addDomainBuffer'],null));
+ chart.scatter.xDomain(ifNull(chartOptions['xDomain'],null));
+ chart.scatter.yDomain(ifNull(chartOptions['yDomain'],null));
+ chart.xAxis.tickFormat(chartOptions['xLblFormat']);
+ chart.yAxis.tickFormat(chartOptions['yLblFormat']);
+ chart.xAxis.showMaxMin(false);
+ chart.yAxis.showMaxMin(false);
+ chart.yAxis.axisLabel(chartOptions['yLbl']);
+ chart.xAxis.axisLabel(chartOptions['xLbl']);
+ chart.dispatch.on('stateChange', chartOptions['stateChangeFunction']);
+ chart.scatter.dispatch.on('elementClick', chartOptions['elementClickFunction']);
+ chart.scatter.dispatch.on('elementMouseout',chartOptions['elementMouseoutFn']);
+ chart.scatter.dispatch.on('elementMouseover',chartOptions['elementMouseoverFn']);
+ return chart;
+}
function formatSumBytes(d) {
return formatBytes(d, false, false, 1);
};
diff --git a/webroot/views/contrail-common.view b/webroot/views/contrail-common.view
index f36e10239..3b76c29ee 100644
--- a/webroot/views/contrail-common.view
+++ b/webroot/views/contrail-common.view
@@ -480,3 +480,26 @@
+
+