Reputation: 2055
I have many CSV files,
I need create from them dataSetSelector
On select I need to get table
But im getting undefined on the end of my table.
And World map based on selected data
So need to get something like
*
to country name (and be good to show popup on mouse over with all duplicates values), on map put all duplicates into description section splitting by newline and show value with *
What I do codepen.io
As I first day studing AmCharts, I cant get dataSetSelector and put data from multiple csv files into it. Also I cant find info how to join stock chart with map and table.
So please help to achieve my wysh.
Upvotes: 0
Views: 535
Reputation: 16012
I'll focus on AmCharts-specific stuff in 2-4 since that's the main point of the question. I am also only going to provide a solution for AmCharts version 3.x. You should be able to handle 1 and 5 from there as you can tweak the CSS to more accommodate 1 and add whatever logic you need to satisfy 5.
To get the easy parts out of the way first
dataSetSelector
is a stock chart property. The only way to reproduce this functionality for maps and serial charts is to write your own <select>
with <option>
tags and JavaScript to trigger the desired load action on change.Taking the above into account, you need to set and position your dropdown, table and chart/map divs and add code to link everything together.
Some basic HTML and CSS for this layout
HTML:
<div id="container">
<div id="selector-table-div">
<select id="data-selector">
<option value="path/to/csv-1">Dataset 1</option>
<option value="path/to/csv-2">Dataset 2</option>
</select>
<div id="datatable"></div>
</div>
<div id="mapdiv"></div>
<div id="chartdiv"></div>
</div>
CSS:
#mapdiv {
width: 70%;
height: 400px;
float: left;
}
#chartdiv {
width: 100%;
height: 250px;
}
#selector-table-div {
width: 20%;
height: 450px;
float: left;
}
You're on your own for making this more responsive for height. I omitted the datatable stuff and highlighted row for brevity.
In your JS, you'll want to attach a change
event to trigger a page update when a different dropdown item is selected:
document
.getElementById("data-selector")
.addEventListener("change", function(e) {
updatePage(e.target.value); //update page calls AmCharts.loadFile, updates/creates the table, map and chart with new data
});
Since you're planning on using both charts and maps on the same page, you need to use amcharts.js
, and ammap_amcharts_extension.js
. Using amcharts.js
and ammaps.js
in the same page will cause bugs with both your charts and maps as both files override each other's methods. Your column chart will need serial.js
:
<script src="https://www.amcharts.com/lib/3/amcharts.js"></script>
<script src="https://www.amcharts.com/lib/3/ammap_amcharts_extension.js"></script>
<script src="https://www.amcharts.com/lib/3/serial.js"></script>
<!-- other stuff omitted -->
Since you want your map to be tied to your data, you'll want to provide an easy way to map each row to a map area. Adding ISO 3166-2 country codes to your CSVs will simplify the process immensely:
country,visits,country_code
USA,2025,US
China,1882,CN
Japan,1809,JP
...
From there, you can set up your map's areas using your newly created country_code column as the MapArea id to activate the area on the map:
var areas = data.map(function(row) {
return {
id: row.country_code, //use ISO code for area ids
value: row.visits
};
});
// ...
AmCharts.makeChart("mapdiv", {
// ..
dataProvider: {
map: "worldLow",
areas: areas
}
});
To capture the min/max and assign it to the area, simply loop through the data and use Math.min
/Math.max
:
var minValue = Number.MAX_VALUE;
var maxValue = Number.MIN_VALUE;
data.forEach(function(row) {
minValue = Math.min(minValue, row.visits);
maxValue = Math.max(maxValue, row.visits);
});
// ...
AmCharts.makeChart("mapdiv", {
// ..
valueLegend: {
minValue: minValue,
maxValue: maxValue
// ...
}
});
You'll also want to adjust your map/chart creation code in separate functions that know when to either create a new map/chart or update an existing one:
var map, chart;
// ...
function updateMap(data) {
// ...
if (map) {
//makeChart here
}
else {
map.dataProvider.areas = areas;
map.valueLegend.minValue = minValue;
map.valueLegend.maxValue = maxValue;
map.validateData(); // update map
}
For the map, you'll also want to make sure that the map label placement code is called not only upon init, but also when the map is updated:
function updateMap(data) {
// ...
if (map) {
//makeChart here
}
else {
// data update here
}
updateLabel(); //update labels - same code as before
Creating your chart is pretty straightforward. You can add a clickGraphItem
and rollOverGraphItem
event to select the corresponding map area and highlight the table row on click/hover:
chart = AmCharts.makeChart("chartdiv", {
type: "serial",
dataProvider: data,
// ...
listeners: [
{
event: "clickGraphItem",
method: handleBarInteraction
}, {
event: "rollOverGraphItem",
method: handleBarInteraction
}
]
function handleBarInteraction(e) {
map.selectObject(map.getObjectById(e.item.dataContext.country_code));
var selected = document.querySelector(".selected");
if (selected) {
selected.classList.remove("selected");
}
document
.getElementById(e.item.dataContext.country_code)
.classList.add("selected");
}
Your undefined line is likely coming from an extra newline in your CSV. You can simply check the last item and pop it out of the array before creating your table, map and chart:
var data = AmCharts.parseCSV(response, {
// ...
});
if (data[data.length -1].country === undefined) {
data.pop();
}
Here's a complete codepen with all of the above plus some restructured code. Note that the labels are placed in weird places. The example you pulled the label code from defines exception latitude and longitude variables for you to set up for specific areas. You'll need to figure out those values.
Upvotes: 2