Javascript and JSON. Looping of sub array fails - javascript

I am trying to loop out a JSON object using Javascript (jQuery).
Each object in the array of the main JSON object got embedded arrays containing tags.
I want to loop trough all files in the main object and at the same time loop through the tags and output them together with the files. The object are parsed before looping.
This is the JSON object:
{
"result": [
{
"id": "4f26f21f09ab66c103000sd00e",
"file_url": "http://thefilesat.s3.amazonaws.com/81/0000/12.jpg",
"tags": [
"image",
"elephants"
]
},
{
"id": "4f2422c509ab668472000005",
"file_url": "http://thefilesat.s3.amazonaws.com/9d/0000/7.jpg",
"tags": [
"image",
"green",
"tree"
]
}
]
}
It tried this code but it does not work:
for (var i=0; i < parsed.result.length; i++) {
for (var j=0; j < parsed.result[i].tags.length; j++) {
tags = '<div class="tag">' + parsed.result[j].tags[j] + '</div>';
};
html = '<div class="file""><img src="' + parsed.result[i].file_url + '" /><div class="tags">' + tags + '</div></div>';
$("#files").append(html);
};

Your problem is that inside the tags loop, you're using the = operator; which is overwriting the variable your assigning to in each iteration.
Instead, try something like this;
var html = '';
for (var i = 0; i < parsed.result.length; i++) {
var tags = '';
for (var j = 0; j < parsed.result[i].tags.length; j++) {
tags += '<div class="tag">' + parsed.result[i].tags[j] + '</div>';
};
html += '<div class="file""><img src="' + parsed.result[i].file_url + '" /><div class="tags">' + tags + '</div></div>';
};
$("#files").append(html);
You also had parsed.result[j].tags[j] rather than parsed.result[i].tags[j].
I've also pulled the appending to $('#files') to be outside the loop so it only happens once, to reduce the amount of DOM lookups and DOM manipulation (as this is slow (in relative terms)).

With:
parsed.result[j].tags[j]
I think you meant:
parsed.result[i].tags[j]
Also, tags = should be tags +=, or you'll just overwrite the previous tag.

You have a typo, the 3rd line must be:
tags = '<div class="tag">' + parsed.result[i].tags[j] + '</div>';
(use result[i] rather than j)

When you're handling objects and arrays it's very cheap to store an extra reference to the array:
var result = parsed.result; // new
for (var i=0; i < result.length; i++) {
var tags = result[i].tags; // new
for (var j = 0; j < tags.length; j++) {
tags += '<div class="tag">' + tags[j] + '</div>';
}
html = '<div class="file""><img src="' + result[i].file_url + '" /><div class="tags">' + tags + '</div></div>';
$("#files").append(html);
};
at which point the fact that you inadvertently included the index i twice in your innermost dereference becomes impossible.
This actually performs better too, since the interpreter doesn't have to repeatedly dereference the entire chain of properties over and over.
FWIW, a cleaner jQuery way of writing this without using the .html() method would be:
var result = parsed.result; // new
for (var i=0; i < result.length; i++) {
var div = $('<div>', {'class': 'file'})
.append('<img>', {src: result[i].file_url });
var tags = result[i].tags; // new
for (var j = 0; j < tags.length; j++) {
$('<div>', {'class': 'tag', text: tags[j]}).appendTo(div);
}
$("#files").append(div);
};
which avoids all of the string concatenation, and quote mark escaping, and ensures that any HTML special characters in your tags are correctly escaped, etc.

Related

Access and munipulate the DOM using a for loop

for a challenge, I am calling an the twitch TV API to get info and update my HTML.
Using a for loop, I succeeded to setAttributes for my divs and appendChilds. but when I want to update those childs, it is updating only the childs of the last div.
I need your help to update all my appended childs. Below is my code:
// variables declarations to update the DOM
var users = usersJson.data;
var i;
var usersIds = [];
var channels = document.getElementById("all").children;
console.log(channels);
// pushing channels ids into an array for a later
for (i = 0; i < users.length; i++) {
usersIds.push(users[i].id);
}
var channelImg = document.createElement("img");
var channelTitle = document.createElement("h3");
for (var i = 0; i < channels.length; i++) {
channels[i].setAttribute("id", users[i].id);
channels[i].setAttribute("class", "channelInfo" + (i + 1) + " " + "channel" + (i + 1));
channels[i].appendChild(channelTitle);
channels[i].appendChild(channelImg).setAttribute("id", "img-holder" + (i + 1));
channelTitle.innerHTML = users[i].display_name;
channelImg.setAttribute("src", users[i].profile_image_url);
}
https://jsfiddle.net/xpcz1r5k/1/
The creation of the elements needs to go in the for loop:
for (var i = 0; i < channels.length; i++) {
var channelImg = document.createElement("img");
var channelTitle = document.createElement("h3");
channels[i].setAttribute("id", users[i].id);
channels[i].setAttribute("class", "channelInfo" + (i + 1) + " " + "channel" + (i + 1));
channels[i].appendChild(channelTitle);
channels[i].appendChild(channelImg).setAttribute("id", "img-holder" + (i + 1));
channelTitle.innerHTML = users[i].display_name;
channelImg.setAttribute("src", users[i].profile_image_url);
}
When the creation is on the outside of the loop, appendChild only moves the element to the next parent. appendChild doesn't clone/duplicate the DOM elements. So you end up constantly updating the same DOM element and the last one ends up winning.

