/* function moveLast(data, region) { data.push( //for first, //data.unshift( data.splice( data.findIndex((d) => d.region === region), 1 )[0] ); } */ class Table { constructor(container, dataset, dataColumns, classList, region, highlight, metric, chart = null) { this.container = container; this.dataset = dataset; this.dataColumns = dataColumns; this.classList = classList; this.region = region; this.highlight = highlight; this.metric = metric; this.chart = chart; } sort() { if (this.metric) { if (this.metric === "rank") return; const testValue = this.dataset.filter((d) => d[this.metric] !== "")[0][this.metric]; if (!isNaN(testValue)) { this.dataset = this.dataset.sort((a, b) => b[this.metric] - a[this.metric]); } else { if (this.metric === "date") { this.dataset = this.dataset.sort((a, b) => b[this.metric].localeCompare(a[this.metric])); } else { this.dataset = this.dataset.sort((a, b) => a[this.metric].localeCompare(b[this.metric])); } } } } update() { this.container.selectAll("*").remove(); const table = this.container.append("table").attr("class", this.classList); this.dataColumns.forEach((column) => { if (column.width) { table.append("col").attr("width", column.width); } }); const thead = table.append("thead"); this.dataColumns.forEach((column) => { if (column.span !== 0) { const th = thead.append("th").html(column.head); if (this.metric) { if (this.metric === column.body) { th.attr("class", "sorted"); } th.on("click", () => { const saveMetric = this.metric; this.metric = column.body; this.sort(); if (["region", "date", "rank"].includes(column.body)) { this.metric = saveMetric; } this.update(); if (this.chart) { if (!["region", "date", "rank"].includes(column.body)) { this.chart.metric = this.metric; } this.chart.update(); } }); } th.attr("colspan", column.span ? column.span : 1); } }); const skipRank = [ "World", "European Union", "South America", "North America", "Africa", "Europe", "Asia", "Oceania", "Upper middle income", "Lower middle income", "High income", "Low income", ]; let rankAdjust = 0; const tbody = table.append("tbody"); this.dataset.forEach((row, i) => { if (skipRank.includes(row.region)) { rankAdjust++; } const tableRow = tbody.append("tr"); if (row.region === this.highlight) tableRow.attr("class", "bold highlighted"); this.dataColumns.forEach((column) => { tableRow .append("td") .html( `${ row.region === "Canada" && column.body === "region" && this.highlight !== "Canada" ? ` ` : "" }${column.fn( row[column.body], i, row.data.map((d) => d[column.body]), row, i + 1 - rankAdjust )}` ) .attr("class", column.body === "region" && row.region === this.region ? "sorted" : "") .on("click", (e, d) => { if (!["region", "date"].includes(column.body)) { this.metric = column.body; if (this.chart) { this.chart.metric = column.body; } } if (this.chart) { this.chart.region = row.region; this.chart.update(); } this.region = row.region; this.update(); }); }); }); if (table.node().offsetHeight > this.container.node().offsetHeight) { this.container.append("div").attr("class", "shadow"); } } }