Changing dateformat in stockcharts from amchart - charts

I created a stockchart from amchart and saved it here: jsfiddle
Now I want to change (a) the date format of the chart cursor to "DD.MM.YYYY" and (b) the date format of the category axis to german format, e.g. "01. Mai 2018". I assume that (a) can somehow be solved with "categoryBalloonDateFormat", but I wasn't able to find the correct place to put it.
chart.ChartCursor.categoryBalloonDateFormat = "DD.MM.YYYY";
Unfortunately this doesn't work.
For (b) I have no clue at all.

For (a) you have to set it in the chartCursorSettings.categoryBalloonDateFormats array for the desired period(s) represented in your chart. If your data is daily, at least set the DD and WW periods (daily and weekly), but depending on the amount of data, you might want to set the MM (monthly) period as well. For example:
chart.chartCursorSettings.categoryBalloonDateFormats = [
{period:"YYYY", format:"YYYY"},
{period:"MM", format:"MMM, YYYY"},
{period:"WW", format:"DD.MM.YYYY"},
{period:"DD", format:"DD.MM.YYYY"},
{period:"hh", format:"JJ:NN"},
{period:"mm", format:"JJ:NN"},
{period:"ss", format:"JJ:NN:SS"},
{period:"fff", format:"JJ:NN:SS"}
]
Similarly for (b), you have to set the categoryAxesSettings.dateFormats array in the same manner as categoryBalloonDateFormats:
chart.categoryAxesSettings.dateFormats = [
{period:"YYYY", format:"YYYY"},
{period:"MM", format:"MMM, YYYY"},
{period:"WW", format:"DD.MM.YYYY"},
{period:"DD", format:"DD.MM.YYYY"},
{period:"hh", format:"JJ:NN"},
{period:"mm", format:"JJ:NN"},
{period:"ss", format:"JJ:NN:SS"},
{period:"fff", format:"JJ:NN:SS"}
]
Demo:
var chart = AmCharts.makeChart("chartdiv", {
"type": "stock",
"theme": "light",
"categoryAxesSettings": {
"dateFormats": [{
period: "YYYY",
format: "YYYY"
},
{
period: "MM",
format: "DD.MM.YYYY"
},
{
period: "WW",
format: "DD.MM.YYYY"
},
{
period: "DD",
format: "DD.MM.YYYY"
},
{
period: "hh",
format: "JJ:NN"
},
{
period: "mm",
format: "JJ:NN"
},
{
period: "ss",
format: "JJ:NN:SS"
},
{
period: "fff",
format: "JJ:NN:SS"
}
]
},
"chartCursorSettings": {
"categoryBalloonDateFormats": [{
period: "YYYY",
format: "YYYY"
},
{
period: "MM",
format: "DD.MM.YYYY"
},
{
period: "WW",
format: "DD.MM.YYYY"
},
{
period: "DD",
format: "DD.MM.YYYY"
},
{
period: "hh",
format: "JJ:NN"
},
{
period: "mm",
format: "JJ:NN"
},
{
period: "ss",
format: "JJ:NN:SS"
},
{
period: "fff",
format: "JJ:NN:SS"
}
],
"valueBalloonsEnabled": true
},
"dataSets": [{
"fieldMappings": [{
"fromField": "value",
"toField": "value"
}],
"dataProvider": generateChartData(),
"categoryField": "date"
}],
"panels": [{
"stockGraphs": [{
"valueField": "value",
"type": "smoothedLine"
}]
}]
});
function generateChartData() {
var chartData = [];
var firstDate = new Date(2012, 0, 1);
firstDate.setDate(firstDate.getDate() - 1000);
firstDate.setHours(0, 0, 0, 0);
for (var i = 0; i < 30; i++) {
var newDate = new Date(firstDate);
newDate.setDate(i);
var a = Math.round(Math.random() * (40 + i)) + 100 + i;
chartData.push({
date: newDate,
value: a
});
}
return chartData;
}
html,
body {
width: 100%;
height: 100%;
margin: 0px;
}
#chartdiv {
width: 100%;
height: 100%;
}
<script src="//www.amcharts.com/lib/3/amcharts.js"></script>
<script src="//www.amcharts.com/lib/3/serial.js"></script>
<script src="//www.amcharts.com/lib/3/themes/light.js"></script>
<script src="//www.amcharts.com/lib/3/amstock.js"></script>
<div id="chartdiv"></div>

