Issue with tooltip on flotchart for date format - charts

I am facing an issue with tooltip showing date in x-axis.
Can anyone help on this?
fiddle code
grid: {
hoverable: true //IMPORTANT! this is needed for tooltip to work
},
tooltip: true,
tooltipOpts: {
content: "<h4>%s</h4><ul><li>Date is %x</li><li>Total Count: %y</li></ul>",
defaultTheme: false
},
points:
{
show: true
},
series: {
bars: {
show: true,
barWidth: 0.1,
order: 1
}
}

You need a function to convert the x value (which is only a number / timestamp) to an actual date.
Use something like this:
tooltipOpts: {
content: function (label, x, y) {
var date = new Date(+x);
var tooltip = '<h4>' + label + '</h4><ul>';
tooltip += '<li>Date is ' + date.toLocaleDateString() + '</li>';
tooltip += '<li>Total Count: ' + y + '</li></ul>';
return tooltip;
},
See this update fiddle.

Related

How do I leave the clicked point highlighted in dygraphs?

I am using the selected shapes to draw a larger diamond shape on my graph. When a user clicks a point. I display the data in another div, but I want to leave the clicked point highlighted. In other words, I want to 'toggle' data behind the points on and off and the clicked points need to show if they are included in the dataset. I believe I have seen this somewhere but I cannot find it. Is there a 'standard' way of leaving a clicked point in the 'highlight' state when you mouse away after clicking?
Here is my code. The pointClickCallback is getting the data through ajax and displaying it in another div. That part works. I just want to leave the point highlighted so I know which points I have clicked on.
I also need the point to revert back to normal when I click a second time. This is a toggle that allows me to select and unselect points.
EDIT: I found the interaction model example but when I add it to my code I lose my pointClickCallback functionality. I saw the call to captureCanvas and the interaction model structure.
var g = new Dygraph(document.getElementById('rothmangraph'), lines, {
//showRangeSelector: true,
title: "Personal Wellness Index (PWI)",
labels: ['Date', 'Index'],
color: ['#006699'],
valueRange: [0, 101],
axisLabelFontSize: 12,
drawPoints: true,
gridLineColor: "#aaaaaa",
includeZero: true,
strokeWidth: 2,
rightGap: 20,
pointSize: 4,
highlightCircleSize: 8,
series : {
Index: {
drawHighlightPointCallback : Dygraph.Circles.DIAMOND
},
},
axes: {
y: {
pixelsPerLabel: 20,
},
x: {
valueFormatter: function(ms) {
return ' ' + strftime('%m/%d/%Y %r',new Date(ms)) + ' ';
},
axisLabelWidth: 60,
axisLabelFormatter: function(d, gran) {
return strftime('%m/%d %I:%M %p',new Date(d.getTime())) ;
}
}
},
underlayCallback: function (canvas, area, g) {
var warning = g.toDomCoords(0,41);
var critical = g.toDomCoords(0,66);
// set background color
canvas.fillStyle = graphCol;
canvas.fillRect(area.x, area.y, area.w, area.h);
// critical threshold line
canvas.fillStyle = "#cc0000";
canvas.fillRect(area.x,warning[1],area.w,2);
// warning threshold line
canvas.fillStyle = "#cccc00";
canvas.fillRect(area.x,critical[1],area.w,2);
},
pointClickCallback: function(e,point) {
var idx = point.idx;
var line = lines[idx];
var sqltime = strftime('%Y-%m-%d %H:%M:%S',new Date(line[0]));
var dispdate = strftime('%m/%d %r',new Date(line[0]));
_secureAjax({
url: '/ajax/getDataPoint',
data: {'patient_id': pid, "rdate": sqltime},
success: function (result) {
// parse and add row to table if not exists.
var data = JSON.parse(result);
var aid = data['id'];
var indexCol = "#a9cced"
if (line[1] <= 65) indexCol = "#ede1b7";
if (line[1] <= 40) indexCol = "#e5bfcc";
var headerinfo = '<th class="'+aid+'"><span class="showindex" style="background-color:'+indexCol+'">'+line[1]+'</span></th>';
var fixdate = dispdate.replace(' ','<br>');
var headerdate = '<th class="'+aid+'">'+fixdate+'</th>';
// skip if already exists
var found = false;
var whichone = false;
$('#headerdate tr th').each(function(idx, item) {
if (fixdate == $(this).html()) {
found = true;
whichone = idx;
}
});
if (!found) {
$.each(data, function (idx, item) {
$('#' + idx).append('<td class="'+aid+'" style="width:70px">' + item + '</td>');
});
$('#headerdate tr').append(headerdate);
$('#headerinfo tr').append(headerinfo);
} else {
$('tr').each(function() {
$('.'+aid).remove();
});
}
}
});
}
});
}

