﻿(function($) {
    $.fn.extend({

        sort: function(params) {

            //expected params
            /*
            {
            sortOn: '.selector',  //selector of the column to sort on
            direction: 'asc' | 'desc' //optional..defaults to asc
            sortType: 'string | date | number' //optional..defaults to string
            }
        
        OR 
        
        an array of the above obj for multi sorting. The order in the array determines
            order of precedence
            */

            //hacky to be backward compatible
            if (!params.length) {
                params = [params];
            }

            var sortFunc = function(a, b) {
                var retval;
                var typedData;

                for (var i = 0; i < params.length; i++) {
                    typedData = getTypedData(a, b, i);
                    retval = innerSort(typedData.a, typedData.b, params[i].direction);
                    if (retval != 0)
                        break;
                }
                return retval;
            }

            var getTypedData = function(a, b, index) {
                var sortType = params[index].sortType;
                var preA, preB;
                var typedA, typedB;

                preA = getValue(a, index);
                preB = getValue(b, index);
                if (sortType == 'date') {
                    typedA = new Date(Date.parse(preA));
                    typedB = new Date(Date.parse(preB));
                }
                else if (sortType == 'number') {
                    typedA = new Number(preA);
                    typedB = new Number(preB);
                }
                else {
                    typedA = new String(preA).toLowerCase();
                    typedB = new String(preB).toLowerCase();
                }
                return { a: typedA, b: typedB };
            }

            var getValue = function(obj, index) {
                var val;
                if (obj.hash[index]) {
                    val = obj.hash[index];
                }
                else {
                    val = findValue(obj.row, params[index].sortOn);
                    obj.hash[index] = val;
                }
                return val;
            }

            var findValue = function(row, selector) {
                return row.find(selector).text();
            }

            var innerSort = function(a, b, direction) {
                var retval;
                if (a > b) {
                    retval = 1;
                }
                else if (a < b) {
                    retval = -1;
                }
                else {
                    retval = 0;
                }
                if (direction == 'desc')
                    retval *= -1;
                return retval;
            }

            var getRowHash = function(rows) {
                var rowHash = [];
                for (var x = 0; x < rows.length; x++) {
                    rowHash[x] = { row: $(rows[x]), hash: [] };
                }
                return rowHash;
            }

            var addRows = function(container, rowHash) {
                var c = $('<div></div>');
                for (var x = 0; x < rowHash.length; x++) {
                    c.append(rowHash[x].row);
                }
                container.append(c.children());
            }

            return this.each(function() {
                var container = $(this);
                var rows = container.children();

                var rowHash = getRowHash(rows);

                rowHash.sort(sortFunc);


                addRows(container, rowHash);

            });

        }
    });
})(jQuery);  