Thanks - that worked! In addition if someone wants to change the month names to another language:
AmCharts.monthNames = [
'Januar',
'Februar',
'März',
'April',
'Mai',
'Juni',
'Juli',
'August',
'September',
'Oktober',
'November',
'Dezember'];
AmCharts.shortMonthNames = [
'Jan.',
'Feb.',
'März',
'April',
'Mai',
'Juni',
'Juli',
'Aug.',
'Sept.',
'Okt.',
'Nov.',
'Dez.'];

Related

echarts stacked bar chart with time xaxis

Can someone check my chart options and suggest a way to make the time xaxis behave correctly? I've tried with timestamps, dates, timestamps / 1000 and nothing looks right
let sales = [
0,84,5,3,2,1,0,0,3,6
]
let listings = [
1,297,23,5,8,6,9,3,6,19
]
let ps = [
1663084060653,
1663089644329,
1663095228005,
1663100811680,
1663106395356,
1663111979032,
1663117562708,
1663123146384,
1663128730059,
1663134313735
]
let color = "red"
option = {
textStyle: {
color
},
legend: {
textStyle: {
color
},
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: [
{
type: 'time',
data: ps,
// axisLabel: {
// formatter: ts => new Date(ts).toTimeString().replace(/ .*/, '')
// }
}
],
yAxis: [
{
// type: 'value'
}
],
series: [
{
name: 'Sales',
type: 'bar',
stack: 'Ad',
emphasis: {
focus: 'series'
},
data: sales
},
{
name: "Listings",
type: 'bar',
stack: 'Ad',
emphasis: {
focus: 'series'
},
data: listings
}
]
}
Your series (listings & sales here) have to have a [date, value] format. Also, you'll have to remove data from xAxis as it will automatically follow the dates that are given in the series.
So, in your example :
//convert listings & sales to a list of [date, value]
listings = listings.map((value, index) => {
return [ps[index], value]
})
sales = sales.map((value, index) => {
return [ps[index], value]
})
xAxis: [
{
type: 'time',
//data: ps, <--- remove this line
}
],

Invisible chart area during print and in exported PDF file in spreadsheet created by service account with Google Sheets API (Node.js) in shared folder

I'm creating a spreadsheet in Node.js environment in shared folder using service account with Google Sheets API v.4 in few steps:
Create spreadsheet itself in shared folder with "Can Edit" permission for service account.
Inserting some data and performing some text formats using spreadsheet ID received as callback from previous step.
Inserting chart using as income data the data inserted in prevoius step.
As the result I have a spreadsheet with expected result (text data and horizontal bar chart on same sheet). But when I'm trying to send it on printer, or download as PDF-file - chart area becomes completely invisible. I didn't find any option in official documentation about possible chart visibility during printing or something like this. And when I'm replacing this created chart with manually created one - everything is ok, I can print it and export to PDF.
So, what is the problem? Am I missing something? Or it's some bug?
index.js
const fs = require('fs');
const { google } = require('googleapis');
const express = require('express');
const bodyParser = require("body-parser");
const app = express();
const PORT = 3000;
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.listen(PORT, () => {
console.log(`Server started at http://localhost:${PORT}`)
})
const SCOPES = ['https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/spreadsheets'];
const FOLDER_ID = '1xG3xHhrucB4AGLmnd8T2TmCyqhmPux5Q';
var timeStamp = new Date().getTime();
console.log(`timeStamp at startup = ${timeStamp}`);
const auth = new google.auth.GoogleAuth({
keyFile: 'credentials.json',
scopes: SCOPES
});
process.env.HTTPS_PROXY = 'http://10.5.0.20:3128';
const sheets = google.sheets({
version: 'v4',
auth: auth,
proxy: 'http://10.5.0.20:3128'
});
const drive = google.drive({
version: 'v3',
auth: auth,
proxy: 'http://10.5.0.20:3128'
});
function createFileName() {
const now = new Date();
let date = String(now.toISOString().slice(0, 10));
let hours = String(now.getHours()).padStart(2, "0");
let minutes = String(now.getMinutes()).padStart(2, "0");
let seconds = String(now.getSeconds()).padStart(2, "0");
let humanDate = date.replaceAll('-', '.');
humanDate = `${humanDate}_${hours}-${minutes}-${seconds}`;
return humanDate;
}
async function saveFileLocally(filePath, data) {
fs.writeFile(filePath, JSON.stringify(data), error => {
if (error) {
console.error(error);
return;
}
});
return true;
}
app.get("/check", (req, res) => {
res.send('server is online...');
});
app.post("/motivation", async (req, res) => {
if(!req.body) return res.sendStatus(400);
try {
const prizv = req.body.prizv;
const name = req.body.name;
const father = req.body.father;
const sex = req.body.sex;
const age = req.body.age;
const factors = req.body.factors;
const testName = 'motivation';
const clientData = { prizv: prizv, name: name, father: father, sex: sex, age: age, factors: factors, testName: testName };
const fileName = `${createFileName()}_${prizv}`;
const filePath = `files/${testName}/${fileName}.txt`;
const isSaved = await saveFileLocally(filePath, clientData);
if (isSaved) {
console.log(`file is saved locally....`);
const sheetID = await createSheetToGoogleDIsk(clientData, fileName);
res.send(sheetID);
}
} catch (error) {
console.log(error)
}
});
async function createSheetToGoogleDIsk(clientData, fileName) {
const file = fileName;
var sheetsMetadata = {
name: file,
mimeType: 'application/vnd.google-apps.spreadsheet',
parents: [FOLDER_ID]
};
const res2 = drive.files.create({
resource: sheetsMetadata,
fields: 'id'
}, function (err, file) {
if (err) {
console.error(err);
} else {
console.log('SheetID: ', file.data.id);
const gSheetID = file.data.id;
pasteDataToGoogleSheet(clientData, gSheetID);
insertChartToGoogleSheet(gSheetID);
return file.data.id;
}
});
}
async function insertChartToGoogleSheet(spreadsheetId) {
spreadsheetId = spreadsheetId;
let requests = [];
// set font size for whole Sheet as 14
requests.push({
"repeatCell": {
"range": {
"sheetId": 0,
"startRowIndex": 0,
"endRowIndex": 100,
},
"cell": {
"userEnteredFormat": {
"textFormat": {
"fontSize": 13,
},
},
},
"fields": "userEnteredFormat.textFormat.fontSize"
},
});
// set header text format as Bold and 18 pt
requests.push({
"repeatCell": {
"range": {
"sheetId": 0,
"startRowIndex": 0,
"endRowIndex": 2,
},
"cell": {
"userEnteredFormat": {
"textFormat": {
"fontSize": 18,
"bold": true
},
},
},
"fields": "userEnteredFormat(textFormat)"
},
});
// set subheader text format as Bold and 15 pt
requests.push({
"repeatCell": {
"range": {
"sheetId": 0,
"startRowIndex": 3,
"endRowIndex": 4,
},
"cell": {
"userEnteredFormat": {
"textFormat": {
"fontSize": 15,
"bold": true
},
},
},
"fields": "userEnteredFormat(textFormat)"
},
});
// set client data as Bold
requests.push({
"repeatCell": {
"range": {
"sheetId": 0,
"startRowIndex": 5,
"endRowIndex": 10,
"startColumnIndex": 3,
"endColumnIndex": 5
},
"cell": {
"userEnteredFormat": {
"textFormat": {
"fontSize": 13,
"bold": true
},
},
},
"fields": "userEnteredFormat(textFormat)"
},
});
// set 1st column width as 20px
requests.push({
"updateDimensionProperties": {
"range": {
"sheetId": 0,
"dimension": "COLUMNS",
"startIndex": 0,
"endIndex": 1
},
"properties": {
"pixelSize": 20
},
"fields": "pixelSize"
}
});
// set 4st column width as 150px
requests.push({
"updateDimensionProperties": {
"range": {
"sheetId": 0,
"dimension": "COLUMNS",
"startIndex": 3,
"endIndex": 4
},
"properties": {
"pixelSize": 150
},
"fields": "pixelSize"
}
});
// set bold factors Values
requests.push({
"repeatCell": {
"range": {
"sheetId": 0,
"startRowIndex": 33,
"endRowIndex": 45,
"startColumnIndex": 4,
"endColumnIndex": 5
},
"cell": {
"userEnteredFormat": {
"textFormat": {
"fontSize": 13,
"bold": true
},
},
},
"fields": "userEnteredFormat(textFormat)"
},
});
requests.push({
"addChart": {
"chart": {
"chartId": 1,
"spec": {
"titleTextFormat": {
},
"basicChart": {
"chartType": "BAR",
"axis": [
{
"position": "BOTTOM_AXIS",
},
{
"position": "LEFT_AXIS",
}
],
"domains": [
{
"domain": {
"sourceRange": {
"sources": [
{
"sheetId": 0,
"startRowIndex": 33,
"endRowIndex": 45,
"startColumnIndex": 1,
"endColumnIndex": 2
}
]
},
},
}
],
"series": [
{
"series": {
"sourceRange": {
"sources": [
{
"sheetId": 0,
"startRowIndex": 33,
"endRowIndex": 45,
"startColumnIndex": 4,
"endColumnIndex": 5
}
]
}
},
"targetAxis": "BOTTOM_AXIS"
}
],
},
},
"position": {
"overlayPosition": {
"anchorCell": {
"sheetId": 0,
"rowIndex": 11,
"columnIndex": 1
},
"offsetXPixels": 0,
"offsetYPixels": -7,
"widthPixels": 800,
"heightPixels": 450
},
},
"border": {
"color": {
"red": 1,
"green": 1,
"blue": 1,
"alpha": 0
},
}
}
}
});
const batchUpdateRequest = { requests };
sheets.spreadsheets.batchUpdate({
spreadsheetId,
resource: batchUpdateRequest,
}, (err, result) => {
if (err) {
// Handle error
console.log(err);
return false
} else {
console.log(`${result.updatedCells} chart inserted`);
return spreadsheetId
}
});
}
async function pasteDataToGoogleSheet(clientData, sheetId) {
ecxelID = sheetId;
let data1 = [
["Тест «Мотиваційний особистісний профіль»"], [""], ["Результати тестування"], [""], ["Прізвище"], ["Імя"], ["По-батькові"], ["Вік"], ["Стать"]
];
let data2 = [
[clientData.prizv], [clientData.name], [clientData.father], [clientData.age], [clientData.sex]
];
let factorsLabels1_6 = [
["1. Матеріальна винагорода:"], ["2. Комфортні умови:"], ["3. Структурованість роботи:"], ["4. Соціальні контакти:"], ["5. Довірливі стосунки:"], ["6. Визнання:"]
];
let factors1_6 = [
[clientData.factors.factor1], [clientData.factors.factor2], [clientData.factors.factor3], [clientData.factors.factor4], [clientData.factors.factor5], [clientData.factors.factor6]
];
let factorsLabels7_12 = [
["7. Досягнення мети:"], ["8. Влада і вплив:"], ["9. Відсутність рутини:"], ["10. Креативність:"], ["11. Самовдосконалення і розвиток:"], ["12. Цікава і корисна діяльність:"]
];
let factors7_12 = [
[clientData.factors.factor7], [clientData.factors.factor8], [clientData.factors.factor9], [clientData.factors.factor10], [clientData.factors.factor11], [clientData.factors.factor12]
];
const data = [{
range: "B2:B10",
values: data1,
},
{
range: "D6:D10",
values: data2,
},
{
range: "B34:B39",
values: factorsLabels1_6,
},
{
range: "E34:E39",
values: factors1_6,
},
{
range: "B40:B45",
values: factorsLabels7_12,
},
{
range: "E40:E45",
values: factors7_12,
}
];
const resource = {
data,
valueInputOption: 'RAW',
};
sheets.spreadsheets.values.batchUpdate({
spreadsheetId: ecxelID,
resource: resource,
}, (err, result) => {
if (err) {
// Handle error
console.log(err);
return false
} else {
console.log(`${result.updatedCells} cells data inserted`);
return spreadsheetId;
}
});
}
I could confirm your situation. In this case, how about the following modification?
From:
"offsetXPixels": 0,
"offsetYPixels": -7,
"widthPixels": 800,
"heightPixels": 450
To:
"offsetXPixels": 0,
"offsetYPixels": 0, // Modified
"widthPixels": 800,
"heightPixels": 450
or
"widthPixels": 800,
"heightPixels": 450
When the values of offsetXPixels and offsetYPixels are the negative values, it was found that such an issue occurs.
When the values of offsetXPixels and offsetYPixels are 0, these values are not required to be included because of the default value.
Note:
When I tested the above modification, I could confirm that your issue could be removed.
Reference:
EmbeddedObjectPosition

Tabulator custom date filter

On table creation, I am trying to HIDE a row of the table if a date is in the past. Appreciate the help big time! Unfortunately I can't figure out how to do this, and really could use the help. There is also a filter that I apply based on user drop down. I am using tabulator package as well as moment for date library
<script type="text/javascript" src="https://unpkg.com/tabulator-tables#4.9.3/dist/js/tabulator.min.js"></script>
<link href="https://unpkg.com/tabulator-tables#4.9.3/dist/css/materialize/tabulator_materialize.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js" integrity="sha512-qTXRIMyZIFb8iQcfjXWCO8+M5Tbc38Qi5WzdPOYZHIlZpzBHG3L3by84BBBOiRGiEb7KKtAOAs5qYdUiZiQNNQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<select id="filter-value">
<option value="">Select A Course</option>
<option value="">All</option>
<option value="Bronze">Bronze</option>
<option value="FirstAid">First Aid</option>
</select>
<script language="JavaScript">
//Define variables for input elements
var valueEl = document.getElementById("filter-value");
//Trigger setFilter function with correct parameters
function updateFilter() {
valueEl.disabled = false;
table.setFilter("course", "starts", valueEl.value);
// table.setFilter(filter, typeVal, valueEl.value);
// table.setFilter(filter, "like", valueEl.value);
}
//Update filters on value change
//document.getElementById("filter-field").addEventListener("change", updateFilter);
//document.getElementById("filter-type").addEventListener("change", updateFilter);
document.getElementById("filter-value").addEventListener("change", updateFilter);
//define some sample data
var tabledata = [
{ sortorder: "A100001", course: "Bronze Medallion with Emergency First Aid & CPR B Crash Course", price: "12", startdate: "Jan 21 2023" },
{ sortorder: "B300001", course: "Bronze Cross", price: "13", startdate: "May 12 1982", info: "Apr 4-May 2nd,<br /> 10am-4pm", pre: "" },
{ sortorder: "B300001", course: "Bronze Cross", price: "12", startdate: "Apr 12 1983", info: "", pre: "" },
{ sortorder: "C400001", course: "Christine Lobowski", price: "42", startdate: "May 22 1982", info: "", pre: "" },
{ sortorder: "A200001", course: "Bronze Medallion Recertification", price: "125", startdate: "Jan 8 1980", info: "", pre: "" },
{ sortorder: "D500001", course: "Margret Marmajuke", price: "16", startdate: "Jan 31 1999", info: "", pre: "" },
];
//create Tabulator on DOM element with id "example-table" RENDER THE TABLE
var table = new Tabulator("#example-table", {
height: 605, // set height of table (in CSS or here), this enables the Virtual DOM and improves render speed dramatically (can be any valid css height value)
data: tabledata, //assign data to table
layout: "fitDataFill",
groupBy: "course",
resizableColumns: false,
responsiveLayout: "collapse",
responsiveLayoutCollapseStartOpen: false,
columns: [ //Define Table Columns
{ formatter: "responsiveCollapse", width: 30, minWidth: 30, hozAlign: "center", resizable: false, headerSort: false },
{ title: "Sort Order", field: "sortorder" },
{ title: "Course", field: "course", width: 350, responsive: 0, headerSort: false },
{ title: "Price", field: "price", hozAlign: "left", headerSort: false },
{ title: "Start Date", field: "startdate", hozAlign: "center", headerSort: false, sorter: "date", cssClass:"date" },
{ title: "Course Information", field: "info", formatter: "html", headerSort: false },
{ title: "Pre-requisites", field: "pre", headerSort: false },
],
initialSort: [
{ column: "startdate", dir: "asc" }, //sort by this first asc desc
{ column: "sortorder", dir: "asc" }, //sort by this second you will see this on screen
],
initialFilter: [
{ field: "startdate", type: ">", value: "" }
],
});
You're comparing strings. I think any string will be '> ""' (or the opposite, no string will be '> ""' - either way, you're not going to get what you want)
Convert those dates to moment()'s (prolly with a mutator at data insertion might be best) and then use a datetime formatter to display them how you want and you will be able to compare/filter/sort them as numbers properly

