﻿function createSortableTable(selector, initialSort) {
    var SortedDescending = "▼";
    var SortedAscending = "▲";
    var extractValue = function(val) {
        var re = /^\s*([\(]{0,1})\$*([\-]{0,1}[\d]+\.{0,1}[\d]*)[\)%]*\s*$/;
        var match = re.exec(val);
        if (match != null) {
            var numericValue = parseFloat(match[2]);
            return (match[1] == '') ? numericValue : -numericValue;
        }
        return val;
    };
    jQuery(selector).each(function() {
        var table = jQuery(this);

        var headers = jQuery("th", table);
        var rows = [];
        var tableRows = jQuery("tr", table);
        tableRows.each(function() {
            var row = jQuery(this);
            var cells = jQuery("td", row);
            if (cells.length > 0) {
                row.attr("hasCells", "1");
                rows.push(function() {
                    var values = [];
                    cells.each(function() {
                        values.push(jQuery(this).text());
                    });
                    return values;
                } ());
            }
        });
        var index = 0;
        var lastSortElement = null;
        headers.each(function() {
            var header = jQuery(this);
            header.append("<span class='sort'></span>");
            header.css("cursor", "pointer");
            var sortElement = jQuery("span.sort", header);
            var headerIndex = index++;
            header.click(function() {
                var sortDirection;
                var sortText = sortElement.text();
                if (lastSortElement != null) {
                    lastSortElement.text("");
                }
                lastSortElement = sortElement;
                if (sortText == SortedAscending) {
                    sortDirection = -1;
                    sortElement.text(SortedDescending);
                }
                else {
                    sortDirection = 1;
                    sortElement.text(SortedAscending);
                }
                rows = rows.sort(function(row1, row2) {
                    var v1 = extractValue(row1[headerIndex]);
                    var v2 = extractValue(row2[headerIndex]);
                    if (v1 == v2) { return 0; }
                    return (v1 < v2) ? -sortDirection : sortDirection;
                });
                var rowIndex = 0;
                tableRows.each(function() {
                    var row = jQuery(this);
                    if (row.attr("hasCells") == "1") {
                        var rowData = rows[rowIndex++];
                        var cellIndex = 0;
                        jQuery("td", row).each(function() {
                            var cell = jQuery(this);
                            cell.text(rowData[cellIndex++]);
                        });
                    }
                });
            });
        });
        if ((initialSort!=null) && (initialSort < headers.length)) {
            jQuery(headers[initialSort]).click();
        }
    });
}