I am trying to load the data from my JSON file using javaScript and i need to represent the hotel2show.rating in form of stars, just represent them dependig on the value from 'hotels.json'
Here is my JavaScript
function getHotels(i){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function()
{
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
hotel=JSON.parse(xhr.responseText);
var hotel2show = hotel.hotels[i];
document.getElementById("img-container").innerHTML =
"<img src='"+hotel2show.imgUrl+"'>"+
"<p id='name'><strong>"+ hotel2show.name +"</strong></p>" +"<br/>" + "<p id='rating'><strong>"+ hotel2show.rating +"</strong></p>" +"<br/>" + "<br/>" +"<p id='price'><strong>"+ '£' +hotel2show.price +
"</strong></p>" + "<p id='text'><strong>"+ 'Total hotel stay' +"</strong></p>";
} else {
alert("Ha existido un error con el servidor");
}
}
};
xhr.open("GET",'hotels.json', true);
xhr.send();
and here is my html
<div class="container">
<div id="lista">
<ul>
<button onclick="getHotels(0)">Hotel Sunny Palms</button>
<button onclick="getHotels(1)">Hotel Snowy Mountains</button>
<button onclick="getHotels(2)">Hotel Windy Sails</button>
<button onclick="getHotels(3)">Hotel Middle Of Nowhere</button>
</ul>
</div>
<div class="banner-section" id="img-container">
</div>
and my hotels.json
"hotels": [
{
"name": "Hotel Sunny Palms",
"imgUrl": "imgs/sunny.jpg",
"rating": 5,
"price": 108.00
},
{
"name": "Hotel Snowy Mountains",
"imgUrl": "imgs/snowy.jpg",
"rating": 4,
"price": 120.00
},
{
"name": "Hotel Windy Sails",
"imgUrl": "imgs/windy.jpg",
"rating": 3,
"price": 110.00
},
{
"name": "Hotel Middle of Nowhere",
"imgUrl": "imgs/nowhere.jpg",
"rating": 4,
"price": 199.00
}
]
any help is appreciated
For example..if you have UTF-8 charset then this should perhaps be fine. The key is createElement function by which you can construct your DOM as you wish.
var hotels = [{
"name": "Hotel Sunny Palms",
"imgUrl": "imgs/sunny.jpg",
"rating": 5,
"price": 108.00
}, {
"name": "Hotel Snowy Mountains",
"imgUrl": "imgs/snowy.jpg",
"rating": 4,
"price": 120.00
}, {
"name": "Hotel Windy Sails",
"imgUrl": "imgs/windy.jpg",
"rating": 3,
"price": 110.00
}, {
"name": "Hotel Middle of Nowhere",
"imgUrl": "imgs/nowhere.jpg",
"rating": 4,
"price": 199.00
}];
buildRating(hotels);
function buildRating(data) {
data.forEach(function(v) {
createRatingElement(v.rating);
});
}
function createRatingElement(numberOfStars) {
var wrapper = document.createElement('div');
for (var i = 1; i <= 5; i++) {
var span = document.createElement('span')
span.innerHTML = (i <= numberOfStars ? '★' : '☆');
span.className = (i <= numberOfStars ? 'high' : '');
wrapper.appendChild(span);
}
document.getElementById('img-container').appendChild(wrapper);
}
span {
display: inline-block;
position: relative;
width: 1.2em;
height: 1.2em;
color: black;
}
.high {
color: rgb(217, 211, 0);
}
<div class="banner-section" id="img-container">
</div>
Also, jsfiddle: https://jsfiddle.net/md4708oq/
I assume you know how to parse out your ratings, right? If you are just displaying single star values (whole numbers), then you can just write out a class onto a span element where you would style it with CSS to change what the background image would be.
So, you could make it show 1-5 stars with 4 different images.
It's a solution; not the cleanest or most scalable, but it works for this situation.
So first off this is a nightmare.
Let's clean it up a bit?
var appendString = [];
appendString[0] = "<img src='"+hotel2show.imgUrl+"'>";
appendString[1] = "<p id='name'><strong>"+ hotel2show.name +"</strong></p><br/>";
switch(hotel2show.rating):
case(1):
appendString[2] = "<p id='rating' class='rating-1'><strong>";
break;
case(2):
appendStirng[2] = "<p id='rating' class='rating-2><strong>";
break;
//etc
appendString[3] = hotel2show.rating +"</strong></p>";
appendString[4] = "<br/><br/>";
appendString[5] = "<p id='price'><strong>'£'" + hotel2show.price + "</strong></p>";
appendString[6] = "<p id='text'><strong>"+ 'Total hotel stay' +"</strong></p>";
document.getElementById("img-container").innerHTML = appendString.join(' ');
Note: the switch statement syntax may be incorrect.
You will have to use AJAX calls to retrieve JSON data and then use pure javascript to parse the JSON data and use it to display your html accordingly. Let me know if this is what you are looking for i will help you out with the same.
Related
I'm trying to make a site of restaurant and now doing some table reservation. So far have one problem:
I have a JSON of tables and want to add date (day/time) to it, when table was clicked.
The problem's next - when I click on some table, the date adds to all JSON elements. And I wand to add it only to the element I clicked.
Here is link to codepen:
https://codepen.io/wilchilly/pen/qBEvegW
(To see the result click on some table and open console)
My HTML:
<p class="href-to italic" id="showMore">Show tables</p>
<div class="wrapper" id="wrapper">
<div class="tables-wrapper" id="tables-wrapper"></div>
</div>
JS:
fetch('tables.json')
.then(response => response.json())
.then(json => {
const myJson = json;
let showTables = document.getElementById('showMore');
//show elements on page
function loadGoods(data) {
let out = '';
for (let key in data) {
if (data[key].isAvailable == false) {
out += '<div class="single-table not-available" data-name="' + data[key]['name'] + '" data-art="' + data[key]['id'] + '">';
out += '<h4>' + data[key]['name'] + '</h4>';
out += '<p>' + data[key]['location'] + '</p>';
out += '</div>';
} else {
out += '<div class="single-table" data-name="' + data[key]['name'] + '" data-art="' + data[key]['id'] + '">';
out += '<h4>' + data[key]['name'] + '</h4>';
out += '<p>' + data[key]['location'] + '</p>';
out += '</div>';
}
}
$('#tables-wrapper').html(out);
}
//set Date (day/time)
function setDate() {
for (let key in myJson) {
myJson[key]['date']['day'] = '10/02';
myJson[key]['date']['time'] = '20:00';
}
console.log(myJson);
}
showTables.addEventListener('click', function () {
loadGoods(myJson);
let singleTable = document.getElementsByClassName('single-table');
Array.from(singleTable).forEach(function (element) {
element.addEventListener('click', setDate);
});
});
})
JSON:
[
{
"id": 0,
"index": 0,
"name": "Table 1",
"capacity": 5,
"isAvailable": true,
"location": "Bar",
"date": {
"day": " ",
"time": ""
}
},
{
"id": 1,
"index": 1,
"name": "Table 2",
"capacity": 5,
"isAvailable": true,
"location": "Patio",
"date": {
"day": " ",
"time": " "
}
},
{
"id": 2,
"index": 2,
"name": "Table 3",
"capacity": 5,
"isAvailable": true,
"location": "Bar",
"date": {
"day": " ",
"time": " "
}
},
{
"id": 3,
"name": "Table 4",
"capacity": 6,
"isAvailable": true,
"location": "Inside",
"date": {
"day": " ",
"time": " "
}
}
]
I found a solution. This might be helpful for someone with a similar question.
function setDate() {
let inputDay = document.getElementById('form-data').value;
let inputTime = document.getElementById('form-time').value;
for (let i = 0; i < myJson.length; i++) {
if (this.getAttribute('data-art') == myJson[i].id) {
myJson[i]['date']['day'] = inputDay;
myJson[i]['date']['time'] = inputTime;
}
}
}
Just use the index from the iteration on table creation as id (or any attr you like) for example (you will probably need a classic for or a foreach) and then, in the event you attached pass the click event as param. Finally you just use the event.target to get the id (or the attr you choose) of the element and use it in the setDate func.
First time being exposed to JSON so please explain like I'm 5 without the jargon.
I have been given a JSON file like this and need to display these items in a list in HTML.
A lot of examples have the JSON object assigned to a variable- this isn't assigned to a variable so I'm unsure how to reference it.
How can I access and display everything in product list.
In my html I have linked to a script.js file and also this json file.
HTML
<h1>My Cart</h1>
<div id="cart">
<h2>Cart Items</h2>
<ul id="cartItemsList">
</ul>
</div>
JSON
"basket": {
"productList": [{
"product": {
"id": "111",
"name": "Dog",
"shortDescription": "<p>Mans best friend</p>",
},
"category": "Canine",
"availability": "In Stock",
"variationType": {
"name": "Breed",
"value": "Collie"
}
},
"quantity": 1,
"price": "$53.00"
}, {
"product": {
"id": "112",
"name": "Dog",
"shortDescription": "<p>Not so best friend</p>",
"category": "feline",
"availability": "Low In Stock",
"variationType": {
"name": "breed",
"value": "Maine Coon"
}
},
"quantity": 1,
"price": "$49.00"
}, {
"product": {
"id": "113",
"name": "Rabbit",
"shortDescription": "Likes carrots",
"category": "cuniculus",
"availability": "In Stock"
},
"quantity": 1,
"price": "$66.00"
}]
}
JavaScript
var products = document.getElementById("cartItemsList");
cartItemsList.innerHTML = "<li>" + product + "</li>";
If you are loading this from an external file, you will need Ajax or a similar type of call. To use Ajax, you'll have to add a library called jQuery to your project's HTML file. Then you can call your JSON without referencing it as a javascript variable as you see in the following working code snippet.
/* I put your JSON into an external file, loaded from github */
var url = "https://raw.githubusercontent.com/mspanish/playground/master/jessica.json";
/* this tells the page to wait until jQuery has loaded, so you can use the Ajax call */
$(document).ready(function(){
$.ajax({
url: url,
dataType: 'json',
error: function(){
console.log('JSON FAILED for data');
},
success:function(results){
/* the results is your json, you can reference the elements directly by using it here, without creating any additional variables */
var cartItemsList = document.getElementById("cartItemsList");
results.basket.productList.forEach(function(element) {
cartItemsList.insertAdjacentHTML( 'beforeend',"<li>" + element.product.name + " : " + element.price+ " </li>");
}); // end of forEach
} // end of success fn
}) // end of Ajax call
}) // end of $(document).ready() function
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>My Cart</h1>
<div id="cart">
<h2>Cart Items</h2>
<ul id="cartItemsList">
</ul>
</div>
if you want to parse an object:
function logTheObj(obj) {
var ret = "";
for (var o in obj) {
var data = obj[o];
if (typeof data !== 'object') {
ret += "<li>" + o + " : " + data + "</li>";
} else {
ret += "<li>" + o + " : " + logTheObj(data) + "</li>";
}
}
return "<ul>" + ret + "</ul>";
}
If your object is in a string:
logTheObj(JSON.parse(jsonString));
JavaScript version using external json file from previous answer by Stacey Reiman
const products = document.getElementById("cartItemsList");
/* get basket items from JSON */
class Basket {
async cartItems() {
try {
let result = await fetch('https://raw.githubusercontent.com/mspanish/playground/master/jessica.json')
let data = await result.json()
// return data
/* destructuring data */
let basketItems = data.basket.productList
basketItems = basketItems.map(item =>{
const price = item.price
const{id,name,shortDescription,category,availability} = item.product
const breed = item.product.variationType
const quantity = item.quantity
return {price,id,name,shortDescription,category,availability,quantity,breed}
})
return basketItems
} catch (error) {
console.log(error)
}
}
}
/* Display stuff from the basket */
class Display {
displayBasket(basket) {
//console.log(basket)
let result = ""
basket.forEach((item)=>{
result += `
<li>
id : ${item.id}
name: ${item.name}
price: ${item.price}
availability: ${item.availability}
category : ${item.category}
quantity : ${item.quantity}
shortDescription : ${item.shortDescription}
</li>
`})
cartItemsList.innerHTML = result
}
}
document.addEventListener("DOMContentLoaded", ()=>{
const basket = new Basket()
const display = new Display()
basket.cartItems().then(basket => display.displayBasket(basket))
})
<h1>My Cart</h1>
<div id="cart">
<h2>Cart Items</h2>
<ul id="cartItemsList">
</ul>
</div>
First, you have to convert the json from long string to acutely js object.
you doing so by the JSON.parse command. like so:
let jsObj = JSON.parse( youreJsonString);
Them, you can loop throw youre products in your productList and build your html code, like so:
var products = document.getElementById("cartItemsList");
jsObj.basket.productList.forEach( function(product ) {
cartItemsList.innerHTML = "<li>" + product.name + " : " + product.price+ " </li>";
});
Unless you use an Ajax call or something similar to load external JSON, you need to convert the JSON you've provided into an object that you can reference as a variable. Also, your JSON is not valid. I tried correcting it here, and am going to reference your JSON as an object you can reference via a variable named obj. Here is a working code snippet.
var obj = {
"basket": {
"productList": [{
"product": {
"id": "111",
"name": "Dog",
"shortDescription": "<p>Mans best friend</p>",
"category": "Canine",
"availability": "In Stock",
"variationType": {
"name": "Breed",
"value": "Collie"
}
},
"quantity": 1,
"price": "$53.00"
}, {
"product": {
"id": "112",
"name": "Dog",
"shortDescription": "<p>Not so best friend</p>",
"category": "feline",
"availability": "Low In Stock",
"variationType": {
"name": "breed",
"value": "Maine Coon"
}
},
"quantity": 1,
"price": "$49.00"
}, {
"product": {
"id": "113",
"name": "Rabbit",
"shortDescription": "Likes carrots",
"category": "cuniculus",
"availability": "In Stock"
},
"quantity": 1,
"price": "$66.00"
}]
}
}
var cartItemsList = document.getElementById("cartItemsList");
obj.basket.productList.forEach(function(element) {
cartItemsList.insertAdjacentHTML( 'beforeend',"<li>" + element.product.name + " : " + element.price+ " </li>");
});
<h1>My Cart</h1>
<div id="cart">
<h2>Cart Items</h2>
<ul id="cartItemsList">
</ul>
</div>
I'm making a bot that answers questions given some key words. It's a very easy code developed by Deni Spasovski. However, my website is in Spanish, and I need to be able to use accent marks & ñ as part of the key words. For example:
{ "keys": ["cómo", "estás"], "value": 0 }
However, despite my efforts, I can't seem to fix the code. I don't know that much about coding. Maybe it's a very easy thing I have to implement to one of the scripts but I really do not know what it is.
I would be more than grateful if you could help me.
Thank you very, very much in advance!!
This is the HTML:
<!DOCTYPE html>
<html>
<head>
<!--Read the source Luke!-->
<title>Answer bot</title>
<style type="text/css">
body, html
{
height: 100%;
}
.wrap
{
height: 80%;
overflow: auto;
max-height: 80%;
display: block;
}
.content
{
height: 100%;
display: table;
vertical-align: bottom;
}
.subcontent
{
display: table-cell;
vertical-align: bottom;
}
.answerbot-input
{
color: #1AA1E1;
}
.answerbot-ai
{
color: #CE5043;
}
</style>
</head>
<body>
<div style="width: 800px; height: 100%; margin: 0 auto;">
<div id="wrap" class="wrap">
<div class="content">
<div class="subcontent" id='subcontent'>
<p class='answerbot-ai'>
Don't be afraid, talk to me.
</p>
</div>
</div>
</div>
<div>
<input type="text" name="inputtext" style="width: 100%;" onkeyup="keypressInput(this, event);"><br />
</div>
</div>
<script type="text/javascript" src="scripts.js"></script>
<script type="text/javascript" src="data.js"></script>
<script type="text/javascript">
var _answerBot = new answerBot();
function keypressInput(sender, event) {
if (event.which == 13) {
document.getElementById('subcontent').innerHTML += _answerBot.processInput(sender.value);
sender.value = '';
correctScroll("wrap");
}
}
function correctScroll(elementId) {
var objDiv = document.getElementById(elementId);
objDiv.scrollTop = objDiv.scrollHeight;
}
</script>
</body>
</html>
This is the data.js:
if (answerBot) {
answerBot.prototype.specialContext = {
"wrongInput": ["I don't understand you.", "Could you rephrase the question?"],
"emptyInput": ["Please say something", "Speak louder", "Well i can't read minds."],
"rephrase": ["Can you tell me if your question was about one of the following things:"]
};
answerBot.prototype.keywords = [
{ "keys": ["hi"], "value": 0 },
{ "keys": ["hello"], "value": 0 },
{ "keys": ["life", "universe", "everything"], "value": 1 },
{ "keys": ["software", "development"], "value": 2 },
{ "keys": ["software", "engineering"], "value": 2 },
{ "keys": ["who", "made", "you"], "value": 3 },
{ "keys": ["who", "wrote", "you"], "value": 3 },
{ "keys": ["who", "coded", "you"], "value": 3 },
{ "keys": ["is", "this", "real", "life"], "value": 4 },
{ "keys": ["who", "is", "deni"], "value": 5 },
{ "keys": ["tell", "me", "about", "deni"], "value": 5 },
{ "keys": ["tell", "me", "about", "author"], "value": 5 },
{ "keys": ["show", "me", "author"], "value": 5 },
{ "keys": ["can", "see", "source"], "value": 6 },
{ "keys": ["can", "see", "sourcecode"], "value": 6 },
{ "keys": ["show", "me", "code"], "value": 6 },
{ "keys": ["how", "are", "you"], "value": 7 },
{ "keys": ["who", "is", "this"], "value": 8 }];
answerBot.prototype.answers = [
{
"description": "Hi!",
"values": ["Hello there!", "Hi how can I help you today", "Hi! What brings you here?"]
},
{
"description": "What is the answer to life the universe and everything?",
"values": ["42"]
},
{
"description": "What is software development?",
"values": ["Programming! Do you speak it?"]
},
{
"description": "Who created me?",
"values": ["I was created by another <a href='http://about.me/deni' target='_blank'>bot</a>.", "The question is who sent you here?"]
},
{
"description": "Is this real life?",
"values": ["No this is the internetz!", "Find out <a href='http://www.youtube.com/watch?v=txqiwrbYGrs' target='_blank'>yourself</a>!"]
},
{
"description": "Who is Deni?",
"values": ["This is his <a href='https://plus.google.com/+DeniSpasovski/' target='_blank'>G+ profile</a>.", "This is his <a href='www.linkedin.com/in/denispasovski' target='_blank'>Linkedin profile</a>."]
},
{
"description": "Where is your source?",
"values": ["Here is the <a href='https://github.com/denimf/Answer-bot' target='_blank'>source</a>."]
},
{
"description": "How are you?",
"values": ["I'm good how are you?"]
},
{
"description": "Who is this?",
"values": ["StackOverflow Exception occurred", "The question is who are you?"]
}
];
}
And this is the scripts.js:
var answerBot = function () {
var _this = this;
_this.processInput = function (text) {
updateUrl(text);
var _result = "<p class='answerbot-input'>" + text + "</p>";
text = text.replace(new RegExp("[^a-zA-Z ]", "g"), " ");
text = text.replace(new RegExp("[ ]{2,}", "g"), " ");
var _words = text.toLowerCase().split(" ");
var _answers = [];
var _title = "";
if (_words.length === 0 || _words.toString() === '') { //if the input is empty
_answers = _this.specialContext.emptyInput;
_title = _this.specialContext.emptyInput;
} else {
var _possibleAnswers = findMatches(_words);
if (_possibleAnswers.length === 0) { //if no answer found
_answers = _this.specialContext.wrongInput;
_title = _this.specialContext.wrongInput;
}
if (_possibleAnswers.length == 1) { //context recognized
_answers = _this.answers[_possibleAnswers[0]].values;
_title = _this.answers[_possibleAnswers[0]].description;
}
if (_possibleAnswers.length > 1) {
_result += formatText(_this.specialContext.rephrase, _this.specialContext.rephrase);
for (var i = 0; i < _possibleAnswers.length; i++) {
_result += formatText(_this.answers[_possibleAnswers[i]].description, _this.answers[_possibleAnswers[i]].description);
}
}
}
if (_answers.length > 0) {
var _rand = Math.floor((Math.random() - 0.001) * _answers.length);
_result += formatText(_answers[_rand], _title);
}
return _result;
};
function formatText(text, title) {
return "<p class=\'answerbot-ai\' title=\'" + title + "\'>" + text + "</p>";
}
function findMatches(words) {
var foundKeywords = [];
var _possibleAnswers = [];
for (var i = 0; i < _this.keywords.length; i++) {
foundKeywords[i] = 0;
for (var j = 0; j < words.length; j++) {
if (_this.keywords[i].keys.indexOf(words[j]) >= 0) {
foundKeywords[i]++;
if (foundKeywords[i] == _this.keywords[i].keys.length) {
return [_this.keywords[i].value];
}
}
}
if (foundKeywords[i] * 2 > _this.keywords[i].keys.length) {
_possibleAnswers.push(_this.keywords[i].value);
}
}
return _possibleAnswers.filter(function (elem, pos) {
return _possibleAnswers.indexOf(elem) == pos;
});
}
function updateUrl(text){
history.pushState(null, null, "#question=" + encodeURIComponent(text));
if(typeof ga === "function")//google analytics
ga('send', 'event', 'question', text);
}
};
Three possible issues:
1) This line:
text = text.replace(new RegExp("[^a-zA-Z ]", "g"), " ");
will replace anything that isn't in the "normal" alphabet with a space. You might choose to replace it at some point to include characters with diacritics, but to get it working you can simply comment it out.
2) Make sure your files (in particular, data.js) are saved with UTF-8 encoding.
3) Ensure you have an appropriate value in the answers array and then use its index in keywords.value. e.g.
{
"description": "cómo estás?",
"values": ["muy bien"]
}
I have data.json in this format:
{
"Users": [
{
"userName": "Herbie",
"weigh-in data": [
{ "date": "2016.01.04", "weight": "114.3" },
{ "date": "2016.01.05", "weight": "114.6" },
{ "date": "2016.01.06", "weight": "114.9" }
]
},
{
"userName": "Wayne",
"weigh-in data": [
{ "date": "2016.02.01", "weight": "120.3" },
{ "date": "2016.02.05", "weight": "123.6" },
{ "date": "2016.02.06", "weight": "123.9" }
]
}
]
}
// etc., more user objects
In my application: a selection of a user is made, an ajax call gets this data, I loop thru it to get only the selected user's weigh-in data, and I'm successfully rendering this data to a table.
Now I'm trying to use the same result in a Dimple chart but Dimple evidently doesn't like my chartData array:
var dataObj = JSON.parse(jsonData);
var usersArray = dataObj.Users;
var chartData = [];
// etc. SNIP
for (var obj of usersArray) {
if (obj.userName === selUser) { // weigh-ins of the selected user only
dataRows.innerHTML = "";
for (var i = 0, j = selUserData.length; i < j; i++) {
var dataDate = selUserData[i].date;
var dataWeight = selUserData[i].weight;
chartData.push('{ "User"' + ': ' + '"'+selUser+'", ' + '"Date":' + ' ' + '"'+dataDate+'", ' + '"Weight":' + ' ' + '"'+dataWeight+'" }');
// SNIP: build rows from the data, load up the table, no problem
dataRows.innerHTML += row;
} // selUserData loop
var svg = dimple.newSvg("#chartContainer", 800, 600);
var chart = new dimple.chart(svg, chartData);
chart.setBounds(60, 30, 505, 305);
var x = chart.addCategoryAxis("x", "Date");
x.addOrderRule("Dates");
var y = chart.addCategoryAxis("y", "Weight");
y.addOrderRule("Weights");
var s = chart.addSeries("weigh-ins", dimple.plot.line);
chart.draw();
... which results in a non-chart. However, if I console.log or alert(chartData) and set the result as chartData, i.e.:
var chartData = [
{ "User": "Wayne", "Date": "2016.02.01", "Weight": "180.3" },
{ "User": "Wayne", "Date": "2016.02.05", "Weight": "123.6" },
{ "User": "Wayne", "Date": "2016.02.06", "Weight": "153.9" }
]
... then I get a chart, ergo my confusion.
Any insight greatly appreciated,
Whiskey
You're pushing the JSON into your array as strings not objects, it should be:
chartData.push({ "User": selUser, "Date": dataDate, "Weight": dataWeight });
Which has the added benefit of being much easier to read!
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>