Google Charts - Exploded pie chart issue while having only 1 input to show

I am using google charts to make exploded pie chart
below is the options that i used for the chart
learnersEngagementCtrl.myChartObject.options = {
legend: 'none',
colors: ['rgb(100, 190, 35)', 'rgb(227, 71, 35)'],
slices: {
1: { offset: 0.1 }
}
};
and this is my data table code
learnersEngagementCtrl.myChartObject.data = {
"cols": [
{ id: "t", label: "Topping", type: "string" },
{ id: "s", label: "Slices", type: "number" }
], "rows": [
{
c: [
{ v: "Engaged users" },
{ v: learnersEngagementCtrl.NumberOfEngagedUsers }
]
},
{
c: [
{ v: "Not Engaged users" },
{ v: learnersEngagementCtrl.NumberOfUnEngagement}
]
}
]
};
this is the output when i am having two inputs which have no issues
but when i have on input .. i face below issue
can you please advice me what to do to solve this issue ?
you could only add the offset option, if both values exist.
initialize the other options...
learnersEngagementCtrl.myChartObject.options = {
legend: 'none',
colors: ['rgb(100, 190, 35)', 'rgb(227, 71, 35)']
};
then add the offset if you have both values...
if ((learnersEngagementCtrl.NumberOfEngagedUsers) && (learnersEngagementCtrl.NumberOfUnEngagement)) {
learnersEngagementCtrl.myChartObject.options.slices = {
1: { offset: 0.1 }
};
} else {
learnersEngagementCtrl.myChartObject.options.slices = null;
}

