I have a small problem with my Highcharts maps. I managed to get it plotting the data I want and even included a selector so the user can adjust which data series is shown. However, it appears that after rendering one particular series once, the Map is appending data objects to each series for those U.S. territories I don't have data for. My biggest series has 53 data objects (US States plus DC, Puerto Rico, Virgin Islands) but after being rendered once the series shows up with 62 structures including those for which I didn't have data (Saint John, Saipan, etc.). This is causing problems with the snippet of code I use to change the state code to the hc-key format needed by this map. While I could just add some extra checks to that function, i would like to understand why Highcharts is adding data to my data structures. Any help would be most appreciated. My Javascript code is below:
<script type="text/javascript">
var states ={resStates: [{code: "AK",value:3},{code: "AL",value:49},{code: "AR",value:9},{code: "AZ",value:28},{code: "CA",value:170},{code: "CO",value:26},{code: "CT",value:12},{code: "DC",value:10},{code: "DE",value:5},{code: "FL",value:126},{code: "GA",value:51},{code: "HI",value:7},{code: "IA",value:5},{code: "ID",value:13},{code: "IL",value:31},{code: "IN",value:28},{code: "KS",value:15},{code: "KY",value:12},{code: "LA",value:17},{code: "MA",value:54},{code: "MD",value:124},{code: "ME",value:13},{code: "MI",value:60},{code: "MN",value:8},{code: "MO",value:19},{code: "MS",value:16},{code: "MT",value:6},{code: "NC",value:43},{code: "ND",value:3},{code: "NE",value:10},{code: "NH",value:14},{code: "NJ",value:72},{code: "NM",value:35},{code: "NV",value:7},{code: "NY",value:70},{code: "OH",value:84},{code: "OK",value:23},{code: "OR",value:11},{code: "PA",value:101},{code: "PR",value:2},{code: "RI",value:20},{code: "SC",value:26},{code: "SD",value:5},{code: "TN",value:19},{code: "TX",value:91},{code: "UT",value:67},{code: "VA",value:112},{code: "VI",value:1},{code: "VT",value:1},{code: "WA",value:29},{code: "WI",value:13},{code: "WV",value:2},{code: "WY",value:4}],
acadStates: [{code: "AK",value:1},{code: "AL",value:47},{code: "AR",value:12},{code: "AZ",value:31},{code: "CA",value:163},{code: "CO",value:34},{code: "CT",value:9},{code: "DC",value:18},{code: "DE",value:7},{code: "FL",value:121},{code: "GA",value:80},{code: "HI",value:6},{code: "IA",value:9},{code: "ID",value:9},{code: "IL",value:29},{code: "IN",value:55},{code: "KS",value:16},{code: "KY",value:8},{code: "LA",value:14},{code: "MA",value:65},{code: "MD",value:81},{code: "ME",value:8},{code: "MI",value:66},{code: "MN",value:7},{code: "MO",value:20},{code: "MS",value:13},{code: "MT",value:4},{code: "NB",value:1},{code: "NC",value:53},{code: "ND",value:4},{code: "NE",value:8},{code: "NH",value:13},{code: "NJ",value:32},{code: "NM",value:32},{code: "NV",value:4},{code: "NY",value:93},{code: "OH",value:83},{code: "OK",value:25},{code: "OR",value:7},{code: "PA",value:123},{code: "PR",value:2},{code: "RI",value:15},{code: "SC",value:17},{code: "SD",value:4},{code: "TN",value:9},{code: "TX",value:103},{code: "UT",value:62},{code: "VA",value:114},{code: "VT",value:2},{code: "WA",value:27},{code: "WI",value:19},{code: "WV",value:4},{code: "WY",value:4}],
empStates: [{code: "AK",value:2},{code: "AL",value:71},{code: "AR",value:4},{code: "AZ",value:12},{code: "CA",value:235},{code: "CO",value:1},{code: "DC",value:36},{code: "FL",value:104},{code: "GA",value:70},{code: "HI",value:5},{code: "IL",value:17},{code: "IN",value:18},{code: "KS",value:14},{code: "LA",value:5},{code: "MA",value:61},{code: "MD",value:244},{code: "MI",value:39},{code: "MN",value:3},{code: "MO",value:4},{code: "MS",value:64},{code: "NC",value:22},{code: "NE",value:2},{code: "NH",value:20},{code: "NJ",value:62},{code: "NM",value:95},{code: "NY",value:22},{code: "OH",value:133},{code: "OK",value:53},{code: "OR",value:7},{code: "PA",value:38},{code: "RI",value:37},{code: "SC",value:26},{code: "TN",value:9},{code: "TX",value:22},{code: "UT",value:75},{code: "VA",value:126},{code: "WA",value:22},{code: "WV",value:2}]};
$(init)
function init() {
drawMap();
}
function drawMap() {
var map_select = $('#smartStates').val();
var map_text = $('#smartStates option:selected').text();
var mydata = states[map_select];
var mycolors = {resStates: {
min: 1,
type: 'linear',
minColor: '#EEEEFF',
maxColor: '#000022',
stops: [
[0, '#EFEFFF'],
[0.67, '#4444FF'],
[1, '#000022']
]
}, acadStates: {
min: 1,
type: 'linear',
minColor: '#FFEEEE',
maxColor: '#220000',
stops: [
[0, '#FFFFEE'],
[0.67, '#FF4444'],
[1, '#220000']
]
}, empStates: {
min: 1,
type: 'linear',
minColor: '#EEFFEE',
maxColor: '#002200',
stops: [
[0, '#EEFFEE'],
[0.67, '#44FF44'],
[1, '#002200']
]
}
}
// Adjusting codes to fit with the us-all-territories map
$.each(mydata, function(){ //looping through each instance of mydata
if (this.code == "PR") {
this.code = "pr-3614";
} else if (this.code == "undefined"){
//not sure what to do here
}
else if (this.code.length==2) {
this.code = "us-" + this.code.toLowerCase();
}
});
// Instanciate the map
$('#container').highcharts('Map', {
chart : {
borderWidth : 1
},
title : {
text : 'SMART Participant Counts by ' + map_text
},
legend: {
layout: 'horizontal',
borderWidth: 0,
backgroundColor: 'rgba(255,255,255,0.85)',
floating: true,
verticalAlign: 'top',
y: 25
},
mapNavigation: {
enabled: true
},
colorAxis: mycolors[map_select],
series : [{
animation: {
duration: 1000
},
data : mydata,
mapData: Highcharts.maps['countries/us/custom/us-all-territories'],
joinBy: ['hc-key', 'code'],
dataLabels: {
enabled: true,
color: '#FFFFFF',
format: '{point.name}'
},
name: 'SMART Participants',
tooltip: {
pointFormat: '{point.name}: {point.value} participants'
}
}]
});
}
</script>
This is because in your mapData property you have this:
mapData: Highcharts.maps['countries/us/custom/us-all-territories'],
us-all-territories, but as you stated, you don't have the data for all of the territories.
The solution is to use a different custom map from Highcharts, unfortunately it doesn't look like they have one with only the US territories you are looking for.
Update: as the comment by Kacper has mentioned: If you set allAreas in series to false, then empty map zones will not be displayed. Example: http://jsfiddle.net/oen00hec/
I am attempting to take the example produced by Highcharts here http://www.highcharts.com/maps/demo/color-axis and substitute the data loaded by the $.getJson with a local JSON file called 'testdata1.json'.
The code I've modified below produces no errors yet the map does not render. I think it's because the testdata1.json is loaded late, after the javascript is executed. If so, is there a better way I should be doing this -- perhaps waiting for the data to load before executing the JS file? I attempted to do this by placing a
$(document).ready(
in front of the function but it didn't work. Any thoughts are greatly appreciated, I think it's something relatively minor that is just escaping me.
Thank you.
$(function () {
// Map options
var options = {
chart : {
renderTo: '#map',
borderWidth : 1
},
title : {
text : 'US population density (/km²)'
},
legend: {
layout: 'horizontal',
borderWidth: 0,
backgroundColor: 'rgba(255,255,255,0.85)',
floating: true,
verticalAlign: 'top',
y: 25
},
mapNavigation: {
enabled: true
},
colorAxis: {
min: 1,
type: 'logarithmic',
minColor: '#EEEEFF',
maxColor: '#000022',
stops: [
[0, '#EFEFFF'],
[0.67, '#4444FF'],
[1, '#000022']
]
},
series : [{
animation: {
duration: 1000
},
mapData: Highcharts.maps['countries/us/us-all'],
joinBy: ['postal-code', 'code'],
dataLabels: {
enabled: true,
color: 'white',
format: '{point.code}'
},
name: 'Population density',
tooltip: {
pointFormat: '{point.code}: {point.value}/km²'
}
}]
};
$.getJSON('static/data/testdata1.json', function (data) {
// Make codes uppercase to match the map data
$.each(data, function () {
this.code = this.code.toUpperCase();
});
options.series.data= data;
var chart = new Highcharts.Chart(options)
});
});
You have three problems. Here's a fiddle based on their sample that uses your approach, but still uses their data, and works: http://jsfiddle.net/g29k24vw/1/
Here are the important parts:
chart : {
renderTo: 'container',
borderWidth : 1,
type: 'map'
},
And:
$.getJSON('http://www.highcharts.com/samples/data/jsonp.php?filename=us-population-density.json&callback=?', function (data) {
// Make codes uppercase to match the map data
$.each(data, function () {
this.code = this.code.toUpperCase();
});
options.series[0].data= data;
var chart = new Highcharts.Chart(options);
});
Note the differences here:
You need to specify the chart type in options if you're going to instantiate the chart object directly instead of using the jQuery helper.
renderTo doesn't want a hash in front of the element name.
options.series[0].data, not options.series.data...series is actually an array of objects.
Here's what I'm trying to do:
Use papa parse to parse a CSV file.
Create two JS Objects(ohlc and volume) with that parsed data.
Then that data is used to create a highstocks chart.
Parsing with papa parse example:
function doStuff(data) {
//do stuff here
console.log(data);
}
function parseData(url, callBack) {
Papa.parse(url, {
download: true,
dynamicTyping: true,
complete: function(results) {
callBack(results.data);
}
});
}
parseData("https://www.quandl.com/api/v3/datasets/WIKI/AAPL.csv", doStuff);
A working Highchart example: jsfiddle
Me trying to combine the top two examples: jsfiddle
$(function () {
var ohlc = [],
volume = [],
dataLength = data.length,
// set the allowed units for data grouping
groupingUnits = [[
'week', // unit name
[1] // allowed multiples
], [
'month',
[1, 2, 3, 4, 6]
]],
i = 1;
function parseData(url, callBack) {
Papa.parse(url, {
download: true,
dynamicTyping: true,
complete: function(results) {
callBack(results.data);
}
});
}
function setObjects(data) {
console.log(data[i][0]);
for (i; i < dataLength; i += 1) {
ohlc.push([
data[i][0], // the date
data[i][1], // open
data[i][2], // high
data[i][3], // low
data[i][4] // close
]);
volume.push([
data[i][0], // the date
data[i][5] // the volume
]);
}
}
parseData("https://www.quandl.com/api/v3/datasets/WIKI/AAPL.csv", setObjects);
// create the chart
$('#container').highcharts('StockChart', {
rangeSelector: {
selected: 1
},
title: {
text: 'AAPL Historical'
},
yAxis: [{
labels: {
align: 'right',
x: -3
},
title: {
text: 'OHLC'
},
height: '60%',
lineWidth: 2
}, {
labels: {
align: 'right',
x: -3
},
title: {
text: 'Volume'
},
top: '65%',
height: '35%',
offset: 0,
lineWidth: 2
}],
series: [{
type: 'candlestick',
name: 'AAPL',
data: ohlc,
dataGrouping: {
units: groupingUnits
}
}, {
type: 'column',
name: 'Volume',
data: volume,
yAxis: 1,
dataGrouping: {
units: groupingUnits
}
}]
});
});
Can anyone help me out with what I am doing wrong? I know two things that haven't been done. The data needs to be reverse so that it is in ascending order by date. And the date needs to be converted to milliseconds. However it would help me to get the current data at least inserting to the objects first and then go from there.
This bit
var i = 1;
dataLength = data.length;
Should be in the first lines of the setObjects function, where data is present and the value dataLength is actually used.
I´m building a dynamic 6 series bar graph with jqPlot. In my implementation, the user will choose which data will go into each serie and the system will load data according to his choice. The function `GetDataFromSeries() loads the series data given a serie number and the available ticks (as categories - it gets all ticks from all series and builds an unique category array).
If the user choose to load all series, everything runs fine. The problem is if the user decide not to load one series (that´s possible). In that case, I will not load that data in GetDataFromSeries() and jqPlot gives me error.
I´m trying several ways to do it, but I´m being successfull. In the code the way it is, I´m getting Uncaught Error: No data specified if the user decides not to load one of the series. I have tried to put dummy data (null or zero) in case one of the series are empty, but doing so the bars are moved and shrinked as If I have more bars to be shown.
Don´t know how to solve that. Appreciate very much any kind of help.
Rds.
[CODE]
function GeneratePlot() {
var tickAxis = new Array();
var data0 = new Array();
var data1 = new Array();
var data2 = new Array();
var data3 = new Array();
var data4 = new Array();
var data5 = new Array();
///
/// Convert series into meaningfull data
///
tickAxis = GetTickAxisFromSeries();
data0 = GetDataFromSeries(0, tickAxis);
data1 = GetDataFromSeries(1, tickAxis);
data2 = GetDataFromSeries(2, tickAxis);
data3 = GetDataFromSeries(3, tickAxis);
data4 = GetDataFromSeries(4, tickAxis);
data5 = GetDataFromSeries(5, tickAxis);
var options = {
title: 'Evolution Plot',
height: 500,
series: [
{ show: (data0.length != 0) },
{ show: (data1.length != 0) },
{ show: (data2.length != 0) },
{ show: (data3.length != 0) },
{ show: (data4.length != 0) },
{ show: (data5.length != 0) }
],
axes: {
xaxis: {
renderer: $.jqplot.CategoryAxisRenderer,
ticks: tickAxis,
tickRenderer: $.jqplot.CanvasAxisTickRenderer,
tickOptions: {
angle: -90,
fontSize: '8pt',
formatter: $.jqplot.DateTickFormatter
}
},
yaxis: {
pad: 1.05,
tickOptions: {
formatString: '%d',
fontSize: '8pt'
}
}
},
seriesDefaults: {
renderer: $.jqplot.BarRenderer,
rendererOptions: {
fillToZero: true
}
},
highlighter: {
show: true,
sizeAdjust: 7.5
},
cirsor: {
show: false
}
}
var plot = $.jqplot('chart', [data0, data1, data2, data3, data4, data5], options).replot();
}
I think this would solve your problem:
function GeneratePlot() {
var tickAxis = new Array();
var data = new Array();
var tempData = [];
///
/// Convert series into meaningfull data
///
tickAxis = GetTickAxisFromSeries();
for(var i = 0; i < 6; i++){
tempData = GetDataFromSeries(i, tickAxis);
if(tempData.length > 0){
data.push(tempData);
}
}
var options = {
title: 'Evolution Plot',
height: 500,
axes: {
xaxis: {
renderer: $.jqplot.CategoryAxisRenderer,
ticks: tickAxis,
tickRenderer: $.jqplot.CanvasAxisTickRenderer,
tickOptions: {
angle: -90,
fontSize: '8pt',
formatter: $.jqplot.DateTickFormatter
}
},
yaxis: {
pad: 1.05,
tickOptions: {
formatString: '%d',
fontSize: '8pt'
}
}
},
seriesDefaults: {
renderer: $.jqplot.BarRenderer,
rendererOptions: {
fillToZero: true
}
},
highlighter: {
show: true,
sizeAdjust: 7.5
},
cirsor: {
show: false
}
}
var plot = $.jqplot('chart', data, options).replot();
}