From c6826cfb85185c291ab9da33009b4aecb7cf0d82 Mon Sep 17 00:00:00 2001 From: Jonas Earendel Date: Wed, 14 Feb 2024 17:53:32 +0100 Subject: [PATCH] Dev (#69) * more tests * enhanceSortableAccessibility can hopefully be imported better * main and module fields in package.json + version bump --- CHANGELOG.md | 7 +++ README.md | 9 +++- enhanceSortableAccessibility.d.ts | 9 ++++ enhanceSortableAccessibility.js | 68 +++++++++++++++++++++++++++ enhanceSortableAccessibility.min.js | 1 + package.json | 4 +- rollup.config.js | 28 ++++++++--- sortable.a11y.d.ts | 1 + sortable.a11y.js | 5 +- sortable.a11y.min.js | 4 +- sortable.d.ts | 38 +++++++++++++++ sortable.js | 2 +- src/enhanceSortableAccessibility.ts | 5 +- src/sortable.test.html | 4 +- src/sortable.test.js | 72 ++++++++++++++++++++++++++++- src/sortable.ts | 2 +- tsconfig.json | 3 +- 17 files changed, 241 insertions(+), 21 deletions(-) create mode 100644 enhanceSortableAccessibility.d.ts create mode 100644 enhanceSortableAccessibility.js create mode 100644 enhanceSortableAccessibility.min.js create mode 100644 sortable.a11y.d.ts create mode 100644 sortable.d.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 64d3ed4..df9b4f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [3.2.0] - 2024-02-14 + +### Added + +- Introduced `main` and `module` fields in `package.json` to enhance compatibility with modern JavaScript tooling and environments. + ## [3.1.0] - 2023-11-16 ### Changed @@ -118,6 +124,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 This CHANGELOG.md was generated with the assistance of [ChatGPT by OpenAI](https://www.openai.com/research/chatgpt). +[3.2.0]: https://github.com/tofsjonas/sortable/releases/tag/3.2.0 [3.1.0]: https://github.com/tofsjonas/sortable/releases/tag/3.1.0 [3.0.0]: https://github.com/tofsjonas/sortable/releases/tag/3.0.0 [2.4.0]: https://github.com/tofsjonas/sortable/releases/tag/2.4.0 diff --git a/README.md b/README.md index 69bcc14..9fc3995 100755 --- a/README.md +++ b/README.md @@ -406,12 +406,19 @@ Sortable is not very accessible in its raw form. It does not support screen read By including the file the global function `enhanceSortableAccessibility` will automatically run through all existing `.sortable` tables, but you can also run it manually, like so: -```javascript +```js enhanceSortableAccessibility([table1, table2,...etc.]) ``` The function adds an `aria-label` to each th, as well as `tabindex="0"` to each th in the thead of each table, making it possible to tab through the headers. It updates the `aria-label` depending on the direction. +if you want to import it instead this _should_ work: (I haven't tested it) + +```ts +import { enhanceSortableAccessibility } from 'sortable-tablesort/enhanceSortableAccessibility' +enhanceSortableAccessibility([table1, table2,...etc.]) +``` + ## Sort on load If you wish to sort a table on load, I would recommend doing something like this: diff --git a/enhanceSortableAccessibility.d.ts b/enhanceSortableAccessibility.d.ts new file mode 100644 index 0000000..842df01 --- /dev/null +++ b/enhanceSortableAccessibility.d.ts @@ -0,0 +1,9 @@ +/** + * This is a "plugin" for the sortable package: + * https://www.npmjs.com/package/sortable-tablesort + * https://github.com/tofsjonas/sortable + * + * Enhances the accessibility of class="sortable" tables by adding ARIA attributes and keyboard event listeners. + * @param tables - A list of HTML table elements to enhance. + */ +export declare const enhanceSortableAccessibility: (tables: NodeListOf) => void; diff --git a/enhanceSortableAccessibility.js b/enhanceSortableAccessibility.js new file mode 100644 index 0000000..1ecfdc2 --- /dev/null +++ b/enhanceSortableAccessibility.js @@ -0,0 +1,68 @@ +/** + * This is a "plugin" for the sortable package: + * https://www.npmjs.com/package/sortable-tablesort + * https://github.com/tofsjonas/sortable + * + * Enhances the accessibility of class="sortable" tables by adding ARIA attributes and keyboard event listeners. + * @param tables - A list of HTML table elements to enhance. + */ +var enhanceSortableAccessibility = function (tables) { + /** + * Generates an aria-label attribute for a table header cell based on its content and current sort direction. + * @param element - The table header cell to update. + * @param default_direction - The default sort direction for the table. + */ + function updateAriaLabel(element, default_direction) { + var _a; + if (default_direction === void 0) { default_direction = ''; } + // Generate aria-label based on header content + var header_text = element.textContent || 'element'; + var current_direction = (_a = element.getAttribute('aria-sort')) !== null && _a !== void 0 ? _a : ''; + var new_direction = 'descending'; + if (current_direction === 'descending' || (default_direction && current_direction !== 'ascending')) { + new_direction = 'ascending'; + } + var aria_label = "Click to sort table by ".concat(header_text, " in ").concat(new_direction, " order"); + element.setAttribute('aria-label', aria_label); + // element.setAttribute('title', aria_label) REMEMBER TO COMMENT OUT WHEN NOT TESTING!! + } + /** + * Handles keyboard events on table header cells and triggers a click event when the Enter key is pressed. + * @param event - The keyboard event to handle. + */ + function handleKeyDown(event) { + if (event.key === 'Enter') { + var element = event.target; + element.click(); + } + } + // Iterate over each table in the input list + tables.forEach(function (table) { + var default_direction = table.classList.contains('asc') ? 'ascending' : ''; + var headers = table.querySelectorAll('th'); + // Iterate over each header cell in the table + headers.forEach(function (header) { + var element = header; + // Skip if the header cell already has a tabindex attribute + if (element.hasAttribute('tabindex')) + return; + var update = function () { + updateAriaLabel(element, default_direction); + }; + // Add tabindex attribute and generate initial aria-label attribute + element.setAttribute('tabindex', '0'); + update(); + // Attach click event listener to update aria-label attribute + element.addEventListener('click', function () { + // Add a delay to allow the new sort order to be applied + setTimeout(update, 50); + }); + // Attach focus event listener to update aria-label attribute + element.addEventListener('focus', update); + // Attach keyboard event listener to trigger click event + element.addEventListener('keydown', handleKeyDown); + }); + }); +}; + +export { enhanceSortableAccessibility }; diff --git a/enhanceSortableAccessibility.min.js b/enhanceSortableAccessibility.min.js new file mode 100644 index 0000000..56229c3 --- /dev/null +++ b/enhanceSortableAccessibility.min.js @@ -0,0 +1 @@ +var t=function(t){function e(t){'Enter'===t.key&&t.target.click()}t.forEach((function(t){var n=t.classList.contains('asc')?'ascending':'';t.querySelectorAll('th').forEach((function(t){var i=t;if(!i.hasAttribute('tabindex')){var a=function(){!function(t,e){var n;void 0===e&&(e='');var i=t.textContent||'element',a=null!==(n=t.getAttribute('aria-sort'))&&void 0!==n?n:'',c='descending';('descending'===a||e&&'ascending'!==a)&&(c='ascending');var r='Click to sort table by '.concat(i,' in ').concat(c,' order');t.setAttribute('aria-label',r)}(i,n)};i.setAttribute('tabindex','0'),a(),i.addEventListener('click',(function(){setTimeout(a,50)})),i.addEventListener('focus',a),i.addEventListener('keydown',e)}}))}))};export{t as enhanceSortableAccessibility}; diff --git a/package.json b/package.json index e943cd4..d405607 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "sortable-tablesort", - "version": "3.1.0", + "version": "3.2.0", "description": "A tiny, Vanilla/Plain JavaScript table sorter", "author": "Jonas Earendel", "license": "Unlicense", @@ -9,6 +9,8 @@ "type": "git", "url": "git+https://github.com/tofsjonas/sortable.git" }, + "main": "sortable.min.js", + "module": "sortable.min.js", "keywords": [ "sort", "html", diff --git a/rollup.config.js b/rollup.config.js index b59bfcd..aa5be1c 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -28,24 +28,38 @@ export default [ plugins: [typescript()], }, { - input: './src/sortable.a11y.ts', + input: './src/sortable.ts', output: { - file: './sortable.a11y.js', + file: './sortable.min.js', + }, + plugins: [typescript(), terser(terser_config)], + }, + { + input: './src/enhanceSortableAccessibility.ts', + output: { + file: './enhanceSortableAccessibility.js', }, plugins: [typescript()], }, - // We will build these using closure compiler before pushing, but it's nice to have them { - input: './src/sortable.a11y.ts', + input: './src/enhanceSortableAccessibility.ts', output: { - file: './sortable.a11y.min.js', + file: './enhanceSortableAccessibility.min.js', }, plugins: [typescript(), terser(terser_config)], }, { - input: './src/sortable.ts', + input: './src/sortable.a11y.ts', output: { - file: './sortable.min.js', + file: './sortable.a11y.js', + }, + plugins: [typescript()], + }, + // We will build these using closure compiler before pushing, but it's nice to have them + { + input: './src/sortable.a11y.ts', + output: { + file: './sortable.a11y.min.js', }, plugins: [typescript(), terser(terser_config)], }, diff --git a/sortable.a11y.d.ts b/sortable.a11y.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/sortable.a11y.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/sortable.a11y.js b/sortable.a11y.js index 920f9f8..479f314 100644 --- a/sortable.a11y.js +++ b/sortable.a11y.js @@ -24,7 +24,7 @@ var enhanceSortableAccessibility = function (tables) { } var aria_label = "Click to sort table by ".concat(header_text, " in ").concat(new_direction, " order"); element.setAttribute('aria-label', aria_label); - element.setAttribute('title', aria_label); + // element.setAttribute('title', aria_label) REMEMBER TO COMMENT OUT WHEN NOT TESTING!! } /** * Handles keyboard events on table header cells and triggers a click event when the Enter key is pressed. @@ -43,6 +43,9 @@ var enhanceSortableAccessibility = function (tables) { // Iterate over each header cell in the table headers.forEach(function (header) { var element = header; + // Skip if the header cell already has a tabindex attribute + if (element.hasAttribute('tabindex')) + return; var update = function () { updateAriaLabel(element, default_direction); }; diff --git a/sortable.a11y.min.js b/sortable.a11y.min.js index 97384a7..f688289 100644 --- a/sortable.a11y.min.js +++ b/sortable.a11y.min.js @@ -1,2 +1,2 @@ -var enhanceSortableAccessibility=function(g){function h(d){"Enter"===d.key&&d.target.click()}g.forEach(function(d){var k=d.classList.contains("asc")?"ascending":"";d.querySelectorAll("th").forEach(function(a){var e=function(){var b=k,c;void 0===b&&(b="");var l=a.textContent||"element",f=null!==(c=a.getAttribute("aria-sort"))&&void 0!==c?c:"";c="descending";if("descending"===f||b&&"ascending"!==f)c="ascending";b="Click to sort table by ".concat(l," in ").concat(c," order");a.setAttribute("aria-label", -b);a.setAttribute("title",b)};a.setAttribute("tabindex","0");e();a.addEventListener("click",function(){setTimeout(e,50)});a.addEventListener("focus",e);a.addEventListener("keydown",h)})})};document.addEventListener("DOMContentLoaded",function(){enhanceSortableAccessibility(document.querySelectorAll(".sortable"))}); +var enhanceSortableAccessibility=function(g){function h(c){"Enter"===c.key&&c.target.click()}g.forEach(function(c){var k=c.classList.contains("asc")?"ascending":"";c.querySelectorAll("th").forEach(function(a){if(!a.hasAttribute("tabindex")){var e=function(){var d=k,b;void 0===d&&(d="");var l=a.textContent||"element",f=null!==(b=a.getAttribute("aria-sort"))&&void 0!==b?b:"";b="descending";if("descending"===f||d&&"ascending"!==f)b="ascending";d="Click to sort table by ".concat(l," in ").concat(b," order"); +a.setAttribute("aria-label",d)};a.setAttribute("tabindex","0");e();a.addEventListener("click",function(){setTimeout(e,50)});a.addEventListener("focus",e);a.addEventListener("keydown",h)}})})};document.addEventListener("DOMContentLoaded",function(){enhanceSortableAccessibility(document.querySelectorAll(".sortable"))}); diff --git a/sortable.d.ts b/sortable.d.ts new file mode 100644 index 0000000..9f22067 --- /dev/null +++ b/sortable.d.ts @@ -0,0 +1,38 @@ +/** + * sortable v3.2.0 + * + * https://www.npmjs.com/package/sortable-tablesort + * https://github.com/tofsjonas/sortable + * + * Makes html tables sortable, No longer ie9+ 😢 + * + * Styling is done in css. + * + * Copyleft 2017 Jonas Earendel + * + * This is free and unencumbered software released into the public domain. + * + * Anyone is free to copy, modify, publish, use, compile, sell, or + * distribute this software, either in source code form or as a compiled + * binary, for any purpose, commercial or non-commercial, and by any + * means. + * + * In jurisdictions that recognize copyright laws, the author or authors + * of this software dedicate any and all copyright interest in the + * software to the public domain. We make this dedication for the benefit + * of the public at large and to the detriment of our heirs and + * successors. We intend this dedication to be an overt act of + * relinquishment in perpetuity of all present and future rights to this + * software under copyright law. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * For more information, please refer to + * + */ diff --git a/sortable.js b/sortable.js index a3e928f..f8afcd2 100644 --- a/sortable.js +++ b/sortable.js @@ -1,5 +1,5 @@ /** - * sortable v3.1.0 + * sortable v3.2.0 * * https://www.npmjs.com/package/sortable-tablesort * https://github.com/tofsjonas/sortable diff --git a/src/enhanceSortableAccessibility.ts b/src/enhanceSortableAccessibility.ts index b5b622f..1453b2b 100644 --- a/src/enhanceSortableAccessibility.ts +++ b/src/enhanceSortableAccessibility.ts @@ -26,7 +26,7 @@ export const enhanceSortableAccessibility = (tables: NodeListOf { const element = header as HTMLTableCellElement + // Skip if the header cell already has a tabindex attribute + if (element.hasAttribute('tabindex')) return + const update = () => { updateAriaLabel(element, default_direction) } diff --git a/src/sortable.test.html b/src/sortable.test.html index 41567e9..2b34106 100644 --- a/src/sortable.test.html +++ b/src/sortable.test.html @@ -187,9 +187,7 @@

Ascending sort

- - -