How to implement this Javascript to Blogger?

Please help, I can't implement this javascript to my Blogger...
(function() {
var pre = document.getElementsByTagName('pre'),
pl = pre.length;
for (var i = 0; i < pl; i++) {
pre[i].innerHTML = '<span class="line-number"></span>' + pre[i].innerHTML + '<span class="cl"></span>';
var num = pre[i].innerHTML.split(/\n/).length;
for (var j = 0; j < num; j++) {
var line_num = pre[i].getElementsByTagName('span')[0];
line_num.innerHTML += '<span>' + (j + 1) + '</span>';
}
}
})();
You can see this Javascript work fine here : http://jsfiddle.net/tovic/AbpRD/1/
If you are seeing that following type of error when you try to add this JavaScript snippet in your theme code -
Error parsing XML: The content of elements must consist of well-formed character data or markup.
Then to resolve this error, use any of the following methods -
1. Wrap the code within a CDATA directive in the script tag. The code will look like -
<script>
//<![CDATA[
(function() {
var pre = document.getElementsByTagName('pre'),
pl = pre.length;
for (var i = 0; i < pl; i++) {
pre[i].innerHTML = '<span class="line-number"></span>' + pre[i].innerHTML + '<span class="cl"></span>';
var num = pre[i].innerHTML.split(/\n/).length;
for (var j = 0; j < num; j++) {
var line_num = pre[i].getElementsByTagName('span')[0];
line_num.innerHTML += '<span>' + (j + 1) + '</span>';
}
}
})();
//]]>
</script>
The only downside of this approach being that Blogger XML parser will ignore any data layout tags (like for example <data:blog.homepageUrl/>) within the CDATA directive. Rather than replacing them with their actual values, it will not interpret them and show them as is.
2. Escape the following characters in your code -
" is replaced with "
& is replaced with &
< is replaced with <
> is replaced with >
After escaping, the code should look like -
<script>
(function() {
var pre = document.getElementsByTagName('pre'),
pl = pre.length;
for (var i = 0; i & lt; pl; i++) {
pre[i].innerHTML = '<span class="line-number"></span>' + pre[i].innerHTML + '<span class="cl"></span>';
var num = pre[i].innerHTML.split(/\n/).length;
for (var j = 0; j & lt; num; j++) {
var line_num = pre[i].getElementsByTagName('span')[0];
line_num.innerHTML += '<span>' + (j + 1) + '</span>';
}
}
})();
</script>
The data layout tags will remain functional when following this method. Remember to not escape <> surrounding the data layout tag (aka <data:blog.homepageUrl/> will work but not <data:blog.homepageUrl/>)
3. If no data layout tags have to be included in the JavaScript. Then you can add it in an HTML/JavaScript gadget via the Layout tab instead of directly including it in the theme code.

Array elements not showing in dynamically created div?

im trying to print array elements with html li element in a dynamically created div but no errors showing and neither array elements just an empty div.
What could be wrong?
Here is my code:
var fruitsName, fruitsLists, numFruits, i;
fruitsName = ["Mango", "Apple", "Banana", "Strawberry", "Blackberry", "Blueberry"];
numFruits = fruitsName.length;
fruitsLists = "<ul>";
for (i = 0; i < numFruits.length; i++)
{
fruitsLists = "<li>" + fruitsName[i] + "</li>";
}
fruitsLists += "</ul>";
var myDiv = document.createElement('div');
myDiv.className = 'bookmarksHolder';
myDiv.id = 'randomItem';
document.getElementById('bookmarks_row').appendChild(myDiv);
document.getElementById('randomItem').innerHTML = fruitsLists;
Two problems: numFruits is already a length of array, so should be just i < numFruits. Second, in loop concatenate previous value with the current:
for (i = 0; i < numFruits; i++) {
fruitsLists += "<li>" + fruitsName[i] + "</li>";
}
Complete sample:
var fruitsName, fruitsLists, numFruits, i;
fruitsName = ["Mango", "Apple", "Banana", "Strawberry", "Blackberry", "Blueberry"];
numFruits = fruitsName.length;
fruitsLists = "<ul>";
for (i = 0; i < numFruits; i++) {
fruitsLists += "<li>" + fruitsName[i] + "</li>";
}
fruitsLists += "</ul>";
var myDiv = document.createElement('div');
myDiv.className = 'bookmarksHolder';
myDiv.id = 'randomItem';
document.getElementById('bookmarks_row').appendChild(myDiv);
document.getElementById('randomItem').innerHTML = fruitsLists;
<div id="bookmarks_row"></div>
You are assigning to fruitsLists in the loop, instead of appending. Also your array length is numFruits, so don't call .length of that. Change your loop to:
for (i = 0; i < numFruits; i++)
{
fruitsLists += "<li>" + fruitsName[i] + "</li>";
}
You can also give the ul as innerHTML to the div prior to attaching the div to the DOM. This will invoke the rendering engine only once, instead of twice, and you wouldn't have to find the div by ID:
var myDiv = document.createElement('div');
myDiv.className = 'bookmarksHolder';
myDiv.id = 'randomItem';
myDiv.innerHTML = fruitsLists;
document.getElementById('bookmarks_row').appendChild(myDiv);
Within the loop, you need to concatenate instead of updating entire value otherwise fruitsLists includes the last generated HTML of li. Although update the for loop condition since numFruits holds the length.
for (i = 0; i < numFruits; i++)
// ---------^^^---
{
fruitsLists += "<li>" + fruitsName[i] + "</li>";
// ---^^^---
}

