jQuery on click function or random quote machine and JSON API - javascript

For the first time using JSON API. Please tell me where and what I'm doing wrong. This is a challenge from freeCodeCamp. We need to do build a random quote machine.
Once I click on New Quote button is should give us a random quote. In jQuery I'm looping through json and on click function has to change me current h2 class = text with the new random quote from JSON.
Project is here http://codepen.io/ekilja01/full/Lbdbpd/.
Please help.
Here is my HTML:
<div class="container-fluid">
<div class = "well">
<div class="row">
<h2 class="text text-center"><i class="fa fa-quote-left"> </i> Hey, what when and why there is no and yes?</h2>
<p class="author">-Alina Khachatrian</p>
<div class="buttons">
<div class="row">
<div class="col-xs-6">
<a id="tweet-quote" title="Tweet current quote" target="_blank" href="#">
<i class="fa fa-twitter fa-2x"></i>
</a>
</div>
<div class="col-xs-6">
<button type="button" class="btn btn-default btn-transparent" id ="getNewQuote" title="Get a new quote">New Quote</button>
</div>
</div>
<footer class="text-center">
<hr>
<p>Written and coded by Edgar Kiljak.</p>
</footer>
</div>
</div>
and JS:
$(document).ready(function(){
$(".btn").on("click", function(){
$.getJSON("http://quotes.rest/qod.json", function (json) {
var html = "";
json.forEach(function(val){
var keys = Object.keys(val);
html += "<div class = 'newQuote>'";
"<h2 = '" + val.quote + "'>";
html += "</h2>";
html += "</div>";
})
$(".text").html(html);
});
});
});
and JSON:
{
"success": {
"total": 1
},
"contents": {
"quotes": [
{
"quote": "Great things are done by a series of small things brought together.",
"length": "67",
"author": "Vincent Van Gogh",
"tags": [
"inspire",
"small-things",
"tso-art"
],
"category": "inspire",
"date": "2016-12-10",
"title": "Inspiring Quote of the day",
"background": "https://theysaidso.com/img/bgs/man_on_the_mountain.jpg",
"id": "DLThmumKP4CCe1833rRvNQeF"
}
]
}
}

