DataTables Example Using reduce()

24 Nov 2020

The table’s data looks like this:

The table uses footerCallback() to populate the footer cell with a total sum of the durations (hours:minutes:seconds) shown in each row.

This then uses a reduce() function to accumulate the running total of durations. The final total is displayed in the table’s footer.

JavaScript
1
2
3
4
5
6
total = api
  .column(0)
  .data()
  .reduce( function(cume, current, idx, api) {
    return addDurations(cume, current);
  }, "00:00:00" );

The "00:00:00" value represents the starting value used by reduce(). It is needed here because the values in each column are assumed to be in the format of a string, as hh:mm:ss.

The full stand-alone code for the page:

JavaScript
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<!doctype html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Demo</title>
  <script src="https://code.jquery.com/jquery-3.5.1.js"></script>
  <script src="https://cdn.datatables.net/1.10.22/js/jquery.dataTables.js"></script>
  <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.22/css/jquery.dataTables.css">
  <link rel="stylesheet" type="text/css" href="https://datatables.net/media/css/site-examples.css">
</head>

<body>

<div style="margin: 20px;">

    <table id="example" class="display dataTable cell-border" style="width:100%">
        <thead>
            <tr>
                <th>Durations</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>09:04:45</td>
            </tr>
            <tr>
                <td>23:45:56</td>
            </tr>
            <tr>
                <td>114:16:19</td>
            </tr>
        </tbody>
        <tfoot>
            <tr>
                <th></th>
            </tr>
        </tfoot>
    </table>

</div>

<script type="text/javascript">

  // https://stackoverflow.com/users/544542/pee2pee

  $(document).ready(function() {

    var table = $('#example').DataTable( {
      "footerCallback": function ( row, data, start, end, display ) {        
        var api = this.api(), data;
        // Total over all pages:
        total = api
            .column(0)
            .data()
            .reduce( function(cume, current, idx, api) {
              return addDurations(cume, current);
            }, "00:00:00" ); // initial value is this string.
        // Update footer:
        $( api.column(0).footer() ).html(total);
      }
    } );

  } );

  // a reduce() function, to add the durations in the column:
  function addDurations(cumeDuration, colDuration) {
    var cumeSeconds = durationToSeconds(cumeDuration);
    cumeSeconds += durationToSeconds(colDuration);
    return secondsToDuration(cumeSeconds);
  }

  // takes a string "hh:mm:ss", creates an int:
  function durationToSeconds(duration) {
    var hms = duration.split(":");
    return (parseInt(hms[0]) * 60 * 60) + (parseInt(hms[1]) * 60) + parseInt(hms[2]);
  }

  // takes an int, creates a string "hh:mm:ss":
  function secondsToDuration(seconds) {
    var hrs = Math.trunc(seconds / (60 * 60));
	// may need to pad mins and secs with leading zero:
    var mins = String(Math.trunc((seconds - (hrs * 60 * 60)) /60)).padStart(2, '0');
    var secs = String(seconds % 60).padStart(2, '0');
    return hrs + ":" + mins + ":" + secs;
  }

</script>

</body>
</html>