DYGRAPHS: Annotation on scatter point of the same date

In my scatter plot, there are points of the same date but i only want to annotate one. How can I specify that in my annotation data?
jsfiddle
g = new Dygraph(
document.getElementById("container"),
"Date,Temperature\n" +
"2008-05-07,75\n" +
"2008-05-08,70\n" +
"2008-05-08,20\n" +
"2008-05-09,80\n"
);
g.ready(function() {
g.setAnnotations([
{
series: "Temperature",
x: "2008-05-08",
shortText: "L",
text: "Coldest Day"
}
]);
});
You could do it this way, by adding a second to your datapoint you don't want to be labeled.
https://jsfiddle.net/55ktaue1/3/
I would then use the formatting functionality to remove the timestamp from the date. 'legendFormatter' examples: http://dygraphs.com/tests/legend-formatter.html http://dygraphs.com/tests/labelsDateMilliseconds.html http://dygraphs.com/tests/labelsDateUTC.html
g = new Dygraph(
document.getElementById("container"),
"Date,Temperature\n" +
"2008-05-07,75\n" +
"2008-05-08,70\n" +
"2008-05-08 00:00:01,20\n" +
"2008-05-09,80\n"
);
g.ready(function() {
g.setAnnotations([
{
series: "Temperature",
x: "2008-05-08",
shortText: "L",
text: "Coldest Day"
}
]);
});

ChartJS / MomentJS - Unable to remove deprecation warning. Graph not showing in firefox/opera

