Question

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?

Was it helpful?

Solution 2

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.

OTHER TIPS

There is no simple solution to your situation, unfortunately. The values that you are dealing with are neither time values (as far as JS is concerned . . . see the JS Date object for more info on time: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date ), nor are they numbers that you can directly subtract, without manipulation.

Your best bet is to split up the values and do the subtraction in the long drawn out way . . . use var timeElements[2] = each.split(".") to get an array of the minutes/seconds/tenths-of-seconds for each value. At that point, you can either:

  1. Do the subtraction the long way . . . subtract each value separately, carrying over values between the "columns", as needed, or
  2. Convert the minutes and seconds into tenths of seconds, combine all three values into "total tenths-of-seconds", do the subtraction, and then convert them back to the three separate values, to get the difference.

The second option is probably the easier logic to pull off, even if it's a lot of steps.


There is also one other option, if you can do without the time differences . . . if you can prepend zeros to all of the time values, so that each of the minutes, seconds and tenths-of-seconds always have the same number of characters, AND if "dns" is the only other value that will ever occur, besides a time, a direct < comparison of the strings will still actually work for sorting, due to the way that greater than/less than works when used on strings. For example:

  • "057:45.1" is less than "087:48.9"
  • "087:48.9" is less than "108:45.1"
  • "108:45.1" is less than "123.54.7"
  • "123.54.7" is less than "243.04.6"
  • "243.04.6" is less than "dns"

This really isn't an optimal approach . . . it doesn't take much to throw off this kind of string comparison . . . but it's still worth mentioning, if you can be very sure of the values that you are getting.

. . . and if you can skip that whole "time difference" part of it. :D

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top