your problem is here: json.forEach(function(val)...
since the JSON is not an array, it should be: json.contents.quotes.forEach(function(val)
json.contents.quotes is an array ([brackets] instead of {}) and forEach is only for arrays

Please post the error you are getting.
Also in your .js file, you are doing :
"<h2 = '" + val.quote + "'>";
which should be
"<h2>'" + val.quote + "'</h2>";
Another advice would be to put the code where you are handling the response in .done(). This method as far as I know, is available with the $.get() method.
From the jQuery Docs,
$.get( "test.cgi", { name: "John", time: "2pm" } )
.done(function( data ) {
alert( "Data Loaded: " + data );
});

Related

How do I loop through arrays within arrays?

I am trying to dynamically create a series of bootstrap cards with returned AJAX data. The AJAX request brings back 12 arrays (see screenshot) but when I try to loop through them and put them on cards only 1 array gets put on all twelve cards (See screenshot)
I'm not sure what I am doing wrong with my loop but hoping someone can help out.
Here is the JS code (sorry about the super long line for the card creation - any advice on how to shorten that would be appreciated).
Below is a reproducible example (the actual data variable is filled by the AJAX call in my code), and here is the JSFiddle:
data = [["The Old Milk Bar", " 144 Dundas Street, Thornbury", "Lorem Ipsum"], ["Little Henri", " 848 High Street, Thornbury", 'Lorem Ipsum'], ["Northern Soul", " 843 High Street, Thornbury", "Lorem Ipsum"]]
window.addEventListener('load', (event) => {
console.log('page is fully loaded');
test(data)
});
const test = function(data) {
console.log(data)
for (i = 0; i < data.length; i++) {
var results = JSON.stringify(data).split('"');
var cafeName = results[1].replace(/[^a-zA-Z0-9éè ]/g, "");
console.log(cafeName)
var cafeAddress = results[3].replace(/[^a-zA-Z0-9éè ]/g, "") + "," + results[2].replace(/[^a-zA-Z0-9éè ]/g, "");
console.log(cafeAddress)
var cafeDescription = results[5];
console.log(cafeDescription)
$(".venue-name").html(cafeName);
$(".venue-address").html(cafeAddress);
$(".venue-description").html(cafeDescription);
$(".share").html('<i class="fas fa-share-alt"></i>');
$(".venue-options").html('<i class="fas fa-ellipsis-h"></i>');
var myCol = $('<div id="col"></div>');
var myPanel = $(
'<div class="card-group"><div class="card card-block m-3 overflow-auto" style="width: 18rem;"><div class="card-body"><h5 class="card-title venue-name"></h5><h6 class="card-subtitle mb-2 text-muted venue-address"></h6><div class="dropdown"><div class="venue-options" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></div><div class="dropdown-menu" aria-labelledby="dropdownMenuButton"><a id="share" class="dropdown-item" href="#">Share</a><a id="addToList" class="dropdown-item" href="#">Add to List</a></div></div><div class="venue-description"></div></div></div></div>'
);
myPanel.appendTo(myCol);
myCol.appendTo('#cardList');
};
}
You don't need to call JSON.stringify() and split(). You already have an array, you can access its elements directly.
When you do $(".venue-name").html(cafeName) you're setting the HTML of all elements with that class, not the card you're creating. In fact, it sets every one except the new one, because you don't add that until after those lines.
Instead, create myPanel first, and then set the HTML of the elements within that DIV. You can do this with myPanel.find(".className") or equivalently $(".className", myPanel).
data = [
["The Old Milk Bar", " 144 Dundas Street, Thornbury", "Lorem Ipsum"],
["Little Henri", " 848 High Street, Thornbury", 'Lorem Ipsum'],
["Northern Soul", " 843 High Street, Thornbury", "Lorem Ipsum"]
]
window.addEventListener('load', (event) => {
console.log('page is fully loaded');
test(data)
});
const test = function(data) {
console.log(data)
data.forEach(([cafeName, cafeAddress, cafeDescription]) => {
var myCol = $('<div id="col"></div>');
var myPanel = $(
`
<div class="card-group">
<div class="card card-block m-3 overflow-auto" style="width: 18rem;">
<div class="card-body">
<h5 class="card-title venue-name"></h5>
<h6 class="card-subtitle mb-2 text-muted venue-address"></h6>
<div class="dropdown">
<div class="venue-options" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></div>
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton"><a id="share" class="dropdown-item" href="#">Share</a><a id="addToList" class="dropdown-item" href="#">Add to List</a></div>
</div>
<div class="venue-description"></div>
</div>
</div>
</div>`
);
$(".venue-name", myPanel).html(cafeName);
$(".venue-address", myPanel).html(cafeAddress);
$(".venue-description", myPanel).html(cafeDescription);
$(".share", myPanel).html('<i class="fas fa-share-alt"></i>', myPanel);
$(".venue-options", myPanel).html('<i class="fas fa-ellipsis-h"></i>');
myPanel.appendTo(myCol);
myCol.appendTo('#cardList');
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="cardList"></div>

JQUERY/AJAX-multiply classes based on content number

I'm trying to extract specific data and send them to the client side so in order to achieve that I used AJAX like below :
<script type ="text/Javascript">
$(document).ready(() => {
$.ajax({
type: 'GET',
dataType : 'json',
url: '/envoi/events/',
})
.done(function(data) {
for(let i =0; i< data.length;i++) {
console.log(data[i].events.eventName);
$("#event1").html(`<b>${data[i].events.eventName}</b>`) // event1 is the id of field name
$("#time1").html(`<b>${data[i].events.eventDate} - ${data[i].events.targetReminder} |
${data[i].events.targetAmPM} </b>`)// time1is the id of field time and date
$("#comment1").html(`<b>${data[i].events.caption}</b>`) // comment1 is the id of field description
$("#location1").html(`<b>${data[i].events.location}</b>`) // location1 is the id of field location
}
})
.fail(function(xhr, status, error) {
console.log(error);
})
.always(function(data){
});
})
</script>
and this is the output
this script works perfectly and fill one container with the requested values but what I'm looking for is to fill every container and multiply them based on data found from my db
which mean :
1- if there is more than one data data[i].events.eventName or other another container must be created and get filled by the new value
the HTML code is below :
<div class="card">
<div class="card-header" id="headingOne-1">
<script type ="text/Javascript">
$(document).ready(() => {
$.ajax({
type: 'GET',
dataType : 'json',
url: '/envoi/events/',
})
.done(function(data) {
for(let i =0; i< data.length;i++) {
console.log(data[i].events.eventName);
$("#event1").html(`<b>${data[i].events.eventName}</b>`)
$("#time1").html(`<b>${data[i].events.eventDate} - ${data[i].events.targetReminder} | ${data[i].events.targetAmPM} </b>`)
$("#comment1").html(`<b>${data[i].events.caption}</b>`)
$("#location1").html(`<b>${data[i].events.location}</b>`)
}
})
.fail(function(xhr, status, error) {
console.log(error);
})
.always(function(data){
});
})
</script>
<div class="event-time">
<time id="time1" datetime="2004-07-24T18:18">9:00am</time>
<div class="more"><svg class="olymp-three-dots-icon"><use xlink:href="svg-icons/sprites/icons.svg#olymp-three-dots-icon"></use></svg>
<ul class="more-dropdown">
<li>
Mark as Completed
</li>
<li>
Delete Event
</li>
</ul>
</div>
</div>
<h5 class="mb-0 title">
<a href="#" data-toggle="collapse" data-target="#collapseOne-1" aria-expanded="true" aria-controls="collapseOne" id = "event1">
Breakfast at the Agency
<i class="fa fa-angle-down" aria-hidden="true"></i>
<span class="event-status-icon" data-toggle="modal" data-target="#public-event">
<svg class="olymp-calendar-icon" data-toggle="tooltip" data-placement="top" data-original-title="UNCOMPLETED"><use xlink:href="svg-icons/sprites/icons.svg#olymp-calendar-icon"></use></svg>
</span>
</a>
</h5>
</div>
<div id="#collapseOne-1" class="collapse show" aria-labelledby="headingOne" data-parent="#headingOne-1">
<div class="card-body" id ="comment1">
Hi Guys! I propose to go a litle earlier at the agency to have breakfast and talk a little more about the new design project we have been working on. Cheers!
</div>
<div class="place inline-items">
<svg class="olymp-add-a-place-icon"><use xlink:href="svg-icons/sprites/icons.svg#olymp-add-a-place-icon"></use></svg>
<span id ="location1">Daydreamz Agency</span>
</div>
</div>
</div>
Any idea how to multiply that box based on data found with the script mentioned above ?
Hope I mentioned everything :-D ?
Best Regards,
Every time your loop works, $("#event1").html(....), $("#-----").html(....) will be replaced with your new values. So why don't you rather create a variable name html outside a loop and every div section or html tags that needs to be rendered in DOM, inside the loop and append after the div you want to render. Like mentioned on above answer,
var html="";
for(let i =0; i< data.length;i++){
html += `<div class="card-header"> ${data[i].event.eventName} </div>` +
`<div class=" -----"> $${data[i].event.eventDate} ` +
------------------and so on---------------------------;
}
$("#NAME OF ID BEHIND YOU WANT TO SHOW YOUR NEW DIV").append(html);
Hope it will work :)
I believe you should just create the whole HTML in javascript then append that HTML to DOM. for example.
let html = "";
for(let i =0; i< data.length;i++) {
html += "<p>"+ data[i].events.eventName + "</p>";
html += "<p>"+ data[i].events.eventDate + "</p>";
}
$("#ParentDivIDWhereToAppendThisContent").html(html);
The above code is just an example of how you can do it. You need to customize it to suit your needs.

How to dynamically add items and attributes to HTML with javascript or jQuery referencing items from a csv or json file

I am trying to make the following bit of code easier to maintain. I am not a web developer so bear with me. I think the following approach is appropriate.
I would like to dynamically add content and attributes to an html file using either javascript or jQuery. The items could reside in a .csv or .json (or something else?) file.
Given content like this
<div class="filtr-container">
<div class="col-12 col-sm-6 col-md-4 card filtr-item" data-category="cat-1" data-date="2018-02-09">
<div class="card-inner-border box-shadow">
<a href="address-1.html">
<img class="card-img-top rounded-top" src="./images/image-1.jpg" alt="img-2-alt">
</a>
<div class="card-body">
<h5 class="card-title">Title-1</h5>
<p class="card-text card-desc">
This is a description for title-1 content.
</p>
<a href="address-1.html">
<button type="button" class="btn btn-sm btn-outline-secondary">View</button>
</a>
<p class="card-text">
<small class="text-muted">Last updated February 2, 2018</small>
</p>
</div>
</div>
</div>
<div class="col-12 col-sm-6 col-md-4 card filtr-item" data-category="cat-2, cat-3" data-date="2018-02-14">
<div class="card-inner-border box-shadow">
<a href="address-2.html">
<img class="card-img-top rounded-top" src="./images/image-2.jpg" alt="img-2-alt">
</a>
<div class="card-body">
<h5 class="card-title">Title-2</h5>
<p class="card-text card-desc">
Here is a long description for title-2 content.
</p>
<a href="address-2.html">
<button type="button" class="btn btn-sm btn-outline-secondary">View</button>
</a>
<p class="card-text">
<small class="text-muted">Last updated February 14, 2018</small>
</p>
</div>
</div>
</div>
<!-- MANY MORE CARDS / ITEMS ... -->
</div> <!-- End of filtr-container -->
I think we could abstract the details into something like this (.csv)
item-id,title,description,categories,address,image,image-alt,update
1,Title-1,This is a description for title-1 content.,cat-1,address-1.html,image-1.jpg,img-1-alt,2018-02-09
2,Title-2,Here is a long description for title-2 content.,"cat-2, cat-2",address-2.html,image-2.jpg,img-2-alt,2018-02-14
What's a nice approach of attack for using `javascript` or `jQuery` to add this content from the `.csv` or `.json` file?
A few concerns:
The headers of the .csv will not match verbatim (e.g. <p class="card-desc"> aligns with the .csv header of description)
There could be embedded comma-separated items (e.g. item 2 has categories cat-2, cat-3 so it gets quotes " in the .csv -- maybe .json would better (?) or perhaps its a non-issue)
If possible can we reuse the date item for both data-date= and the final piece of text <small class="text-muted"> which converts the date into Last updated month-name-long, dd, yyyy instead of yyyy-mm-dd.
Some attributes are partial references (e.g. the src for an image is just the final part of the path; stated as image-1.jpg in the .csv not ./images/image-jpg).
To hopefully help make this feel less complicated, here's a picture with the highlighted elements that could be "referenced" from the .csv file.
To me this feels like:
Read in the .csv file.
For each item in the .csv file, append objects to $(".filtr-container") with the shell layout...
But I'm lost when it comes to the particulars or if that's an appropriate approach.
You seem to be searching for template parsing. You can find many libraries that will ease this burden. In its simplest form, template parses carry out the steps in the following code. If you don't need the flexibility, power, features, etc. from a template parser library or full framework, you should consider not including the thousands of lines of code if all you want to accomplish is what is shown below.
Since you mentioned both JSON and CSV I've included the code to parse both. I'll leave the AJAX and date formatting magic to you. I don't think I populate the ID either, but this shows that more data than template attributes will work fine.
let template = document.getElementById('card-template').innerHTML;
let container = document.querySelector('.filtr-container');
// Do some ajax magic to get csv file
let csv = `item-id,title,description,categories,address,image,image-alt,update
1,Title-1,This is a description for title-1 content.,cat-1,address-1.html,https://via.placeholder.com/75,img-1-alt,2018-02-09
2,Title-2,Here is a long description for title-2 content.,cat-2 cat-2,address-2.html,https://via.placeholder.com/75,img-2-alt,2018-02-14`;
let csvLines = csv.split("\n");
let csvHeaders = csvLines.shift().split(',');
csvLines.forEach(line => {
let parsed = template;
let props = line.split(',');
props.forEach((prop, idx) => {
parsed = parsed.replace('{{' + csvHeaders[idx] + '}}', props[idx]);
});
container.innerHTML = container.innerHTML + parsed;
});
let json = `[{
"item-id": "1",
"title": "Title-1",
"description": "This is a description for title-1 content.",
"categories": "cat-1",
"address": "address-1.html",
"image": "https://via.placeholder.com/75",
"image-alt": "img-1-alt",
"update": "2018-02-09"
}, {
"item-id": "2",
"title": "Title-2",
"description": "Here is a long description for title-2 content.",
"categories": "cat-2 cat-2",
"address": "address-2.html",
"image": "https://via.placeholder.com/75",
"image-alt": "img-2-alt",
"update": "2018-02-14"
}]`;
let data = JSON.parse(json);
data.forEach(col => {
let jParsed = template;
for (prop in col) {
jParsed = jParsed.replace('{{' + prop + '}}', col[prop]);
}
container.innerHTML = container.innerHTML + jParsed;
});
<div class="filtr-container">
<script type="template" id="card-template">
<div class="col-12 col-sm-6 col-md-4 card filtr-item" data-category="{{categories}}" data-date="{{date}}">
<div class="card-inner-border box-shadow">
<a href="{{address}}">
<img class="card-img-top rounded-top" src="{{image}}" alt="{{image-alt}}">
</a>
<div class="card-body">
<h5 class="card-title">{{title}}</h5>
<p class="card-text card-desc">
{{description}}
</p>
<a href="{{address}}">
<button type="button" class="btn btn-sm btn-outline-secondary">View</button>
</a>
<p class="card-text">
<small class="text-muted">Last updated {{update}}</small>
</p>
</div>
</div>
</div>
</script>
This post might help you parse your CSV document. If your data lives in a JSON, you can use JSON.parse
Once you properly retrieved and parsed your data, it's a matter or rendering it to the DOM.
You can do it using the standard javascript library, JQuery or frameworks such as React or VueJS

Jquery convert dynamic form data to json

I am working with my project that will create quizzes that form. I want it to be submitted into json format, which will be look like this:
[
{
"questions": [
{
"question": "Who is Mark Zuckerberg?",
"options": [
{
"answer": "Facebook CEO",
"correct": 1
},
{
"answer": "Google Programmer",
"correct": 0
}
]
},
{
"question": "Who is the founder of Apple?",
"options": [
{
"answer": "Mark Zuckerberg",
"correct": 0
},
{
"answer": "Bill Gates",
"correct": 0
},
{
"answer": "Steve Jobs",
"correct": 1
}
]
}
]
}
]
I have my form that allows the user to add & delete questions and options. User can also select the correct answer in the list of options.
Here is the JSFiddle link.
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="row">
<button id="btn-add-tab" type="button" class="btn btn-primary pull-right">Add Question</button>
</div>
<div class="row">
<form id="form">
<!-- Nav tabs -->
<ul id="tab-list" class="nav nav-tabs" role="tablist">
<li class="active">Question 1</li>
</ul>
<!-- Tab panes -->
<div id="tab-content" class="tab-content">
<br>
<div class="tab-pane fade in active" id="tab1">
<div class="input-group">
<input type="text" class="form-control" id="question" placeholder="Your question" required>
<span class="input-group-btn">
<button class="btn btn-success" id="add-option" type="button">Add Option</button>
</span>
</div>
<br>
<div id="options">
<!--- OPTIONS -->
<div class="well">
<textarea id="answer" class="form-control" placeholder="Your answer" required></textarea>
<div class="radio"><label><input type="radio" id="correct-answer" name="correct-ans-1" required>Correct Answer</label></div>
</div>
<!--- END OPTIONS -->
</div>
</div>
</div>
</div>
<div class="row">
<button id="btn-get-json" type="submit" class="btn btn-success pull-right btn-block">Get JSON</button>
</div>
</form>
</div>
</div>
</div>
With myjavascript code, I am experiencing an error which only shows json from the first question. Also, it doesn't display the list of options. In my code I used each to get all input fields in the form. Then I used JSON.stringify(); to convert array to JSON.
$("#form").submit(function(e) {
var jsonArr = [];
var obj = {};
var questionsArr = [];
var questionsCont = {};
var tabs = $("#form :input:not(input[type='submit'],button[type='button'])");
$(tabs).each(function(k,v){
var id = $(this).attr("id");
var value = $(this).val();
questionsCont[id] = value;
});
questionsArr.push(questionsCont);
obj["questions"] = questionsArr;
jsonArr.push(obj);
var json = JSON.stringify(jsonArr, null, "\t");
alert(json);
e.preventDefault();
});
I would like to have a json result that will looked-like from the post above. For testing my code, please see this JSFiddle link.
Any help is appreciated. Thank you!
First, IDs are meant to be unique -- so you cannot have two or more elements with the same ID. When you open a new tab or create a new option, you violate that rule.
Therefore, you should change your IDs to classes and/or names (using []). So, what I did is change input elements to use names and other problem elements to use classes.
How I see of going about is to start by looping through each tab pane. On each pane, find the question and its options, and add them to a data structure that will hold all your data. I am using the $.map to translate each tab into a question.
$("#form").submit(function(e) {
e.preventDefault();
var json = {};
// loop through each tab pane
json.questions = $('.tab-pane').map(function() {
return {
question: $('[name^=question]', this).val(),
// loop through each answer
options: $('[name^=answer]', this).map(function() {
return {
answer: $(this).val(),
correct: $(this).siblings('.radio').find('[name^=correct-ans]').prop('checked')
};
}).get()
};
}).get();
alert(JSON.stringify(json, null, "\t"));
});
Demo

Append inner objects in multi-dimensional array with a loop

I have a multi-dimensional array of comment objects and I figured out how I can loop through the first-level of objects and then append them, but I am having a really hard time figuring out how to bring the replies along with the comments that have replies. My strategy was to use an "if" statement that checks to see if there's a reply, and then loops through the replies like I do the comments, but I think that the closest() function is the issue, I'm not quite sure how to access the DOM element that corresponds to that comment to use it as a selector. I think maybe another strategy would be to process the replies at the same time as the comments with one .each loop. Any help would be greatly appreciated!
var myCommentArray = [
{
_id: "888888888888888888",
index: 1,
name: "Perez",
message: "First Comment .......",
subject: "enim officias",
replies: [ // notice this comment has replies (just 1 but it is still an array)
{
_id: "77777777777777777777",
index: 0,
name: "Reply to First Comment Ines for Perez",
message: "...",
subject: "reply subject consequat"
}
]
},
{
_id: "999999999999",
index: 0,
name: "Shelton",
message: "2nd Comment....a",
subject: "enim irure",
replies: null // notice this comment has no replies and as such is null. this is better than an empty array
},
{
_id: "666666666666666666",
index: 2,
name: "Perez",
message: "3rd Comment.......",
subject: "enim officias",
replies: [
{
_id: "55555555555555555555",
index: 0,
name: "1st Reply to 3rd Comment",
message: "...",
subject: "reply subject consequat"
},
{
_id: "44444444444444444444",
index: 1,
name: "2nd Reply to 3rd Comment",
message: "...",
subject: "reply subject consequat"
}
]
}
];
sabio.page.processComments = function (i, currentComment) {
var commentsFormat = '<br> <div class="comment-avatar media-left"> <img src="http://placehold.it/50x50" alt="avatar">' +
'</div><div class="comment-content media-body clearfix"> <div class="comment-avatar media-left"></div><h3 class="media-heading">' +
currentComment.subject + '</h3> <div class="comment-meta">By ' + currentComment.name + '</div> <div class="comment-body"> <p>'
+ currentComment.message + '</p><a href="#" class="replyButton">' +
'<i class="fa fa-reply"> </i> Reply </a> </div> </div>';
$('.comments').append(commentsFormat);
};
$.each(myCommentArray, sabio.page.processComments);
sabio.page.processReplies = function (j, currentComment) {
var repliesFormat = '<br> <div class="comment-avatar media-left"> <img src="http://placehold.it/50x50" alt="avatar">' +
'</div><div class="comment-content media-body clearfix"> <div class="comment-avatar media-left"></div><h3 class="media-heading">' + currentComment.subject + '</h3> <div class="comment-meta">By ' + currentComment.name + '</div> <div class="comment-body"> <p>' + currentComment.message + '</p><a href="#" class="btn btn-gray more reply">' +
'<i class="fa fa-reply"> </i> Reply </a> </div> </div>';
var closestComment= $(currentComment).closest();
$(closestComment).append(repliesFormat);
});
if (myCommentArray.replies) {
$.each(myCommentArray.replies, sabio.page.processReplies);
};
There is definitely some misunderstanding here of what jQuery's .closest takes as a parameter and there are some curious scoping errors with currentComment. However, the primary thing to fix is that if replies is a property of each comment object, then you will need to process the replies for each comment item - that is, the code to process replies should be handled somehow by the processComments function.
With that said, I will propose to you what I think is a better solution to your problem. Because you are trying to render HTML from your comments array, I think a much cleaner and elegant solution would be to use a JavaScript template. I will use the .template method from the Underscore.js library:
<script id="CommentsTemplate" type="text/template">
<div>
<% _.each(comments, function (comment) { %>
<div class="comment-avatar media-left">
<img src="http://placehold.it/50x50" alt="avatar" />
</div>
<div class="comment-content media-body clearfix">
<div class="comment-avatar media-left"></div>
<h3 class="media-heading"><%- comment.subject %></h3>
<div class="comment-meta">By <%- comment.name %></div>
<div class="comment-body">
<p><%- comment.message %></p>
<i class="fa fa-reply"> </i> Reply
</div>
</div>
<div>
<% _.each(comment.replies, function (reply) { %>
<div class="comment-avatar media-left">
<img src="http://placehold.it/50x50" alt="avatar" />
</div>
<div class="comment-content media-body clearfix">
<div class="comment-avatar media-left"></div>
<h3 class="media-heading"><%- reply.subject %></h3>
<div class="comment-meta">By <%- reply.name %></div>
<div class="comment-body">
<p><%- reply.message %></p>
<i class="fa fa-reply"> </i> Reply
</div>
</div>
<% }); %>
</div>
<% }); %>
</div>
</script>
With our template in place, our rendering can be reduced to some very simple code:
var template = _.template($('#CommentsTemplate').html());
$('.comments').html(template({ comments: comments }));

Categories

Resources