Trying to access json content and display in a grid fashion - javascript

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>

Related

moving the content at the end of a table row

I'm having this issues with the below table in which I want to set the 'view book' link and reserved to be the last in the row, but apparently the x = TABLE_ROW.insertCell(-1) is not working.
I just want to have the link/span at the end of the table row. Shouldn't the -1 argument be enough for this?
Can you please help me identifying what I'm doing wrong?
var data = {
"headings": {
"propBook": "Book",
"propAuthor": "Author",
"propYear": "Year",
},
"items": [{
"fields": {
"propBook": "The Great Gatsby",
"propAuthor": "F Scott Fitzgerald",
"propYear": "1925",
},
"button": {
"name": "View book",
"propURL": "https://google.com"
}
},
{
"fields": {
"propBook": "The Grapes of Wrath",
"propAuthor": "John Steinbeck",
"propYear": "1939",
},
"button": {
"name": "View book",
"propURL": ""
}
},
{
"fields": {
"propBook": "A Wild Sheep Chase",
"propAuthor": "Haruki Murakami",
"propYear": "1982",
},
"button": {
"name": "View book",
"propURL": "https://google.com"
}
}
]
}
const HEADINGS = data.headings;
const ITEMS = data.items;
const TABLE_WRAPPER = document.querySelector('.book-component .table-wrapper');
const TABLE = document.createElement('table');
TABLE.setAttribute('class', 'pagination');
TABLE_WRAPPER.appendChild(TABLE);
for (const field in data) {
const TABLE_ROW = document.createElement('tr');
TABLE_ROW.setAttribute('id', 'myRow');
if (field == 'headings') {
for (const child in HEADINGS) {
const HEADER_CELL = document.createElement('th');
TABLE_ROW.appendChild(HEADER_CELL);
HEADER_CELL.setAttribute('class', 'sort-cta');
HEADER_CELL.innerText = HEADINGS[child];
TABLE.appendChild(TABLE_ROW);
}
} else if (field == 'items') {
for (const child in ITEMS) {
const TABLE_ROW = document.createElement('tr');
let item = ITEMS[child].fields;
let btn = ITEMS[child].button;
if (btn.propURL !== '') {
let link = document.createElement('a');
link.setAttribute('href', btn.propURL);
link.innerHTML = btn.name;
x = TABLE_ROW.insertCell(-1);
x.appendChild(link);
} else {
let link = document.createElement('span');
link.innerHTML = 'Reserved';
x = TABLE_ROW.insertCell(-1);
x.appendChild(link);
}
for (const row in item) {
const TABLE_DATA = document.createElement('td');
TABLE_ROW.appendChild(TABLE_DATA);
TABLE_DATA.innerText = item[row];
TABLE.appendChild(TABLE_ROW);
}
}
}
}
tr.inactive {
display: none;
}
.table-wrapper {
display: flex;
flex-direction: column-reverse;
}
.pager {
display: flex;
justify-content: center;
padding: 0;
margin-top: 10px;
font-weight: 800;
}
.pager-item.selected {
outline: none;
border-color: #0077cc;
background: #0077cc;
color: #fff;
cursor: default;
}
<div class="book-component">
<div class="table-wrapper">
</div>
</div>
You just should inset cell data first. Then insert the link cell at the end of a table row.
http://jsfiddle.net/u1bvq376/
Here is a sample. Hope to help, my friend :))
for (const field in data) {
const TABLE_ROW = document.createElement('tr');
TABLE_ROW.setAttribute('id', 'myRow');
if (field == 'headings') {
for (const child in HEADINGS) {
const HEADER_CELL = document.createElement('th');
TABLE_ROW.appendChild(HEADER_CELL);
HEADER_CELL.setAttribute('class', 'sort-cta');
HEADER_CELL.innerText = HEADINGS[child];
TABLE.appendChild(TABLE_ROW);
}
} else if (field == 'items') {
for (const child in ITEMS) {
const TABLE_ROW = document.createElement('tr');
let item = ITEMS[child].fields;
let btn = ITEMS[child].button;
// insert the cell data first
for (const row in item) {
const TABLE_DATA = document.createElement('td');
TABLE_ROW.appendChild(TABLE_DATA);
TABLE_DATA.innerText = item[row];
TABLE.appendChild(TABLE_ROW);
}
// then insert the link
if (btn.propURL !== '') {
let link = document.createElement('a');
link.setAttribute('href', btn.propURL);
link.innerHTML = btn.name;
x = TABLE_ROW.insertCell(-1);
x.appendChild(link);
} else {
let link = document.createElement('span');
link.innerHTML = 'Reserved';
x = TABLE_ROW.insertCell(-1);
x.appendChild(link);
}
}
}
}

