logo

stagit

STAtic GIT web view generator (in C) git clone https://hacktivis.me/git/stagit.git
commit: 16cfec4fba0837841406f546cd71612274ad7c9c
parent b34a16de39cdb2ba60ed7fb887a109fc935b68fc
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Thu,  6 Jun 2024 06:08:47 +0200

sorttable: Import

Diffstat:

MMakefile6+++++-
Asorttable.css13+++++++++++++
Asorttable.js147+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 165 insertions(+), 1 deletion(-)

diff --git a/Makefile b/Makefile @@ -57,7 +57,7 @@ dist: rm -rf ${NAME}-${VERSION} mkdir -p ${NAME}-${VERSION} cp -f ${MAN1} ${HDR} ${SRC} ${COMPATSRC} ${DOC} \ - Makefile favicon.png logo.png style.css \ + Makefile favicon.png logo.png style.css sorttable.css sorttable.js \ example_create.sh example_post-receive.sh \ ${NAME}-${VERSION} # make tarball @@ -84,6 +84,8 @@ install: all # installing example files. mkdir -p ${DESTDIR}${DOCPREFIX} cp -f style.css\ + sorttable.css\ + sorttable.js\ favicon.png\ logo.png\ example_create.sh\ @@ -101,6 +103,8 @@ uninstall: # removing example files. rm -f \ ${DESTDIR}${DOCPREFIX}/style.css\ + ${DESTDIR}${DOCPREFIX}/sorttable.css\ + ${DESTDIR}${DOCPREFIX}/sorttable.js\ ${DESTDIR}${DOCPREFIX}/favicon.png\ ${DESTDIR}${DOCPREFIX}/logo.png\ ${DESTDIR}${DOCPREFIX}/example_create.sh\ diff --git a/sorttable.css b/sorttable.css @@ -0,0 +1,13 @@ +table.sortable th.made_sortable { + cursor: pointer; +} +table.sortable th.made_sortable:not(.sorttable_sorted):not(.sorttable_sorted_reverse):not(.sorttable_nosort)::after { + content: "⭥"; + opacity: 0.5; +} +table.sortable th.made_sortable.sorttable_sorted:not(.sorttable_sorted_reverse):not(.sorttable_nosort)::after { + content: "⭣"; +} +table.sortable th.made_sortable.sorttable_sorted_reverse:not(.sorttable_sorted):not(.sorttable_nosort)::after { + content: "⭡"; +} diff --git a/sorttable.js b/sorttable.js @@ -0,0 +1,147 @@ +/* + * Copyright 2007 Stuart Langridge http://www.kryogenix.org/code/browser/sorttable/ + * Copyright 2018, 2023 Haelwenn (lanodan) Monnier <contact@hacktivis.me> + * SPDX-License-Identifier: X11 + */ + +/* Usage: + * Add <script src="sorttable.js"></script> to your (x)HTML pages + * Add class="sortable" to any table you'd like to make sortable + * See sorttable.css for an example of styling + */ + +sorttable = { + done : false +}; + +sorttable.init = function() { + // quit if this function has already been called + if(sorttable.done) return; + // flag this function so we don't do the same thing twice + sorttable.done = true; + + var sortableElements = document.getElementsByClassName("sortable"); + Array.prototype.filter.call(sortableElements, function(sortableElement) { + if(sortableElement.nodeName == "TABLE" || sortableElement.nodeName == "table") + { + sorttable.makeSortable(sortableElement); + } + }); +}; + +sorttable.makeSortable = function(table) { + // Only one thead row is supported + if(table.tHead.rows.length != 1) return; + // work through each column and calculate its type + headrow = table.tHead.rows[0].cells; + for(var i = 0; i < headrow.length; i++) + { + // skip this col + if(!headrow[i].classList.contains("sorttable_nosort")) + { + // make it clickable to sort + headrow[i].sorttable_columnindex = i; + headrow[i].sorttable_tbody = table.tBodies[0]; + headrow[i].addEventListener("click", event => { + if(event.target) + { + sorttable.innerSortFunction(event.target) + } + }); + headrow[i].addEventListener("keydown", event => { + if(event.target && (event.key && event.key == "Enter")) + { + sorttable.innerSortFunction(event.target); + } + }); + headrow[i].setAttribute("tabindex", "0"); + headrow[i].classList.add('made_sortable'); + } + } +}; + +sorttable.compareFn = function(a, b) { + // Note: Returns are reversed + if(a[0]<b[0]) {return 1}; + if(a[0]>b[0]) {return -1}; + return 0; +}; + +sorttable.innerSortFunction = function(tr) { + if(tr.classList.contains("sorttable_sorted")) + { + sorttable.reverse(tr.sorttable_tbody); + tr.classList.replace('sorttable_sorted', 'sorttable_sorted_reverse'); + } + else if(tr.classList.contains("sorttable_sorted_reverse")) + { + sorttable.reverse(tr.sorttable_tbody); + tr.classList.replace('sorttable_sorted_reverse', 'sorttable_sorted'); + } + else + { + // remove sorttable_sorted classes + theadRow = tr.parentNode; + theadRow.childNodes.forEach(function( + cell) { cell.classList.remove('sorttable_sorted_reverse', 'sorttable_sorted'); }); + // build an array to sort. This is a Schwartzian transform thing, + // i.e., we "decorate" each row with the actual sort key, + // sort based on the sort keys, and then put the rows back in order + // which is a lot faster because you only do getInnerText once per row + row_array = []; + col = tr.sorttable_columnindex; + rows = tr.sorttable_tbody.rows; + for(var j = 0; j < rows.length; j++) + { + row_array[row_array.length] = + [ sorttable.getElementValue(rows[j].cells[col]), rows[j] ]; + } + row_array.sort(sorttable.compareFn); + tb = tr.sorttable_tbody; + row_array.forEach(function(row) { tb.appendChild(row[1]); }); + tr.classList.add('sorttable_sorted'); + } +}; + +// - Use data-value="" attribute if you want to override innerHTML +// - Use data-type="" attribute if you want to use non-lexical sorting +// Example: <td data-value="1337" data-type="int">Leet</td> +sorttable.getElementValue = function(element) { + if(element === undefined) + { + return "\u0000"; // null + console.log("Warning: Empty cells found"); + }; + + let value = element.dataset.value ? element.dataset.value : element.innerText; + switch(element.dataset.type) + { + case undefined: + return value; + case "int": + var v = parseInt(value); + return v != NaN ? v : value; + case "float": + var v = parseFloat(value); + return v != NaN ? v : value; + default: + console.log(`Warning: Unhandled type ${element.dataset.type}`); + return value; + }; +}; + +sorttable.reverse = function(tbody) { + // reverse the rows in a tbody + newrows = []; + for(var i = 0; i < tbody.rows.length; i++) + { + newrows[newrows.length] = tbody.rows[i]; + } + for(var i = newrows.length - 1; i >= 0; i--) + { + tbody.appendChild(newrows[i]); + } + delete newrows; +}; + +sorttable.init()