How to set div's order by condition in Jquery /js? - javascript

I want to stack divs one after another, by class, so if div has class of "icon1" then the following div will be "icon2". I want to to id within the each loop.. to prevent multiple Dom manipulations
var arr = [{
"id": 1,
"name": "foo"
}, {
"id": 1,
"name": "foo"
}, {
"id": 2,
"name": "foo"
}, {
"id": 1,
"name": "foo"
}];
var type = '';
var template ='';
$.each(arr, function() {
if (this['id'] == 1) {
type = 'icon1';
} else {
type = 'icon2';
}
template += '<div class="icon '+type+'">'+
'<p>ID: '+type+' Name: '+this['name']+'<p></div>';
});
$('#foo').html(template);
.icon1 {
color: red;
}
.icon2 {
color: pink;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo">
</div>
The result i'm looking for will be :
icon1
icon2
icon1
icon2
icon1
icon2
etc...

This is a solution:
var array = [
{
"id": 1,
"name": "foo"
},
{
"id": 1,
"name": "foo"
},
{
"id": 2,
"name": "foo"
},
{
"id": 1,
"name": "foo"
}
];
var lsts = [ [], [] ];
$.each( array, function() {
lsts[ this.id - 1 ].push( this );
} );
var lst1 = lsts[ 0 ],
lst2 = lsts[ 1 ];
for ( var i = 0, l = lst1.length, l2 = lst2.length; i < l || i < l2; i++ ) {
if ( i < l )
appendElement( lst1[ i ] );
if ( i < l2 )
appendElement( lst2[ i ] );
}
function appendElement( obj ) {
$( '#bar' ).append( '<div class="icon' + obj.id + '">' + obj.name + '</div>' );
}
.icon1 {
color: red;
}
.icon2 {
color: pink;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="bar"><div>
Beware of another ID numbers.

You can use css nth-child property to get this styles
div:nth-child(odd) {
color: red;
}
div:nth-child(even) {
color: pink;
}

Related

Getting items from an array with certain attributes and displaying them on one div

ex:
{
"data": [
{
"name": "grape",
"color": "purple"
},
{
"name": "apple",
"color": "green"
},
{
"name": "strawberry",
"color": "red"
}
]
}
I am looping through the array with this:
for (var i=0; i < data.length; i++) {
var item = "<button>"+data[i].name+"</button>";
$('#items').append(item)
}
Let's say I want to have it so when you click on the button, display a div of the color value, but use the same div for every item in the array. How would I do this?
Add an event handler to the buttons. It searches the data array for the object with the same name as the button text, and displays the color.
var data = [{
"name": "grape",
"color": "purple"
},
{
"name": "apple",
"color": "green"
},
{
"name": "strawberry",
"color": "red"
}
];
for (var i = 0; i < data.length; i++) {
var item = "<button data-color=" + data[i].color + ">" + data[i].name + "</button>";
$('#items').append(item)
}
$("button").click(function() {
var name = $(this).text();
var obj = data.find(el => el.name == name);
$("#outputdiv").text(obj.color);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="items"></div>
<div id="outputdiv"></div>
You can attach a click event handler to each button as you create them, such that when that button is clicked, the event handler will format the target <div> with the specified item.
Here's a quick demo:
const data = [{
"name": "grape",
"color": "purple"
},
{
"name": "apple",
"color": "green"
},
{
"name": "strawberry",
"color": "red"
}
];
const displayDatum = (datum) => (event) =>
$('#output').css({ background: datum.color }).text(datum.name);
for (var i = 0; i < data.length; i++) {
var item = $('<button>').text(data[i].name);
item.click(displayDatum(data[i]));
$('#items').append(item);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="items" />
<div id="output" />
var data = [
{
"name": "grape",
"color": "purple"
},
{
"name": "apple",
"color": "green"
},
{
"name": "strawberry",
"color": "red"
}
];
for (var i=0; i < data.length; i++) {
var item = "<button data-color="+data[i].color+">"+data[i].name+"</button>";
$('#items').append(item)
}
$( "button" ).click(function() {
$("#output" ).css('background', $(this).attr("data-color"));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="items" />
<div id="output" style="width:100%; height:20px"/>
you can use pure js
let d={"data":[{"name":"grape","color":"purple"},
{"name":"apple","color":"green"},{"name":"strawberry","color":"red"}]}
let b= (i) => {
box.style.background=d.data[i].color;
box.innerText = d.data[i].name;
}
d.data.map((x,i)=>btns.innerHTML+=`<button onclick="b(${i})">${x.name}</button>`)
#box { margin:10px; width:99px; height:99px; color:#fff; transition:1s }
<div id="btns"></div>
<div id="box"></div>

Trying to access json content and display in a grid fashion

I have a JSON file having the following content.
{
"rooms":[
{
"id": "1",
"name": "living",
"Description": "The living room",
"backgroundpath":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrsU8tuZWySrSuRYdz72WWFiYaW5PCMIwPAPr_xAIqL-FgmQ4qRw",
"Settings": {
"Sources": [
{
"srcname":["DirectTV","AppleTV","Sonos"],
"iconpath":["src/assets/images/ThemeEditorImgLib_iTVLight5d3a46c1ad5d7796.png","path2"]
}
],
"hex": "#000"
}
},
{
"id": "2",
"name": "dining",
"Description": "The Dining room",
"backgroundpath":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTjjspDkQEzbJJ1sSLS2ReWEx5P2ODNQmOtT572OIF9k3HbTGxV",
"Settings": {
"Sources": [
{
"srcname":["Climate","Shades"],
"iconpath":["path1","path2"]
}
],
"hex": "#000"
}
}
]
}
My HTML file Has:
<div class="roww">
<div class="col-md-4 col-sm-6 col-12">
</div>
</div>
I want to display my JSON content in the HTML.
So far I have tried the following.
private initTileGrid():void
{
var col = document.getElementsByClassName("roww")[0];
var outeritems=this.room_list.rooms;
// console.log(outeritems);
for(var i=0;i<outeritems.length;i++){
var tile = document.getElementsByClassName("col-md-4 col-sm-6 col-12 tile no-padding")[0];
var outerdiv = document.createElement("div");
var h5 = document.createElement("h5");
h5.innerHTML = outeritems[i].Description;
outerdiv.appendChild(h5);
var p = document.createElement("p");
p.innerHTML = outeritems[i].name;
outerdiv.appendChild(p);
// col.appendChild(outerdiv);
tile.appendChild(outerdiv);
var inneritem=outeritems[i].Settings.Sources.srcname;
console.log(inneritem);
var innerdiv = document.createElement("div");
for(var j=0;j<inneritem.length;j++)
{
console.log("hi")
var h5inner = document.createElement("h5");
h5inner.innerHTML = inneritem.srcname;
console.log(h5inner);
innerdiv.appendChild(h5inner);
}
tile.appendChild(innerdiv);
}
I am able to display the description and name from the json but not able to fetch the list of sources.
My final solution should be a grid with number of tiles equal to the number of objects in the JSON, with each tile having a background image from the json and its content.
Can anybody tell me where I am going wrong?
Any help appreciated!
I would suggest and recommend generating your dynamic HTML the following way with Template Literals.
Using Array#map, Array#join and Destructuring assignment
const data = {"rooms":[{"id":"1","name":"living","Description":"The living room","backgroundpath":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrsU8tuZWySrSuRYdz72WWFiYaW5PCMIwPAPr_xAIqL-FgmQ4qRw","Settings":{"Sources":[{"srcname":["DirectTV","AppleTV","Sonos"],"iconpath":["src/assets/images/ThemeEditorImgLib_iTVLight5d3a46c1ad5d7796.png","path2"]}],"hex":"#000"}},{"id":"2","name":"dining","Description":"The Dining room","backgroundpath":"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTjjspDkQEzbJJ1sSLS2ReWEx5P2ODNQmOtT572OIF9k3HbTGxV","Settings":{"Sources":[{"srcname":["Climate","Shades"],"iconpath":["path1","path2"]}],"hex":"#000"}}]}
const res = data.rooms.map(({name, Description, Settings:{Sources}})=>{
const inner = Sources.map(({srcname})=>{
return srcname.map(src=>`<h5>${src}</h5>`).join("");
}).join("");
return `
<div>
<h5>${Description}</h5>
<p>${name}</p>
<div class="inner">
${inner}
</div>
</div>
`
}).join("");
document.body.innerHTML = res;
body>div{background-color:lightgrey;padding:5px;margin-top:5px}body>div::before{content:"row"}body>div>*{margin-left:10px}h5{background-color:blue;color:white;padding:5px}h5::before{content:"outer h5:: "}p{background-color:purple;color:white;padding:5px}p::before{content:"p:: "}div.inner{padding:5px;background-color:grey}div.inner::before{content:"inner div"}div.inner>h5{background-color:green;color:white}div.inner>h5::before{content:"inner h5:: "}
Unminified CSS:
body > div {
background-color: lightgrey;
padding: 5px;
margin-top: 5px;
}
body > div::before {
content: "row";
}
body > div > * {
margin-left: 10px;
}
h5 {
background-color: blue;
color: white;
padding: 5px;
}
h5::before {
content: "outer h5:: "
}
p {
background-color: purple;
color: white;
padding: 5px;
}
p::before {
content: "p:: ";
}
div.inner {
padding: 5px;
background-color: grey;
}
div.inner::before {
content: "inner div";
}
div.inner > h5 {
background-color: green;
color: white;
}
div.inner > h5::before {
content: "inner h5:: "
}
V_Stack as discussed, this is just the tweak I would do to the sources section of the JSON, moving forward it will make working with a source easier, especially if you add additional properties. Note it is an array of self contained objects now.
{
"rooms": [{
"id": "1",
"name": "living",
"Description": "The living room",
"backgroundpath": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrsU8tuZWySrSuRYdz72WWFiYaW5PCMIwPAPr_xAIqL-FgmQ4qRw",
"Settings": {
"Sources": [{
"srcname": "DirectTV",
"iconpath": "src/assets/images/ThemeEditorImgLib_iTVLight5d3a46c1ad5d7796.png"
},
{
"srcname": "AppleTV",
"iconpath": "path2"
},
{
"srcname": "Sonos",
"iconpath": ""
}
],
"hex": "#000"
}
},
{
"id": "2",
"name": "dining",
"Description": "The Dining room",
"backgroundpath": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTjjspDkQEzbJJ1sSLS2ReWEx5P2ODNQmOtT572OIF9k3HbTGxV",
"Settings": {
"Sources": [{
"srcname": "Climate",
"iconpath": "path1"
},
{
"srcname": "Shades",
"iconpath": "path2"
}
],
"hex": "#000"
}
}
]
}
Try this:
var col = document.getElementsByClassName("roww")[0];
var outeritems = this.room_list.rooms;
// console.log(outeritems);
for (var i = 0; i < outeritems.length; i++) {
var tile = document.getElementsByClassName("col-md-4")[0];
var outerdiv = document.createElement("div");
var h5 = document.createElement("h5");
h5.innerHTML = outeritems[i].Description;
outerdiv.appendChild(h5);
var p = document.createElement("p");
p.innerHTML = outeritems[i].name;
outerdiv.appendChild(p);
// col.appendChild(outerdiv);
tile.appendChild(outerdiv);
outeritems[i].Settings.Sources.forEach(source => {
var inneritem = source.srcname;
console.log(inneritem);
var innerdiv = document.createElement("div");
for (var j = 0; j < inneritem.length; j++) {
console.log("hi")
var h5inner = document.createElement("h5");
h5inner.innerHTML = inneritem[j];
console.log(h5inner);
innerdiv.appendChild(h5inner);
}
tile.appendChild(innerdiv);
});
}
}
You need to loop through the Settings.Sources and srcname because all of them are arrays
Your main problem starts at this line var inneritem=outeritems[i].Settings.Sources.srcname; Sources is an array so you need to access it like Sources[j] where j is a number within the arrays length.
The inner loop is fine, you just need to loop through Sources properly
I also had to add classes to the tiles class to match your getElementsByClassName query
const room_list = {
"rooms": [{
"id": "1",
"name": "living",
"Description": "The living room",
"backgroundpath": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSrsU8tuZWySrSuRYdz72WWFiYaW5PCMIwPAPr_xAIqL-FgmQ4qRw",
"Settings": {
"Sources": [{
"srcname": ["DirectTV", "AppleTV", "Sonos"],
"iconpath": ["src/assets/images/ThemeEditorImgLib_iTVLight5d3a46c1ad5d7796.png", "path2"]
}],
"hex": "#000"
}
},
{
"id": "2",
"name": "dining",
"Description": "The Dining room",
"backgroundpath": "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTjjspDkQEzbJJ1sSLS2ReWEx5P2ODNQmOtT572OIF9k3HbTGxV",
"Settings": {
"Sources": [{
"srcname": ["Climate", "Shades"],
"iconpath": ["path1", "path2"]
}],
"hex": "#000"
}
}
]
}
var col = document.getElementsByClassName("roww")[0];
var outeritems = room_list.rooms;
// console.log(outeritems);
for (var i = 0; i < outeritems.length; i++) {
var tile = document.getElementsByClassName("col-md-4 col-sm-6 col-12 tile no-padding")[0];
var outerdiv = document.createElement("div");
var h5 = document.createElement("h5");
h5.innerHTML = outeritems[i].Description;
outerdiv.appendChild(h5);
var p = document.createElement("p");
p.innerHTML = outeritems[i].name;
outerdiv.appendChild(p);
// col.appendChild(outerdiv);
tile.appendChild(outerdiv);
var inneritems = outeritems[i].Settings.Sources
var innerdiv = document.createElement("div");
for (var j = 0; j < inneritems.length; j++) {
var inneritem = inneritems[j];
var h5inner = document.createElement("h5");
h5inner.innerHTML = inneritem.srcname;
innerdiv.appendChild(h5inner);
}
tile.appendChild(innerdiv);
}
<div class="roww">
<div class="col-md-4 col-sm-6 col-12 tile no-padding">
</div>
</div>

How to Create a menu with JSON fetched from Webserver PHP?

I want to make a mobile application using Cordova for my school homework project, and i need to fetch data from PHP Web Server, me already have JSON for this.
This is the example of my mobile app map :
http://prntscr.com/fhq63c .
This is the looks of my JSON :
Product Category :
[[
{"id":1,"name":"Product 1","created_at":"2017-06-06 08:31:34","updated_at":"2017-06-06 09:16:18"},
{"id":2,"name":"Product 2","created_at":"2017-06-06 09:16:12","updated_at":"2017-06-06 09:16:12"},
{"id":3,"name":"Product 3","created_at":"2017-06-06 09:16:24","updated_at":"2017-06-06 09:16:24"}
]]
Package Cateogry :
[[
{"id":1,"product_id":"1","name":"Package 1-1","jumlah_user":"1","created_at":"2017-06-06 09:34:11","updated_at":"2017-06-06 09:34:11"},
{"id":2,"product_id":"1","name":"Package 1-2","jumlah_user":"1","created_at":"2017-06-06 09:35:49","updated_at":"2017-06-06 10:03:43"},
{"id":3,"product_id":"2","name":"Package 2-1","jumlah_user":"1","created_at":"2017-06-07 03:03:35","updated_at":"2017-06-07 03:03:35"},
{"id":4,"product_id":"2","name":"Package 2-2","jumlah_user":"1","created_at":"2017-06-07 03:30:11","updated_at":"2017-06-07 03:30:11"},
{"id":5,"product_id":"3","name":"Package 3-1","jumlah_user":"12","created_at":"2017-06-07 03:31:36","updated_at":"2017-06-07 03:31:36"},
]]
List Price
[[
{"id":1,"package_id":"1","harga":"700000.00","masa_training":"2 x 1 jam","masa_maintenance":"2 bulan","tanggal_efektif":"2018-01-01","created_at":"2017-06-07 03:45:20","updated_at":"2017-06-07 03:45:20"},
{"id":2,"package_id":"2","harga":"500000.00","masa_training":"500","masa_maintenance":"100","tanggal_efektif":"2019-01-01","created_at":"2017-06-07 03:48:23","updated_at":"2017-06-07 03:48:23"},
{"id":3,"package_id":"3","harga":"50000.00","masa_training":"10","masa_maintenance":"20","tanggal_efektif":"2017-11-30","created_at":"2017-06-08 23:11:49","updated_at":"2017-06-08 23:11:49"}
]]
and this is how my menu will looks :
<ul class="list-group">
<li class="btn btn-lg btn-default list-group-item btn-menu">
<p class="productid" hidden>1</p>
<p class="productname">Product Name</p>
</li>
<li class="btn btn-lg btn-default list-group-item btn-menu">
<p class="productid" hidden>1</p>
<p class="productname">Product Name</p>
</li>
<li class="btn btn-lg btn-default list-group-item btn-menu">
<p class="productid" hidden>1</p>
<p class="productname">Product Name</p>
</li>
</ul>
```
and each button directly go to price list that connected to the product category.
Anyone have idea and can solved mine? thanks.
Assuming we have the json data stored in its corresponding variables, we could do like this:
(function() {
var productCategories = [
[{
"id": 1,
"name": "Product 1",
"created_at": "2017-06-06 08:31:34",
"updated_at": "2017-06-06 09:16:18"
},
{
"id": 2,
"name": "Product 2",
"created_at": "2017-06-06 09:16:12",
"updated_at": "2017-06-06 09:16:12"
},
{
"id": 3,
"name": "Product 3",
"created_at": "2017-06-06 09:16:24",
"updated_at": "2017-06-06 09:16:24"
}
]
];
var packageCategories = [
[{
"id": 1,
"product_id": "1",
"name": "Package 1-1",
"jumlah_user": "1",
"created_at": "2017-06-06 09:34:11",
"updated_at": "2017-06-06 09:34:11"
},
{
"id": 2,
"product_id": "1",
"name": "Package 1-2",
"jumlah_user": "1",
"created_at": "2017-06-06 09:35:49",
"updated_at": "2017-06-06 10:03:43"
},
{
"id": 3,
"product_id": "2",
"name": "Package 2-1",
"jumlah_user": "1",
"created_at": "2017-06-07 03:03:35",
"updated_at": "2017-06-07 03:03:35"
},
{
"id": 4,
"product_id": "2",
"name": "Package 2-2",
"jumlah_user": "1",
"created_at": "2017-06-07 03:30:11",
"updated_at": "2017-06-07 03:30:11"
},
{
"id": 5,
"product_id": "3",
"name": "Package 3-1",
"jumlah_user": "12",
"created_at": "2017-06-07 03:31:36",
"updated_at": "2017-06-07 03:31:36"
},
]
];
var listPrice = [
[{
"id": 1,
"package_id": "1",
"harga": "700000.00",
"masa_training": "2 x 1 jam",
"masa_maintenance": "2 bulan",
"tanggal_efektif": "2018-01-01",
"created_at": "2017-06-07 03:45:20",
"updated_at": "2017-06-07 03:45:20"
},
{
"id": 2,
"package_id": "2",
"harga": "500000.00",
"masa_training": "500",
"masa_maintenance": "100",
"tanggal_efektif": "2019-01-01",
"created_at": "2017-06-07 03:48:23",
"updated_at": "2017-06-07 03:48:23"
},
{
"id": 3,
"package_id": "3",
"harga": "50000.00",
"masa_training": "10",
"masa_maintenance": "20",
"tanggal_efektif": "2017-11-30",
"created_at": "2017-06-08 23:11:49",
"updated_at": "2017-06-08 23:11:49"
}
]
];
function buildProductCategoryMenu(productCategories) {
var ul = "",
i, obj, len = productCategories.length;
ul = "<ul class=\"list-group\">";
for (i = 0; i < len; i++) {
obj = productCategories[i];
ul += "<li class=\"btn btn-lg btn-default list-group-item btn-menu\">";
ul += "<p class=\"productid\" hidden>";
ul += obj.id;
ul += "</p>";
ul += "<p class=\"productname\">";
ul += obj.name;
ul += "</p>";
ul += "</li>";
}
ul += "</ul>";
return ul;
}
function setEventsProductCategoryMenu() {
var elems = document.getElementsByClassName("productname"),
i, len = elems.length,
ele;
for (i = 0; i < len; i++) {
ele = elems[i];
ele.onclick = function() {
showPackageName(this.previousSibling.innerHTML, packageCategories[0]);
};
}
}
function showPackageName(id, packageCategories) {
var packageCategory = packageCategories.find(function(x) {
return x.product_id === id;
});
if (packageCategory !== undefined) {
document.getElementById("packageName").innerHTML = "Package Name: " + packageCategory.name;
document.getElementById("price").innerHTML = "Price: " + showPriceBasedPackageCategory(packageCategory.id, listPrice[0]);
}
}
function showPriceBasedPackageCategory(id, listPrice) {
var obj;
obj = listPrice.find(function(x) {
return x.package_id === id.toString();
});
return (obj === undefined) ? "" : obj.harga;
}
document.getElementById("menu").innerHTML = buildProductCategoryMenu(productCategories[0]);
setEventsProductCategoryMenu();
})();
#menu {
border: solid 1px #ccc;
}
#content {
border: solid 1px #555;
}
<div id="menu"></div>
<div id="content">
<p id="packageName"></p>
<p id="price"></p>
</div>
With AJAX (Native JavaScript XMLHttpRequest() object):
By using a simple json file which contains all the data getting from the server.
JSON File: https://gist.githubusercontent.com/dannyjhonston/786a8e7c3f4ff1a0569013a1d4d1b8ad/raw/eb62b89d43e310997f9507be2d25f7fa375ddb6c/productCategoryPackageCategoryListPrice.json
(function() {
var newXHR = null;
// XMLHttpRequest helper function.
function sendXHR(type, url, data, callback) {
newXHR = new XMLHttpRequest() || new window.ActiveXObject("Microsoft.XMLHTTP");
newXHR.open(type, url, true);
newXHR.send(data);
newXHR.onreadystatechange = function() {
if (this.status === 200 && this.readyState === 4) {
callback(this.response);
}
};
}
function buildProductCategoryMenu(productCategories) {
var ul = "",
i, obj, len = productCategories.length;
ul = "<ul class=\"list-group\">";
for (i = 0; i < len; i++) {
obj = productCategories[i];
ul += "<li class=\"btn btn-lg btn-default list-group-item btn-menu\">";
ul += "<p class=\"productid\" hidden>";
ul += obj.id;
ul += "</p>";
ul += "<p class=\"productname\">";
ul += obj.name;
ul += "</p>";
ul += "</li>";
}
ul += "</ul>";
return ul;
}
function setEventsProductCategoryMenu(packageCategories, listPrice) {
var elems = document.getElementsByClassName("productname"),
i, len = elems.length,
ele;
for (i = 0; i < len; i++) {
ele = elems[i];
ele.onclick = function() {
showPackageName(this.previousSibling.innerHTML, packageCategories, listPrice);
};
}
}
function showPackageName(id, packageCategories, listPrice) {
var packageCategory = packageCategories.find(function(x) {
return x.product_id === id;
});
if (packageCategory !== undefined) {
document.getElementById("packageName").innerHTML = "Package Name: " + packageCategory.name;
document.getElementById("price").innerHTML = "Price: " + showPriceBasedPackageCategory(packageCategory.id, listPrice);
}
}
function showPriceBasedPackageCategory(id, listPrice) {
var obj;
obj = listPrice.find(function(x) {
return x.package_id === id.toString();
});
return (obj === undefined) ? "" : obj.harga;
}
sendXHR("GET", "https://gist.githubusercontent.com/dannyjhonston/786a8e7c3f4ff1a0569013a1d4d1b8ad/raw/eb62b89d43e310997f9507be2d25f7fa375ddb6c/productCategoryPackageCategoryListPrice.json", null, function(response) {
if (response !== null && response.length > 0) {
var jsonResponse = JSON.parse(response);
document.getElementById("menu").innerHTML = buildProductCategoryMenu(jsonResponse.data.productCategories[0]);
setEventsProductCategoryMenu(jsonResponse.data.packageCategories[0], jsonResponse.data.listPrice[0]);
}
});
})();
#menu {
border: solid 1px #ccc;
}
#content {
border: solid 1px #555;
}
<div id="menu"></div>
<div id="content">
<p id="packageName"></p>
<p id="price"></p>
</div>
By using three json files which contains its corresponding data getting from the server.
JSON Files:
Product Categories: https://gist.githubusercontent.com/dannyjhonston/3e2689ac7197d69a9624b32d5600e150/raw/18e36651acb9b9883732081a18c7deae7388eb0f/productCategories.json.
Package Categories: https://gist.githubusercontent.com/dannyjhonston/5d0caaffd3e22506fe1311eb4e31b7cc/raw/09a305b83cb725907d8ee9c24d487bdd85591b14/packageCategories.json.
List Price: https://gist.githubusercontent.com/dannyjhonston/cd73c2caf8d53ff1f453eafc14046357/raw/c943af91e7dd3e5e14e5763d8a2a14f649ddd810/listPrice.json.
(function() {
var newXHR = null;
// XMLHttpRequest helper function.
function sendXHR(type, url, data, callback) {
newXHR = new XMLHttpRequest() || new window.ActiveXObject("Microsoft.XMLHTTP");
newXHR.open(type, url, true);
newXHR.send(data);
newXHR.onreadystatechange = function() {
if (this.status === 200 && this.readyState === 4) {
callback(this.response);
}
};
}
function buildProductCategoryMenu(productCategories) {
var ul = "",
i, obj, len = productCategories.length;
ul = "<ul class=\"list-group\">";
for (i = 0; i < len; i++) {
obj = productCategories[i];
ul += "<li class=\"btn btn-lg btn-default list-group-item btn-menu\">";
ul += "<p class=\"productid\" hidden>";
ul += obj.id;
ul += "</p>";
ul += "<p class=\"productname\">";
ul += obj.name;
ul += "</p>";
ul += "</li>";
}
ul += "</ul>";
return ul;
}
function setEventsProductCategoryMenu(packageCategories, listPrice) {
var elems = document.getElementsByClassName("productname"),
i, len = elems.length,
ele;
for (i = 0; i < len; i++) {
ele = elems[i];
ele.onclick = function() {
showPackageName(this.previousSibling.innerHTML, packageCategories, listPrice);
};
}
}
function showPackageName(id, packageCategories, listPrice) {
var packageCategory = packageCategories.find(function(x) {
return x.product_id === id;
});
if (packageCategory !== undefined) {
document.getElementById("packageName").innerHTML = "Package Name: " + packageCategory.name;
document.getElementById("price").innerHTML = "Price: " + showPriceBasedPackageCategory(packageCategory.id, listPrice);
}
}
function showPriceBasedPackageCategory(id, listPrice) {
var obj;
obj = listPrice.find(function(x) {
return x.package_id === id.toString();
});
return (obj === undefined) ? "" : obj.harga;
}
sendXHR("GET", "https://gist.githubusercontent.com/dannyjhonston/3e2689ac7197d69a9624b32d5600e150/raw/18e36651acb9b9883732081a18c7deae7388eb0f/productCategories.json", null, function(response) {
if (response !== null && response.length > 0) {
var jsonResponse = JSON.parse(response);
document.getElementById("menu").innerHTML = buildProductCategoryMenu(jsonResponse.productCategories[0]);
sendXHR("GET", "https://gist.githubusercontent.com/dannyjhonston/5d0caaffd3e22506fe1311eb4e31b7cc/raw/09a305b83cb725907d8ee9c24d487bdd85591b14/packageCategories.json", null, function(response) {
if (response !== null && response.length > 0) {
jsonResponse = JSON.parse(response);
var packageCategories = jsonResponse.packageCategories;
sendXHR("GET", "https://gist.githubusercontent.com/dannyjhonston/cd73c2caf8d53ff1f453eafc14046357/raw/c943af91e7dd3e5e14e5763d8a2a14f649ddd810/listPrice.json", null, function(response) {
if (response !== null && response.length > 0) {
jsonResponse = JSON.parse(response);
var listPrice = jsonResponse.listPrice;
setEventsProductCategoryMenu(packageCategories[0], listPrice[0]);
}
});
}
});
}
});
})();
#menu {
border: solid 1px #ccc;
}
#content {
border: solid 1px #555;
}
<div id="menu"></div>
<div id="content">
<p id="packageName"></p>
<p id="price"></p>
</div>

Generate HTML table from intricate JSON

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>

Get the unique items - Handlebars

My JSON looks like this:
{
"features": [
{
"id": "belly",
"scenarios": [
{
"id": "belly;a-few-cukes",
"tags": [
{
"name": "#tag1"
}
],
"steps": [
{
"name": "I have 42 cukes in my belly"
},
{
"name": "I wait 1 hour"
},
{
"name": "my belly should growls"
}
]
},
{
"id": "belly;a-few-cukes-with-new-test",
"tags": [
{
"name": "#tag2"
}
],
"steps": [
{
"name": "I have 42 cukes in my belly"
},
{
"name": "I wait 1 hour"
},
{
"name": "my belly should growl"
}
]
}
]
},
{
"id": "newbelly",
"scenarios": [
{
"id": "newbelly;a-few-cukes-with-new-feature",
"tags": [
{
"name": "#tag1"
}
],
"steps": [
{
"name": "I have 42 cukes in my belly"
},
{
"name": "I wait 1 hour"
},
{
"name": "my belly should growls"
}
]
}
]
}
]
}
I would like to retrieve all the unique tag names: i.e., #tag1, #tag2. If you notice, the #tag1 is repeated twice.
My template:
{{#getTags features}}
{{#scenarios}}
{{#tags}}
<p>{{name}}</p>
{{/tags}}
{{/scenarios}}
{{/getTags}}
Custom Helper that I created so far:
Handlebars.registerHelper('getTags', function(context, block) {
var ret = "";
for (var i = 0; i < context.length; i++) {
ret += block.fn(context[i]);
};
return ret;
});
The above custom helper returns all the tags, but I want unique ones.
Something along these lines may work:
Handlebars.registerHelper('getTags', function(context, block) {
var ret = "";
var got = [];
function contains(obj, a) {
for (var i = 0; i < a.length; i++) {
if (a[i] === obj) {
return true;
}
}
return false;
}
for (var i = 0; i < context.length; i++) {
if (!this.contains(context[i],got)) {
got.addObject(context[i]);
ret += block.fn(context[i]);
}
}
return ret;
});
Code used for testing, all javascript:
var ret = "";
var got = [];
var data = ["tag1", "tag1", "tag2", "tag3"]
function contains(obj, a) {
for (var i = 0; i < a.length; i++) {
if (a[i] === obj) {
return true;
}
}
return false;
}
for (var i = 0; i < data.length; i++) {
if (!contains(data[i],got)) {
got.push(data[i]);
ret += data[i];
}
}
console.log( ret);

Categories