Flotr2 - hover on point in line chart - javascript

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.

Related

dc.js bar chart - calculate bar size by sum of multiple data entries

Sorry for the title, it is hard to sumarize what I am trying to achieve in one sentence.
I have a bar chart that uses a crossfilter that is also used by 6 other charts. My data looks as follows (note: this is only a small sample, there are more keys in each object)
var data = [
{ clientime : '20210603000000', calendarweek : '22', x : 9, y : 4 },
{ clientime : '20210603000007', calendarweek : '22', x : 5, y : 5 },
{ clientime : '20210607000000', calendarweek : '23', x : 1, y : 2 },
{ clientime : '20210607000007', calendarweek : '23', x : 5, y : 5 },
{ clientime : '20210615000000', calendarweek : '24', x : 10, y : 20 },
{ clientime : '20210615000011', calendarweek : '24', x : 5, y : 5 },
];
The category for each bar is the calendarweek and I wan the the value to be the sum of all x devided by the sum of all y.
According to the above sample I would like to see 3 bars.
Bar '22' should have the value `sum(9,5)/sum(4,5)` = 1.556
Bar '23' should have the value `sum(1,5)/sum(2,5)` = 0.857
Bar '24' should have the value `sum(10,5)/sum(20,5)` = 0.6
My first intention wasto use the reduce function where I would add or remove the sums in a custom dictionary.
var x_key = "calendarweek";
var dim = crossfilter.dimension( d => d[x_key] );
var grp = dim.group().reduce(
( p, v ) => {
p.sum_x += v.x;
p.sum_y += v.y;
return p;
},
( p, v ) => {
p.sum_x -= v.x;
p.sum_y -= v.y;
return p;
},
() => ( { sum_x : 0, sum_y : 0 } )
);
var chart = dc.barChart( "#chart" );
chart
.width( 490 )
.height( 280 )
.dimension( dim )
.group( grp )
.x( d3.scaleBand() )
.xUnits( dc.units.ordinal )
.elasticX( true )
.elasticY( true )
.controlsUseVisibility( true )
.margins( {
top : 10, right : 50, bottom : 20, left : 40,
} );
grp.all() does seem to look fine but from here on out I am not sure how to set the data correctly to chart. Using the created group no bars are shown at all because I creted an object in the reduce function that dc.js does not understand.
Additionally I would like to still be able to limit the bars to N entries.
Thanks to Gordon in the comments pointing me into the right direction I was able to solve my problem using the valueAccesor.
chart_mttrhist.valueAccessor( function( d ) {
return ( d.value.sum_x / d.value.sum_y );
} );
Please note that the code in the question changed a little.

C3JS - Group dates correctly

I'm using the library c3js to show an area chart.
I've a problem with my dates data. I've a lot of dates (+/- 1000) and I want to group correctly my dates.
Here is my actuel render :
[
You can see that some dates appear two time on x axis.
Here is the code of my chart :
var usedList = JSON.parse(usedList);
var format = informations[0];
var counts = informations[1];
var amounts = new Array('Evolution');
var dates = new Array("x");
for (var i = 0; i < usedList.length; i++)
{
amounts.push(usedList[i].price);
dates.push(usedList[i].date);
}
var chart = c3.generate({
bindto : '#js-chart',
size : {
height : 220
},
area: {
zerobased: false
},
data : {
selection : {
draggable : false
},
x : 'x',
columns : [ dates, amounts ],
types : {
Evolution : 'area'
},
colors : {
Evolution : '#143FB4'
}
},
axis : {
x : {
type : 'timeseries',
tick : {
fit: true,
format : format
},
padding: {
left: 0,
right: 0,
}
}
},
point : {
r : 0
},
grid : {
y : {
show : true
}
}
});
How do you think I can do to regroup date in order to have just one repetition of each month ?
Thank you,
David
What if push only one date for a month?
for (var i = 0; i < usedList.length; i++)
{
amounts.push(usedList[i].price);
// replacing existing dates with empty string, keeping array size
var d = usedList[i].date;
dates.push(dates.indexOf(d) == -1 ? d : '');
}
This should work if dates are stored as 'MM/YYYY'.
If dates are stored in a different format, different check is needed.
But general idea stays the same - only one date for a month at x-axis.

Highcharts | Custom plotOptions->series->dataLabels

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,

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.

Jqplot tooltip values incorrect when chart has two lines

I have a jqplot chart that has two lines. I'm using tooltipContentEditor to modify the text displayed in the tooltip. Prior to adding the second line, the tooltips displayed the values fine. Now that I have added another line, the tooltips always show the data for the second line (thus incorrectly for the first). How do I have the correct values displayed?
Blue line tooltip shows yellow line value:
Chart initialization (tooltipContentEditor function inside):
$.jqplot('mychart', [coords, paidCoords], {
//title:'Sales for ' + name,
animate: !$.jqplot.use_excanvas,
axesDefaults: {
tickRenderer: $.jqplot.CanvasAxisTickRenderer ,
},
axes:{
xaxis:{
renderer:$.jqplot.DateAxisRenderer,
tickInterval: tickInterval,
tickOptions: { formatString: formatString, angle: -30 }
},
yaxis:{
min:0
}
},
highlighter: {
show: true,
sizeAdjust: 7.5,
tooltipContentEditor: function(str, pointIndex, index, plot){
console.log('logging in tooltipeditor');
console.log(str);
console.log(pointIndex);
console.log(index);
console.log(plot);
var splitted = plot._plotData[1][index];
var x = splitted[0];
var y = splitted[1];
x = new Date(x);
x = x.toString();
return x + "<br/>$" + y;
}
},
cursor:{
show: true,
zoom:true,
showTooltip:false
}
});
Nevermind! I figured it out! In the tooltipContentEditor function I needed to do this:
var splitted = str.split(",");
Instead of this:
var splitted = plot._plotData[1][index];

Categories

Resources