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

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;
});
}

Related

How to show grid-lines when chart data is empty, in High Stock charts?

I need to show grid lines when my chart has no data. (For now, It shows a blank division when there is no data) How to show grid lines? Is it possible to do? I tried but couldn't find an useful answer. Following is the method I used to draw the chart.
public drawChart(): void {
this.options = new StockChart ({
rangeSelector: {
selected: 0,
inputEnabled: false,
},
chart: {
type: 'spline',
},
yAxis: {
labels: {
formatter: function(): string {
return this.value + '';
},
},
opposite: false,
},
plotOptions: {
series: {
showInNavigator: true,
},
},
series: [],
});
}
To show the gridlines yAxis needs to have defined some min and max values. When series is applied those values are calculated and set to the yAxis, but in the case of the empty data, we need to apply them as the dummy values. Later, when data will be applied we can reset those values by using the yAxis.update feature.
Demo: https://jsfiddle.net/BlackLabel/zcsp8nfr/
API: https://api.highcharts.com/class-reference/Highcharts.Axis#update
API: https://api.highcharts.com/class-reference/Highcharts.Series#update

How to draw a chart with nonlinear x-axis (logarithmic scale)?

I am trying to draw a Critical Power Chart like this:
The data I get is linear. One value for every second from 1 up to 18000.
I have no clue how to teach flot to draw an non-linear x-axis.
I tried to set custom ticks, but this seems to just have impact to the labels, not the line.
The x axis ticks will always be the same and don't need to be calculated:
[1s,5s,15s,30s,1m,2m,3m,5m,10m,20m30m,1h,2h,3h,5h]
Playground including tons of data: https://jsfiddle.net/ogeo2ygx/6/
Code:
$.plot($("#cpChart"), [{data: data,label: "Critical Power", labelBoxBorderColor: 0, color: '#cbcbcb',yaxis:1,lines: { show: true, fill: true } }], {
xaxes: [{
//here should be some Magic to Draw an nice Critical Power Chart
tickFormatter: (t, v) => {
return t + "s";
}
}],
yaxes: [{
alignTicksWithAxis: 1,
position: "left",
tickFormatter: (t, v) => {
return t.toFixed(0) + " Watt"
}
}],
legend: {
position: 'sw',
labelBoxBorderColor: 0
},
colors: ["#1ab394"],
grid: {
color: "#999999",
clickable: true,
tickColor: "#D4D4D4",
borderWidth: 0,
hoverable: true
}
});
You can achieve that (which is called logarithmic scale) with two steps:
Transform the x-axis values using the Math.log function (with a +1 because the logarithm of zero is -infinity).
Define a custom ticks array with your ticks.
See the documentation for more information.
Relevant code:
xaxes: [{
ticks: [[1, '1s'],[5, '5s'], [15, '15s'],[30, '30s'],[60, '1m'],[120, '2m'],[180, '3m'], [300, '5m'], [600, '10m'], [1200, '20m'], [1800, '30m'],[3600, '1h'], [7200, '2h'], [10800, '3h'], [18000, '5h']],
transform: (x) => { return Math.log(1 + x); },
inverseTransform: (x) => { return Math.exp(x) - 1; }
}],
Updated fiddle: https://jsfiddle.net/ogeo2ygx/8/

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
}
});
}
);
});

Sencha Charts: Uncaught TypeError: Object [object Object] has no method 'getDirection'

