Getting JSON from Google for Highmaps - javascript

I'm pretty rusty with JavaScript, so I'm hoping someone can help me out. I'm working with Highmaps and would like to link the map to data in a Google Spreadsheet. (It's a U.S. map of counties which will be updated regularly, so having it all in the script itself is a little unwieldy.)
This is what my code looks like now:
<script type="text/javascript">
var example = 'us-counties',
theme = 'default';
(function($) { // encapsulate jQuery
$(function() {
var data = [{
"code": "us-al-001",
"name": "Autauga County, AL",
"value": 0
},
…
{
"code": "us-pr-153",
"name": "Yauco Municipio, PR",
"value": 0
}],
countiesMap = Highcharts.geojson(Highcharts.maps['countries/us/us-all-all']),
lines = Highcharts.geojson(Highcharts.maps['countries/us/us-all-all'], 'mapline'),
options;
// Add state acronym for tooltip
Highcharts.each(countiesMap, function(mapPoint) {
mapPoint.name = mapPoint.name + ' County, ' + mapPoint.properties['hc-key'].substr(3, 2);
});
series: [{
name: 'County',
mapData: countiesMap,
data: data,
joinBy: ['hc-key', 'code'],
tooltip: {
enabled: true,
positioner: function () {
return { x: 0, y: 250 };
},
pointFormat: '{point.name}',
borders: 0.5
},
borderWidth: 0.5
}, {
type: 'mapline',
name: 'State borders',
data: [lines[0]],
color: 'white'
}, {
type: 'mapline',
name: 'Separator',
data: [lines[1]],
color: 'gray'
}]
};
// Instanciate the map
$('#container').highcharts('Map', options);
});
$(document).ready(function() {
$("#view-menu").click(function(e) {
$("#wrap").toggleClass("toggled");
});
$("#sidebar-close").click(function(e) {
$("#wrap").removeClass("toggled");
});
});
})(jQuery);
</script>
Of course, since there's over 3,200 counties, I'd rather store that data elsewhere and pull it into the var data = [] string, but I'm not sure how to do that.
Any help would be appreciated.

