I'm trying to work out how to plot labels to the correct places using Chart.js
var json = {
"competition one": [
{
"date": "2015-05-20",
"position": 37
},
{
"date": "2015-05-21",
"position": 22
}
],
"competition two": [
{
"date": "2015-05-20",
"position": 29
},
{
"date": "2015-05-21",
"position": 19
}
]
}
How can I plot the labels to the correct places? With the dates going to the correct labels so it isn't repeated?
Specifically, I'm struggling to get "competition one" into the label of the dataset array (label: "competition one")
I need it to resemble the following data structure that is required by Chart.js?
var data = {
labels: ["2015-05-20", "2015-05-21"],
datasets: [
{
label: "competition one",
data: [37, 22]
},
{
label: "Competition two",
data: [29, 19]
}
]
};
As mentioned in comments you can get the properties names like thus:
var json = {
"competition one": [
{
"date": "2015-05-20",
"position": 37
},
{
"date": "2015-05-21",
"position": 22
}
],
"competition two": [
{
"date": "2015-05-20",
"position": 29
},
{
"date": "2015-05-21",
"position": 19
}
]
}
var keys = Object.keys(json);
for (var i = 0; i < keys.length; i++)
{
var key = keys[i];
//"competition one", "competition two", etc
console.log(key);
}
Fiddle
you then just need to manipulate these values into your desired object structure.
var keys = Object.keys(json);
//set up our object containing an array called datasets
var data = {datasets:[]};
for (var i = 0; i < keys.length; i++)
{
var key = keys[i];
//push the key into the dataset array as an object {}
data.datasets.push({label:key, data:...});
}
Related
I have a json object,which contains following data.
var myData = [{
"sNo": "1.0",
"boqName": "Installation of pole 11 KV",
"unit": "Nos",
"opportunityBoqOverHeadMasterList": [{
"opportunityBoqOverHeadMasterId": 14,
"value": 41.3
},
{
"opportunityBoqOverHeadMasterId": 16,
"value": 41.3
},
{
"opportunityBoqOverHeadMasterId": 24,
"value": 100
}
]
},
{
"sNo": "2.0",
"boqName": "Installation of pole 33 KV",
"unit": "Nos",
"opportunityBoqOverHeadMasterList": [{
"opportunityBoqOverHeadMasterId": 15,
"value": 52.92
},
{
"opportunityBoqOverHeadMasterId": 17,
"value": 52.92
},
{
"opportunityBoqOverHeadMasterId": 25,
"value": 0
}
]
},
];
}
i need to display the value of opportunityBoqOverHeadMasterList next to the unit cell.
Please help me to display data in handsontable. Please refer jsfiddle for working example https://jsfiddle.net/Umanath16/aty5wfg7/22/
You could try processing the data. Notice below that I changed your columns array, create a new myNewData variable and create nested loops to format the data.
var columns = [
{
"data": "sNo"
},
{
"data": "boqName"
},
{
"data": "unit"
},
,
{
"data": "Percentage1"
},
{
"data": "Percentage2"
},
{
"data": "Percentage3"
}
];
Change the data obj...
var myNewData = [];
for (var i = 0; i < myData.length; i++) {
myNewData.push({
sNo: myData[i].sNo,
boqName: myData[i].boqName,
unit: myData[i].unit
});
for (var j = 0; j < myData[i].opportunityBoqOverHeadMasterList.length; j++) {
myNewData[i]["Percentage"+(j+1)] = myData[i].opportunityBoqOverHeadMasterList[j].value;
}
}
hot = new Handsontable(example, {
data: myNewData,
rowHeaders: true,
columns: columns,
rowHeaderWidth: 100,
colWidths: 120,
colHeaders: colHeaders
});
}
This is just one possible solution. Please think about possible improvements. What if the data does not have the same fields? It would need to be dynamic regardless of the field names. Also how would you improve the loops, etc.
I have an API response in form of JSON.
"reports": [
{
"columnHeader": {
"dimensions": [
"ga:date"
],
"metricHeader": {
"metricHeaderEntries": [
{
"name": "ga:sessions",
"type": "INTEGER"
},
{
"name": "ga:users",
"type": "INTEGER"
}
]
}
},
"data": {
"rows": [
{
"dimensions": [
"20210623"
],
"metrics": [
{
"values": [
"13",
"13"
]
}
]
},
{
"dimensions": [
"20210624"
],
"metrics": [
{
"values": [
"18",
"16"
]
}
]
}
]}}]}
I need to get each metric (metricHeaderEntries) with its values in a separate Object, which is therefore is in an array "dataTracesAll".
//Example of the construction
//dataTracesAll is an array, containing objects with key "trace" + int
dataTracesAll['trace' + (i+1)] = {
name: metricsTitles[i].name, //metric title "sessions"
x: dimensions, //list of dimensions ["20210623", "20210624"]
y: dataClear //list of metrics for each metrics is separate ["13", "18"]
}
//The full code:
var titles = [];
var dataTracesAll = [];
//raw data
for (var i=0; i < data.reports.length; i++) {
//get titles
var metricsTitles = data.reports[i].columnHeader.metricHeader.metricHeaderEntries;
metricsTitles.forEach(function(title) {
titles.push(title.name.split("ga:")[1]);
});
//values and dates raw
var dimensions = [];
var dataClear = [];
var values = data.reports[i].data.rows;
//get dates and values
values.forEach(function(val) {
dimensions.push(val.dimensions[0]);
dataClear.push(val.metrics[0].values[0]); //only the first array value is added
});
//clear values
console.log(values);
//constuct array with values
dataTracesAll['trace' + (i+1)] = {
name: metricsTitles[i].name,
x: dimensions,
y: dataClear
}
}
Result of the code:
The problem is that it adds only the first value of the metrics value array and I cannot get how to parse everything, so there is actually 2 traces.
My ideal result is:
dataTracesAll = [
trace1: {
name: "ga:sessions",
x: ['20210623', '20210624']
y: ['13', '18']
},
trace2: {
name: "ga:users",
x: ['20210623', '20210624']
y: ['13', '16']
}
];
Try this:
var data = {"reports": [
{
"columnHeader": {
"dimensions": [
"ga:date"
],
"metricHeader": {
"metricHeaderEntries": [
{
"name": "ga:sessions",
"type": "INTEGER"
},
{
"name": "ga:users",
"type": "INTEGER"
}
]
}
},
"data": {
"rows": [
{
"dimensions": [
"20210623"
],
"metrics": [
{
"values": [
"13",
"13"
]
}
]
},
{
"dimensions": [
"20210624"
],
"metrics": [
{
"values": [
"18",
"16"
]
}
]
}
]}}]};
var titles = [];
var dataTracesAll = [];
var length = data.reports[0].data.rows[0].metrics[0].values.length;
//raw data
for (var i=0; i < length; i++) {
//get titles
var metricsTitles = data.reports[0].columnHeader.metricHeader.metricHeaderEntries;
metricsTitles.forEach(function(title) {
titles.push(title.name.split("ga:")[1]);
});
//values and dates raw
var dimensions = [];
var dataClear = [];
var values = data.reports[0].data.rows;
//get dates and values
values.forEach(function(val) {
dimensions.push(val.dimensions[0]);
dataClear.push(val.metrics[0].values[i]);
});
//constuct array with values
dataTracesAll.push({});
dataTracesAll[i]['trace' + (i+1)] = {
name: metricsTitles[i].name,
x: dimensions,
y: dataClear
}
}
console.log(dataTracesAll);
Edit: The result was supposed to be an array, so I changed the code accordingly.
I have updated you logic to make it fit for your requirement. Hope this will work.
const data =
{
"reports": [
{
"columnHeader": {
"dimensions": [
"ga:date"
],
"metricHeader": {
"metricHeaderEntries": [
{
"name": "ga:sessions",
"type": "INTEGER"
},
{
"name": "ga:users",
"type": "INTEGER"
}
]
}
},
"data": {
"rows": [
{
"dimensions": [
"20210623"
],
"metrics": [
{
"values": [
"13",
"13"
]
}
]
},
{
"dimensions": [
"20210624"
],
"metrics": [
{
"values": [
"18",
"16"
]
}
]
}
]
}
}]
}
const dataTracesAll = {};
const report = data.reports[0];
for (var i = 0; i < report.data.rows.length; i++) {
dataTracesAll[`trace${i + 1}`] = {
name: report.columnHeader.metricHeader.metricHeaderEntries[i].name,
x: [],
y: [],
}
}
Object.keys(dataTracesAll).forEach((key, index) => {
for (var i = 0; i < report.data.rows.length; i++) {
dataTracesAll[key].x.push(report.data.rows[i].dimensions[0]);
dataTracesAll[key].y.push(report.data.rows[i].metrics[0].values[index]);
}
})
console.log(dataTracesAll);
I have an array of data that looks like this:
{
"data": [
{
"id": "20200722_3",
"eventDate": "2020-07-22T00:00:00",
"eventName": "Football",
"eventDetails": [
"Men's First Round (2 matches)"
],
"eventVenue": "Venue A"
},
{
"id": "20200722_1",
"eventDate": "2020-07-22T00:00:00",
"eventName": "Football",
"eventDetails": [
"Men's First Round (2 matches)"
],
"eventVenue": "Venue B"
}
]
}
Now I wanted to group the data by multiple properties. For example, by eventDate, eventName, eventDetails, and eventVenue. Which I've done with this code referenced from this post:
const groupBy = (array, attrs) => {
var output = [];
for (var i = 0; i < array.length; ++i) {
var ele = array[i];
var groups = output;
for (var j = 0; j < attrs.length; ++j) {
var attr = attrs[j];
var value = ele[attr];
var gs = groups.filter(g => {
return g.hasOwnProperty('label') && g['label'] === value;
});
if (gs.length === 0) {
var g = {};
if (isArray.g['label'] ) {
}
g['label'] = value;
g['groups'] = [];
groups.push(g);
groups = g['groups'];
} else {
groups = gs[0]['groups'];
}
}
groups.push(ele);
}
return output;
}
var result = groupBy(data, ['eventDate', 'eventName', 'eventDetails', 'eventVenue'])
Which results in an array like this:
[{
"label": "2020-07-23T00:00:00",
"groups": [{
"label": "Football",
"groups": [{
"label": [
"Men's First Round (2 matches)"
],
"groups": [{
"label": "Venue A",
"groups": [
"Object"
]
}]
},
{
"label": [
"Men's First Round (2 matches)"
],
"groups": [{
"label": "Venue B",
"groups": [
"Object"
]
}]
}
}]
}]
}]
You can see that for the output above, there are two separate "groups" that have the label "Men's First Round (2 matches)". I'm trying to figure out how I can combine these objects that have duplicate value ? I'm looking for something that would output like this:
[{
"label": "2020-07-23T00:00:00",
"groups": [{
"label": "Football",
"groups": [{
"label": [
"Men's First Round (2 matches)"
],
"groups": [{
"label": "Venue A",
"groups": [
"Object"
]
},
{
"label": "Venue B",
"groups": [
"Object"
]
}]
}]
}]
}]
Any help would be greatly appreciated.
I'll share the answer that I came up with for those that are curious.
For my needs, I know that if the array with the eventName only contained 1 attribute, it could be a duplicate. So in order to fix that, I converted the array that only had 1 value to a string:
if (ele[attr] && ele[attr].length === 1) {
var value = ele[attr].toString();
} else {
var value = ele[attr];
}
I have a json file and I want to convert the data into a table with Javascript. I found some similar questions How to convert the following table to JSON with javascript? , loop through a json object, but they all use jQuery and show the table on html web. I just need a simple loop to insert row into the table. I tried 'append', 'insert' and 'insertRow', all not work. Could anyone give me a hint?
Json file:
{
"name": "lily",
"country": "china",
"age": 23
},
{
"name": "mike",
"country": "japan",
"age": 22
},
{
"name": "lucy",
"country": "korea",
"age": 25
}
My code:
var jdata = {};
jdata.cols = [
{
"id": "1",
"label": "name",
"type": "string"
},
{
"id": "2",
"label": "country",
"type":"string"
}
];
for(var i = 1; i < 3; i++){
row = [
{
"c": [
{
"v": json["hits"]["hits"][i]["_source"]["name"]
},
{
"v": json["hits"]["hits"][i]["_source"]["country"]
}
]
}
];
jdata.rows.insertRow(row);
}
Edit: Add expected output: change the json file to the following structure.
[
['lily', 'china'],
['mike', 'japan'],
['lucy', 'korea'],
]
I guess you need push (Or concat / push(...elements) if you want to add array of rows)
jdata.rows = [];
for(var i = 1; i < 3; i++){
row = [
{
"c": [
{
"v": json["hits"]["hits"][i]["_source"]["name"]
},
{
"v": json["hits"]["hits"][i]["_source"]["country"]
}
]
}
];
jdata.rows.push(row);
// for elements from row
// jdata.rows.push(...row)
}
There are a few errors in your code
The JSON needs to be an array so you can loop through each object to display.
insertRow() is a method from the Table object, jdata.rows is not a Table object but an array.
Since, you have used insertRow(), I have rewritten your code to display the table data using the Table Object methods. Here is a code snippet
Edit: You can use the push() method to create your required JSON structure. I have edited the code snippet to create your required JSON.
var jdata = {
cols: [{
"id": "1",
"label": "name",
"type": "string"
},
{
"id": "2",
"label": "country",
"type": "string"
}
],
rows: []
};
var persons = [{
"name": "lily",
"country": "china",
"age": 23
},
{
"name": "mike",
"country": "japan",
"age": 22
}, {
"name": "lucy",
"country": "korea",
"age": 25
}
];
var table = document.getElementById("table");
var header = table.createTHead();
var footer = table.createTFoot();
var rowHeader = header.insertRow(0);
jdata.cols.forEach((col, index) => {
var cell = rowHeader.insertCell(index);
cell.innerHTML = col.label;
});
persons.forEach((person, index) => {
var rowFooter = footer.insertRow(index);
rowFooter.insertCell(0).innerHTML = person.name;
rowFooter.insertCell(1).innerHTML = person.country;
jdata.rows.push([person.name, person.country]);
});
console.log(jdata.rows);
<table id="table">
</table>
I am working on chart library,
I have json format, which will be coming from server, year and month format
{
"id": 1,
"name": "name1",
"present": "18",
"target": "18",
"status": "yellow"
}
Now I need to pass present and target values in a array format.
the data must be passed or parsed like below.
How to do I do this in javascript and jquery?
I tried all the available solutions, since I am new to the javascript world!
Expected result
var legendsText = [["present name1","target name1"]],
jsonFormat = [[18, 18],[15,18],[36, 18]];
FIDDLE
This is the fiddle our friend Eli Gassert has created, it is the closeset one
http://http://jsfiddle.net/Yq3DW/126/
but it is loading only present values of all 3 months
i want present and target values of each name.
For example
name1 link clicked, chart should load name1 present and target for all 3 months.
name2 link clicked, chart should load name2 present and target for all 3 months.
name3 link clicked, chart should load name3 present and target for all 3 months.
My JSON format which is coming dynamically from server
data={
"perspective": "something",
"year": "2014",
"measures": [
{
"id": 1,
"name": "some name",
"target": "200",
"responsiblePerson": null
},
{
"id": 2,
"name": "some name",
"target": "100",
"responsiblePerson": null
}
],
"values": {
"jan": [
{
"id": 1,
"name": "name1",
"present": "18",
"target": "18",
"status": "yellow"
},
{
"id": 2,
"name": "name2",
"present": "21",
"target": "22",
"status": "red"
},
{
"id": 3,
"name": "name3",
"present": "50",
"target": "50",
"status": "yellow"
}
],
"feb": [
{
"id": 1,
"name": "name1",
"present": "18",
"target": "18",
"status": "yellow"
},
{
"id": 2,
"name": "name2",
"present": "21",
"target": "22",
"status": "red"
},
{
"id": 3,
"name": "name3",
"present": "50",
"target": "50",
"status": "yellow"
}
],
"mar": [
{
"id": 1,
"name": "name1",
"present": "18",
"target": "18",
"status": "yellow"
},
{
"id": 2,
"name": "name2",
"present": "22",
"target": "22",
"status": "yellow"
},
{
"id": 3,
"name": "name3",
"present": "52",
"target": "50",
"status": "yellow"
}
]
}
}
HTML
<div id="chart"></div>
JS
var legendsText = [];
for(var i = 0; i != data.measures.length; ++i)
legendsText.push(data.measures[i].name);
legendsText = [legendsText];
var rows = [];
for(var i in data.values)
{
var row = []
for(var j = 0; j != data.values[i].length; ++j)
{
row.push(data.values[i][j].present);
}
rows.push(row);
}
rows = legendsText.concat(rows.sort(function (a, b) { }));
console.log(rows);
var chart = c3.generate({
bindto: '#chart',
data: {
rows: rows,
type: 'bar',
}
});
Any help is appreciated.
Here's an updated fiddle that transforms your data to the results: http://jsfiddle.net/Yq3DW/119/
Key aspects:
Your Legend Text can be gotten dynamically from your measures data. The format for the legendsText is an "array of arrays" so that's why I wrap it in [...] at the end of the loop.
var legendsText = [];
for(var i = 0; i != data.measures.length; ++i)
legendsText.push(data.measures[i].name);
legendsText = [legendsText];
Your rows can be gotten from your "values" data. But because it's not an array, like measures you need to use a for each loop instead of for loop:
var rows = [];
for(var i in data.values)
{
var row = []
for(var j = 0; j != data.values[i].length; ++j)
{
row.push(data.values[i][j].present);
}
rows.push(row);
}
EDIT: Updated question. To show just one label's worth of data but show both values for that data, and give nice labels: http://jsfiddle.net/Yq3DW/130/
The key here:
Switch to columns instead of rows, allowing one "row" of data to stand-in for the label indexer
Only add the data if the name in the value data matches the name you're searching for (had to update your data JSON so the names matched)
Had to use a 'tick' formatter to format the labels from 1-3 to jan, feb, mar. You can further customize it by using upper case/proper case conversions. That is outside the scope of this question and I'm not including it here. If you need further formatting, search for an answer first and if you can't find it, start a new Q.
Display a dynamic list of links to click that calls your loadData function to change the data in the chart between the various measure names
HTML:
<ul id="links"></ul>
<div id="chart"></div>
JS:
var $links = $('#links');
$links.html('');
for(var i = 0; i != data.measures.length; ++i)
{
(function()
{
var name = data.measures[i].name;
$('<li></li>')
.text(data.measures[i].name)
.click(function() { loadData(name); })
.appendTo($links);
})();
// legendsText.push(data.measures[i].name);
}
function loadData(name)
{
//var legendsText = [ ["present", "target"] ];
var columns = [ ["labels"], [ "present" ], [ "target" ]];
var labels = [];
for(var i in data.values)
{
var row = []
for(var j = 0; j != data.values[i].length; ++j)
{
if(data.values[i][j].name == name)
{
labels.push(i);
columns[0].push(labels.length);
columns[1].push(data.values[i][j].present);
columns[2].push(data.values[i][j].target);
}
}
//rows.push(row);
}
console.log(columns);
//rows = legendsText.concat(rows.sort(function (a, b) { }));
var chart = c3.generate({
bindto: '#chart',
data: {
x: 'labels',
columns: columns,
type: 'bar',
},
axis: {
x: {
tick: {
format: function(index) { return labels[index-1]; }
}
}
}
});
}