Display nested array data in a click event

I have this data and I'm displaying the name. But when I click on, in this case Sweden, I want to display additional info. In the code below I just want to display the country code, but this creates four additional <p> tags because of .forEach loop. That's not really what I want.
How would I go about if I just want to display the country code, and what if I wanted to display all the additional info? I'm kinda stuck as of now.
let data = [
{"name": "Swaziland", "code": "SZ"},
{"name": "Sweden",
"info": [
{"code": "SE"},
{"population": "10.2 million"},
{"area": "447 435km"},
{"capital": "Stockholm"},
{"Language": "Swedish"}]
},
{"name": "Switzerland", "code": "CH"},
{"name": "Syrian Arab Republic", "code": "SY"}
]
let output = '<ul class="searchresultCountries">';
let countries = data;
countries.forEach((value) => {
output += '<li>' + value.name + '</li>';
});
output += '</ul>';
document.querySelector('#countries').innerHTML = output;
document.addEventListener('click', (e) => {
data.forEach((item) => {
if(item.name === e.target.textContent) {
if(item.info) {
item.info.forEach((items) => {
let extraInfo = document.createElement("p");
extraInfo.textContent = items.code;
e.target.appendChild(extraInfo);
});
}
}
});
});
ul {
padding: 0;
}
.searchresultCountries li {
list-style-type: none;
border: 1px solid grey;
margin-bottom: 10px;
padding: 5px;
}
<div id="countries"></div>
You should have some kind of button or link upon which clicking you can show/hide the extra information.
You can try the following way:
let data = [
{"name": "Swaziland", "code": "SZ"},
{"name": "Sweden",
"info": [
{"code": "SE"},
{"population": "10.2 million"},
{"area": "447 435km"},
{"capital": "Stockholm"},
{"Language": "Swedish"}]
},
{"name": "Switzerland", "code": "CH"},
{"name": "Syrian Arab Republic", "code": "SY"}
]
let output = '<ul class="searchresultCountries">';
let countries = data;
countries.forEach((value) => {
output += '<li>' + value.name + '</li>';
});
output += '</ul>';
document.querySelector('#countries').innerHTML = output;
document.addEventListener('click', (e) => {
data.forEach((item) => {
if(item.name === e.target.textContent) {
if(item.info) {
let extraInfo = document.createElement("p");
extraInfo.textContent = item.info[0].code;
e.target.appendChild(extraInfo);
if(item.info.length > 1){
let btnExtra = document.createElement("button");
btnExtra.textContent = "Show More";
e.target.appendChild(btnExtra);
btnExtra.addEventListener('click', function(){
let container = document.createElement("div");
if(!document.querySelector('.extra')){
container.classList.add('extra');
item.info.forEach(function(el, i){
if(i > 0){ // skip the first
let extra = document.createElement("p");
extra.textContent = Object.values(el)[0];
container.appendChild(extra);
}
});
e.target.appendChild(container);
btnExtra.textContent = "Show Less";
}
else{
document.querySelector('.extra').remove();
btnExtra.textContent = "Show More";
}
});
}
}
else{
let extraInfo = document.createElement("p");
extraInfo.textContent = item.code;
e.target.appendChild(extraInfo);
}
}
});
});
ul {
padding: 0;
}
.searchresultCountries li {
list-style-type: none;
border: 1px solid grey;
margin-bottom: 10px;
padding: 5px;
}
<div id="countries"></div>

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>

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

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;
}

Looping through JSON Data to Generate HTML