Morning,
I am using Sencha Touch 2.3, Sencha Cmd 4.0.2.67
Unfortunately, I do not know enough about Sencha to be able to explain and diagnose my problem, so please forgive any omissions.
When I try to run my app, which creates several gauges and bar charts, before any charts have been drawn, the app crashes and console.log give the following error message:
Uncaught TypeError: Object [object Object] has no method 'getDirection'
It says the error is on line 683 of chart.series.Series.js, which looks like this (this is how it came out of the box):
for (i = 0, ln = axes.length; i < ln; i++) {
axis = axes[i];
if (!directionMap[axis.getDirection()]) {// <-- line 683
directionMap[axis.getDirection()] = [axis];
} else {
directionMap[axis.getDirection()].push(axis);
}
}
I have checked axis.Axis.js, and I can see that line 543 has the following:
getDirection: function () {
return this.getChart().getDirectionForAxis(this.getPosition());
},
console.log(axes[i]) shows the following:
Class {titleStyle: Class, labelStyle: Class, gridStyle: Class, initConfig: function, initialConfig: Object…}
_chart: Class
_fields: Array[0]
_labels: Array[0]
_margin: 10
_maximum: 10
_minimum: 0
_position: "gauge"
_steps: 10
_title: false
axisId: "ext-axis-12"
config: objectClass
eventDispatcher: Class
getEventDispatcher: function () {
getObservableId: function () {
getUniqueId: function () {
gridStyle: Class
id: "ext-chart-axis-gauge-1"
initConfig: function (){}
initialConfig: Object
labelStyle: Class
managedListeners: Object
observableId: "#ext-chart-axis-gauge-1"
titleStyle: Class
usedSelectors: Array[1]
__proto__: Object
My app generates both gauges AND bar charts. If I disable the gauges then I no longer get this error. So, the problem lies with the function which creates my gauges. Here it is:
var gaugeTitle = thetabs[tt].Entries[tt2].Title;
var currentValue = (thetabs[tt].Entries[tt2].CurrentValue > 0)?thetabs[tt].Entries[tt2].CurrentValue:0;
var baseValue = thetabs[tt].Entries[tt2].BaseValue;
var centreValue = thetabs[tt].Entries[tt2].CentreValue;
var generated = thetabs[tt].Entries[tt2].Generated;
var gaugeData = thetabs[tt].Entries[tt2];// this data populates the gauge store
// now we create a store for the gauge
var gaugeStore = Ext.create('Ext.data.Store', {
storeId: 'gaugeStore',
fields: [{'name':'BaseValue','type':'int'},
{'name':'CentreValue','type':'int'},
{'name':'CurrentValue','type':'int'},
{'name':'Generated'},
{'name':'Title'},
{'name':'Type'}],
data: gaugeData
});
gaugeStore.setData(gaugeData); // Use the add function to add records or model instances.
// set the maximum value on the gauge, then round it to whole number
var gaugemax = (thetabs[tt].Entries[tt2].CentreValue>10)? thetabs[tt].Entries[tt2].CentreValue*2:10;
// ensure gauge max is never less than currentValue
if(gaugemax < currentValue){
gaugemax = currentValue+(currentValue*.1); // use 110% of currentValue
}
// show whole numbers only
gaugemax = Math.round(gaugemax/10)*10;
//set gauge colour
gaugeColor = setGaugeColour(siteName);
/// new gauge
var chartgx = {
cls: 'thegauge',
itemId: 'gauge'+tt2,
xtype: 'chart',
shadow: true,
store: gaugeStore,
width : 'auto',
animate: true,
insetPadding: 50,
axes: [{
type: 'gauge',
position: 'gauge',
minimum: 0,
maximum: gaugemax,
steps: 10,
margin: 10
}],
series: [{
type: 'gauge',
minimum: 0,
maximum: gaugemax,
steps: 10,
margin: 10,
angleField: 'CurrentValue',
donut: 30,
colorSet:[gaugeColor,'#e1e1e1']
}]
};
`
Can someone please advise me how to correct.
Removing the axes from the gauge seems to have fixed this problem, but now I am presented with another :-(

Show legend of "Indicator plot" in dojo charts

Is there a way to create a Legend control for series that belong to Indicator Plot with Dojo Charting.
I've tried some standard well described ways from the documentation. But with no success! Legend are not appearing for Indicator Plot.
Maybe somebody know is it possible to draw legend for this case or not?
Thanks in advance!
EDIT(my code added):
1. id - id of chart dom element.
2. opts.chartOpts - chart options from outside js.
3. legname - id of legend dom element.
4. scale.avg - is just a double value.
this.chart = new Chart(id, this.opts.chartOpts);
this.chart.addPlot("default", {
animate: { duration: 1000, easing: easing.linear },
type: ColumnsPlot,
markers: true,
gap: 1
});
this.chart.addPlot("avgline", {
type: IndicatorPlot,
vertical: false,
lineStroke: { color: "#00ff00", style: "ShortDash" },
stroke: { width: '1.2px' },
fill: '#eeeeee',
font: 'normal normal normal 11px Arial',
labels: 'none',
offset: { x: 32, y: 4 },
values: [scale.avg],
precision: this.opts.precision
});
//Add axis code goes here... cutted for clearance
this.chart.addSeries('Power', chartOptions.data);
this.chart.addSeries('Average', [scale.avg], { plot: 'avgline' });
var tip = new Tooltip(this.chart, "default", { 'class' : 'kaboom' });
var mag = new Magnify(this.chart, "default");
var hightlight = new Highlight(this.chart, "default");
this.chart.render();
this.leg = new Legend({ chart: this.chart, horizontal: false }, this.legName);
And as result of this code I see legend for 'default' plot 'Power' series only. And nothing for 'Average' series.