// Copyright Epic Games, Inc. All Rights Reserved. // Sortable stats table view. const US_PER_MS = 1000; function escapeHtml(s) { return String(s).replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", "\"": """, "'": "'", }[c])); } export class StatsView { constructor(tbody, headerRow, model, onSelect) { this.tbody = tbody; this.headerRow = headerRow; this.stats = model.scopeStats.slice(); this.onSelect = onSelect; this.sortKey = "count"; this.sortAsc = false; this.selectedName = null; for (const th of headerRow.querySelectorAll("th[data-sort]")) { th.addEventListener("click", () => this.handleSort(th.dataset.sort)); } this.render(); } handleSort(key) { if (this.sortKey === key) { this.sortAsc = !this.sortAsc; } else { this.sortKey = key; this.sortAsc = key === "name"; } this.render(); } selectByName(name) { this.selectedName = name; for (const tr of this.tbody.querySelectorAll("tr")) { tr.classList.toggle("selected", tr.dataset.name === name); if (tr.dataset.name === name) { tr.scrollIntoView({ block: "nearest" }); } } } render() { const key = this.sortKey; const asc = this.sortAsc; this.stats.sort((a, b) => { const av = a[key]; const bv = b[key]; if (typeof av === "string") { return asc ? av.localeCompare(bv) : bv.localeCompare(av); } return asc ? av - bv : bv - av; }); for (const th of this.headerRow.querySelectorAll("th[data-sort]")) { th.classList.toggle("sorted", th.dataset.sort === key); th.classList.toggle("asc", th.dataset.sort === key && asc); } const rows = []; for (const stat of this.stats) { const selected = stat.name === this.selectedName ? " class=\"selected\"" : ""; rows.push( `