1

I'm receiving JSON from the server which looks something like this.

{"genres": [{
        "genre": "RPG",
        "publishers": [{
            "publisher": "Square",
            "games": [{
                "game": "FFX",
                "rating": [
                    12, 15
                ]
            }]
        }, {
            "publisher": "Blizzard",
            "games": [{
                "game": "Starcraft",
                "rating": [
                    10, 12
                ]
            }, {
                "game": "Diablo",
                "rating": [
                    15
                ]
            }, ]
        }]
    }, {
        "genre": "Action",
        "publishers": [{
            "publisher": "EA",
            "games": [{
                "game": "COD",
                "rating": [
                    18, 20
                ]
            }, {
                "game": "Titanfall",
                "rating": [
                    18
                ]
            }]
        }]
    }
}

I'm trying to build a drop down menu using the publishers from this data, at the moment i can get the Drop downs to return the genre, but not the publisher.

I've been trying to use .each to take the publisher from each genre, so in the drop down i will end up with: Square Blizzard EA

My code so far is:

  function renderCombo(){
  var parseData= JSON.parse($myData);
 $(parseData.Genre).each(function (i) {
     $("#pubCombo").append($("<option/>", {
         val: this.publisher,
         html: this.publisher
     }));
     $('#pubCombo').selectpicker("refresh");
 });

};

$myData is the data retrieved from the server, it works fine for all my other drop downs, so i know it's my renderCombo function.

Any ideas how this can be achieved?

2
  • 1
    The answers so far have all used constructions of the form $({ some Javascript plain object }).each(func), when they should be using $.each({ some Javascript plain object }, func). From jQuery docs: At present, the only operations supported on plain JavaScript objects wrapped in jQuery are: .data(), .prop(), .on(), .off(), .trigger() and .triggerHandler(). Commented Mar 27, 2014 at 16:43
  • Thanks for the answers, i ended up using Wilmer for the caching, but much appreciated for the responses! Commented Mar 28, 2014 at 10:04

3 Answers 3

2

(Edited this answer now that I see the question really is how to eliminate duplicates)

The problem (besides some typos in your source data, and "Genre" instead of "genre" in your function) is that you have more than one publisher per genre, so you won't be able to get them in a single pass.

var uniquePublishers = {};
$(parsedData.genres).each(function () {
    $(this.publishers).each(function () {
        uniquePublishers[this.publisher] = true;
    });
});
for (publisher in uniquePublishers) {
    $("#pubCombo").append($("<option/>", {
        val: publisher,
        html: publisher
    }));
};

Fiddle

Sign up to request clarification or add additional context in comments.

2 Comments

yeah that is exactly the problem i'm having, for example i'm seeing a lot of EA's since they publish in every genre
@Hagbard updated my answer to account for duplicates.
2

You don't have to use JSON.parse — jQuery can read objects and arrays directly without parsing :) you should also check your object for syntax errors, just in case.

If you intend to simply collect a list of all publishers in your data, you can use the code below:

$.each($myData.genres, function () {
    $.each(this.publishers, function() {
        $("#pubCombo").append($("<option/>", {
            val: this.publisher,
            html: this.publisher
        }));
    });
});

See proof-of-concept fiddle here: http://jsfiddle.net/teddyrised/N6FAk/

Update: If you want to return a unique array of publishers, you can use take advantage of jQuery's .unique() method:

var parseData = $myData,
    pubList = [];

$(parseData.genres).each(function () {
    $(this.publishers).each(function() {
        pubList.push(this.publisher);
    });
});

var uniquePubList = pubList.filter(function(v,i,pubList) {
    return i == pubList.indexOf(v);
});

$.each(uniquePubList, function (i,v) {
    $("#pubCombo").append($("<option/>", {
        val: v,
        html: v
    }));
});

See fiddle here: http://jsfiddle.net/teddyrised/N6FAk/3/

2 Comments

Hi, thanks, thats great, is there a way of applying a "distinct" to it though, for example EA also do Sport games, i only need to see it once instead of listed multiple times in the drop down.
@Hagbard Fixed the $.each()? issue pointed out by a commenter in your question, also added the filtering function to remove redundant publishers.
1

Add another each too traverse the publishers:

function renderCombo() {
    var parseData = JSON.parse($myData);
    $(parseData.genres).each(function (i) {
        $(this.publishers).each(function (i) {
            appendOption(this);
        });
    });
    $('#pubCombo').selectpicker("refresh");//refresh when finished
};

Updated to not append duplicate options:

function appendOption(option) {

    if ( !appendOption.distinct[option.publisher] ) {//check cache

        $("#pubCombo").append($("<option/>", {
            val: option.publisher,
            html: option.publisher
        }));
        appendOption.distinct[option.publisher] = option.publisher;

    }
}

appendOption.distinct= {};//cache

UPDATE: Improved second function to use a pseudo cache.

2 Comments

Hi, this works well too, but like my other comment, i should have made clear, is there a way of applying a unique/distinct filter? Because if a publisher appears in multiple genres, i'll see it many times. Thanks
I've updated my answer to check the existing options by value.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.