I use highcharts for draw charts. I have 2d json object and I don't know how to set this object to highcharts. And this is my json object data:
And I want my chart like this picture(column-parsed example of highchart):
And this is my code:
$.ajax({
url:"../../teachersem",
type:"get",
data:{
id:$.trim(tableData[0])
},
success:function(data){
$('div[class|="col-md-7 col-md-offset-3"]').css("display","none");
//console.log(data.accept);
//console.log(data.fail);
var accept=new Array();
var fail =new Array();
for (i = 0; i < data.accept.length; i++){
accept.push([data.accept[i].year, parseInt(data.accept[i].count)]);
alert("accept: "+data.accept[i].year+" "+parseInt(data.accept[i].count));
}
//console.log(accept.toString());
for (i = 0; i < data.fail.length; i++){
fail.push([data.fail[i].year, parseInt(data.fail[i].count)]);
alert("fail: "+data.fail[i].year+" "+parseInt(data.fail[i].count));
}
$('#container').highcharts({
chart: {
type: "column"
},
title: {
text: "Student data"
},
xAxis: {
allowDecimals: false,
title: {
text: "Branch of studies"
}
},
yAxis: {
title: {
text: "Number of students"
}
},
series: [{
data: [accept,fail]
}],
});
},
error:
alert('error!')
})
});
But this has any result? please help,thank u!
You actually want two series: data parameters (one for each column).
The first column will be the accept data and the second column will be your fail data since I am guessing that your category label which in the example image is Apples will be a Branch of Studies.
Your series should look something similar to the following:
series: [{
name: "Accept",
data: accept,
},
{
name: "Fail",
data: fail,
}]
Your accept and fail arrays are currently arrays of arrays, but they can actually be a simple list as seen in the Highcharts demo here. You can then specify in the xAxis parameter the categories: that are your Branch of Studies.
Related
I have two JSON end points. I am trying to plot a Highcharts bar graph with drilldown. The drilldown will point to another JSON endpoint. In the graph data is coming dynamically from end points.
JSON 1 :- https://api.myjson.com/bins/156yh3
JSON 1 Structure :-
[{
"name": "cricket",
"number": "2"
}]
It will first plot the graph with JSON 1 Data. In the first graph, X-Axis represents "name" and Y-Axis represents "number". Whenever we click on any bar then it will call the JSON 2 endpoint and pass the clicked bar "name" as URL parameter.
JSON 2 end point looks like, api.domain.com/{{name}}//
if we click on "orange" bar then request url will change to api.domain.com/cricket/
JSON 2 Structure :-
[{
"player": "xyz",
"points": "2"
}]
In the second graph, X-Axis represents "player" and Y-Axis represents "points". I think, I have to call a Ajax request in drilldown when a bar is clicked. I can plot the first graph but what is the recommended way to plot the second graph, which will come in drill down.
Code for graph 1 :-
$(function() {
$.getJSON("https://api.myjson.com/bins/156yh3", function(data) {
console.log(data);
Highcharts.chart('container', {
chart: {
type: 'column'
},
title: {
text: 'Name Vs Numbers'
},
subtitle: {
text: 'Chart View Here'
},
xAxis: {
type: 'category',
categories: data.map(function(x) {
return x.name;
})
},
yAxis: {
title: {
text: 'Numbers'
}
},
legend: {
enabled: false
},
plotOptions: {
series: {
borderWidth: 0,
dataLabels: {
enabled: true,
format: '{point.y:.1f}'
}
}
},
tooltip: {
headerFormat: '<span style="font-size:11px">{series.name}</span><br>',
pointFormat: '<span style="color:{point.color}">{point.name}</span>: <b>{point.y:.2f}</b> of total<br/>'
},
series: [{
colorByPoint: true,
data: data.map(function(x) {
return x.number * 1;
})
}]
});
});
});
HTML :-
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="container" style="min-width: 310px; height: 400px; margin: 0 auto;"></div>
Refer to this live demo: http://jsfiddle.net/kkulig/1o4mr6jk/
It always adds a new drilldown series (with randomly generated data from the API) on point click event and performs drilldown.
In callback for series.point.events.click I used addSeriesAsDrilldown:
plotOptions: {
series: {
point: {
events: {
click: function(e) {
var point = this,
chart = point.series.chart;
$.getJSON('https://canvasjs.com/services/data/datapoints.php?xstart=1&ystart=10&length=10&type=json&callback=?', function(data) {
chart.addSeriesAsDrilldown(point, {
data: data
});
});
}
}
}
}
},
You can use the value of point.name to construct your URL.
It seems that there's some issue with the core code - it throws an error on drillup (you can check that by commenting out everything before var chart = Highcharts.chart('container', {). this.ddDupes in H.Chart.prototype.drillUp function is undefined so its length property cannot be accessed. I modified the core code by changing the following piece of code:
this.ddDupes.length = []; // #3315
to this:
if (this.ddDupes) {
this.ddDupes.length = []; // #3315
}
and everything works fine.
EDIT
I found a better solution. It's based on the official Highcharts demo referred in the API record for chart.events.drilldown: https://api.highcharts.com/highcharts/chart.events.drilldown
Live demo: http://jsfiddle.net/kkulig/u1z5z40b/
var chart = Highcharts.chart('container', {
chart: {
type: 'column',
events: {
drilldown: function(e) {
var chart = this;
$.getJSON('https://canvasjs.com/services/data/datapoints.php?xstart=1&ystart=10&length=10&type=json&callback=?', function(data) {
chart.addSeriesAsDrilldown(e.point, {
data: data
});
});
}
}
},
series: [{
data: [{
name: 'John',
y: 1,
drilldown: true
}, 2],
}]
});
drilldown: true indicates that the drilldown event should happen even though there's no drilldown series explicitly assigned to the point yet.
I have been customizing the following jsfiddle in order to display data from a database. http://jsfiddle.net/jlbriggs/7ntyzo6u/
I am using JSON in order to retrieve data in my database. In the jsfiddle, there are 3 charts which can be switched between by clicking buttons. But when you load the page, chart1 is the default chart showing. Now I have edited chart1 so that it will display my database data:
var chart,
chartOptions = {},
chartData = {};
chartData.chart2 = randomData(10, true);
chartData.chart3 = randomData(65, true, 300);
chartOptions.chart1 = {
chart: {
type: 'column'
},
title: {
text: 'Chart 1 Title'
},
xAxis: {
categories: []
},
yAxis: {
title: {
text: 'Chart 1<br/>Y Axis'
}
},
series: [{
name: 'Chart 1 Series',
data: []
}]
};
var tableName = '<?php echo $tableName; ?>'
$.getJSON("../../companies/charts/Data.php", {id: escape(tableName)}, function(json) {
chartOptions.chart1.xAxis.categories = json[0]['data'];
chartOptions.chart1.series[0].data = json[6]['data'];
});
My problem is, that the chart shows up as empty after loading the page. Only when I click the chart1 button will the data show up. Can anyone tell me if this is because I am missing something after setting the xAxis and series data in the above code?
Since $.getJSON is asynchronous (see comment below) I have tried to now send the request using ajax instead. Below is my attempt, but this is flawed since the chart will now not even display data upon clicking the 'chart1' button. The chart does come up, but is empty:
chartOptions.chart1 = {
chart: {
type: 'column'
},
title: {
text: 'Chart 1 Title'
},
xAxis: {
categories: []
},
yAxis: {
title: {
text: 'Chart 1<br/>Y Axis'
}
},
series: [{
name: 'Chart 1 Series',
data: []
}]
};
var tableName = '<?php echo $tableName; ?>'
$.ajax({
url: "../../companies/charts/Data.php",
data: {id: escape(tableName)},
dataType: "json",
async: false,
succes: function(data) {
chartOptions.chart1.xAxis.categories = json[0]['data'];
chartOptions.chart1.series[0].data = json[6]['data'];
}
});
Thanks in advance for your assistance!
My assumption is that since $.getJSON is asynchronous , the chart is already loaded before the data is populated.
You can try calling the setData method on the series inside the $.getJSON block.This will force a chart redraw :
chartOptions.chart1.series[0].setData(json[6]['data'],true);
Or try to send the request using $.ajax with async:false.Replace the following block with the $.getJSON block.
$.ajax({
url: "../../companies/charts/Data.php",
data: {id: escape(tableName)},
async:false
}).done(function() {
chartOptions.chart1.xAxis.categories = json[0]['data'];
chartOptions.chart1.series[0].data = json[6]['data'];
});
I think this should get you going.
Read more about it over here: jQuery.ajax
I'm currently working on dynamically building column graphs in MVC, using C3 Charts. While I can bring the data from the database using AJAX/JSON, I am able to bind only the Y-Axis coordinates using the JSON property of C3, not the X-Axis categories.
What I want to do: Build column charts dynamically. For instance, the marks of students of multiple years will be calibrated as (Year 1: 50),(Year 2: 100) and so on, with the first part (category:Year) going on the X-Axis and the numeric part (Marks) going to the Y-Axis. The number of such combinations is dynamic, depending on the user's requirements (brought from the database as two columns, with multiple rows).
Problems I'm running into:
Specifying two different data types in the keys renders the non-numeric part (the category) as a separate series altogether, which I don't want and which isn't even working.
Whatever I do, the X-Axis comes with whole numbers depending on the number of columns visible. I'd like to change that to the actual category names.
Here is what I am doing. I took inspiration from Daniel's method here (https://groups.google.com/d/msg/c3js/RV1X18GZoGY/-p39m9Ngt-gJ)
$.ajax({
url: <Method in Controller here>,
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8",
data: JSON.stringify(parameters),
success: function (data) {
var myData = jQuery.parseJSON(data);
var testJson = $.map(myData, function (item) {
return {
Year: item.Year,
Marks: item.Marks
}
});
var chart = c3.generate({
bindto: '#chart',
size: {
width: 800
},
data: {
json: testJson,
mimeType: 'json',
keys: {
value: ['Marks']
},
}
});
}
});
Looking forward to some assistance. Thanks in advance!
Edit: I want the data to look like this in the end:
Sample Chart
You can try the following code:
var jsonTest = [
{ year: 1, marks: 50 },
{ year: 2, marks: 70 },
{ year: 3, marks: 75 },
{ year: 4, marks: 45 },
];
// The variable name chart will automatically bind itself to an id = chart
var chart = c3.generate({
data: {
type : 'bar',
json: jsonTest,
keys: {
x: 'year',
value: ['marks']
}
},
size: {
width: 400,
},
axis: {
x: {
type: 'category'
}
},
bar: {
width: {
ratio: 0.5
}
}
});
I was getting the following output:
Here's the JSBin example: Bar Chart Example
I'm using Highcharts, and I used to be able to get labels on the side. But it's not working now, am I missing something? The red arrow is where I would want the labels like in the following example.
http://jsfiddle.net/gh/get/jquery/1.9.1/highslide-software/highcharts.com/tree/master/samples/highcharts/demo/bar-basic/
This is the code I'm using, I add the series in a dynamic way.
credits: {
enabled: false
},
chart: {
type: 'bar'
},
xAxis: {
categories: ['Jan', 'Feb'],
labels: {
enabled: true,
}
},
yAxis: {
min: 0,
max: 100,
title: {
text: 'Score',
align: 'high'
}
},
plotOptions: {
bar: {
dataLabels: {
enabled: true
}
}
}
});
// Add Series
var detailchart = $('#chart-detail').highcharts();
var categories = new Array;
// Set Chart Title
detailchart.setTitle({text: results[0].category});
$.each(results, function(i, data){
categories.push(data.name);
detailchart.addSeries({
name: data.name,
data: [data.score]
});
});
detailchart.xAxis[0].setCategories(["1", "2"]);
$('#chart-detail').highcharts().reflow();
Results is an array that looks like this (I get it through ajax):
As I understand from your code here, you wish to specify two categories with names 1 and 2 but you are not specifying any data for second category, So the only category that is showing on your chart is 1. Your data array for each series must have elements per each category. For example if you have two category you should consider having two data elements in each series. In this line data: [data.score] you are just specifying one element in data array. Your code should be something like this: (make it dynamic per your need)
$.each(results, function(i, data){
categories.push(data.name);
detailchart.addSeries({
name: data.name,
data: [data.score, 40], //40 is some data for your second category.
});
});
Demo: http://jsfiddle.net/u6crkatv/
Only what you need is use 4 series, each of them with single data point.
series: [{
name: 'Year 1800',
data: [107]
}, {
name: 'Year 1900',
data: [138]
}, {
name: 'Year 2008',
data: [973]
},{
name: 'Year 20098',
data: [973]
}]
Example: http://jsfiddle.net/y9wzggc4/
I'm trying to implement a Highcharts Column-Drilldown Chart in my Rails application using lazy_high_charts. I want to display data that's being pulled from my database and stored in four arrays (areas, areaScores, departments, and deptScores). I'm having trouble converting the JS from the example (JSFiddle) listed on the highchart site into ruby. I have not been able to find any resources on creating a column-drilldown chart in ruby. Any help on how to integrate the drilldown chart into my ruby application would be highly appreciated.
I have included the sample JavaScript shown on the Highcharts demo page and my controller method that populates the four arrays with data and builds the highchart.
Highcharts Column-Drilldown Chart Example (Javascript)
$(function () {
Highcharts.data({
csv: document.getElementById('tsv').innerHTML,
itemDelimiter: '\t',
parsed: function (columns) {
var brands = {},
brandsData = [],
versions = {},
drilldownSeries = [];
// Parse percentage strings
columns[1] = $.map(columns[1], function (value) {
if (value.indexOf('%') === value.length - 1) {
value = parseFloat(value);
}
return value;
});
$.each(columns[0], function (i, name) {
var brand,
version;
if (i > 0) {
// Remove special edition notes
name = name.split(' -')[0];
// Split into brand and version
version = name.match(/([0-9]+[\.0-9x]*)/);
if (version) {
version = version[0];
}
brand = name.replace(version, '');
// Create the main data
if (!brands[brand]) {
brands[brand] = columns[1][i];
} else {
brands[brand] += columns[1][i];
}
// Create the version data
if (version !== null) {
if (!versions[brand]) {
versions[brand] = [];
}
versions[brand].push(['v' + version, columns[1][i]]);
}
}
});
$.each(brands, function (name, y) {
brandsData.push({
name: name,
y: y,
drilldown: versions[name] ? name : null
});
});
$.each(versions, function (key, value) {
drilldownSeries.push({
name: key,
id: key,
data: value
});
});
// Create the chart
$('#container').highcharts({
chart: {
type: 'column'
},
title: {
text: 'Browser market shares. November, 2013'
},
subtitle: {
text: 'Click the columns to view versions. Source: netmarketshare.com.'
},
xAxis: {
type: 'category'
},
yAxis: {
title: {
text: 'Total percent market share'
}
},
legend: {
enabled: false
},
plotOptions: {
series: {
borderWidth: 0,
dataLabels: {
enabled: true,
format: '{point.y:.1f}%'
}
}
},
tooltip: {
headerFormat: '<span style="font-size:11px">{series.name}</span><br>',
pointFormat: '<span style="color:{point.color}">{point.name}</span>: <b>{point.y:.2f}%</b> of total<br/>'
},
series: [{
name: 'Brands',
colorByPoint: true,
data: brandsData
}],
drilldown: {
series: drilldownSeries
}
})
}
});
});
My Controller:
def generateOrgBreakdownReport
# First, query the database for the data you need for the report
#jsonanswerBRKD = queryDatabaseForOrgProgressReport()
# Second, process and combine data as needed for the report
#areaBreakdown, #deptBreakdown, #employBreakdown = computeAreaAndDeptPrepareScore(#jsonanswerBRKD)
# Third, you'll need to put the processed data into a format
# Highcharts will understand for the data series it uses
# for the graph.
#THESE ARRAYS HOLD THE NAMES AND SCORES OF AREAS AND DEPARTMENTS
#deptScores, #departments, #areaScores, #areas = cycleThroughProcessedDataAndCreateHighChartsDataSetsBreakdown(#areaBreakdown, #deptBreakdown, #employBreakdown)
# Last, we put the newly made data sets for Highcharts to work its magic.
#DONT KNOW HOW TO IMPLEMENT DRILLDOWN FOR RUBY
#orgBreakdown = LazyHighCharts::HighChart.new('column') do |f|
f.chart( type: 'column' )
f.xAxis(
title: { text: "Areas" },
type: 'category'
)
f.yAxis(
title: { text: "Preparedness Score (%)"},
)
f.series(
name: "Department Score",
colorByPoint: true,
data: #deptScores
)
f.series(
name: "Area Score",
data: #areaScores
)
f.title(
text: "Organizational Breakdown"
)
f.options[:xAxis][:categories] = #areas
f.drilldown({:series=>{
name:"Dept. Score",
data: #deptScore
}
})
end
end
Thanks,
Matt
I haven't used Lazy Highcharts, but assuming it mirrors the JSON from the JavaScript API you need to add the sub-series by name, e.g.
f.series(
name: "Department Score",
colorByPoint: true,
data: #deptScores,
drilldown: "subdept" #add this
)
Then you'll need to add drilldown data, and if Lazy Highcharts supports it, it might look something like this:
f.drilldown(
series: {
id: "subdept",
data: [
["One", 1],
["Two", 2],
["Three", 3]
]
}
)
See this basic drilldown fiddle to see how the resulting Javascript should look.
To get drilldown to work in Rails you have to make sure you include the drilldown module in your JavaScript manifest file (application.js).
I also had to download the file as it was not my highcharts module catalogue. You can find the file here: http://code.highcharts.com/modules/drilldown.js
Add this to application.js:
//= require highcharts/modules/drilldown
Outside of Rails you can include the drilldown module like this:
<script src="http://code.highcharts.com/modules/drilldown.js"></script>