Currently trying to loop through a JSON file and for each object, create a article tag around the data as I format it with HTML, I am successful and creating the first article tag but the I cannot loop through to the next object with the $.each function
HTML code
<body>
<div id='container'>
<div id='content'>
<article class='tumblrPost'>
<header>
<h1> Dragonball Z Motivation </h1>
</header>
<img src='images/dragonball_z.jpg' alt='dragonball z' title='dbz' />
<footer>
<h1> Watch the Video Life & Motivation with Dragonball Z </h1>
</footer>
</article>
</div>
</div>
</body>
</html>
('document').ready(function() {
getPosts();
});
function getPosts() {
var articlePosts = $('div#content article');
$.getJSON('animeTest.json', function(data) {
$.each(data, function(key, val) {
output = "<article>";
output += "<header>";
output += "<h1>" + val.header + "</h1>";
output += "</header>";
output += "<img src='images/" + val.image + "' title='image' />";
output += "<footer>";
output += "<h1>" + val.footer + "</h1>";
output += "</footer>";
output += "</article>";
});
articlePosts.last().after(output);
});
}
You are overwriting output on each cycle
output = "<article>";
Quick fix: try appending the content inside the loop cycle too (and don't declare a global)
$.each(data, function(key, val) {
var output = "<article>";
output += "<header>";
output += "<h1>" + val.header + "</h1>";
output += "</header>";
output += "<img src='images/" + val.image + "' title='image' />";
output += "<footer>";
output += "<h1>" + val.footer + "</h1>";
output += "</footer>";
output += "</article>";
articlePosts.last().after(output);
});
BTW, I feel more comfortable operating on jQuery elements instead of concatenating html. You should try it!
var output = $('<article></article');
var header= $('<header></header');
header.append("<h1>" + val.header + "</h1>").appendTo(output);
output.append("<img src='images/" + val.image + "' title='image' />");
var footer= $ ('<footer></footer>');
footer.append("<h1>" + val.footer + "</h1>").appendTo(output);
articlePosts.last().after(output);
it saves you the pain of closing tags
You're resetting output on each iteration. Technically, you are probably only seeing the last result shown as an article in the HTML.
Instead, declare output right before $.each(), and then only ever append to it. Once you're done looping, append the entire result to your page:
function getPosts() {
var articlePosts = $('div#content article');
$.getJSON('animeTest.json', function(data) {
var output = ''; // make sure you use 'var' so it's not a global variable
$.each(data, function(key, val) {
output += "<article>";
output += "<header>";
output += "<h1>" + val.header + "</h1>";
output += "</header>";
output += "<img src='images/" + val.image + "' title='image' />";
output += "<footer>";
output += "<h1>" + val.footer + "</h1>";
output += "</footer>";
output += "</article>";
});
articlePosts.last().after(output);
});
}
Lastly, if you find yourself building HTML like this often, I would suggest looking into various HTML/JavaScript templating solutions. They would make your JavaScript code far cleaner and easier to maintain by keeping your HTML and JavaScript separate.
Related
I would like to style json feed output. I want to be able to arrange it as I want. So far this is my javascript code. I would like to achieve something like this IMG, information's such as age number etc would be possible to change location etc. I want this to work on jquery mobile as i am building an application.
function listPosts(data) {
var output = '<ul data-role="listview" data-filter="true">';
$.each(data.posts, function(key, val)
{
var tempDiv = document.createElement("tempDiv");
tempDiv.innerHTML = val.excerpt;
$("a", tempDiv).remove();
var excerpt = tempDiv.innerHTML;
output += '<li>';
output += '<a href="#blogpost" onclick = "showPost('+ val.id +') ">';
output += '<h3>' + val.title + "</h3>";
output += (val.thumbnail) ?
'<img src="' + val.thumbnail + '" alt="' + val.title + '">':
'<img src="images/itblogo.png" alt="ITB Logo">';
output += '<h3>' + val.custom_fields.gender + "</h3>";
output += '<h3>' + val.custom_fields.age + "</h3>";
output += '</a>';
output += '</li>';
}); //go through each post
output += "</ul>";
$('#postlist').html(output);
} //listPosts
function showPost(id) {
$.getJSON('http://www.pawmatch.info?json=get_post&post_id=' + id + '&callback=?', function(data) {
var
output ='<img src="'+data.post.thumbnail + '">'
output += '<h3>' + data.post.custom_fields.dogs_name + '</h3>'
output +='<h3>'+data.post.custom_fields.dog_size + '</h3>'
output +='<h3>'+data.post.custom_fields.age + '</h3>'
output +='<h3>'+data.post.custom_fields.gender + '</h3>'
output +='<h3>'+data.post.custom_fields.breed + '</h3>'
output +='<h3>'+data.post.custom_fields.extra_information + '</h3>'
$('#mypost').html(output);
});
}
I need to use join() as JS own method to add a table format to the values in those arrays.
This is an example of my two arrays to diplay, and the table layout should look like this.
This is the part of my code; ovbiously is not working ok, because Im getting a wrong "L" table style format when it runs.
I know its look terrible to parse HTML like that, but this code is in
Google Apps Scripts, so this table is gonna be send it by email.
Any idea how to get the proper format?
Thanks.
|-------|-------|
| user | skill |
|-------|-------|
| user | skill |
|-------|-------|
body +=
"<table style=" + STYLE.TABLE + ">" +
outUsers.join("<tr><td style=" + STYLE.TD + ">") + "</td></tr>" +
outSkills.join("<tr><td style=" + STYLE.TD + ">") + "</td></tr>" +
"</table>";
In this case Array.prototype.join() doesn't do the job I'd use Array.prototype.reduce() instead
Here is an example of what it could look like:
EDIT according to PHPglue comment to have both users and skills on the same row:
var body ='';
var outUsers = ['me', 'you', 'her'],
outSkills = ['eating', 'sleeping', 'working hard'],
STYLE = {
TABLE: "border: red;",
TD: "border: blue;"
},
getTR = function (prev, curr, index) {
return prev + '<tr>' + openingTD + curr + '</td>' + openingTD + outSkills[index] + '</td></tr>';
};
var openingTD = '<td style="' + STYLE.TD + '">';
body += '<table style="' + STYLE.TABLE + '">' +
outUsers.reduce(getTR, '') +
"</table>";
I think this is what you need to see:
var table = '<table><tbody>';
for(var i=0,l=outUsers.length; i<l; i++){
table += '<tr><td>'+outUsers[i]+'</td><td>'+outSkills[i]+'</td></tr>';
}
table += '</tbody></table>';
You should style with CSS. You should read my comments above, as well.
Project: Shopping List
I have created a function that will take input from a form. I am able to display what the user entered. Now I want to add a checkbox next to item displayed, so I can eventually give the option to check the item and remove it.
This is my function:
function addItem() {
var item = [];
item = document.getElementById('items-listed');
item.innerHTML += "<li>" + document.form.itemEntered.value + "</li>";
// item.innerHTML += "<li><input type="checkbox" />" + document.form.itemEntered.value + "</li>";
}
I attempted to create the checkbox but it was not working, so I commented it out.
Here is the project running in Code Pen
http://cdpn.io/JGCDB
This should do it:
item.innerHTML += "<li><input type='checkbox'>" + document.form.itemEntered.value + "</li>";
The issue you experienced is called escaping.
You are generating a string in JS using double-quotes so if you want to use a literal double-quote inside your string then you need to escape it, please study the code below:
item.innerHTML += "<li><input type=\"checkbox\">" + document.form.itemEntered.value + "</li>"; //good
item.innerHTML += '<li><input type="checkbox">' + document.form.itemEntered.value + '</li>'; //good
item.innerHTML += '<li><input type=\'checkbox\'>' + document.form.itemEntered.value + '</li>'; // good
item.innerHTML += "<li><input type="checkbox">" + document.form.itemEntered.value + "</li>"; //bad
item.innerHTML += '<li><input type='checkbox'>' + document.form.itemEntered.value + '</li>'; //bad
The devil is always in the details.
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.
I am working on cleaning up some adopted code - there is a lot of duplication.
There is a set of jQuery callbacks where we get back JSON like this:
[
{"location":{"id":164,"name":"place 1"},"users":[{"id":1,"name":"joe"},{"id":2,"name":"jack"}]},
{"location":{"id":162,"name":"place 2"},"users":[{"id":3,"name":"joe"},{"id":4,"name":"jon"}]}
]
I go through with these functions:
function locations_view(r) {
str = "";
$.each(r.data, function(k, v) {
str += v.location.name + "<br />";
iterate_users(v.users);
});
$("#locations").html(str);
}
function iterate_users(users) {
str += '<strong>users:</strong>' + users.length + '<br />';
$.each(users, function(k1, v1) {
str += "<a href='/users/" + v1.id + "'>" + v1.name + "</a> ";
});
str += "<br />";
}
This seems to work but it looks a little ugly. Is there a better way to do this. Also, I want to minimize memory consumption (returning the string rather than have a global str was causing performance issues). Is there a better, more elegant way to do this? Would having multiple copies of str ever cause a problem? Like if I have products_view that also uses a str?
It might be a bit faster doing concatenation in one step, like
function locations_view(r) {
var peices = [], br = "<br />";
$.each(r.data, function(k, v) {
peices.push(v.location.name, br);
peices.push.apply(peices, iterate_users(v.users));
});
$("#locations").html(peices.join(""));
}
Yes, if something else uses str in the wrong way (i.e. also globally) then that will cause a problem. Best not to have any globals at all. You could change them to this:
function locations_view(r) {
var str = "";
$.each(r.data, function(k, v) {
str += v.location.name + "<br />";
str += iterate_users(v.users);
});
$("#locations").html(str);
}
function iterate_users(users) {
var str = '<strong>users:</strong>' + users.length + '<br />';
$.each(users, function(k1, v1) {
str += "<a href='/users/" + v1.id + "'>" + v1.name + "</a> ";
});
return str + "<br />";
}
And that would be much better. If there are other functions that use iterate_users, they'll need to be changed too.
Also, if you're not already doing this, consider escaping the HTML in v1.name to prevent script injection. You could also use jQuery/DOM manipulation instead.
I've cleaned up your code:
function locations_view(r){
var str = ""; // don't forget var
$.each(r.data, function(k,v){
str += v.location.name + "<br />";
str += iterate_users(v.users); // iterate_users now returns a string, concat it
});
$("#locations").html(str);
}
function iterate_users(users){
var str = '<strong>users:</strong>' + users.length + '<br />'; // redefine str locally
$.each(users, function (k1,v1){
str += '' + v1.name + ' '; // flipped use of ' and ", it's more correct
});
return str + "<br />"; // return str
}
I don't see much wrong with it. I suppose there might be more efficient ways to do it, buy why? This seems like a decent and most importantly: obvious way to do it.
Also, JSLint, it will hurt your feelings but save you headaches
function locations_view(r) {
var $loc = $("#locations");
$.each(r.data, function (k, v) {
$loc.append(v.location.name + "<br/>");
$loc.append('<strong>users:</strong>' + v.users.length + '<br />');
$.each(v.users, function (k1, v1) {
$loc.append("<a href='/users/" + v1.id + "'>" + v1.name + "</a> ");
});
$loc.append("<br />");
});
}