cancel
Showing results for 
Search instead for 
Did you mean: 

DYNAMICALLY FORMATTED DATA LABELS

cartercjb
10 - ETL
10 - ETL

Does anyone have suggestions on how to do the following: 

cartercjb_0-1641935078307.png

  1. Script the data labels so that they never overlap? I'm not sure if that's possible but I can hope!
  2. Add additional formatting around the data labels similar to the screenshot below where each data label is surrounded in a colored shape?

Bar.png

1 ACCEPTED SOLUTION

harikm007
13 - Data Warehouse
13 - Data Warehouse

@cartercjb 

I believe there is insufficient space on the right side of the chart, which is why the data label is visible inside the bar. One way to fix this is to dynamically increase the Max value. The script has been updated.  Please change value of the variable 'increasePercent' as required.

//Formatting datalabels 
widget.on('processresult', function(se,ev){
	var maxValue = 0
	var increasePercent = 0.2 //variable to adjust right space. Change this value as needed
		
	$.each(ev.result.series, function(seriesIndex, value){
		
		$.each(value.data, function(di, dataItem){
			if(dataItem.y > maxValue)
				maxValue = dataItem.y
		})
		
		value.dataLabels = {
									backgroundColor: '#f5d142', //data label color
									color: 'white',
									padding: 5,
									borderRadius: 5
								}
	
	})
	
	ev.result.yAxis[0].max = maxValue + (increasePercent * maxValue) ;
		
})

//Adjusting position of datalabels
widget.on('domready', function(se,ev){
	
	barWidth = $('.highcharts-series-group .highcharts-series rect', element).width()
	
	$('.highcharts-data-labels .highcharts-label', element).each(function(){
		labelWidth = $(this).find('rect').width()
		labelHeight = $(this).find('rect').height()
		
		$(this).find('rect').attr('x', ($(this).find('rect').attr('x') + 2))
		$(this).find('rect').attr('height', barWidth)
		$(this).find('rect').attr('y', ((labelHeight - barWidth)/2))
	
	})

});

 Thanks

-Hari

View solution in original post

12 REPLIES 12

harikm007
13 - Data Warehouse
13 - Data Warehouse

Hi @cartercjb ,

1. I found this article to separate overlapping data labels : 

https://support.sisense.com/kb/en/article/separating-overlapping-value-labels

2. Please try this widget script for column chart:

//Formatting datalabels 
widget.on('processresult', function(se,ev){
	
	$.each(ev.result.series, function(index, value){
		value.dataLabels = {
									backgroundColor: value.color,
									color: 'white',
									padding: 5,
									borderRadius: 5
								}
	
	})
	
})

//Adjusting position of datalabels
widget.on('domready', function(se,ev){
	
	barWidth = $('.highcharts-series-group .highcharts-series rect', element).width()
	
	$('.highcharts-data-labels .highcharts-label', element).each(function(){
		labelWidth = $(this).find('rect').width()
		labelHeight = $(this).find('rect').height()
		$(this).find('rect').attr('width', barWidth)
		$(this).find('rect').attr('height', labelHeight - 5)
		$(this).find('rect').attr('x', ((labelWidth - barWidth)/2))
	
	})

});

This is how the column chart will looks like after applying the above script : 

Formatted datalabels.jpg

Thanks

-Hari

@harikm007 Hari,

First off, THANK  YOU!! You are extremely helpful. Two follow-up questions. Please reference the screenshot below. 

  1. Is there anything that can be done to make the spacing more dynamic? See the green bars on the REHAB DAYS widget? There is no space in between the bars and the label.
  2. Is there a way to make all data labels 1 single color?

 

cartercjb_0-1642186546932.png

 

harikm007
13 - Data Warehouse
13 - Data Warehouse

@cartercjb 

Previous script is only for column chart. Please try below script for bar chart. Also script is updated to make all data labels same color

//Formatting datalabels 
widget.on('processresult', function(se,ev){
	
	$.each(ev.result.series, function(index, value){
		value.dataLabels = {
									backgroundColor: '#f5d142', //data label color
									color: 'white',
									padding: 5,
									borderRadius: 5
								}
	
	})
	
})

