From 841bcf0fe711efd796c4c84bcc70f3950820fc7b Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Thu, 20 Jul 2023 17:34:21 +0200 Subject: [PATCH] Make columns sortable (no reverse sort). --- ultimate.js | 78 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 7 deletions(-) diff --git a/ultimate.js b/ultimate.js index 56ee933..32dd249 100644 --- a/ultimate.js +++ b/ultimate.js @@ -49,7 +49,17 @@ function add_cell(tr, element_type, text) { } function add_th(tr, text, colspan) { - let element = add_cell(tr, 'th', text); + let element = document.createElement('th'); + let link = document.createElement('a'); + link.style.cursor = 'pointer'; + link.addEventListener('click', (e) => { + sort_by(element); + process_matches(global_json, global_filters); + }); + link.textContent = text; + element.appendChild(link); + tr.appendChild(element); + if (colspan > 0) { element.setAttribute('colspan', colspan); } else { @@ -729,19 +739,20 @@ function make_table_general(players) { rows.push(header); } - for (const [q,p] of Object.entries(players)) { + for (const [q,p] of get_sorted_players(players)) { if (q === 'globals') continue; let row = document.createElement('tr'); let pm = p.goals + p.assists + p.hockey_assists + p.defenses - p.throwaways - p.drops - p.was_ds; let soft_pm = p.offensive_soft_plus + p.defensive_soft_plus - p.offensive_soft_minus - p.defensive_soft_minus; let o_efficiency = make_efficiency_ci(p.offensive_points_won, p.offensive_points_completed, z); let d_efficiency = make_efficiency_ci(p.defensive_points_won, p.defensive_points_completed, z); - add_3cell(row, p.name, 'name'); // TODO: number? + let name = add_3cell(row, p.name, 'name'); // TODO: number? add_3cell(row, pm > 0 ? ('+' + pm) : pm); add_3cell(row, soft_pm > 0 ? ('+' + soft_pm) : soft_pm); add_3cell_ci(row, o_efficiency); add_3cell_ci(row, d_efficiency); add_3cell(row, p.points_played); + row.dataset.player = q; rows.push(row); } @@ -785,7 +796,7 @@ function make_table_offense(players) { let catches = 0; let drops = 0; let was_ds = 0; - for (const [q,p] of Object.entries(players)) { + for (const [q,p] of get_sorted_players(players)) { if (q === 'globals') continue; let throw_ok = make_binomial_ci(p.num_throws - p.throwaways, p.num_throws, z); let catch_ok = make_binomial_ci(p.catches, p.catches + p.drops + p.was_ds, z); @@ -811,6 +822,7 @@ function make_table_offense(players) { add_3cell_ci(row, catch_ok); add_3cell(row, '+' + p.offensive_soft_plus); add_3cell(row, '-' + p.offensive_soft_minus); + row.dataset.player = q; rows.push(row); num_throws += p.num_throws; @@ -860,7 +872,7 @@ function make_table_defense(players) { add_th(header, 'Soft +/-', 6); rows.push(header); } - for (const [q,p] of Object.entries(players)) { + for (const [q,p] of get_sorted_players(players)) { if (q === 'globals') continue; let sum_time = 0; for (const t of p.pull_times) { @@ -887,6 +899,7 @@ function make_table_defense(players) { } add_3cell(row, '+' + p.defensive_soft_plus); add_3cell(row, '-' + p.defensive_soft_minus); + row.dataset.player = q; rows.push(row); } return rows; @@ -907,7 +920,7 @@ function make_table_playing_time(players) { rows.push(header); } - for (const [q,p] of Object.entries(players)) { + for (const [q,p] of get_sorted_players(players)) { if (q === 'globals') continue; let row = document.createElement('tr'); add_3cell(row, p.name, 'name'); // TODO: number? @@ -918,6 +931,7 @@ function make_table_playing_time(players) { add_3cell(row, Math.floor(p.field_time_ms / 60000) + ' min'); add_3cell(row, p.offensive_points_completed); add_3cell(row, p.defensive_points_completed); + row.dataset.player = q; rows.push(row); } @@ -959,7 +973,7 @@ function make_table_per_point(players) { let throwaways = 0; let receiver_errors = 0; let touches = 0; - for (const [q,p] of Object.entries(players)) { + for (const [q,p] of get_sorted_players(players)) { if (q === 'globals') continue; // Can only happen once per point, so these are binomials. @@ -984,6 +998,7 @@ function make_table_per_point(players) { } else { add_3cell(row, 'N/A'); } + row.dataset.player = q; rows.push(row); goals += p.goals; @@ -1450,3 +1465,52 @@ function possibly_close_menu(e) { add_submenu.style.display = 'none'; } } + +let global_sort = {}; + +function sort_by(th) { + let tr = th.parentElement; + let child_idx = 0; + for (let column_idx = 0; column_idx < tr.children.length; ++column_idx) { + let element = tr.children[column_idx]; + if (element === th) { + ++child_idx; // Pad. + break; + } + if (element.hasAttribute('colspan')) { + child_idx += parseInt(element.getAttribute('colspan')); + } else { + ++child_idx; + } + } + + global_sort = {}; + let table = tr.parentElement; + for (let row_idx = 1; row_idx < table.children.length - 1; ++row_idx) { // Skip header and globals. + let row = table.children[row_idx]; + let player = parseInt(row.dataset.player); + let value = row.children[child_idx].textContent; + global_sort[player] = value; + } +} + +function get_sorted_players(players) +{ + let p = Object.entries(players); + if (global_sort.length !== 0) { + p.sort((a,b) => { + let ai = parseFloat(global_sort[a[0]]); + let bi = parseFloat(global_sort[b[0]]); + if (ai == ai && bi == bi) { + return bi - ai; // Reverse numeric. + } else if (global_sort[a[0]] < global_sort[b[0]]) { + return -1; + } else if (global_sort[a[0]] > global_sort[b[0]]) { + return 1; + } else { + return 0; + } + }); + } + return p; +} -- 2.39.2