How can I display my high-chart correctly and import data?

On my highchart how can I set the Y AXIS (dataItem) so that it will populate accordingly to amount of times a country appears in my json data. So in my snippet it should show GB as 66% instead of two 33%?
Also what would be a good way to import my json data if I was to keep in in a separate file. Was thinking of keeping it in a separate file called (json_data.json).
Please help.
$(document).ready(function () {
var json=
[
{
"Hot": false,
"Country": "NETHERLANDS",
"DomCountry": "NA",
"DomPortCode": "*PI",
"Code": "RTM",
"Origin": "NL",
"CodeDest": "NA",
},
{
"Hot": true,
"Country": "GREAT BRITAIN",
"DomCountry": "POLAND",
"DomPortCode": "*PI",
"Code": "CAL",
"Origin": "GB",
"CodeDest": "PL",
},
{
"Hot": true,
"Country": "GREAT BRITAIN",
"DomCountry": "POLAND",
"DomPortCode": "*PI",
"Code": "CAL",
"Origin": "GB",
"CodeDest": "PL",
}
];
var listData=json;
console.log(listData);
var dataList = []
var dataItem;
for (var i = 0; i < listData.length; i++) {
dataItem={
name: listData[i].Country,
y: 1
}
dataList.push(dataItem); //dataItem push
}
// Build the chart
$('#container').highcharts({
chart: {
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false,
type: 'pie'
},
title: {
text: 'SHIPPING INFO'
},
tooltip: {
pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>'
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: false
},
showInLegend: true
}
},
series: [{
name: "Try",
colorByPoint: true,
data: dataList
}]
});
});
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<title>Highcharts Examples</title>
</head>
<div id="container" style="min-width: 310px; height: 400px; max-width: 600px; margin: 0 auto"></div>
You need to loop through your data and count the occurrences.
Then you need to calculate the percentages, and format the data in a way that Highcharts can use.
You can loop through it and build your first set up something like this:
var countryCounts = {};
var countryNames = [];
var totalCount = 0;
//loop through the object
$.each(json, function(i, node) {
//get the country name
var countryName = node["Country"];
//build array of unique country names
if($.inArray(countryName, countryNames) == -1) {
countryNames.push(countryName);
}
//add or increment a count for the country name
if(typeof countryCounts[countryName] == 'undefined') {
countryCounts[countryName] = 1;
}
else {
countryCounts[countryName]++;
}
//increment the total count so we can calculate %
totalCount++;
});
That gives you what you need to calculate from.
Then you can loop through your country names and build a data array:
var data = [];
//loop through unique countries to build data for chart
$.each(countryNames, function(i, countryName) {
data.push({
name: countryName,
y: Math.round((countryCounts[countryName] / totalCount) * 100)
});
});
This keeps it dynamic so that you can have any number of countries.
Then you just add your data array to your chart:
http://jsfiddle.net/jlbriggs/e2qq2j2L/