Highstock - Can't update using value from file, data type? - variables

I'm still pretty new to JS, JQuery and Highcharts.
From the "dynamic-update" example in HighStock:
chart: {
events: {
load: function() {
var series = this.series[0];
var y = 1;
setInterval(function() {
var x = (new Date()).getTime();
$.get('get_most_recent_point_from_database.php',function(data){
alert( data);
var y = data;
// y = 10;
alert( y);
series.addPoint([x, y], true, true);
});
}, 1000);
}
}
},
"get_most_recent_point_from_database.php" produces an integer.
The alerts show the integer, but series.addPoint doesn't add the integer to the chart. The chart just goes blank.
The "y = 10;" (commented out in the code) will update the chart with 10.
I set y to integer by "var y = 1;" thinking that might help.
Any thoughts? I can put it all in JSFiddle if it helps.
THE FIX ======================
setInterval(function() {
var x = (new Date()).getTime(), y;
$.get('get_most_recent_point_from_database.php',function(data){
y = parseFloat(data).toFixed(1);
series.addPoint([x, y], true, true);
});
}, 1000);

How your data looks like? probably it is string, so try to convert it by parseFloat(data) (if it is single point) or use json_encode() in php. (All depends how your php file looks like)

Related

Highcharts with decrease order in each interval

Is it possible to create a graph sorted in each time interval using Highcharts?
For expample, in this picture for January data will be in order: New York, Tokyo, London, Berlin. The same for each months - data should be shown decrease order
Highcharts doesn't have a built-in function to do that, but for example you can use the render event and organize columns, by changing their positions in the way you need.
events: {
render: function() {
var series = this.series,
longestSeries = series[0],
sortedPoints = [],
selectedPoints = [];
// find a series with the highest amount of points
series.forEach(function(s) {
if (s.points.length > longestSeries.points.length) {
longestSeries = s;
}
});
longestSeries.points.forEach(function(point) {
series.forEach(function(s) {
selectedPoints.push(s.points[point.index]);
});
sortedPoints = selectedPoints.slice().sort(function(a, b) {
return b.y - a.y;
});
selectedPoints.forEach(function(selectedPoint) {
if (
selectedPoints.indexOf(selectedPoint) !==
sortedPoints.indexOf(selectedPoint) &&
selectedPoint.graphic
) {
// change column position
selectedPoint.graphic.attr({
x: sortedPoints[selectedPoints.indexOf(selectedPoint)].shapeArgs.x
});
}
});
sortedPoints.length = 0;
selectedPoints.length = 0;
});
}
}
Live demo: https://jsfiddle.net/BlackLabel/tnrch8v1/
API Reference:
https://api.highcharts.com/highcharts/chart.events.render
https://api.highcharts.com/class-reference/Highcharts.SVGElement#attr
#ppotaczek Thank You for help a lot! I solve my issue, but i had to make some changes to your code:
events: {
render: function() {
if (this.series.length === 0) return
var series = this.series,
longestSeries = series[0],
sortedPoints = [],
selectedPoints = [];
// find a series with the highest amount of points
series.forEach(function(s) {
if (s.points.length > longestSeries.points.length) {
longestSeries = s;
}
});
longestSeries.points.forEach(function(point) {
series.forEach(function(s) {
selectedPoints.push(s.points[point.index]);
});
sortedPoints = selectedPoints.slice().sort(function(a, b) {
return b.y - a.y;
});
selectedPoints.forEach(function(selectedPoint) {
if (
selectedPoints.indexOf(selectedPoint) !==
sortedPoints.indexOf(selectedPoint) &&
selectedPoint.graphic
) {
// change column position
selectedPoint.graphic.attr({
x: selectedPoints[sortedPoints.indexOf(selectedPoint)].shapeArgs.x
});
}
});
sortedPoints.length = 0;
selectedPoints.length = 0;
});
}
},
}
So i changed:
// change column position
selectedPoint.graphic.attr({
x: sortedPoints[selectedPoints.indexOf(selectedPoint)].shapeArgs.x
});
to:
// change column position
selectedPoint.graphic.attr({
x: selectedPoints[sortedPoints.indexOf(selectedPoint)].shapeArgs.x
});

c3.js total count in title of pie chart

