Loop through object and order sub values - javascript

First of all:
I created a forum structure in MYSQL:
Table: [boards] -> id, parent_board, title, description
Simple and good.
This is the database response:
[{"id":1,"parent_board":0,"title":"Lorem 1","description":"ec40db959345153a9912"},
{"id":2,"parent_board":0,"title":"Lorem 2","description":"bb698136a211ebb1dfedb"},
{"id":3,"parent_board":1,"title":"Lorem 1-1","description":"6062bc28a9f781e06417d"}]
As you can see board id 3 is a sub-board of board id 1 since its parent_board value is set to 1.
I would like to receive the following output:
Lorem 1
Lorem 1-1
Lorem 2
But this is my result:
Lorem 1
Lorem 2
Lorem 1-1
How can I loop this object so that sub-board (board 3) will be below board 1?
I use the <ul> and <li> tags.
Here is my code:
var html = "</ul>";
for(var i = 0; i < boards.length; i++){
if(boards[i].parent_board == 0){
html += "<li>" + boards[i].title + "</li>";
}else{
html += "<ul>";
html += "<li>" + boards[i].title + "</li>";
html += "</ul>";
}
}

I would put an ID attribute on the <li> for each board. Then whenever I iterate through a sub-board, I just append the new items as children of the parent with the matching id, to do this, you would have to create and add each element to the document as you encounter them instead of storing them in a string first.
var htmlElem = document.getElementById('htmlElemId');
htmlElem.innerHTML = "";
for(var i = 0; i < boards.length; i++){
if(boards[i].parent_board == 0){
htmlElem.innerHTML += "<li id='" + boards[i].id + "'>" + boards[i].title + "</li>";
}else{
var parent = document.getElementById(boards[i].parent_board);
if (parent){
parent.innerHTML += "<ul><li id='" + boards[i].id + "'>" + boards[i].title + "</li></ul>";
}
}
}
Replace 'htmlElemId' with the actual id of your container element, and also make sure that it is of type <ul>.
EDIT: You may also want to consider using some kind of prefix in your ID, so you aren't just using plain numbers that could conflict with things elsewhere
"<li id='SomePrefix-" + boards[i].id + "'>" + boards[i].title + "</li>"
var parent = document.getElementById("SomePrefix-" + boards[i].parent_board);
EDIT2: Here is a JSFiddle

Related

How to append each object to its respective 'block' of elements?

