diff --git a/docs/documentation/components/table-sortable.html b/docs/documentation/components/table-sortable.html index ab95b40f..b661cf17 100644 --- a/docs/documentation/components/table-sortable.html +++ b/docs/documentation/components/table-sortable.html @@ -53,29 +53,54 @@
Om inzicht te krijgen in de data kan het behulpzaam zijn om de gebruiker de data te - laten sorteren. Bijvoorbeeld op basis van op of aflopende data. + laten sorteren.
button
toe binnen de th
om sorteerelemeent
- klikbaar te maken.
+ Voeg een <button>
toe binnen de <th>
van elke sorteerbare kolom.
+ <button>
alleen toe aan sorteerbare kolommen. Niet elke kolom hoeft sorteerbaar te zijn.<button>
, zodat de hele kolomkop klikbaar is.abbr=""
toe aan de <th>
met een korte duidelijke
- omschrijving om de gebruikerservaring te verbeteren voor gebruikers die gebruik
- maken van een screenreader.
+ Voeg een toelichting over de sorteerknoppen toe aan de <caption>
. Bijvoorbeeld: "kolomkoppen met knoppen zijn sorteerbaar".
+ visually-hidden
class.visually-hidden
<>span>
kan bijvoorbeeld een komma toegevoegd worden voorafgaand aan de hint-tekst.abbr=""
toe aan de <th>
indien de tekst in de <th>
erg lang is.
+ abbr=""
wordt gebruikt door screenreaders bij het voorlezen van een cel in de bijbehorende kolom.aria-sort=""
toe aan de <th>
van de kolom waarop gesorteerd wordt.
+ aria-sort="ascending"
wanneer de sortering oplopend is.aria-sort="descending"
wanneer de sortering aflopend is.- | |||
---|---|---|---|
Lorem | -Ipsum | +Janine | +Hinde | +
Henk | +de Vries | ||
Lorem | -Ipsum | +Maria | +Lin | +
John | +Doe |
<div class="horizontal-scroll">
<table>
- <caption>Tabelvoorbeeld met sorteerbare data:</caption>
+ <caption>
+ Tabelvoorbeeld met sorteerbare data
+ <span class="visually-hidden">, kolomkoppen met knoppen zijn sorteerbaar</span>
+ </caption>
<thead>
<tr>
- <th scope="col" abbr="Ascending data">
- <button title="Sort descending">Descending <span class="icon icon-ascending"></button>
+ <th scope="col">
+ <button>
+ Voornaam
+ <span class="icon icon-sortable"></span>
+ </button>
</th>
- <th scope="col" abbr="Descending data">
- <button title="Sort ascending">Ascending <span class="icon icon-descending"></span></button>
+ <th scope="col" abbr="Achternaam">
+ <button>
+ Achternaam (met tussenvoegsel)
+ <span class="icon icon-sortable"></span>
+ </button>
</th>
</tr>
</thead>
<tbody>
<tr>
- <td>Lorem</td>
- <td>Ipsum</td>
+ <td>Janine</td>
+ <td>Hinde</td>
+ </tr>
+ <tr>
+ <td>Henk</td>
+ <td>de Vries</td>
+ </tr>
+ <tr>
+ <td>Maria</td>
+ <td>Lin</td>
</tr>
<tr>
- <td>Lorem</td>
- <td>Ipsum</td>
+ <td>John</td>
+ <td>Doe</td>
</tr>
</tbody>
</table>
diff --git a/docs/js/main.js b/docs/js/main.js
index 846e5d40..e98c4aeb 100644
--- a/docs/js/main.js
+++ b/docs/js/main.js
@@ -5,3 +5,4 @@ import "@minvws/manon/form-help.js";
import "@minvws/manon/collapsible.js";
import "@minvws/manon/sidemenu.js";
import "@minvws/manon/language-selector.js";
+import "./sortable-table.js";
diff --git a/docs/js/sortable-table.js b/docs/js/sortable-table.js
new file mode 100644
index 00000000..30d673ef
--- /dev/null
+++ b/docs/js/sortable-table.js
@@ -0,0 +1,74 @@
+import { onDomReady } from "@minvws/manon/utils.js";
+
+onDomReady(initSortableTable);
+
+function initSortableTable() {
+ var thead = document.querySelector("#sortable-table-example thead");
+ var tbody = document.querySelector("#sortable-table-example tbody");
+ if (!(thead instanceof HTMLTableSectionElement) || !(tbody instanceof HTMLTableSectionElement)) {
+ return;
+ }
+ thead.addEventListener("click", function(event) {
+ var button = event.target;
+ if (!(button instanceof HTMLButtonElement)) {
+ return;
+ }
+ var sortStatus = getSortStatus(thead);
+ var columnIndex = getColumnIndex(button.parentElement);
+ if (columnIndex === sortStatus.columnIndex) {
+ sortStatus.direction = sortStatus.direction === 'ascending' ? 'descending' : 'ascending';
+ } else {
+ sortStatus.columnIndex = columnIndex;
+ sortStatus.direction = 'ascending';
+ }
+ updateSortButtons(thead, sortStatus);
+ sortTableBody(tbody, sortStatus);
+ });
+}
+
+function getColumnIndex(th) {
+ return Array.prototype.indexOf.call(th.parentElement.children, th);
+}
+
+function getSortStatus(thead) {
+ var sorted = thead.querySelector("[aria-sort]");
+ if (!sorted) {
+ return { columnIndex: -1, direction: null };
+ }
+ return {
+ columnIndex: getColumnIndex(sorted),
+ direction: sorted.getAttribute("aria-sort")
+ }
+}
+
+function updateSortButtons(thead, sortStatus) {
+ var ths = thead.querySelectorAll("th");
+ var sorted = thead.querySelector("th[aria-sort]");
+ if (sorted && getColumnIndex(sorted) !== sortStatus.columnIndex) {
+ sorted.removeAttribute("aria-sort");
+ var icon = sorted.querySelector(".icon");
+ if (icon) {
+ icon.classList.remove("icon-sortable", "icon-ascending", "icon-descending");
+ icon.classList.add("icon-sortable");
+ }
+ }
+ var sort = ths[sortStatus.columnIndex];
+ if (sort) {
+ sort.setAttribute("aria-sort", sortStatus.direction);
+ var icon = sort.querySelector(".icon");
+ if (icon) {
+ icon.classList.remove("icon-sortable", "icon-ascending", "icon-descending");
+ icon.classList.add("icon-" + sortStatus.direction);
+ }
+ }
+}
+
+function sortTableBody(tbody, sortStatus) {
+ var cells = tbody.querySelectorAll("tr > td:nth-of-type(" + (sortStatus.columnIndex + 1) + ")");
+ var comparator = sortStatus.direction === "ascending"
+ ? function (a, b) { return ('' + a.innerText).localeCompare(b.innerText); }
+ : function (a, b) { return ('' + b.innerText).localeCompare(a.innerText); };
+ Array.prototype.slice.call(cells).sort(comparator).forEach(function (cell) {
+ tbody.appendChild(cell.parentNode);
+ });
+}