Highcharts | Custom plotOptions->series->dataLabels - javascript

I'm trying to do a really specific graph with HighChart, I hope I will be clear.
I give an example, I have votes for each country like this :
France 2 yes / 1 No
England 1 yes / 0 No
I have to display in plotOptions->series->dataLabels the information like this :
France yes : 2 votes/66% Because we have 3 votes in total for France
France no : 1 votes/33%
England yes : 1 votes/100% Because we have 1 vote in total for England
England no : 0 votes/0%
In Php / Symfony 3 / Javascript I did something like this :
$ob->plotOptions->series(
array(
'dataLabels' => array(
'enabled' => true,
'formatter' => new Expr('function () {
return this.y + "<br/>(" + Math.round(((this.y / '.$numberOfResultsByCountry.') * 100) * 100) / 100 + " %)"
}')
)
)
);
It works, but the calcul is wrong, $numberOfResultsByCountry change in function of my country, for France the value is 3, for England the value is 1.
How can I custom the dataLabels for each result ? I checked doc (http://api.highcharts.com/highcharts#plotOptions.series.dataLabels) and It seems that plotOptions->series->dataLabels does not accept an array here. So I have no idea how to do it.
I hope I have been clear to explain my problem.
TY

I think that you can add your total votes number as a 'total' parameter, and then find this parameter using this.point.total.
$(function() {
$('#container').highcharts({
xAxis: {
type: 'category'
},
series: [{
type: 'column',
keys: ['x', 'y', 'total'],
data: [
[0, 3, 5],
[1, 1, 4],
[2, 3, 3],
[3, 0, 4]
],
dataLabels: {
enabled: true,
formatter: function() {
return this.y + "<br/>(" + Math.round(((this.y / this.point.total) * 100) * 100) / 100 + " %)"
}
}
}]
});
});
I am using keys for adding new parameter to my points. You can find information about this parameter here: http://api.highcharts.com/highcharts#plotOptions.series.keys
Here you can find an example how it can work:
http://jsfiddle.net/m28ob7r7/
Regards,

Related

Defining 'step' attribute in Zingchart renders the graph unusable

Scenario:
I am able to get a status graph with Zingchart, using a stacked hbar and plotting data intervals where the status of an element doesn't change:
However, I would like to have more resolution in the axis that provides the time.
Problem:
I am not able to increase the number of ticks in the y-axis (this is an stacked hbar graph, so the usual x-axis is actually the y-axis).
If I introduce step:"1hour", in the scaleY field I get back to epoch 0 and this is what I obtain:
Question:
What am I doing wrong? I would like either:
To have more time references in the axis of the time.
Or (and this may be another question) to be able to know on mouse over (in the tooltip?) at what time I am. Since I am plotting time increments I lost the actual time on where the change of status happens. Is there a direct way to do this in this particular situation? Or do I have to carry another data-customValue for the actual date of the start / end of the interval?
In the code, I jump from epoch 0 to the time I start having data, and define minValue to plot as the first epoch I have data minus one second.
This is the working code (no step attribute defined):
<!DOCTYPE html>
<html>
<head>
<script src="/home/eballes/Work/backup/zingchart_test/zingchart_2.3.3/zingchart.min.js"></script>
<script>
zingchart.MODULESDIR = "/home/eballes/Work/backup/zingchart_test/zingchart_2.3.3/modules/";
</script>
<style></style>
</head>
<body>
<div id='myChart'></div>
<script>
var myConfig = {
type: "hbar",
utc:true,
title: {
text: 'Status'
},
scaleY:{
transform:{
type:'date',
all:"%d/%M/%Y\n%H:%i:%s",
},
minValue:1456693864000,
zooming:true,
label:{
"text": "Time",
},
tick:{
"line-color":"black",
"line-width":"2px",
"size":8,
},
maxItems:10,
itemsOverlap:true,
item:{
"font-size":10
},
},
scaleX:{
label:{
"text": "Item",
},
},
plot:{
stacked:true,
exact:false,
barWidth:10,
rules:[
{
rule:'%data-customValue == 0',
alpha:0, // Transparent
},
{
rule:'%data-customValue == 1',
backgroundColor:'#0000FF' // Dark Blue
},
{
rule:'%data-customValue == 2',
backgroundColor:'#00FFFF' // Light Blue
},
{
rule:'%data-customValue == 3',
backgroundColor:'#FF7F50' // Orange
},
{
rule:'%data-customValue == 4',
backgroundColor:'#FFFF00' // Yellow
},
{
rule:'%data-customValue == 5',
backgroundColor:'#EE82EE' // Purple
},
{
rule:'%data-customValue == 6',
backgroundColor:'#00FF00' // Green
},
{
rule:'%data-customValue == 7',
backgroundColor:'#FF0000' // Red
},
]
},
tooltip:{
jsRule:"CustomFn.formatTooltip()",
},
series : [
{
values : [
[1,1456693864000],
[2,1456693864000],
.... // From 1 to 36
[36,1456693864000],
],
'data-customValue':[0,0,0,0,0,0,
0,0,0,0,0,0,
0,0,0,0,0,0,
0,0,0,0,0,0,
0,0,0,0,0,0,
0,0,0,0,0,0],
},
{
values : [
[11, 32000], [12, 10270000], [14, 5033000], [18, 79000], [20, 43000], [24, 76000], [26, 4043000], [8, 33000], [9, 63000],
],
'data-customValue':[2, 6, 6, 0, 1, 2, 6, 1, 0, ],
},
{
values : [
[14, 3000], [19, 20000], [26, 1000], [8, 86000], [9, 13000],
],
'data-customValue':[2, 2, 2, 0, 1, ],
},
// All intervals
]
};
CustomFn = {};
CustomFn.formatTooltip = function(p){
var hours = Math.floor(p.value / 3600000);
var minutes = Math.floor((p.value % 3600000) / 60000);
var seconds = (p.value % 60000)/1000;
var tooltipText = "Item: " + p.scaletext + "\nDuration: ";
var hoursText = (hours == 0) ? "" : (hours + "h ");
var minutesText = (minutes == 0) ? "" : (minutes + "m");
var secondsText = (seconds == 0) ? "" : (seconds + "s");
tooltipText = tooltipText + hoursText + minutesText + secondsText + "\n";
tooltipText = tooltipText + "Value: " + p['data-customValue'];
var alpha = 70;
// We don't want any tooltip for the time-jump
if (hours > 300000) {
tooltipText = "";
alpha = 0;
}
return {
text : tooltipText,
backgroundColor : "#222",
alpha: alpha,
}
};
zingchart.render({
id : 'myChart',
data : myConfig,
height: 670,
width: '100%'
});
</script>
</body>
</html>
This is the link to the Plunker with the whole example, not working. If you remove the line step:"1hour", it will work.
Funny enough, step:20 works fine. But I would prefer to have my steps in a normal way, like hourly.
Note: Just to provide some more context, this question is the continuation of this other previous question.
Full Disclosure, I'm a member of the ZingChart team.
The first problem being
step:'1hour'
That string value is being interpreted by our library as the value 0. This is because the string '1hour' does not match any of our keywords nor does it evaluate to a Number type. We are not simply using parseInt so it does not evaluate to 1.
If you want an hourly step you would do the step count in milliseconds. This is documented in our scales page.
step:3600000
For display the scale value we do have a tokens list which allows you to add values from your scale to your tooltip. In your customFn.formatTooltip you would add this line.
...
tooltipText = tooltipText + "Value: " + p['data-customValue'];
tooltipText += '<br> %vv'
The %vv is in our tokens list and will grab the transformed value off the y-axis. If you did %vt it would give you the millisecond value.

Flotr2 - hover on point in line chart

I have a Flotr2 barchart with linecharts on them, when you hover the linechart you should see the coordinates in a tooltip.
The problem is that the tooltips are not show for the 2 lowest points in the linechart on top of the green bar chart.
See this jsfiddle: http://jsfiddle.net/P855Q/1/
This is the javascript for the charts:
(function basic_bars (container, horizontal) {
var NumberOfBars = 3;
var barcenters = [];
var barWidth = ( (1 / NumberOfBars) * 0.8 )
var barcenterAdjust = (barWidth * (NumberOfBars/2)) - (barWidth/2.2);
for (i = 0; i < NumberOfBars; i++) {
var barcenter = (i *(( 1 / NumberOfBars ) * 0.8));
barcenter = barcenter - barcenterAdjust;
barcenters.push(barcenter);
}
var dummyVar,
d0=[
[barcenters[0] + 3, 5],
[barcenters[0] + 3, 8.1333],
[barcenters[0] + 3, 9]
],
d7=[
[barcenters[1] + 3, 5],
[barcenters[1] + 3, 8.1333],
[barcenters[1] + 3, 9]
],
d14=[
[barcenters[2] + 3, 5],
[barcenters[2] + 3, 8.1333],
[barcenters[2] + 3, 9]
];
var a = [[3,8.303000]];
var b = [[3,8.574500]];
var c = [[3,8.222200]];
Flotr.draw(
container,[
{ data : a, label : 'a' , bars: {show : true, horizontal : false, shadowSize : 0, barWidth : 0.8, grouped: true, mouse:{track:false}} },
{ data : b, label : 'b' , bars: {show : true, horizontal : false, shadowSize : 0, barWidth : 0.8, grouped: true, mouse:{track:false}} },
{ data : c, label : 'c' , bars: {show : true, horizontal : false, shadowSize : 0, barWidth : 0.8, grouped: true, mouse:{track:false}} },
{ data : d7 , lines : { show : true }, points : { show : true },mouse:{track:true,trackFormatter: function(obj){ return obj.y; },relative: true}, color: '#999999'},
{ data : d14 , lines : { show : true }, points : { show : true },mouse:{track:true,trackFormatter: function(obj){ return obj.y; },relative: true}, color: '#999999'},
{ data : d0 , lines : { show : true }, points : { show : true },mouse:{track:true,trackFormatter: function(obj){ return obj.y; },relative: true}, color: '#999999'},
],
{
yaxis : {min : 1,max: 10,noTicks: 10,tickDecimals: 0,autoscaleMargin : 1},
xaxis : {min: 0,ticks: [["1", "1"],["2", "2"],["3", "3"],["4", "4"],["5", "5"],["6", "6"],["7", "7"],["8", "8"]]}
}
);
})(document.getElementById("example"));
I have analysed its details and found out that the fiddle is fine!
Also code looks fine,(Except barcenters part of code which seems of causing some issue..
but with some value tags the event is not firing which will change value for
<div class="flotr-mouse-value">
the above is the div with class which gives us the tooltip for the point value.
It is relocated dynamically each time we hover on any point.
I have done some tweaking to test whether the reason is due to drawing on same point 3 but with that I found no issue..(although one point started functioning) B(8.1) which was not working started working !! without any certain change But B(5.0) is still not working..
Now as the point is not getting focus>> the even is not fired which enables the toolTip(which shows point value)
As in the element <div id="example"></div> is dynamically filled by the script we can conclude the floatr script has some internal bug within the overlay drawing part,that is causing this issue..
Update 1: One weird behavior observed with the Bar in center, as that is only seems to not working, with the overlay lines changed on that; check updated fiddle
I am still looking in details, if something new comes up in will Update my answer.

Highcharts X-Axis Issue

I have googled and searched stack overflow alot before deciding to ask this question here because while some questions seemed similar, none of the solutions worked for me.
I have categorised data from sometimes a very wide range eg 1881 - 2012 and would like to dynamically calculate and divide this range into only 11 points on the x-axis which is what I have room to display with no zooming enabled. If data is from from 1881 - 2012, I would like it for example want it to show(not exactly calculated) from 1881, 1901, 1921, 1941.....if its from 1958 - 2013, then 1958, 1968, 1978....
xAxis: {
categories: range(start_year,end_year),
tickmarkPlacement: "on",
tickInterval: Math.ceil(range(start_year,end_year).length/11),
},
.......
function range(start_year,end_year)
{
var years = [];
for(var i = start_year;i<=end_year;i++)
{
years.push(i);
}
return years;
}
What this code does is just skip the labels for certain years but still plots the points on the graph leading to overlapping years on the x-axis.
Any leads on this would be highly appreciated.
Here's the fiddle illustrating my dilemma http://jsfiddle.net/YUPzk/4/
You can use tickPositioner and prepare your own calculating function.
The JavaScript below is one example of how this can be done:
Highcharts.chart('container', {
title: {
text: 'Custom tick positions'
},
subtitle: {
text: 'through axis.tickPositions and axis.tickPositioner'
},
xAxis: {
tickPositions: [0, 1, 2, 4, 8]
},
yAxis: {
tickPositioner: function () {
var positions = [],
tick = Math.floor(this.dataMin),
increment = Math.ceil((this.dataMax - this.dataMin) / 6);
if (this.dataMax !== null && this.dataMin !== null) {
for (tick; tick - increment <= this.dataMax; tick += increment) {
positions.push(tick);
}
}
return positions;
}
},
series: [{
data: [ [0, 1],[1, 3],[2, 2],[4, 4],[8, 3] ]
}]
});
The above demo code can be found at this jsfiddle
For anyone else struggling to get this done, here's what you need because i did lot's of googling with no answers to be found for people experiencing same challenge
Highcharts ; x-axis scaling issue

jqPlot points not correct when numberTicks set

I'm trying to limit the number of ticks on a dynamic jqplot I'm setting up. Unfortunately, when I do it, the points do not look accurate. Here's what it looks like:
As you can see, the point on 10/05/12, for example, is not on it's correct axis. I realize that now these points are estimated, but the points must look accurate on the graph -- especially when hovering over the points gives you their correct date and y-axis value.
Here's my code for this intilization, if that helps:
var datepickerBegin = $("#datepicker_start").datepicker({dateFormat: "dd/mm/yyyy"}).val();
var datepickerEnd = $("#datepicker_to").datepicker({dateFormat: "dd/mm/yyyy"}).val();
var startDiff = $("#datepicker_start").datepicker("getDate");
var endDiff = $("#datepicker_to").datepicker("getDate");
alert(startDiff)
alert(endDiff)
// Check if dates are more than a week apart
if(endDiff - startDiff >= 15 * 86400 * 1000) {
var plot2 = $.jqplot('chart2', jsonurl,{
title: "Storage Space",
dataRenderer: ajaxDataRenderer,
dataRendererOptions: {unusedOptionalUrl: jsonurl},
axes: {
xaxis: {
'numberTicks' : 15,
min: datepickerBegin,
max: datepickerEnd,
renderer:$.jqplot.DateAxisRenderer,
rendererOptions:{tickRenderer:$.jqplot.CanvasAxisTickRenderer},
tickInterval: '1 day',
tickOptions:{formatString:'%#m/%#d/%Y'
}
},
yaxis: {
label: "MB",
tickOptions:{formatString:'%d '},
min: 0
}
},
highlighter: {
show: true,
sizeAdjust: 7.5
}
});
// Somehow fix the line?
plot2.redraw({});
}
Anyone out there have a fix for this? Thanks!

How to set Date Value for x Axis using gRaphael Line Graph

I've recently started to use gRaphael for my graphing needs and am pretty impressed so far. However, I have run into some difficulty when producing line graphs, specifically that when I attempt to set the values for the X axis to dates, the graph fails to render. My code to generate the graph is:
<script type='text/javascript' charset='utf-8'>
var r = Raphael('holder');
var lines = r.g.linechart(20, 20, 600, 300, [[1, 2, 3, 4, 5, 6, 7]], [['4.16','6.35','1.77','3.1','9.79','10.03','-0.3']], {nostroke: false, axis: '0 0 1 1', symbol: 'o', smooth: false}).hoverColumn(function () {
this.tags = r.set();
for (var i = 0, ii = this.y.length; i < ii; i++) {
this.tags.push(r.g.tag(this.x, this.y[i], this.values[i], 160, 10).insertBefore(this).attr([{fill: '#fff'}, {fill: this.symbols[i].attr('fill')}]));
}
}, function () {
this.tags && this.tags.remove();
});
lines.symbols.attr({r: 3});
</script>
<div id='holder'></div>
How would I be able to replace the X axis values '1, 2, 3, 4, 5, 6, 7' with say, 'Jan 2001, Feb 2001, Mar 2001...etc...etc....'?
Many thanks indeed, all help much appreciated!
At first you have to give the chart some values that it will not complain about.
In your case you could save the UNIX timestamp etc
Then you can alter the values using something like this (Using prototype etc):
lines.axis[0].text.items.each( function ( index, label ) {
//Get the timestamp you saved
originalText = label.attr('text');
newText = 'CONVERT TIMESTAMP TO DATE USING originalText as input HERE';
//label.rotate(75);
label.attr({'text': newText});
});
The .each can be replaced by a regular
for(var x = 0; x < lines.axis[0].text.length; x++)
loop if you like.
$.each(lines.axis[0].text.items , function ( index, label ) {
var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
date = new Date(parseInt(label.attr("text"))),
day = date.getDate(),
month = months[date.getMonth()];;
dateText = month + " " + day;
//label.rotate(75);
label.attr({'text': dateText});
});

Categories

Resources