Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions profiles/w3c.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ const modules = [
import("../src/core/list-sorter.js"),
import("../src/core/highlight-vars.js"),
import("../src/core/dfn-panel.js"),
import("../src/core/sortable-table.js"),
import("../src/core/data-type.js"),
import("../src/core/algorithms.js"),
import("../src/core/anchor-expander.js"),
Expand Down
28 changes: 28 additions & 0 deletions src/core/sortable-table.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// @ts-check
import css from "../styles/sortable-table.css.js";
import { fetchBase } from "./text-loader.js";

export const name = "core/sortable-table";

export async function run() {
if (!document.querySelector("table.sortable")) {
return;
}

const style = document.createElement("style");
style.textContent = css;
document.head.insertBefore(style, document.querySelector("link"));

const script = document.createElement("script");
script.id = "respec-dfn-panel";
script.textContent = await loadScript();
document.body.append(script);
}

async function loadScript() {
try {
return (await import("text!./sortable-table.runtime.js")).default;
} catch {
return fetchBase("./src/core/sortable-table.runtime.js");
}
}
82 changes: 82 additions & 0 deletions src/core/sortable-table.runtime.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
if (document.respec) {
document.respec.ready.then(setupSortableTable);
} else {
setupSortableTable();
}

function setupSortableTable() {
/** @type {WeakMap<HTMLTableElement, WeakMap<HTMLTableCellElement, -1 | 1>>} */
const STATE = new WeakMap();

/**
* @param {HTMLTableCellElement} th
* @param {-1 | 0 | 1} dir
*/
const createOrUpdateButton = (th, dir) => {
const textValue = [" descending", "", " ascending"][dir + 1];
const iconValue = ["▼", "▲/▼", "▲"][dir + 1]; // TODO: fix these mappings
const label = th.dataset.text || th.textContent;
if (!th.dataset.text) th.dataset.text = label;

const button =
th.querySelector("button") || document.createElement("button");
const text = `Sort${textValue} by ${label}`;
button.title = text;
button.setAttribute("aria-label", text);
button.textContent = iconValue;
return button;
};

/** @type {NodeListOf<HTMLTableElement>} */
const tables = document.querySelectorAll("table.sortable");
for (const table of tables) {
for (const th of table.tHead.querySelectorAll("th")) {
th.append(createOrUpdateButton(th, 0));
}
}

/** @type {(el: MouseEvent)=> HTMLTableCellElement | null} */
const getTrigger = ev => {
if (!(ev.target instanceof HTMLElement)) return null;
const el = ev.target;
if (el.localName === "th") {
return el;
}
if (el.localName === "button" && el.parentElement.localName === "th") {
return el.parentElement;
}
return null;
};

document.addEventListener("click", ev => {
const th = getTrigger(ev);
if (!th) return;

/** @type {HTMLTableElement | null} */
const table = th.closest("table.sortable");
if (!table) return;

ev.preventDefault();

const state =
STATE.get(table) || STATE.set(table, new WeakMap()).get(table);
const direction = state.get(th) === 1 ? -1 : 1; // -1: ascending, 1: descending
state.set(th, direction);

createOrUpdateButton(th, direction);

const tbody = table.tBodies[0];
const headers = th.closest("tr").cells;
const colIndex = Array.from(headers).findIndex(node => node === th);
const rows = Array.from(tbody.rows).sort((a, b) => {
Comment thread
marcoscaceres marked this conversation as resolved.
const x = a.cells[colIndex].textContent.trimStart();
const y = b.cells[colIndex].textContent.trimStart();
return direction * x.localeCompare(y);
});

/** @type {typeof tbody} */
const tbodyCone = tbody.cloneNode(false);
tbodyCone.append(...rows);
tbody.replaceWith(tbodyCone);
});
}
24 changes: 24 additions & 0 deletions src/styles/sortable-table.css.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const css = String.raw;

export default css`
.sortable th {
vertical-align: middle;
white-space: nowrap;
}

.sortable th button {
background: inherit;
color: inherit;
border: none;
font-size: 0.6em;
padding: 0.5em;
}

.sortable th button:hover {
cursor: pointer;
}

.sortable th button:focus {
outline: 1px solid;
}
`;