I have a question about the pie chart in c3.js.
How can I add the total count of a pie chart in the title??
var title = new Array('data1.sql','data2.sql')
var dtitle = new Array('title1','title2')
var chart = new Array('chart0', 'chart1')
for(var i = 0; i < title.length; i++){
chart[i] = c3.generate({
bindto : '#chart' + i,
size: {
height: 550,
width: 800
},
data : {
url : '/json/sql/data/test/' + title[i],
mimeType : 'json',
type : 'donut'
},
donut: {
title: dtitle[i] + ' - Total:' ,
label: {
format: function(value, ratio, id) {
return value;
}
}
}
});
}
The annoying thing here is that the title option can take a function, but the chart variable is not initialised within it so using the c3 api methods can't be done at this point.
So the best (maybe only) way is to add an onrendered callback that adds up the data as you'd need to anyways and then replace the text in the chart's title text using a spot of d3:
onrendered: function () {
var data = this.api.data();
var total = data.reduce (function (subtotal, t) {
return subtotal + t.values.reduce (function (subsubtotal,b) { return subsubtotal + b.value; }, 0);
}, 0);
d3.select(this.config.bindto + " .c3-chart-arcs-title").text("Total: "+total);
}
Edit: If you want it to keep track of a total as you hide/show series use this
var data = this.api.data.shown.call (this.api);
instead of
var data = this.api.data();

Odd behavior when charting in dimple.js

