Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort JSON array based on value with jQuery

I've got two dropdown select dropdowns: one for regions and one for cities in the selected region. The result is loaded by AJAX and in my response i get all cities in an JSON array:

{
    1709: "Geertruidenberg", 
    1710: "Netersel", 
    1711: "Macharen", 
    1712: "Beers", 
    1713: "Hank", 
    1714: "Oudemolen", 
    1715: "Nistelrode"
}

I'm using this small plugin to load the data in the select dropdown:

(function($, window) {
    $.fn.replaceOptions = function(options) {
        var self, $option;

        this.empty();
        self = this;

        $.each(options, function(index, option) {
            $option = $("<option></option>")
                .attr("value", index)
                .text(option);
            self.append($option);
        });
    };
})(jQuery, window);

And this piece of javascript to do the AJAX request:

$('select#Profile_regionId').change(function() {
    $.post('/ajax/getcities', {regionid: $(this).val()}, function(data){
        //console.log(data.cities);
        $("select#Profile_cityId").replaceOptions(data.cities);
    }, 'json');
});

All works totally fine, except the city dropdown is automatically sorted on the JSON array key. I tried to use the sort() method for this, but it won't work because it's an Object and not an array. Then i tried to create an array of it:

var values = [];
$.each(data.cities, function(index,value)) {
    values[index] = value;
}

But for some reason, the dropdown list fills itself up from 1 to the first found id (key of array) of the city, and i don't know why it's doing that (array itself looks fine).

How can i sort the thing so my cities are ordered alphabetically in the dropdown list?

like image 977
davey Avatar asked Aug 28 '13 14:08

davey


2 Answers

It needs to be converted to an array so that it can be sorted. Let's assume this is your object. Note that I rearranged it to be unsorted, to prove this works.

originalData = {
    1712: "Beers", 
    1709: "Geertruidenberg", 
    1710: "Netersel", 
    1713: "Hank", 
    1714: "Oudemolen", 
    1711: "Macharen", 
    1715: "Nistelrode"
};

Now to create an array version we need to create an array, and insert objects into it. I'm calling the keys "year". Note that we're calling parseInt on the keys. Keys in JavaScript (except for arrays) are always strings. For example, {foo: "bar"} has a string key "foo". This also applies to numerical looking keys.

var dataArray = [];
for (year in originalData) {
    var word = originalData[year];
    dataArray.push({year: parseInt(year), word: word});
}

There's a chance that we have our data out of sort right now, so we manually sort it. Note that this is a case sensitive sort. For example, "Qux" comes before "foo".

dataArray.sort(function(a, b){
    if (a.word < b.word) return -1;
    if (b.word < a.word) return 1;
    return 0;
});

The function now just pulls option.year and option.word from our array.

$.fn.replaceOptions = function(options) {
    var self, $option;

    this.empty();
    self = this;

    $.each(options, function(index, option) {
        $option = $("<option></option>")
            .attr("value", option.year)
            .text(option.word);
        self.append($option);
    });
};

And then you finally use the plugin, passing the array. You can put all of this code in the plugin, if that works best for you.

$('#mylist').replaceOptions(dataArray);

fiddle

like image 139
Brigand Avatar answered Oct 14 '22 00:10

Brigand


This will do what you want and take care of the empty ids/undefined values:

var data = {
    1709: "Geertruidenberg", 
    1710: "Netersel", 
    1711: "Macharen", 
    1712: "Beers", 
    1713: "Hank", 
    1714: "Oudemolen", 
    1715: "Nistelrode"
};

var values = [];
$.each(data, function(index, value) {
    values[index] = value;
});

values.sort();

$.each(values, function(index, value) {
    if(value != undefined) {
        $("#Profile_cityId").append("<option>"+ value +"</option");
    }
});

Just replace the append I put in with your own function because jsFiddle was giving me trouble using that. Demo: http://jsfiddle.net/R4jBT/3/

like image 3
Floris Avatar answered Oct 14 '22 02:10

Floris