I have JSON data that looks like this:
data = {
"tennis": [{
"Description": "Insert description here.",
"Price": 379.99,
"ProductName": "Babolat Play Pure Drive",
}, {
"Description": "Insert description here.",
"Price": 199.99,
"ProductName": "Yonex AI 98 Tennis Racquet",
}],
"basketball": [{
"Description": "Insert description here.",
"Price": 64.99,
"ProductName": "Wilson NCAA Solution Official Game Basketball",
}, {
"Description": "Insert description here.",
"Price": 59.99,
"ProductName": "Spalding NBA NeverFlat Size 7 Composite Leather Basketball",
}]
}
I am using this data to generate HTML so it looks properly formatted and easily readable for the user. The way I am doing this is by creating a for loop to read through tennis and basketball categories. For example:
for (var i = 0; i < data.tennis.length; i++) {
tennisProducts.push(data.tennis[i]);
var tennisProductsTitle = tennisProducts[i].ProductName;
var tennisProductsDescription = tennisProducts[i].Description;
var tennisProductsPrice = tennisProducts[i].Price;
var badge = document.createElement('div');
badge.className = 'badge';
badge.innerHTML =
'<h1>' + tennisProductsTitle + '</h1>' +
'<h2>' + tennisProductsDescription + '</h1>' +
'<div class="options-only-phone">' +
'<a class="service-provider-call" href="#" target="_blank"> Buy for $' + tennisProductsPrice + '</a>';
document.getElementById('tennis-products-list').appendChild(badge);
}
How can I create one for loop that can read through both (or multiple) categories?
Here is my working example in this JSFiddle: https://jsfiddle.net/dsk1279b/1
Double loop, one to iterate the object properties, the next to iterate the array:
for (var key in data) {
for (var i = 0; i < data[key].length; i++) {
//HTML logic
}
}
Final code:
for (var key in data) {
for (var i = 0; i < data[key].length; i++) {
var title = data[key][i].ProductName;
var desc = data[key][i].Description;
var price = data[key][i].Price;
var badge = document.createElement('div');
badge.className = 'badge';
badge.innerHTML =
'<h1>' + title + '</h1>' +
'<h2>' + desc + '</h1>' +
'<div class="options-only-phone">' +
'<a class="service-provider-call" href="#" target="_blank"> Buy for $' + price + '</a>';
//I gave the div the same ID's as the keys in the object for ease
document.getElementById(key).appendChild(badge);
}
}
data = {
"tennis": [{
"Description": "Insert description here.",
"Price": 379.99,
"ProductName": "Babolat Play Pure Drive",
}, {
"Description": "Insert description here.",
"Price": 199.99,
"ProductName": "Yonex AI 98 Tennis Racquet",
}],
"basketball": [{
"Description": "Insert description here.",
"Price": 64.99,
"ProductName": "Wilson NCAA Solution Official Game Basketball",
}, {
"Description": "Insert description here.",
"Price": 59.99,
"ProductName": "Spalding NBA NeverFlat Size 7 Composite Leather Basketball",
}]
}
for (var key in data) {
for (var i = 0; i < data[key].length; i++) {
var title = data[key][i].ProductName;
var desc = data[key][i].Description;
var price = data[key][i].Price;
var badge = document.createElement('div');
badge.className = 'badge';
badge.innerHTML =
'<h1>' + title + '</h1>' +
'<h2>' + desc + '</h1>' +
'<div class="options-only-phone">' +
'<a class="service-provider-call" href="#" target="_blank"> Buy for $' + price + '</a>';
document.getElementById(key).appendChild(badge);
}
}
body {
font-family: Arial, sans-serif;
line-height: 125%;
}
h1 {
font-size: 0.875em;
padding: 0;
margin: 0;
}
h2,
a {
font-size: 0.750em;
padding: 0;
margin: 0;
font-weight: normal;
}
a:hover {
text-decoration: none;
}
.badge {
border-radius: 2px;
border: 1px solid rgba(0, 0, 0, 0.15);
padding: 12px;
margin: 12px 0;
}
.badge:hover {
border: 1px solid rgba(0, 0, 0, 0.3);
}
<div id="tennis">
</div>
<hr>
<div id="basketball">
</div>
tymeJV has a good approach, but this can be made even easier.
for(var product in data) {
// logic
}
If you look at your data, you have an object that we're already iterating over in key/value form.
Since you have arrays of items per key, you can use the Array.forEach() function.
for(var product in data) {
// current is the current object in the array
data[product].forEach(function(current){
//HTML logic
})
}
You change the place where you're appending the html template, so I would recommend updating your data object to be something like this:
data = {
"tennis": {
"products: [
{
"Description": "Insert description here.",
"Price": 379.99,
"ProductName": "Babolat Play Pure Drive"
},
{
"Description": "Insert description here.",
"Price": 199.99,
"ProductName": "Yonex AI 98 Tennis Racquet"
}
],
"templateTarget": '#tennis-products-list'
}
"basketball":
"products": [
{
"Description": "Insert description here.",
"Price": 64.99,
"ProductName": "Wilson NCAA Solution Official Game Basketball"
},
{
"Description": "Insert description here.",
"Price": 59.99,
"ProductName": "Spalding NBA NeverFlat Size 7 Composite Leather Basketball"
}
],
"templateTarget": '#basketball-products-list'
}
Something like that is going to allow you to do this:
for(var product in data) {
// current is the current object in the array
product.forEach(function(current){
var badge = document.createElement('div');
badge.className = 'badge';
badge.innerHTML =
'<h1>' + current.productName + '</h1>' +
'<h2>' + current.description + '</h1>' +
'<div class="options-only-phone">' +
'<a class="service-provider-call" href="#" target="_blank"> Buy for $' + current.price + '</a>';
document.getElementById(current.templateTarget).appendChild(badge);
})
}
This can be further optimized by having that giant html string hidden in a script tag with type="text/x-template" (since the browser ignores script types it doesn't understand) and grabbing it with the innerHTML function by referencing the id property on the script tag.
Hope that helps!
Flatten the data to a single array of values with category as a property:
var _data = Object.keys(data).reduce(
(m,c) => m.concat(data[c].map(
(i) => (i.category = c) && i))
, []);
console.log(_data);
Use flattened array for UI:
_data.forEach((d) => {
var badge = document.createElement('div');
badge.className = 'badge';
badge.innerHTML = [
'<h1>',
d.ProductName,
'</h1><h2>',
d.Description,
'</h1><div class="options-only-phone">',
'<a class="service-provider-call" href="#" target="_blank"> Buy for $',
d.Price,
'</a>'].join('');
document.getElementById(d.category + '-products-list').appendChild(badge);
})
'use strict';
var data = {
"tennis": [{
"Description": "Insert description here.",
"Price": 379.99,
"ProductName": "Babolat Play Pure Drive",
}, {
"Description": "Insert description here.",
"Price": 199.99,
"ProductName": "Yonex AI 98 Tennis Racquet",
}],
"basketball": [{
"Description": "Insert description here.",
"Price": 64.99,
"ProductName": "Wilson NCAA Solution Official Game Basketball",
}, {
"Description": "Insert description here.",
"Price": 59.99,
"ProductName": "Spalding NBA NeverFlat Size 7 Composite Leather Basketball",
}]
}
var _data = Object.keys(data).reduce((m,c) => m.concat(data[c].map((i) => (i.category = c) && i) ), []);
console.log(_data);
_data.forEach((d) => {
var badge = document.createElement('div');
badge.className = 'badge';
badge.innerHTML = [
'<h1>',
d.ProductName,
'</h1><h2>',
d.Description,
'</h1><div class="options-only-phone">',
'<a class="service-provider-call" href="#" target="_blank"> Buy for $',
d.Price,
'</a>'].join('');
document.getElementById(d.category + '-products-list').appendChild(badge);
})
body {
font-family: Arial, sans-serif;
line-height: 125%;
}
h1 {
font-size: 0.875em;
padding: 0; margin: 0;
}
h2, a {
font-size: 0.750em;
padding: 0; margin: 0;
font-weight: normal;
}
a:hover {
text-decoration: none;
}
.badge {
border-radius: 2px;
border: 1px solid rgba(0, 0, 0, 0.15);
padding: 12px;
margin: 12px 0;
}
.badge:hover {
border: 1px solid rgba(0, 0, 0, 0.3);
}
<div id="tennis-products-list">
</div>
<hr>
<div id="basketball-products-list">
</div>

Categories