I am using dimplejs to create line charts on some sample data that I have.
The data looks like this (see html section, it is stored in data.tsv).
d3.js = dimplejs.org/lib/d3.v3.4.8.js
and the dimple code is:
<head>
<script src="d3.js"></script>
<script src="http://dimplejs.org/dist/dimple.v2.1.2.min.js"></script>
</head>
<body>
<script type="text/javascript">
// Pass in an axis object and an interval.
var cleanAxis = function (axis, oneInEvery) {
// This should have been called after draw, otherwise do nothing
if (axis.shapes.length > 0) {
// Leave the first label
var del = false;
// If there is an interval set
if (oneInEvery > 1) {
// Operate on all the axis text
axis.shapes.selectAll("text")
.each(function (d) {
// Remove all but the nth label
if (del % oneInEvery !== 0) {
this.remove();
// Find the corresponding tick line and remove
axis.shapes.selectAll("line").each(function (d2) {
if (d === d2) {
this.remove();
}
});
}
del += 1;
});
}
}
};
var svg = dimple.newSvg("body", 800, 600);
d3.tsv("data.tsv", function (data) {
var myChart = new dimple.chart(svg, data);
myChart.setBounds(60, 30, 505, 305);
var x = myChart.addCategoryAxis("x", "Month");
x.addOrderRule("Date");
var y =myChart.addMeasureAxis("y", "Returns");
y.overrideMax = 200;
myChart.addSeries("Name", dimple.plot.line);
myChart.addLegend(60, 10, 500, 20, "right");
myChart.draw();
cleanAxis(x, 20);
});
/*var data = [
{ "Word":"Hello", "Awesomeness":2000 },
{ "Word":"World", "Awesomeness":3000 }
];*/
/*var chart = new dimple.chart(svg, data);
chart.addCategoryAxis("x", "Word");
chart.addMeasureAxis("y", "Awesomeness");
chart.addSeries(null, dimple.plot.bar);
chart.draw();*/
</script>
</body>
And the final chart looks like this:
And the questions are:
Why are the numbers not matching?
Why is there the big drop in the end of the data?
The representation of the data seems inconsistent, and there is no way this library was released with a bug like this.
Thank you for any pointers
Because you're plotting the Month field on the x axis, dimple is summing all of the returns for each month, so those are in fact month totals you are seeing (the drop at the end is presumably due to a partial month).
I think you may have more success with a time axis on x. You will not need the clean axis code then either. Try this (I haven't tested this code but it should be pretty close):
var svg = dimple.newSvg("body", 800, 600);
d3.tsv("data.tsv", function (data) {
var myChart = new dimple.chart(svg, data);
myChart.setBounds(60, 30, 505, 305);
myChart.addTimeAxis("x", "Date", "%m/%d/%Y", "%b-%Y");
myChart.addMeasureAxis("y", "Returns");
myChart.addSeries("Name", dimple.plot.line);
myChart.addLegend(60, 10, 500, 20, "right");
myChart.draw();
});

Creating dynamic labels for dojo bar chart

I have bar chart, whose x-axis labels is generated dynamically from db, I am getting these values through ajax call data
'{value:1,text:"x"},{value:2,text:"Vikash"},{value:3,text:"y"},{value:4,text:"z"}'.
How to pass these values to label parameter. I tried passing it as an array and also as json but nothing seems to work.. Any ideas..
Here is my code:
makeBarChart=function() {
animChart = new dojox.charting.Chart2D("animChart");
animChart.setTheme(dojox.charting.themes.MiamiNice)
.addAxis("x",{
labels: [ myLabelSeriesarray ], gap: 20}).
addAxis("y", {
vertical: true,
fixLower: "major",
fixUpper: "major",
includeZero: true
}).
addPlot("default", {
type: "ClusteredColumns",
gap: 10
}).
addSeries("Series A", closedSeries).
addSeries("Series B", othersSeries).
render();
};
dojo.addOnLoad(makeBarChart);
jsp code:
var labelDis = new Array(pieData.length); // pieData is the JSON value getting from Java
for(var i = 0;i<pieData.length;i++){
labelDis[i] = new Array(2);
labelDis[i]['value'] = i + 1;
labelDis[i]['text'] = pieData[i]['axis'];
}
Java/Servlet code:
JSONObject jSONObject = new JSONObject();
jSONObject.put("axis", "value from database");
jSONArray.put(jSONObject);
out.print(jSONArray.toString());
Suppose you have received data in json format through ajax call and you want to create dynamic labels using that data.
var jsonArray= ["label1","label2","label3"];
var labelsArray = [];
for (var i = 0; i < jsonArray.length; i++,) {
var obj = {};
obj.value = i;
obj.text = jsonArray[i];
labelsArray.push(obj);
}
Set the labels in x Axis to this labelsArray
this.chart1.addAxis("x", {
title: "Collection Date",
titleOrientation: "away",
titleGap:20,
labels:labelsArray
})

Adding Columns Dynamically to SlickGrid with AJAX. Columns don't show up

Using SlickGrid to display some pretty elaborate grids. The Example I am showing here isn't my code but basically an example given by the SlickGrid people duplicating my issue. My Grids need to have columns added dynamically with the column names being fed through an AJAX feed. Creating the column object in JS is not a problem and even adding them using the .push is seems to work fine as I can see them in the firebug console. The new columns never seem to rendner. I get a a bunch of tiny empty cells at the end of the grid but they never populate.
The script below can be replaced with the script in the "example1-simple.html" viewed here.
<script src="../lib/jquery.jsonp-1.1.0.min.js"></script>
<script>
var grid;
var data = [];
var columns = [
{id:"title", name:"Title", field:"title"},
{id:"duration", name:"Duration", field:"duration"},
{id:"%", name:"% Complete", field:"percentComplete"},
{id:"start", name:"Start", field:"start"},
{id:"finish", name:"Finish", field:"finish"},
{id:"effort-driven", name:"Effort Driven", field:"effortDriven"}
];
var dynamicColumns = [];
var options = {
enableCellNavigation: true,
enableColumnReorder: false
};
$(function() {
data = [];
BuildExtraColumnsAJAX();
for (var i = 0; i < 2000; i++) {
data[i] = {
title: "Task " + i,
duration: "5 days",
percentComplete: Math.round(Math.random() * 100),
start: "01/01/2009",
finish: "01/05/2009",
effortDriven: (i % 5 == 0)
};
for (var x = 0; x < 20; x++) {
var columnName = "dynamicColumn" + x;
data[i][columnName] = x;
}
}
//alert("Go Pack Go");
grid = new Slick.Grid("#myGrid", data, dynamicColumns, options);
$("#myGrid").show();
})
function BuildExtraColumnsAJAX(){
//dynamicColumns = [];
for (var x = 0; x < columns.length; x++){
dynamicColumns.push(columns[x]);
}
var url = "http://services.digg.com/search/stories? query=apple&callback=C&offset=0&count=20&appkey=http://slickgrid.googlecode.com&type=javascript";
$.jsonp({
url: url,
callbackParameter: "callback",
cache: true, // Digg doesn't accept the autogenerated cachebuster param
success: onSuccess,
error: function(){
alert("BOOM Goes my world");
}
});
}
function onSuccess(resp) {
for (var i = 0; i < resp.stories.length; i++) {
dynamicColumns.push( {
id: "dynamicColumn" + i,
name: "Dynamic Column" + i,
field: "dynamicColumn" + i
});
}
}
function BuildExtraColumns(){
dynamicColumns = [];
for (var x = 0; x < columns.length; x++){
dynamicColumns.push(columns[x]);
}
for (var i = 0; i < 20; i++) {
dynamicColumns.push( {
id: "dynamicColumn" + i,
name: "Dynamic Column" + i,
field: "dynamicColumn" + i
});
}
}
If I put the line grid = new Slick.Grid("#myGrid", data, dynamicColumns, options); in the firebug console and run it the grid than renders fine. It is almost like the script is still executing lines of code even though its not done creating the dynamicColumns.
The Digg AJAX call is just to similute an AJAX call, I of course would be using my own.
The grid is getting initialized before the AJAX call to get the additional columns completes.
Either wait until the columns have loaded to initialize the grid, or update the grid after the additional columns have loaded:
grid.setColumns(dynamicColumns);