so browsers throw
warning about using momentJS incorrectly.
Deprecation warning: value provided is not in a recognized ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.
Arguments:
[0] _isAMomentObject: true, _isUTC: false, _useUTC: false, _l: undefined, _i: 12.30, _f: false, _strict: undefined, _locale: [object Object]
Error
So i looked at my code
data: {
labels: ['01.01', '02.01', '03.01', '04.01', '05.01', '06.01', '07.01', '08.01', '09.01', '10.01', '11.01', '12.01'],
datasets: createChatterData(data, this)
},
And read that I should provide a format when dealing with non iso strings.
labels: [moment('01.01', 'MM.DD'), moment('02.01', 'MM.DD'), ...];
Ok that removed first deprecation.
But my datasets data also contains of date
dataset.data.pushObject({
x: moment(datum).format('MM.DD'),
y: parseInt(moment(datum).format('YYYY'))
});
So I tried different variations to that (premodified ambigious datetime)
x: moment(date, 'YYYY.MM.DD').format('MM.DD')
and
x: moment(date, 'MM.DD')
But my graph doesnt map correctly anymore.
Example of codepen chart working in chrome: http://codepen.io/kristjanrein/pen/wJrQLE
Does not display in firefox/opera
I see a couple of issues here.
1) Since you want your X axis to be a time scale, then you should leave your X data value as a moment object. Your current implementation is creating a moment object from a date string and then formatting it back to a string. When you do this, chart.js then takes the string and tries to create a moment object internally when it builds the chart.
Therefore, It is best to keep the data as either a Date or Moment object and use the time scale configuration properties to determine how the data is displayed on the chart. This prevents chart.js from having to construct the moment object and guess at the string format.
2) You are using the pre-2.0 way to create a chart when you use Chart.Scatter. Instead you should use the new style (new Chart()) and pass in a type property.
Here is a modified version of you code that results in no browser warnings and works in Chrome and Firefox (I did not test in Opera).
var getData = function() {
var dummyDataset = [
'2007-11-09T00:00:00.000Z',
'2006-08-04T00:00:00.000Z',
'2006-08-06T00:00:00.000Z',
'2008-01-10T00:00:00.000Z'
];
return dummyDataset.map(function(datum) {
var myMoment = moment(datum);
return {
x: myMoment,
y: parseInt(myMoment.format('YYYY')),
};
});
};
var ctx = document.getElementById("chart1").getContext("2d");
var myScatter = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
label: "My First dataset",
borderColor: 'rgb(255, 99, 132)',
fill: false,
pointRadius: 4,
pointHoverRadius: 8,
showLine: false,
data: getData()
}]
},
options: {
responsive: true,
title: {
display: true,
text: 'Random Data'
},
legend: {
display: true,
labels: {
fontSize: 10,
boxWidth: 20
}
},
elements: {
point: {
pointStyle: 'rect'
}
},
hover: {
mode: 'nearest'
},
scales: {
xAxes: [{
type: 'time',
position: 'bottom',
scaleLabel: {
display: true,
labelString: 'Months'
},
time: {
unit: 'month',
displayFormats: {
month: 'MM'
},
}
}],
yAxes: [ {
type: 'linear',
ticks: {
min: 2005,
max: 2015,
stepSize: 1
},
scaleLabel: {
display: true,
labelString: 'Year'
}
}]
}
}
});
You can see it in action at this forked codepen.
One other thing to keep in mind is that because your data spans multiple years, you will see duplicate months on the X axis. Remember, a time scale is used to plot dates so even if you only display the months, a data point with the same month but with different years will not be plotted at the same location.
If you are actually only wanting to show month string/number values in the X axis, then you should not use the time scale at all and use the linear scale instead. Then when you build your data values, you would extract the month from the data (the same way you are already doing for your Y value).
var getData = function() {
var dummyDataset = [
'2007-11-09T00:00:00.000Z',
'2006-08-04T00:00:00.000Z',
'2006-08-06T00:00:00.000Z',
'2008-01-10T00:00:00.000Z'
];
return dummyDataset.map(function(datum) {
var myMoment = moment(datum);
return {
x: parseInt(myMoment.format('MM')),
y: parseInt(myMoment.format('YYYY')),
};
});
};
So in addition to jordan's answer
I changed my labels and x axis from
['01.01', '02.01', ...] to [1,2,...]
and
from type: 'time' to type: 'linear'
And to make it map not only by month but also by day. I had to make date objects to correct floats. 05.20 to 5.66
const date = datum.key;
const day = parseInt(moment(date).format('DD')) / 30 * 100;
const fullDate = parseFloat(moment(date).format('MM') + '.' + Math.round(day))
// 05.10 would be 5.3 (10 of 30 is 33%)
{
x: fullDate,
y: parseInt(moment(date).format('YYYY'))
date: date, // for tooltip
count: count // for tooltip
}
And i also had to make corrections to my tooltips
callbacks: {
title: function([tooltipItem], data) {
const tooltipInfo = getTooltip(tooltipItem, data.datasets);
return tooltipInfo.date;
},
label: function(tooltipItem, data) {
const tooltipInfo = getTooltip(tooltipItem, data.datasets);
return i18n.t('chart.count') + ': ' + tooltipInfo.count;
},
}
corresponding tooltip dataset
function getTooltip(tooltipItem, datasets) {
return datasets[tooltipItem.datasetIndex].data.find(datum => {
return datum.x === tooltipItem.xLabel && datum.y === tooltipItem.yLabel;
});
}

