Jonathan Clark
Jonathan Clark

Reputation: 20538

Javascript and JSON. Looping of sub array fails

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);

};

Upvotes: 2

Views: 590

Answers (4)

Alnitak
Alnitak

Reputation: 339816

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.

Upvotes: 0

Matt
Matt

Reputation: 75317

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)).

Upvotes: 4

xpapad
xpapad

Reputation: 4456

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)

Upvotes: 0

James M
James M

Reputation: 16718

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.

Upvotes: 2

Related Questions