Although this isn't something I've done, it looks like this should be relatively straightforward to do (although nothing is as simple as it looks of course).
There is an API for Google Sheets (https://developers.google.com/google-apps/spreadsheets/) and you can Google examples of how to retrieve data - this one looks clear (https://developers.google.com/gdata/docs/json) although it does point out that there are newer versions of some of the relevant APIs.
If you pull in the JSON data from the Google Sheet you then just need to put the values into the 'value' element of your data variable. You could do all of that within your main function or do it separately and pass it to your function as a parameter.

Related

Chartjs bar chart appears empty when page loads

I am using the ChartJS library to display a bar chart on my HTML page. The issue I am facing is when the page loads, it displays an empty bar chart without the data I have passed into it and without rendering the bars. After one click to the legend, the chart resizes and my labels appear on the x-axis, on the second click the bars are rendered and the y-axis populates to my passed in data. I am not sure why the chart is behaving this way.
I tested the chart with the code provided in the chart.js documentation and it appears instantly. I think the issue has to do with how I am calling my express backend to retrieve data from my endpoint.
Not sure how to resolve this issue. Any help is appreciated.
index.html:
<canvas
id="patents-per-category-bar-chart"
width="400"
height="400"
></canvas>
<script type="text/javascript">
var categoryLabels = [];
var categoryValues = [];
var centerLabels = [];
var centerValues = [];
$.getJSON("http://localhost:5000/api").done((data) => {
for (let item in data.patentsPerCategory) {
if (!data.patentsPerCategory.hasOwnProperty(item)) {
continue;
}
categoryLabels.push(item);
categoryValues.push(data.patentsPerCategory[item]);
}
for (let item in data.patentsPerCenter) {
if (!data.patentsPerCenter.hasOwnProperty(item)) {
continue;
}
centerLabels.push(item);
centerValues.push(data.patentsPerCenter[item]);
}
});
var ctx = document
.getElementById("patents-per-category-bar-chart")
.getContext("2d");
var barChartConfig = {
type: "bar",
data: {
labels: categoryLabels,
datasets: [
{
backgroundColor: "blue",
label: "# Patents Per Category",
data: categoryValues,
},
],
},
options: {
legend: {
onClick: null,
},
responsive: true,
scales: {
yAxes: [
{
ticks: {
beginAtZero: true,
},
},
],
},
},
};
var categoryBarChart = new Chart(ctx, barChartConfig);
</script>
mock data returned from the api:
{
"category": {
"health medicine and biotechnology": 37,
"instrumentation": 38,
"storage": 30,
"systems": 71,
"aeronautics": 1,
"electronics": 47,
"optics": 60,
"materials": 119,
"undefined": 3,
"communications": 32,
"sensors": 102,
"robotics": 37,
"software": 49,
"propulsion": 9,
"manufacturing": 40,
"environment": 24,
"aerospace": 79
}
}
After returning this data from the api, I iterate over it and push the keys and values into separate arrays which are categoryLabels, categoryValues. Then pass these arrays directly into the labels and data for the chart
Created a jsFiddle:
https://jsfiddle.net/tkdamxr5/2/
It works fine in the jsFiddle enviornment so the issue must be in the way I am calling my data using jQuery. Can anyone clarify how I need to call my express backend to get the data and pass it into the chart so it works correctly?
Figured it out. In my original code I was using
$.getJSON('http://localhost:5000/api').done((data) => {}
to call my expressjs backend.
I changed it to use
$.ajax({
url: "http://localhost:5000/api",
success: function (result) {
let labels = [];
let data = [];
for (let item in result.category) {
if (!result.category.hasOwnProperty(item)) {
continue;
}
labels.push(item);
data.push(result.category[item]);
}
},
error: function(err) { console.log(err); }
})
and was able to display my bar chart successfully and as expected.

Plot a bar graph using Highcharts drilldown with two different JSON end points

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.

Highcharts navigator not working with data set

Can someone please take a look at this example? It works when I use a smaller data set, but when I use a larger historical data set, it stops working and the data series does not render. Please help.
Small data set example - http://jsfiddle.net/Yrygy/250/
Large data set example (SERIES DOES NOT RENDER) - http://jsfiddle.net/Yrygy/249
var chart = new Highcharts.StockChart({
chart: {
renderTo: 'container',
height: 120
},
navigator: {
series: {
data: chartData
}
},
series: [{
data: [null],
markers: {
enabled:true
}
}]
});
You need to have your data sorted in ascending time order. Currently your "large" data set is not.
There is a couple of problems. First of all, as said #wergeld, you need to sort your data:
chartData.sort(function(a,b) { return a[0] - b[0]; });
Then the problem is with setting option for navigator:
navigator: {
series: [{
name: 'MSFT',
data: chartData
}]
},
When should be an object, not an array:
navigator: {
series: {
name: 'MSFT',
data: chartData
}
},
And the last one, do you really need to set xAxis.min/max ? Escpecially to values 2 and 4. when you have timestamps like
Working demo: http://jsfiddle.net/Yrygy/253/

How to implement Highcharts column-drilldown chart in Rails application?

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>

Highcharts not plotting Date string as Category

I am using Highcharts to plot JSON Data. The dates are in the string format.
JSON Data:
[{"BRENT_SPOT":70.88,"TRADE_DATE":"31-JUL-2009"},{"BRENT_SPOT":73.28,"TRADE_DATE":"03-AUG-2009"},{"BRENT_SPOT":74.31,"TRADE_DATE":"04-AUG-2009"},{"BRENT_SPOT":74.96,"TRADE_DATE":"05-AUG-2009"},{"BRENT_SPOT":74.4,"TRADE_DATE":"06-AUG-2009"},{"BRENT_SPOT":72.84,"TRADE_DATE":"07-AUG-2009"},{"BRENT_SPOT":73.29,"TRADE_DATE":"10-AUG-2009"},{"BRENT_SPOT":72.04,"TRADE_DATE":"11-AUG-2009"}]
HighCharts / JQuery Code :
<script>
var chart;
$(function() {
var options = {
chart: {
renderTo: 'container',
zoomType: 'xy',
type: 'line'
},
title: {
text: 'Brent Daily Price Curve (FPC as at <cfoutput>#f_date#</cfoutput>)'
},
xAxis: {
labels: {
rotation: 45,
step: 3
},
type: 'category'
},
yAxis: {
lineWidth: 1,
title: {
text: '$ USD'
},
min: 0
},
series: []
};
$.getJSON("brentpricehc_test.cfm?f_date=<cfoutput>#f_date#</cfoutput>", {}, function(jsonResult) {
var BrentUSDPrice = {
name: "Brent Spot (USD)",
type: "line",
data: [],
marker: {
radius: 2
}
};
$(jsonResult).each(function(index) {
BrentUSDPrice.data.push([this.TRADE_DATE, this.BRENT_SPOT]);
});
/*options.series[0] = BrentUSDPrice;*/
options.series.push(BrentUSDPrice);
chart = new Highcharts.Chart(options);
});
});
</script>
I'm unable to plot any values wrt each of the date strings. I tried converting the JSON dates to datetime instead but still the same issue.
Few More details (for testing purposes):
Modifying to the below line plots the graph with the correct "brent_spot" values. This means that the issue lies with the way the "trade_dates" are 'not' plotting.
BrentUSDPrice.data.push([index, this.BRENT_SPOT]);
Edit 2 : (Using Datetime type to make the code work)
JSON Data (New): Returned as TO_CHAR(TRADE_DATE, 'YYYY/MM/DD')
[{"BRENT_SPOT":70.88,"TRADE_DATE":"2009\/07\/31"},{"BRENT_SPOT":73.28,"TRADE_DATE":"2009\/08\/03"},{"BRENT_SPOT":74.31,"TRADE_DATE":"2009\/08\/04"},{"BRENT_SPOT":74.96,"TRADE_DATE":"2009\/08\/05"},{"BRENT_SPOT":74.4,"TRADE_DATE":"2009\/08\/06"},{"BRENT_SPOT":72.84,"TRADE_DATE":"2009\/08\/07"},{"BRENT_SPOT":73.29,"TRADE_DATE":"2009\/08\/10"},{"BRENT_SPOT":72.04,"TRADE_DATE":"2009\/08\/11"}]
$(jsonResult).each(function(index) {
BrentUSDPrice.data.push([new Date(this.TRADE_DATE), this.BRENT_SPOT]);
});
Server side language used : Coldfusion
Database : Oracle
Am I doing something silly somewhere?
I have just tried your code, and it works perfectly fine, see: http://jsfiddle.net/3bQne/1026/
I guess, you need to update to Highcharts 3.0.10 to get this working.
If you are using type: 'category' then you need to assign name: to the data points. See the categories entry at http://api.highcharts.com/highcharts#xAxis
If categories are present for the xAxis, names are used instead of numbers for that axis. Since Highcharts 3.0, categories can also be extracted by giving each point a name and setting axis type to "category".
So the question is whether you are using Highcharts 3.0 and if you do then it needs to look something like this:
data: [{
name: 'Point 1',
color: '#00FF00',
y: 0
}, {
name: 'Point 2',
color: '#FF00FF',
y: 5
}]
see: http://api.highcharts.com/highcharts#series.data

Categories

Resources