//Adjusting position of datalabels
widget.on('domready', function(se,ev){
	
	barWidth = $('.highcharts-series-group .highcharts-series rect', element).width()
	
	$('.highcharts-data-labels .highcharts-label', element).each(function(){
		labelWidth = $(this).find('rect').width()
		labelHeight = $(this).find('rect').height()
		
		$(this).find('rect').attr('x', ($(this).find('rect').attr('x') + 2))
		$(this).find('rect').attr('height', barWidth)
		$(this).find('rect').attr('y', ((labelHeight - barWidth)/2))
	
	})

});

 Thanks

-Hari

@harikm007 Hari - 

Thanks for your feedback! That definitely helped - but there is still a bit of overlap that you will notice on the largest blue bar. Is there any additional scripting that can be done or is that as good as it will get? Thanks!

-Carter

 

cartercjb_0-1642197980340.png

 

harikm007
13 - Data Warehouse
13 - Data Warehouse

@cartercjb 

I believe there is insufficient space on the right side of the chart, which is why the data label is visible inside the bar. One way to fix this is to dynamically increase the Max value. The script has been updated.  Please change value of the variable 'increasePercent' as required.

//Formatting datalabels 
widget.on('processresult', function(se,ev){
	var maxValue = 0
	var increasePercent = 0.2 //variable to adjust right space. Change this value as needed
		
	$.each(ev.result.series, function(seriesIndex, value){
		
		$.each(value.data, function(di, dataItem){
			if(dataItem.y > maxValue)
				maxValue = dataItem.y
		})
		
		value.dataLabels = {
									backgroundColor: '#f5d142', //data label color
									color: 'white',
									padding: 5,
									borderRadius: 5
								}
	
	})
	
	ev.result.yAxis[0].max = maxValue + (increasePercent * maxValue) ;
		
})

//Adjusting position of datalabels
widget.on('domready', function(se,ev){
	
	barWidth = $('.highcharts-series-group .highcharts-series rect', element).width()
	
	$('.highcharts-data-labels .highcharts-label', element).each(function(){
		labelWidth = $(this).find('rect').width()
		labelHeight = $(this).find('rect').height()
		
		$(this).find('rect').attr('x', ($(this).find('rect').attr('x') + 2))
		$(this).find('rect').attr('height', barWidth)
		$(this).find('rect').attr('y', ((labelHeight - barWidth)/2))
	
	})

});

 Thanks

-Hari

BOOM! That worked! Thank you so much! @harikm007 

 

@harikm007  what would the equivalent of this be for column chart?

harikm007
13 - Data Warehouse
13 - Data Warehouse

@cartercjb This is the script for column chart : 

//Formatting datalabels 
widget.on('processresult', function(se,ev){
	var maxValue = 0
	var increasePercent = 0.2//variable to adjust right space. Change this value as needed
		
	$.each(ev.result.series, function(seriesIndex, value){
		
		$.each(value.data, function(di, dataItem){
			if(dataItem.y > maxValue)
				maxValue = dataItem.y
		})
		
		value.dataLabels = {
									backgroundColor: '#f5d142', //data label color
									color: 'black',
									padding: 5,
									borderRadius: 5
								}
	
	})
	
	ev.result.yAxis[0].max = maxValue + (increasePercent * maxValue) ;
		
})

//Adjusting position of datalabels
widget.on('domready', function(se,ev){
	
	barWidth = $('.highcharts-series-group .highcharts-series rect', element).width()
	
	$('.highcharts-data-labels .highcharts-label', element).each(function(){
		labelWidth = $(this).find('rect').width()
		labelHeight = $(this).find('rect').height()
		$(this).find('rect').attr('width', barWidth)
		$(this).find('rect').attr('height', labelHeight - 5)
		$(this).find('rect').attr('x', ((labelWidth - barWidth)/2))
	
	})

});

Thanks

-Hari

@harikm007  Hari - 

Any idea what would be causing this  widget to not show any of the bars, even though there is data present?  

 
var categories= ['NF','NE','ND','NC','NB','NA'];
var breakBy = [];
 
// ---------- DO NOT EDIT BELOW THIS LINE ----------
 