var clubbingLocations = $('#clubbing-locations');
$.getJSON("/js/location.json", function(data) { //load json
for (var i = 1; i <= data.locations.length; i++){ //loop through json, append html and objects
clubbingLocations.append("<div class='night-type location'>" +
"<a href='location.html'>" +
"<div class='overlay'>" +
"<div class='overlay'>" +
"<span class='fav checked glyphicon glyphicon-heart' aria-hidden='true'></span>" +
"<h4>" + data.locations[i].name + "</h4>" +
"<div class='rating-hold'>" +
"</div>" +
"</div>" +
"</a>" +
"</div>"
);
for (var j = 1; j <= data.locations[i].rating; j++){
$('.rating-hold').append("<span class='filled glyphicon glyphicon-star' aria-hidden='true'></span>");
}
}
I am trying to append the object's review to each of its respective rating-hold, however, the reviews are accumulating and adding themselves on to each other instead of appending to the respective class, them moving on.
The first rating inserts its self perfectly, but after that they start adding themselves onto each other.
Create a jQuery object with your html string first.
Then you can search within that object to find the current rating-hold and append icons to it.
Finally, append the whole object including the icons to clubbingLocations
for (var i = 0; i <= data.locations.length - 1; i++){ //loop through json, append html and objects
// create jQuery object
var $nightType= $("<div class='night-type location'>" +
"<a href='location.html'>" +
"<div class='overlay'>" +
"<div class='overlay'>" +
"<span class='fav checked glyphicon glyphicon-heart' aria-hidden='true'></span>" +
"<h4>" + data.locations[i].name + "</h4>" +
"<div class='rating-hold'>" +
"</div>" +
"</div>" +
"</a>" +
"</div>"
);
for (var j = 0; j <= data.locations[i].rating; j++){
// append icons to object created above
$nightType.find('.rating-hold').append("<span class='filled glyphicon glyphicon-star' aria-hidden='true'></span>");
}
// append object to dom
clubbingLocations.append($nightType);
}
You can use JQuery .each documentation
$('.rating-hold').each(function(index){
$(this).append('html code here');
})
Your are appending using the .rating-hold alone, which will append all to the first location, try giving locations ids, and assign stars to each separately using this instead:
var clubbingLocations = $('#clubbing-locations');
$.getJSON("/js/location.json", function(data) { //load json
for (var i = 0; i <= data.locations.length - 1; i++){ //loop through json, append html and objects
clubbingLocations.append(
"<div id='location" + i + "' class='night-type location'>" +
"<a href='location.html'>" +
"<div class='overlay'>" +
"<div class='overlay'>" +
"<span class='fav checked glyphicon glyphicon-heart' aria-hidden='true'></span>" +
"<h4>" + data.locations[i].name + "</h4>" +
"<div class='rating-hold'>" +
"</div>" +
"</div>" +
"</a>" +
"</div>"
);
for (var j = 0; j <= data.locations[i].rating; j++){
$('#location' + i + ' .rating-hold').append("<span class='filled glyphicon glyphicon-star' aria-hidden='true'></span>");
}
}

this.id is not working to detect which link is clicked in href

I am new to javascript and I am creating a bookstore using the google API. I have a small issue which I couldn't figure out. In the below piece of code that I saw from example code of google api bookstore function, I am trying to create href for the title of the book and pass its selfLink to the destination page i.e book-description.html.
When I put alert(this.id) on onclick It works, but for a normal method get(this) it does not work. I do not need an alertbox I want to take the id of the link clicked in href and pass it to another html.
handleResponse(response) {
for (var i = 0; i < response.items.length; i++) {
var item = response.items[i];
var a = item.volumeInfo.title;
var selfL = item.selfLink;
//var b = a.link("book-description.html");
var image = item.volumeInfo.imageLinks.smallThumbnail;
document.getElementById("content").innerHTML += "</br>" + "</br>" + "<br>" + "<img src =" + "'" + image + "'" + " class='im'/>";
document.getElementById("content").innerHTML += "<h4 class='right'>" + "<a href = 'book-description.html'id = " + "'" + selfL + "'" +
"onclick ='get(this);'>" + a + "</a></h4>";
function get(e) {
var link = e.id;
localStorage.setItem("Link", link);
}
document.getElementById("content").innerHTML += "<h4 class='right'>" + "AUTHOR:" + item.volumeInfo.authors + "</h4>";
document.getElementById("content").innerHTML += "<h5 class='right'>" + "PUBLISHER:" + item.volumeInfo.publisher + "</h5>";
var rating = item.volumeInfo.averageRating;
if (rating) {
document.getElementById("content").innerHTML += "<h5 class='right' id='rating'>" + rating + "</h5>";
} else {
document.getElementById("content").innerHTML += "<h5 class = 'right' id ='rating'>Not Rated Yet</h5>";
}
//document.getElementById("content").innerHTML += "<br>" + "<br>" + "<br>" + item.volumeInfo.publisheddate;
}
}
There are a number of problems with your code, but specifically in answer to your question; your function get is scoped so it is only available within the function handleResponse. For it to be accessible from an onclick it must be in page scope.
Simply move this
function get(e) {
var link = e.id;
localStorage.setItem("Link", link);
}
Into the head of your page
In programming there is the concept of DRY (Don't repeat yourself). So store a reference to document.getElementById("content") and reuse that variable.
var content = document.getElementById("content");
content.innerHTML = ...
You're missing some spaces in your output html. This may work in some browsers, others will struggle
<a href = 'book-description.html'id=
Should have a space between the end of one attribute and the start of another
<a href='book-description.html' id=
And for heaven sake, sort out the concatenation of your strings. You dont need a + if its just a simple string
document.getElementById("content").innerHTML += "</br>" + "</br>";
should be
document.getElementById("content").innerHTML += "</br></br>";

Inserting custom text in JS output

I have below line in my js code. i runs from 0 to 2. I want to put a custom text in place of: ' + info[i] + ' for each of the i's(over iterations of i). How do I do that?
for(var i=0; i < origins.length-1; i++) {
var results = response.rows[i].elements;
output += '<tr><td>' + info[i] + '</td><td>' + origins[i] + '</td><td></td><td>' + destinations[i+1] + '</td><td></td><td>' + results[i+1].distance.text + '</td></tr>';
}
. I want to put a custom text in place of: ' + info[i] + ' for each of the i's(over iterations of i).
Not sure what is "custom text" but assume your custom text should be in an array:
var customText = ["Custom text for i=0",
"Custom text for i=1",
"Custom text for i=2"];
for(var i=0; i < origins.length-1; i++) {
var results = response.rows[i].elements;
output += '<tr><td>' + customText[i] + '</td><td>' + //....
}
Also how to align the out-put of the code at the center of my webpage?
This is connected to CSS rather than with JS. Use CSS property text-align: center for a table, div or wharever you want to center.
If the custom text isn't in a variable, just put it directly into the HTML that you're generating:
output += '<tr><td>Custom Text</td><td>' + origins[i] + '</td><td></td><td>' + destinations[i+1] + '</td><td></td><td>' + results[i+1].distance.text + '</td></tr>';

creating dynamic li elements from json with typeahead - loop error

Using typeahead.js I'm creating li elements from the color item in the json response
Json:
"results": [
{
"title": "The Collection",
"attribute": "The Collection",
"url": "#/test",
"image": "images/products/londonretro-caine.jpg",
"color": ["brown", "yellow", "grey"]
},
The json has a color key that is sometimes a string, and sometimes an array with several colors
I've looped through the response and created a html dynamically
html += '<li></li>'
I've added a conditional to check if the item in the json is an array of colors.
If it is an array of colors, I've replaced the html with as many li items, as there are colors in the array
I've tried two methods:
1. One is that I make html equal to the new li elements like so: html += '<li></li>...'
the other is that I've changed html to an array and I pushed the li elements into it replacing the original html : html.push('<li></li>')
With method 1, I get the following result:
I get all the colors in a separate li,
but I also get an extra first li with the colors like so:
<li class='product-spot__variants-variant' style='background-color:brown,yellow,grey' title='brown,yellow,grey'>'brown,yellow,grey'</li>
With method 2, I only get the last li with the last color:
<li class='product-spot__variants-variant' style='background-color:grey' title='grey'>'grey'</li>
I left both solutions in the following code.
Any ideas? Thanks, Ask please if it's unclear..
my typeahead code:
suggestion: function (item) {
var glassesColor = item.color;
var html = "<li class='product-spot__variants-variant' style='background-color:"+ glassesColor +"' title='"+ glassesColor +"'>'"+ glassesColor +"'</li>";
_.forEach(item.color, function (k) {
if (typeof item.color === 'object') {
html += "<li class='product-spot__variants-variant' style='background-color:"+ k +"' title='"+ k +"'>'"+ k +"'</li>";
html = [];
html.push("<li class='product-spot__variants-variant' style='background-color:" + k + "' title='" + k + "'>'" + k + "'</li>");
var myhtml = html.join('');
html = myhtml;
}
});
//console.log(html);
var output = '<div class="search-autocomplete search-glasses">\n';
output += '<a href="' + item.url + '">';
output += (item.image ? '<img class="search-autocomplete__image" src="' + item.image + '" alt="' + item.title + '">' : '');
output += '<span class="search-autocomplete__title">' + item.title + '</span>';
output += (item.attribute ? '<span class="search-glasses__attribute">' + item.attribute + '</span>' : '');
output += '<ul class="product-spot__variants">';
output += html;
output += '</ul>';
output += '</a>\n';
output += '</div>\n';
return output;
}
ok so I just created another conditional for the string and put the html equals code there..
otherwise everything was fine
if (typeof item.color === 'string') {
html = "<li class='product-spot__variants-variant' style='background-color:"+ glassesColor +"' title='"+ glassesColor +"'>'"+ glassesColor +"'</li>";
}

Add anchor point to headers?

I have a really big html-document consisting of a number of <h4> headers accompanied by a short <p> 'body'.
I need to add an anchor point (is it the correct term, btw?) to each of the headers.
I'm iterating over the headers, and adding them to a menu-ul:
headz = document.getElementsByTagName("h4");
arrayOfHeaders=[];
x = 0;
y = headz.length;
$("#menu").html("<ul>")
while (x<y){
arrayOfHeaders[x] = "<li><a href='#" + x +"'>" + headz[x].innerText + "</a></li>";
$("#menu").append(arrayOfHeaders[x])
x++;
}
$("#menu").append("</ul>")
I need a way to attach the anchor points to the headers.
Edit: To clarify - what i need is the add a name-tag to each of the -elements.
The first header should be edited from '<h4>' header'</h4>' to '<h4 name="0">'...
Without editing the html, of course.
Set ids to the if they do not have one.
headz = document.getElementsByTagName("h4");
arrayOfHeaders=[];
x = 0;
y = headz.length;
var str = "<ul>";
while (x<y){
var elem = headz[x];
var id = elem.id || "heading_" + x;
elem.id = id;
str += "<li><a href='#" + id +"'>" + elem.innerText + "</a></li>";
x++;
}
$("#menu").append( str + "</ul>");
and FYI innerText is not cross browser friendly.
jQuery solution
var str = "<ul>";
$("h4").each(
function(i){
var id = this.id || "header_" + i;
this.id=id;
str += '<li>' + this.innerHTML + '</li>';
}
);
str += "</ul>";
$("#menu").append(str);
Since you used jquery already, thought id write it all in it:
var html = '<ul>';
$('h4').each(function (index, header) {
html += '<li>' + header.html() + '</li>';
});
html += '</ul>';
$('#menu').append(html);
This might solve your problem
headz = document.getElementsByTagName("h4");
arrayOfHeaders=[];
x = 0;
y = headz.length;
var html = "<ul>";
while (x<y){
html += "<li><a href='#" + headz[x].id +"'>" + headz[x].innerText + "</a></li>";
x++;
}
$("#meny").append( html + "</ul>")
This one is similar to rissicay's answer but I think it's more concise:
var html = []; // create an empty array to store iterated html in
// loop over every heading...
$('h4').each(function(index) {
// and add it to array previously created
html.push("<li><a href='#" + index +"'>" + $(this).html() + "</a></li>");
// add name attribute to heading
$(this).attr('name', index);
});
// finally, append all to menu together with unordered list
$('#menu').append('<ul>' + html.join() + '</ul>');
Basically, try to minimize dom manipulation (.append(), .prepend(), .html()) as much as possible
I think the concept you refer to is sometimes known as an "internal link" - see here under the second section "HTML Links - The id Attribute".
Now looking at your example code you are clearly using jQuery so why not make the most of it?
$("h4").each(function() {
$("#links").append("<a href='#" + this.id + "'>link to " + this.id + "</a><br /><br />");
});
See the following fiddle - http://jsfiddle.net/r0k3t/PhrB6/
Hope that helps.

Categories

Resources