I am having difficulty showing a string separated with dates on a basic high chart
I am getting and saving the tweets from twitter into arrays and then converting the array into a string separated by commas and quotes.
Unfortunately I cant display them on the graph, I have no idea what I'm doing wrong.
function search(){
var value = $('#box').val();
var array=[];
var dateArray = [];
var dateString;
if (value!==""){$.getJSON("",
function(data){
$.each(data.results, function(i, item){
var user=item.from_user;
var created_at=new Date(item.created_at);
var month = created_at.getMonth();
var day = created_at.getDate();
var year = created_at.getFullYear();
var created= day +'/'+ month+ '/'+ year;
array.push({date:created,username:user});
});
// console.log(array);
for (var i in array) {
dateArray.push(array[i].date);
}
dateString="'" + dateArray.join("','") + "'";
console.log(dateString);
});
}
var chart;
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'line',
marginRight: 130,
marginBottom: 25
},
title: {
text: 'Monthly Average Temperature',
x: -20 //center
},
subtitle: {
text: 'Source: WorldClimate.com',
x: -20
},
xAxis: {
categories: [dateString]
},
Fixed JsFiddle
Your x-axis parameter should be as follows:
xAxis: {
categories: dateString
},
Als, just change this :-)
for (var i in array) {
dateString.push(array[i].date);
}
highchart(dateString);
Oh, and you should change to this, definately.
<input type="text" id="box" value="a"/>
Extra investigation info:
It appeared that (in the old situation)
console.log(stringArray);
highchart(stringArray);
was empty. Would you pass
highchart(["ab", "b", "c"]);
then you'd be fine. This is because you are passing an empty array, you are creating the chart before you have the JSON data. I therefore moved the creation to the JSON function.
Why not use xAxis as datetime:
xAxis: {
type: 'datetime'
},
Parse the dates into JS time from the twitter data and have something like this as your series data array:
[[<jstime1>, "big cool tweet1"], [<jstime2>, "big cool tweet2"]]
Related
So i'm currently trying to fix a problem with a Google Charts. I am drawing a chart that shows numeric values on the Y-axis and dates on the X-axis. I want the date to adpat according to the specified timezone. For that i'm using the DateFormatter Object from Google charts, providing the patter and the Timezone like so:
var dateFormatter = new google.visualization.DateFormat({
timeZone: _timeZone, //timezone
pattern: $scope.selectedResolution.pattern
});
The pattern attribute receives a string containing a format string and the timeZone receves a value representing the number of hours regarding the timezone offset (example, -4, -5, etc).
I Format the chart values like so:
dateFormatter.format($scope.data, 0);
Being that the column "0" is the column where i have my dates.
I then draw the chart, standard stuff:
chart = new google.visualization.ComboChart(document.getElementById(chart_name));
//generateTicks($scope.data, options);
chart.draw($scope.data, options);
The thing is that, the values showed in the X-Axis are not formatted whatsover, be it in the format or the timezon.
Problem Showcase
As you can see in the image above, the X-Axis shows "13:00" where it should show "15:00", in this particular case.
I also went and check the data i'm feeding the chart with to see if the formatter was actually doing any work on the data itself and it appears to be working properly:
Chart Data
Also, here's my charts options for reference:
var series = {}, firstSerie, row, title, tempRows = [];
// Create the data table
series[0] = {targetAxisIndex: 0, color: '#3182BD'};
series[1] = {color: '#FF7F00', type: 'line'};
options = {
tooltip: {isHtml: true},
titleTextStyle: {fontSize: 12, bold: false},
isStacked: false,
backgroundColor: 'transparent',
legend: {position: 'none'},
height: 300,
pointSize: 1,
series: series,
vAxes: {
// Adds titles to each axis.
0: {
textStyle: {color: $scope.widgetOptions.text_color || '#333333'},
format: $scope.vLabel === '%' ? '#\'%\'' : generateVerticalAxisPattern() + $filter('trustedHtml')($scope.vLabel),
minValue: 0,
gridlines: {
color: 'transparent'
}
}
},
hAxis: {
//title: graphLegend,
textStyle: {color: $scope.widgetOptions.text_color || '#333333'},
titleTextStyle: {color: $scope.widgetOptions.text_color || '#333333'},
viewWindows: {
min: moment().subtract(24, 'hours'),
max: moment()
},
gridlines: {
color: 'transparent',
units: {
hours: {format: ['HH:mm', 'ha']}
},
count: -1
},
minorGridlines: {
count: 0
}
},
vAxis: {
viewWindowMode: 'maximized',
viewWindow: {
min: $scope.widgetOptions.lower_limit
}
},
animation: {
duration: 500,
easing: 'out'
}
};
So, does anyone have any clue of what's going on? Im working with angularjs btw.
Thanks in advance
the format method, as follows, only formats the data, not the chart or chart axis.
dateFormatter.format($scope.data, 0);
basically, the above is used to display the correct format in the tooltip when hovering a data point.
to format an axis, you would normally set the format configuration option.
hAxis: {
format: $scope.selectedResolution.pattern
}
however, in this case, since you are changing the time zone,
you will need to provide custom ticks on the x-axis.
you can build an array of ticks from the data table rows,
using the formatValue method from the formatter.
var ticks = [];
for (var i = 0; i < $scope.data.getNumberOfRows(); i++) {
var dateValue = $scope.data.getValue(i, 0);
ticks.push({
v: dateValue,
f: dateFormatter.formatValue(dateValue)
});
}
// then add above to ticks to options...
hAxis: {
ticks: ticks
}
each tick will need to be an object,
with properties for v: for value,
and f: for formatted value.
the only problem with the above routine,
it assumes you want to display a tick for each row in the data table.
if you do not have room to display them all,
you will need to figure out your own algorithm to display the correct number of ticks.
edit
another method is to find the min and max dates within the data table,
using data table method getColumnRange
then build each tick after a particular duration.
for instance, to display a tick every four hours along the axis, between the min and max dates...
const FOUR_HOURS = (1000 * 60 * 60 * 4);
var ticks = [];
var dateRange = $scope.data.getColumnRange(0);
for (var i = dateRange.min.getTime(); i <= dateRange.max.getTime(); i = i + FOUR_HOURS) {
var dateValue = new Date(i);
ticks.push({
v: dateValue,
f: dateFormatter.formatValue(dateValue)
});
}
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];
The Goal
I'm attempting to render a long series of data (around 200 ticks, from small float values like 1.3223) into a line chart.
The Issue
When I use a series of data that changes only a small amount (around 0.0001 every tick), the chart is rendered as very jagged (scissor like). I would like to somehow fix it to have a "saner" radius between each point on the graph.
A Good Example
On the other hand, when rendering higher values (around 1382.21) with bigger difference between ticks (from 0.01 to 0.05 +/-) the graph is rendered more smooth and aesthetically pleasing.
Edit: As user Arie Shaw pointed out, the actual low or high values don't make a difference and it remains an issue of representing small "monotonous" changes is a less jagged form.
The Code
var initChart = function(data, container) {
new Highcharts.Chart({
chart: {
type: "area",
renderTo: container,
zoomType: 'x'
},
title: {
text: ''
},
xAxis: {
labels: {
enabled: false
}
},
yAxis: {
title: {
text: ''
}
},
legend: {
enabled: false
},
color: '#A3D8FF',
plotOptions: {
area: {
fillColor: '#C6E5F4',
lineWidth: 1,
marker: {
enabled: false
},
shadow: false,
states: {
hover: {
lineWidth: 1
}
},
threshold: null
}
},
exporting: {
enabled: false
},
series: [{
name: "TEST",
data: data
}]
});
};
Both graphs, and sample data sets are presented in the following fiddle:
http://jsfiddle.net/YKbxy/2/
The problem you're experiencing is unavoidable: If you have a lot of small variations over time, the graph is going to appear jagged provided that you show each data point.
The key point is that last phrase.
One way to 'smooth out' the rough parts would be to average the data. For example:
var myData = []; //... Some array of data; assuming just numbers
var averageData = function (data, factor) {
var i, j, results = [], sum = 0, length = data.length, avgWindow;
if (!factor || factor <= 0) {
factor = 1;
}
// Create a sliding window of averages
for(i = 0; i < length; i+= factor) {
// Slice from i to factor
avgWindow = data.slice(i, i+factor);
for (j = 0; j < avgWindow.length; j++) {
sum += avgWindow[j];
}
results.push(sum / avgWindow.length)
sum = 0;
}
return results;
};
var var initChart = function(data, container) {
new Highcharts.Chart({
series: [{
name: "TEST",
data: averageData(myData, 2)
}]
});
});
This method also has the advantage that you could (potentially) reuse the function to compare the averaged data to the regular data, or even toggle between how much to average the data.
You can always use areaspline instead of area, see: http://jsfiddle.net/YKbxy/3/
why dont you treat you .00001 data as 1, so times 10000, and then write it in your legend like that.
You should even do that as a test, since if the chart looks fine then, it means there is a problem in the dataset numbers when you return it to normal, since high charts takes the difference between high and low...
Either you must approximate your data by only using a few decimal places or you must average out the values using something like:
var data = new Array(200);
var smallArray = new Array(5);
var averagedData = new Array(20);
for (var index=0; index<=averagedData.length; index++){
for(var i = 0; i<=smallArray.length; i++){
smallArray[i] = data[i + index * 5];
}
averagedData[index] = (smallArray[1] + smallArray[2] + smallArray[3] + smallArray[4] + smallArray[5])/smallArray.length;
}
Then you will only need to plot 20 averaged points on an array of 200 data points. You can change the values for what you need.
In the end the issue is in the frequency of the points or their plotting on yAxis.
When I provide more realistic positioning (e.g timestamp) it will look good.
Meaning that jaggedness is a result of the small changes over constant yAxis progression, which is most similar to nt3rp's answer
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!
I've been trying to insert min and max string dates into my highcharts graph as follows:
var formatted_startDate = startDate.replace(/-/g, ",");
var formatted_endDate = endDate.replace(/-/g, ",");
//Format now is "yyyy,mm,dd"
options = {
chart: {
renderTo: 'container',
type: 'bar'
},
xAxis: {
type: "datetime",
dateTimeLabelFormats: {
day: '%m-%d'
},
tickInterval: 24 * 3600 * 1000,
min: Date.UTC(formatted_startDate),
max: Date.UTC(formatted_endDate)
},
Clearly the above won't work because I'm passing in a string. I've just written it like this to illustrate what I am trying to do rather than post code of numerous failed attempts. I've attempted using JSON.parse and eval() but had problems with the syntax.
Any help would be appreciated. Cheers
ended up just uses the setExtremes method within highcharts API
var formatted_startDate = startDate.replace(/-/g, ",");
var formatted_endDate = endDate.replace(/-/g, ",");
//Format now is "2000,00,00"
var startdatearray = formatted_startDate.split(",");
var enddatearray = formatted_endDate.split(",");
var sy = parseInt(startdatearray[0]);
var sm = parseInt(startdatearray[1],10) - 1;
var sd = parseInt(startdatearray[2]);
var ey = parseInt(enddatearray[0]);
var em = parseInt(enddatearray[1],10) - 1;
var ed = parseInt(enddatearray[2]);
chart = new Highcharts.Chart(options);
chart.xAxis[0].setExtremes(Date.UTC(sy,sm,sd), Date.UTC(ey, em, ed));