var findIndex = function(val, list) {
 if (list=='breakby') { 
  return breakBy.indexOf(val) 
 } else if (list=='categories') { 
  return categories.indexOf(val)
 }
};

widget.on('processresult',function(se,ev){
 //determine if we should sort categories or breakbys
 categoryStatus=false;
 breakStatus=false;
 
 for (p=0; p<ev.widget.metadata.panels.length; p++){
  if (ev.widget.metadata.panels[p].name=="categories" && ev.widget.metadata.panels[p].items.length>0 && categories.length>0){
   categoryStatus=true;
  }
  else if (ev.widget.metadata.panels[p].name=="break by" && ev.widget.metadata.panels[p].items.length>0 && breakBy.length>0){
   breakStatus=true;
  }
 };
 
 if (categoryStatus){
  ev.result.series.forEach( function(bb) {
   newData= new Array(categories.length);
   var blankcat;
   bb.data.forEach( function(cat) {
    if (typeof cat.selectionData !== 'undefined'){
     newData[findIndex(cat.selectionData[0].trim(), 'categories')]=cat;
    }
    else{
     blankcat=cat; 
    }
   })
   for (i=0; i<newData.length; i++) {
    if (typeof newData[i] === 'undefined') {
     newData[i]=blankcat; 
    }
   }
   bb.data=newData;
  });
  ev.result.xAxis.categories=categories;
 };
 
 if (breakStatus) {
  ev.result.series.sort(function(a,b){
   if (findIndex(a.name, 'breakby') < findIndex(b.name,'breakby')) {
    return -1
   } else if (findIndex(a.name,'breakby') > findIndex(b.name,'breakby')) {
    return 1
   }
   return 0;
  });
 };
});


//Formatting datalabels 
widget.on('processresult', function(se,ev){
	var maxValue = 0
	var increasePercent = 0.2//variable to adjust right space. Change this value as needed
		
	$.each(ev.result.series, function(seriesIndex, value){
		
		$.each(value.data, function(di, dataItem){
			if(dataItem.y > maxValue)
				maxValue = dataItem.y
		})
		
		value.dataLabels = {
									backgroundColor: value.color, //data label color
									color: 'white',
									padding: 2,
									borderRadius: 2
								}
	
	})
	
	ev.result.yAxis[0].max = maxValue + (increasePercent * maxValue) ;
		
})

//Adjusting position of datalabels
widget.on('domready', function(se,ev){
	
	barWidth = $('.highcharts-series-group .highcharts-series rect', element).width()
	
	$('.highcharts-data-labels .highcharts-label', element).each(function(){
		labelWidth = $(this).find('rect').width()
		labelHeight = $(this).find('rect').height()
		$(this).find('rect').attr('width', barWidth)
		$(this).find('rect').attr('height', labelHeight - 5)
		$(this).find('rect').attr('x', ((labelWidth - barWidth)/2))
	
	})

});

harikm007
13 - Data Warehouse
13 - Data Warehouse

@cartercjb ,

Can you try following steps:

Remove/comment script to sort categories and see if bars are visible.

If bars are visible, check if all categories are showing in widget and category names are exactly same as 'categories' array in script (check if there is trailing and leading spaces in table)

var categories= ['NF','NE','ND','NC','NB','NA'];

 

 

Also you can try below script to sort categories : 

var categories= ['NF','NE','ND','NC','NB','NA'];

widget.on('queryend',function(se,ev){
	ev.rawResult.values.sort(function(a, b){
		var aIndex = categories.indexOf(a[0].data.trim());
		var bIndex = categories.indexOf(b[0].data.trim());

		if (aIndex < bIndex)
			return -1;
		if (aIndex > bIndex)
			return 1;

		return 0;
	})
})

 

Hari @harikm007 - 

How would you add to this script so that the x-axis labels align left? I've tried a few different things but neither work. 

harikm007
13 - Data Warehouse
13 - Data Warehouse

Hi @cartercjb ,

Are you looking for something like this?

harikm007_0-1647338881863.png

If yes, try this script:

widget.on('processresult', function(se, ev){
	ev.result.xAxis.labels.align = 'left'
	ev.result.xAxis.labels.reserveSpace = true
})

-Hari