Search code examples
javascriptjqueryhtmlarraystablesorter

Javascript array to sorted html table by time


I need to transform an array to html table sorted by time, add rank and calculate time loss for the first place. Array example:`

var array = [
  ["McNulty Oscar", "USA", "108:45.1"],
  ["Johansson Anton", "SWE", "87:48.9"],
  ["Schneider Florian", "SUI", "dns"],
  ["Rio Nicolas", "FRA", "57:45.1"]
];`

Final HTML table should look like this:

1 Rio Nicolas       FRA  57:45.1
2 Johansson Anton   SWE  87:55.9  30:10.8
3 McNulty Oscar     USA 107:45.2  51:03.1
  Schneider Florian SUI      dns      dns

My idea how to do it is in Jquery transform Array to HTML table and then sort it using tablesorter plugin. I still don't know when and how to calculate the time loss. Is it good way or am I totally out?


Solution

  • I put together this demo using tablesorter and the tablesorter build table widget.

    HTML

    <div id="result"></div>
    

    Script

    $(function () {
        var array = [
            ["Name", "Country", "Time", "Diff"],
            ["McNulty Oscar", "USA", "108:45.1", ""],
            ["Johansson Anton", "SWE", "87:48.9", ""],
            ["Schneider Florian", "SUI", "dns", ""],
            ["Rio Nicolas", "FRA", "57:45.1", ""]
        ],
        // time column (zero-based index)
        timeColumn = 3,
        diffColumn = 4,
    
        // convert min:sec.ms => sec.ms
        convertTime = function (time) {
            var val;
            if (time && /:/.test(time)) {
                val = time.split(':');
                return parseFloat(val[0] || 0) * 60 + parseFloat(val[1] || 0);
            } else {
                return Number.POSITIVE_INFINITY;
            }
        },
        // convert sec.ms => min:sec.ms
        formatTime = function (time) {
            var minutes = parseInt(time / 60);
            return minutes + ':' + (time - (minutes * 60)).toFixed(1);
        },
        calculateDiff = function (table) {
            var $tds, minTime,
            $table = $(table),
            $trs = $table.children('tbody').children(),
            times = [];
            $trs.each(function () {
                $tds = $(this).children();
                times.push(convertTime($tds.eq(timeColumn).text()));
            });
            minTime = Math.min.apply(Math, times);
            $trs.each(function (i) {
                var diff = times[i] - minTime,
                result = times[i] === Number.POSITIVE_INFINITY ? 'dns' :
                diff === 0 ? '' : formatTime(diff);
                $(this).children()
                .eq(0).html(result !== 'dns' ? i + 1 : '').end()
                .eq(diffColumn).html(result);
            })
            .trigger('update');
        };
    
        $('#result').tablesorter({
            theme: 'blue',
            emptyTo: 'zero',
            widgets: ['zebra', 'build'],
            sortList: [[3, 0]],
            widgetOptions: {
                build_source: array,
                build_footers: {
                    rows: 0
                },
                build_numbers: {
                    // include row numbering column?
                    addColumn: "Rank",
                    // make column sortable?
                    sortable: true
                }
            },
            initialized: function (table) {
                calculateDiff(table);
            }
        });
    });
    

    Update: Modified code and demo to include rank column and sort.