Simple javascript onClick for table data

I have a table of images in rows of 10 and I'm trying show the id of each image when I click on it. I've tried many, many different ways of this (code below) but no joy. Hopefully someone can set me straight. No point in any jquery or other clever stuff though - I don't understand it yet. Just some simple pointers would help a lot.
document.writeln('<table border = 1 >');
for (var j = 0; j < myArray.length; j++){
if (j % 10 == 0 && j !== 0){
document.writeln('</tr><tr>');
}
document.writeln('<td ><img id = "' + myArray[j].id + '" src="' + myArray[j].src + '" onclick = selectImage() /></td>');
}
document.writeln('</tr></table>');
function selectImage() {
alert(document.getElementById(id));
}
You need add a parameter to selectImage method, so we can send some information to those method. As you can see on my snippet:
var myArray = [
{
id: "id01",
src: "src01.jpg"
},
{
id: "id02",
src: "src02.jpg"
},
{
id: "id03",
src: "src03.jpg"
},
];
document.writeln('<table border = 1 >');
for (var j = 0; j < myArray.length; j++){
if (j % 10 == 0 && j !== 0){
document.writeln('</tr><tr>');
}
document.writeln('<td ><img id = "' + myArray[j].id + '" src="' + myArray[j].src + '" onclick = selectImage(this) /></td>');
}
document.writeln('</tr></table>');
function selectImage(a) {
console.log(a.getAttribute('src'));
console.log(a.getAttribute('id'));
}
when making a call to selectImage, try passing the current image element by using the 'this' keyword i.e selectImage(this)
and then in the script, you can receive the passed object and retrieve the id attribute from there.
function selectImage(obj)
{
alert(obj.id);
}

Javascript: How can I join all links (array)

I have HTML like :
<div id="divid">
1
2
3
.....................
</div>
I used script below to join, but it cannot join. Check for me.
var links = document.getElementById('divid').getElementsByTagName('a');
for (var i = 0; i < links.length; i++) {
links[i] = links[i].href;
}
document.write('<div class="' + links.join(" ") + '">Class is added links</div>');
It means after joining I have HTML :
<div class="d#link1 d#link2 d#link3">Class is added links</div>
var as = document.getElementById('divid').getElementsByTagName('a');
var links = [];
for (var i = 0; i < as.length; i++) {
links[i] = as[i].href;
}
// work with links here
console.log('<div class="' + links.join(" ") + '">Class is added links</div>');
JSfiddle here.
Note that this causes trouble because the links are fully resolved, relative to the current domain. You might want to use another attribute to contain the classes.
Check for me.
Check it yourself.
document.getElementsByTagName returns a NodeList not an array, you'll need to
transform the nodelist into an array or just use a new array where you put in the hrefs...
Introduce a new variable:
var links = document.getElementById('divid').getElementsByTagName('a'),
hrefs = [];
for (var i = 0; i < links.length; i++) {
hrefs[i] = links[i].href;
}
document.write('<div class="' + hrefs.join(" ") + '">Class is added links</div>');
You'll need to create a separate array to hold the links.
Something like:
var links = document.getElementsByTagName('a');
var linkarr = new Array();
for (var i = 0; i < links.length; i++) {
linkarr[i] = links[i].href;
}
document.write('<div class="' + linkarr.join(" ") + '">Class is added links</div>');
Try this with jquery:
var links = $('#divid').children('a');
var linkArr = '';
for (var i = 0; i < links.length; i++) {
linksArr += links[i].attr('href') + ' ';
}
document.write('<div class="' + linksArr + '">Class is added links</div>');

Categories

Resources