How to set xAxis in TIME type and formatted like {hh:mm} in Echarts?

I want to set xAxis in TIME type and formatted like {hh:mm} , such as 17:45.
In this demo, configuration works:
xAxis: {
type: "time",
},
value: [
[now.getFullYear(), now.getMonth() + 1, now.getDate()].join('/'),
Math.round(value)
]
But this fails, here is my demo in Echarts gallery :
xAxis: {
type: "time",
},
value: [
[now.getHours(), now.getMinutes()].join(":"),
Math.round(value)
]
I tried type: "value", still not working.
As mention above you need to use xAxis.axisLabel.formatter.
Here is your example.
// Horizontal axis
xAxis: [{
type: 'time',
axisLabel: {
formatter: (function(value){
let label;
if (value.getMinutes() < 10){
label = value.getHours() + ":0" +value.getMinutes();
}
else {
label = value.getHours() + ":" +value.getMinutes();
}
return label;
})
}
}],
Use xAxis.axisLabel.formatter. This can be a formatter string or a function.
Use this as reference: https://ecomfe.github.io/echarts-doc/public/en/option.html#xAxis.axisLabel.formatter
I made your demo working.
I've changed the value like this:
value: [
[now.getFullYear(), now.getMonth() + 1, now.getDate()].join('/') + 'T' +
[now.getHours(), now.getMinutes()].join(':'),
Math.round(value)
]
Please see this screenshot:
For anyone looking for the answer, the link provided in the accepted answer is correct but has 404'd.
Here's the current working one: https://echarts.apache.org/en/option.html#xAxis.axisLabel.formatter

How to make xaxis to show dates using jqPlots

I'm trying to make a bar chart using jqPlots. I'm taking data from database with ajax. In vertical it is shown prices-they are correct. But my problem is how to show dates in xaxis. Every bar should be placed in the correct place in horizontal depending on date.For example my current dates for the three bars are: 2015-06-06,2015-06-08, 2015-06-30.
If I use renderer: $.jqplot.CategoryAxisRenderer, dates in xaxis are shown correct but bars aren't positioned dependent on that date.
http://prntscr.com/7ew365
If I use renderer:$.jqplot.DateAxisRenderer, it looks in that way:
http://prntscr.com/7ew1ot
Dates aren't displayed. They should be:
var ticks2 = ['2015-05-31', '2015-06-06', '2015-06-13', '2015-06-20','2015-06-27','2015-07-03'];
But when I put: ticks: ticks2, my bars disappear.
My view is:
$(document).ready(function(){
var ticks2 = ['2015-05-31', '2015-06-06', '2015-06-13', '2015-06-20','2015-06-27','2015-07-03'];
var ticks = ['0.02', '0.04', '0.06', '0.08','0.1','0.12'];
$.ajax({
url: "<?= base_url() ?>index.php/receivedOrders/get_prices",
dataType:"json",
}).success(function(responseText) {
console.log(responseText)
$.jqplot.config.enablePlugins = true;
var plot2 = $.jqplot('column_chart', responseText, {
seriesDefaults:{
renderer: $.jqplot.BarRenderer,
rendererOptions: {
barPadding: 1,
barMargin: 15,
barDirection: 'vertical',
barWidth: 50
},
pointLabels: { show: true }
},
axes: {
xaxis:{
renderer:$.jqplot.DateAxisRenderer,
// ticks: ticks2,
tickOptions: {
formatString:' %Y-%m-%d %H:%M'
//, min:'2015-06-06', max:'2015-06-30', tickInterval:'7 days'
},
},
yaxis: {
ticks: ticks,
tickOptions: {
formatString: '%.2f'
},
}
},
highlighter: {
sizeAdjust: 7.5
},
cursor: {
show: true
}
});
}
);
});