I have some JSON data I wish to generate into a nice looking HTML table for seeing stats about someone's performance on a test. In my JSON data I've grouped every student by name, and put their scores in JSON array.
With a simpler JSON like { "Name" : "Alfreds Futterkiste", "City" : "Berlin", "Country" : "Germany" } it would be a lot easier as I could generate a <td> for each JSON object.
So to be clear: I need a way to put the objects in the nested arrays in each their <tr>.
My PHP-generated JSON looks like this:
[
{
"school":"St. Paul"
},
{
"class":"4a"
},
{
"student":"Andreas",
"taskid":[
2,
1
],
"level":[
3,
4
],
"hint":[
1,
0
],
"correctanswer":[
1,
1
],
"timeused":[
30,
20
]
}
]
Are there any simple ways to make a table like this? I am open for any libraries that are relatively simple to set up.
Student x
____________________________________________
|#taskid|level|hint|correctanswer|time used|
|‾‾‾‾‾‾‾|‾‾‾‾‾|‾‾‾‾|‾‾‾‾‾‾‾‾‾‾‾‾‾|‾‾‾‾‾‾‾‾‾|
|‾‾‾‾‾‾‾|‾‾‾‾‾|‾‾‾‾|‾‾‾‾‾‾‾‾‾‾‾‾‾|‾‾‾‾‾‾‾‾‾|
‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
I have an answer for you, below is test run for it, took my 4 hours, used only JavsScript no third party library like jquery etc.
You can further improvise it.
Enjoy.
var jsonData = [{
"school": "St. Paul"
}, {
"class": "4a"
}, {
"student": "Natalie",
"taskid": [
3,
4
],
"level": [
1,
2
],
"hint": [
1,
6
],
"correctanswer": [
1,
4
],
"timeused": [
30,
10
]
}, {
"school": "St. Paul"
}, {
"class": "4a"
}, {
"student": "Andreas",
"taskid": [
2,
1
],
"level": [
3,
4
],
"hint": [
1,
0
],
"correctanswer": [
1,
1
],
"timeused": [
30,
20
]
}]
for (var i = 0; i < jsonData.length; i++) {
var nodeTable = document.createElement("table");
var nodeTbody = document.createElement("tbody");
for (var x = 0; x < Object.keys(jsonData[i]).length; x++) {
var headerText = document.createTextNode(Object.keys(jsonData[i])[x]);
var nodeTH = document.createElement("th");
nodeTH.appendChild(headerText);
document.getElementById("schoolRecord").appendChild(nodeTable).appendChild(nodeTbody).appendChild(nodeTH);
}
var maxLength = [];
for (var x = 0; x < Object.keys(jsonData[i]).length; x++) {
for (var z = 0; z < jsonData[i][Object.keys(jsonData[i])[x]].length; z++) {
if (typeof(jsonData[i][Object.keys(jsonData[i])[x]]) !== 'string') {
maxLength.push(jsonData[i][Object.keys(jsonData[i])[x]].length);
}
}
}
if (maxLength.length > 0) {
maxLength = Math.max.apply(Math, maxLength);
}
if (maxLength.length === undefined) {
for (var z = 0; z < maxLength; z++) {
var nodeTR = document.createElement("tr");
nodeTbody.appendChild(nodeTR);
createTD(z);
}
} else {
var nodeTR = document.createElement("tr");
nodeTbody.appendChild(nodeTR);
createTD();
}
function createTD(nodeValue) {
for (var x = 0; x < Object.keys(jsonData[i]).length; x++) {
if (typeof(jsonData[i][Object.keys(jsonData[i])[x]]) === 'string') {
var tdText = document.createTextNode(jsonData[i][Object.keys(jsonData[i])[x]]);
var nodeTD = document.createElement("td");
nodeTD.appendChild(tdText);
nodeTR.appendChild(nodeTD);
} else {
var tdText = document.createTextNode(jsonData[i][Object.keys(jsonData[i])[x]][nodeValue]);
var nodeTD = document.createElement("td");
nodeTD.appendChild(tdText);
nodeTR.appendChild(nodeTD);
}
}
}
}
table th,
table td {
border: 1px solid black;
border-collapse: collapse;
}
<div id="schoolRecord">
</div>
Related
I am reading learnjsdata.com and came across this unfamiliar JavaScript syntax. The syntax is as follows:
lookupIndex[row[lookupKey]] = row;
Anyone know what's happening here? I haven't seen syntax like this. Used in context:
Data
var articles = [{
"id": 1,
"name": "vacuum cleaner",
"weight": 9.9,
"price": 89.9,
"brand_id": 2
}, {
"id": 2,
"name": "washing machine",
"weight": 540,
"price": 230,
"brand_id": 1
}, {
"id": 3,
"name": "hair dryer",
"weight": 1.2,
"price": 24.99,
"brand_id": 2
}, {
"id": 4,
"name": "super fast laptop",
"weight": 400,
"price": 899.9,
"brand_id": 3
}];
var brands = [{
"id": 1,
"name": "SuperKitchen"
}, {
"id": 2,
"name": "HomeSweetHome"
}];
Function & Invocation
function join(lookupTable, mainTable, lookupKey, mainKey, select) {
var l = lookupTable.length,
m = mainTable.length,
lookupIndex = [],
output = [];
for (var i = 0; i < l; i++) { // loop through l items
var row = lookupTable[i];
lookupIndex[row[lookupKey]] = row; // create an index for lookup table
}
for (var j = 0; j < m; j++) { // loop through m items
var y = mainTable[j];
var x = lookupIndex[y[mainKey]]; // get corresponding row from lookupTable
output.push(select(y, x)); // select only the columns you need
}
return output;
};
var result = join(brands, articles, "id", "brand_id", function(article, brand) {
return {
id: article.id,
name: article.name,
weight: article.weight,
price: article.price,
brand: (brand !== undefined) ? brand.name : null
};
});
console.log(result);
Appreciate any answers or pointers, thanks!
Think of it as two separate function calls:
var rowLookup = row[lookupKey];
lookupIndex[rowLookup] = row;
It's the same as doing it all in the same line:
lookupIndex[row[lookupKey]] = row;
I'm failing to access the number inside the DATA array, which would be the ID mentioned in the COLUMNS.
My JSON is as follows:
{
"COLUMNS": [
"ID",
"DESCRIPTION",
"DATE"
],
"DATA": [
[
53,
"Try to do something test123",
"September, 05 2017 00:00:00 +0100"
]
]
}
My current attempt was this, but with this, I get the whole 3 elements
var jsonLength= JSON.DATA.length;
for (dataIndex = 0; dataIndex < jsonLength; dataIndex++) {
var dataLength= JSON.DATA[dataIndex].length;
for (noteIndex = 0; noteIndex < dataLength; noteIndex++) {
alert(JSON.DATA[dataIndex]);
}
}
Your code is almost correct, you're just missing the second index accessor on your 2D DATA array. You can use the noteIndex incrementing variable from your loop:
var JSON = {
"COLUMNS": [ "ID", "DESCRIPTION", "DATE" ],
"DATA": [
[ 53, "Try to do something test123", "September, 05 2017 00:00:00 +0100" ]
]
}
var jsonLength = JSON.DATA.length;
for (dataIndex = 0; dataIndex < jsonLength; dataIndex++) {
var dataLength = JSON.DATA[dataIndex].length;
for (noteIndex = 0; noteIndex < dataLength; noteIndex++) {
console.log(JSON.DATA[dataIndex][noteIndex]); // note the additional [] here
}
}
var jsonLength= JSON.DATA.length;
for (var i = 0; i < jsonLength; i++) {
var note = JSON.DATA[i]
var id = note[0] // access id value
}
Also, if you are the owner of server, why not return more suitable and preferred json structure like this? :
[
{"id": 1, "description": "..."},
{"id": 1, "description": "..."}
]
I've stuck for this for 2 days, tried so many ways still couldn't get it right. I can't change the API data so I have to deal with front end handling. I really need some help.
$scope.stationary = [{
"name": "Pen",
"data": [{
"date": "1-10-2017",
"inventory": 25
}, {
"date": "2-10-2017",
"inventory": 21
}]
}, {
"name": "Color Pencil",
"data": [{
"date": "1-10-2017",
"inventory": 3
}, {
"date": "2-10-2017",
"inventory": 0
}]
}, {
"name": "Color Pencil Special",
"data": [{
"date": "1-10-2017",
"inventory": 2
}, {
"date": "2-10-2017",
"inventory": 1 // make this view to '-' since inventory of color pencil is zero
}]
}]
http://jsfiddle.net/op2zd2vr/
The case is if color pencil's inventory is zero, should display '-' on color pencil special column.
Try this:
Updated Answer:
myApp.filter('customFilter', function() {
return function(items) {
for (var i = 0; i < items.length; i++) {
for (var k = 0; k < items[i].data.length; k++) {
if (i != 0 && items[i - 1].data[k].inventory == 0) {
items[i].data[k]['isZero'] = true;
} else {
items[i].data[k]['isZero'] = false;
}
}
}
return items;
};
});
See Updated jsfiddle link.
It's working for me.
Guess you have to manipulate the datas itselves, you cannot simply use a filter for this particular case.
Here's my fiddle: http://jsfiddle.net/op2zd2vr/2/
Solution used (depending ont the datas' names):
var positions = [];
$scope.stationary.forEach(function (s) {
if(s.name === 'Color Pencil'){
for(var i = 0; i < s.data.length; i++){
if(s.data[i].inventory === 0){
positions.push(i);
}
}
}
if(s.name === 'Color Pencil Special'){
for(var i = 0; i < s.data.length; i++){
if(positions.indexOf(i) >= 0){
s.data[i].inventory = '-';
}
}
}
});
I have two arrays containing key/value pairs.
{
"containerOne": [{
"Id": 1,
"Title": "TitleOne",
"Responsibility": "ValueOne"
}, {
"Id": 2,
"Title": "TitleTwo",
"Responsibility": "ValueTwo"
}]
}
{
"containerTwo": [{
"Id": 1,
"Title": "TitleOne",
"Responsibility": null
}, {
"Id": 2,
"Title": "TitleTwo",
"Responsibility": "null
}
]
}
I'd like to compare both arrays and compare the title of each container. If the titles match, then I'd like to copy the Responsibility value from containerOne to containerTwo. The ID's will not match, so that can be ruled out. Only the titles will be consistent.
What is the most efficient way to do this please?]
Thanks
=====================================================================
EDIT
=====================================================================
Looking at the arrays a little closer, there is a subtle difference in the data being returned:
{
"AMLookupTasksList":
[
{
"Id":1,
"Title":"Create and Maintain an Onboarding Document",
"Responsibility":"1. Onboarding|f101ccf1-c7d5-42e7-ba8f-48e88ac90a3d"
},
{
"Id":2,
"Title":"Execute Onboarding for New Consultants",
"Responsibility":"1. Onboarding|f101ccf1-c7d5-42e7-ba8f-48e88ac90a3d"
}
]
}
{
"AMTasksList":
[
{
"Id":4,
"Title":
{
"$M_1":13,"$c_1":"Create and Maintain an Onboarding Document"
},
"Responsibility":null
},
{
"Id":17,
"Title":
{
"$M_1":12,"$c_1":"Execute Onboarding for New Consultants"
},
"Responsibility":null
}
]
}
Do I have additional looping to get to the Title value in the second array?
This might be a bit of overkill but it ignores the sequence and does a look up in each object.
I had to fix some syntax in your objects but I include that: named the objects and took a quote off one of the null values.
var obj1 = {
"containerOne": [{
"Id": 1,
"Title": "TitleOne",
"Responsibility": "ValueOne"
}, {
"Id": 2,
"Title": "TitleTwo",
"Responsibility": "ValueTwo"
}]
};
var obj2 = {
"containerTwo": [{
"Id": 1,
"Title": "TitleOne",
"Responsibility": null
}, {
"Id": 2,
"Title": "TitleTwo",
"Responsibility": null
}]
};
Now the code:
// lookup for first object:
var lookup = {};
// create referece to list above and use it everywhere
lookup.list = obj1;
for (var i = 0, len = lookup.list.containerOne.length; i < len; i++) {
lookup[lookup.list.containerOne[i].Title] = lookup.list.containerOne[i];
}
// lookup for second object
var otherLookup = {};
otherLookup.list = obj2;
for (var i = 0, len = otherLookup.list.containerTwo.length; i < len; i++) {
otherLookup[otherLookup.list.containerTwo[i].Title] = otherLookup.list.containerTwo[i];
}
// copy value for Responsibility from first to second on each matched in second.
var i = 0;
var len = lookup.list.containerOne.length;
for (i; i < len; i++) {
// looks up value from second list in the first one and if found, copies
if (lookup[otherLookup.list.containerTwo[i].Title]) {
otherLookup.list.containerTwo[i].Responsibility = lookup[otherLookup.list.containerTwo[i].Title].Responsibility;
}
}
// alerts new value using lookup
alert(otherLookup["TitleOne"].Responsibility);
EDIT for new structure, but same answer really:
var obj1 = {
"AMLookupTasksList": [{
"Id": 1,
"Title": "Create and Maintain an Onboarding Document",
"Responsibility": "1. Onboarding|f101ccf1-c7d5-42e7-ba8f-48e88ac90a3d"
}, {
"Id": 2,
"Title": "Execute Onboarding for New Consultants",
"Responsibility": "1. Onboarding|f101ccf1-c7d5-42e7-ba8f-48e88ac90a3d"
}]
};
var obj2 = {
"AMTasksList": [{
"Id": 4,
"Title": {
"$M_1": 13,
"$c_1": "Create and Maintain an Onboarding Document"
},
"Responsibility": null
}, {
"Id": 17,
"Title": {
"$M_1": 12,
"$c_1": "Execute Onboarding for New Consultants"
},
"Responsibility": null
}]
};
var lookup = {};
// create refernece to list above and use it everywhere
lookup.list = obj1;
for (var i = 0, len = lookup.list.AMLookupTasksList.length; i < len; i++) {
lookup[lookup.list.AMLookupTasksList[i].Title] = lookup.list.AMLookupTasksList[i];
}
var otherLookup = {};
otherLookup.list = obj2;
for (var i = 0, len = otherLookup.list.AMTasksList.length; i < len; i++) {
otherLookup[otherLookup.list.AMTasksList[i].Title.$c_1] = otherLookup.list.AMTasksList[i];
}
// copy value for Responsibility from first to second
var i = 0;
var len = otherLookup.list.AMTasksList.length;
for (i; i < len; i++) {
if (lookup[otherLookup.list.AMTasksList[i].Title.$c_1]) {
otherLookup.list.AMTasksList[i].Responsibility = lookup[otherLookup.list.AMTasksList[i].Title.$c_1].Responsibility;
}
}
alert(otherLookup["Create and Maintain an Onboarding Document"].Responsibility);
Fiddle for second answer: http://jsfiddle.net/n22V8/
First, create a dictionary from containerTwo:
var c2dict = {};
var c2i = containerTwo.innerContainer;
for (var i = 0; i < c2i.length; i++) {
c2dict[c2i[i].Title] = c2i[i];
}
Now use this to do the copying of propertyies when titles match:
var c1i = containerOne.innerContainer;
for (var i = 0; i < c1i.length; i++) {
if (c2dict[c1i[i].Title]) {
c2dict[c1i[i].Title].Property = c1i[i].Property;
}
}
You should compare properties and set them as the following:
containerOne.innerContainer.forEach(function (element,index) {
containerTwo.innerContainer.forEach(function (element2,index2) {
if (element.Title === element2.Title && element.Property != element2.Property) {
element2.Property = element.Property;
}
});
});
I have JSON string from my php script like this:
var r.co = {
"A20018425":[
{"balance":"1390.31"}, // 1
{"balance":"1304.11"}, // 2
{"balance":"1188.11"}, // 3
{"balance":"1421.71"} // 4
],
"A25005922":[
{"balance":"1000"}, // 1
{"balance":"1000.86"}, // 2
{"balance":"986.32"}, // 3
{"balance":"988.96"}, // 4
{"balance":"980.26"}, // 5
{"balance":"980.16"} // 6 MAX
],
"A25005923":[
{"balance":"1001"}, // 1
{"balance":"1000.16"}, // 2
]
}
I don't know how many AXXXXXXXX elements and how many elements it contains.
To get A elements I have use the code below:
var accounts = [];
for(var key in r.co) {
if(r.co.hasOwnProperty(key)) {
accounts.push(key);
}
}
Now I know my A elements length
var accounts_length = accounts.length; // 3 for example
Now I need to know max length of elements in A:
var accounts_elements_length = [];
for (var c = 0; c < accounts.length; c++) {
accounts_elements_length.push(r.co[accounts[c]].length);
}
var accounts_elements_length_max = accounts_elements_length.max() // 6 For example
How can I get this output array for the chart?
var outputData = [{
count: 1,
A20018425: 1390.31,
A25005922: 1000,
A25005923: 1001
}, {
count: 2,
A20018425: 1304.11,
A25005922: 1000.86,
A25005923: 1000.16
}, {
count: 3,
A20018425: 1188.11,
A25005922: 986.32
}, {
count: 4,
A20018425: 1421.71,
A25005922: 988.96
}, {
count: 5,
A25005922: 980.26
}, {
count: 6,
A25005922: 980.16
}
}];
Thanks!
Just combined your algorythms:
var outputData = [];
for (var key in r.co) {
if (r.co.hasOwnProperty(key)) {
var account_length = r.co[key].length;
for (var c = 0; c < account_length; c++) {
if (outputData[c] === undefined) {
outputData[c] = { count: c+1 };
}
outputData[c][key] = r.co[key][c].balance;
}
}
}
console.log(outputData);
jsfiddle
Code :
var outputData = [];
for (var i = 0; i < 6; i++) { // filter should be - i < accounts_elements_length_max
var temp = {
'count': i + 1
};
for (var j = 0; j < accounts.length; j++) {
if (r[accounts[j]][i]) temp[accounts[j]] = r[accounts[j]][i].balance;
}
outputData.push(temp);
}
Note that i hard code the accounts_elements_length_max(6).
Output that i get:
[{
"count": 1,
"A20018425": "1390.31",
"A25005922": "1000",
"A25005923": "1001"},
{
"count": 2,
"A20018425": "1304.11",
"A25005922": "1000.86",
"A25005923": "1000.16"},
{
"count": 3,
"A20018425": "1188.11",
"A25005922": "986.32"},
{
"count": 4,
"A20018425": "1421.71",
"A25005922": "988.96"},
{
"count": 5,
"A25005922": "980.26"},
{
"count": 6,
"A25005922": "980.16"}]
Working fiddle