Search code examples
javascriptsortingtitaniumappceleratortitanium-alloy

Appcelerator Titanium / Alloy Models: How do I modify this sorting method to sort a string that contains numbers


I have created a model in an Appcelerator, which has sorting methods. One of the properties (date) is a string that contains only numbers. I need to sort this by ascending or deceasing order, as if it were an integer. However, because the field is a UTC date time stamp, sometimes older dates have less digits and start with a higher number, therefore causing these to be at the top when sorting by most recent, or at the bottom when sorting by oldest.

Here is my model file:

exports.definition = {
    config: {
        columns: {
            "name": "text",
            "rating": "integer",
            "location": "text",
            "notes": "text",
            "date": "text",
            "latitude": "integer",
            "longitude": "integer",
            "api_id": "text"  
        },
        adapter: {
            type: "sql",
            collection_name: "test"
        }
    },
    extendModel: function(Model) {
        _.extend(Model.prototype, {
            // extended functions and properties go here
        });
        return Model;
    },
    extendCollection: function(Collection) {
        _.extend(Collection.prototype, {
            // extended functions and properties go here
            initialize: function () {
                 this.sortField = "date";
                 this.sortDirection = "DESC";
            },
            comparator: function (collection) {
                 var that = this;
                 return collection.get(that.sortField);
            },
            setSortField: function (field, direction) {
                this.sortField = field;
                this.sortDirection = direction;
            },
            sortBy: function (iterator, context) {
                var obj = this.models;
                var direction = this.sortDirection;

                return _.pluck(_.map(obj, function (value, index, list) {
                    return {
                        value: value,
                        index: index,
                        criteria: iterator.call(context, value, index, list)
                    };
                }).sort(function (left, right) {
                    // swap a and b for reverse sort
                    var a = direction === "ASC" ? left.criteria : right.criteria;
                    var b = direction === "ASC" ? right.criteria : left.criteria;

                    if (a !== b) {
                        if (a > b || a === void 0) return 1;
                        if (a < b || b === void 0) return -1;
                    }
                    return left.index < right.index ? -1 : 1;
                }), 'value');
            }
        });
        return Collection;
    }
};

Here is the code in my index.js that sorts the beers

theBeers.setSortField("date", "ASC");
theBeers.sort();

How can I amend the code above to fix this issue?

Bare in mind that I still need the other properties which are strings to be sorted as normal, such as the name, location, etc.


Solution

  • Best way is to convert the date to an integer before comparing, put simply:

    You need to declare a local variable for the sort field, same as direction:

    var field = this.sortField;
    

    Just before the if statement, add the following:

    if (field == "date") {
        a = parseInt(a);
        b = parseInt(b);
    }
    

    Might need to add checking for void like you have in your code.

    So full answer:

        sortBy: function (iterator, context) {
                var obj = this.models;
                var direction = this.sortDirection;
                var field = this.sortField;
    
                return _.pluck(_.map(obj, function (value, index, list) {
                    return {
                        value: value,
                        index: index,
                        criteria: iterator.call(context, value, index, list)
                    };
                }).sort(function (left, right) {
                    // swap a and b for reverse sort
                    var a = direction === "ASC" ? left.criteria : right.criteria;
                    var b = direction === "ASC" ? right.criteria : left.criteria;
    
                    if (field == "date") {
                        a = parseInt(a);
                        b = parseInt(b);
                    }
    
                    if (a !== b) {
                        if (a > b || a === void 0) return 1;
                        if (a < b || b === void 0) return -1;
                    }
                    return left.index < right.index ? -1 : 1;
                }), 'value');
            }