Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/tofsjonas/sortable

Vanilla JavaScript table sort
https://github.com/tofsjonas/sortable

event-listener javascript sort sortable table table-sorting tablesort tablesorter tiny vanilla-javascript vanilla-js

Last synced: about 2 months ago
JSON representation

Vanilla JavaScript table sort

Awesome Lists containing this project

README

        

sortable


- a tiny, vanilla/plain JavaScript table sorter

![GitHub Issues or Pull Requests](https://img.shields.io/github/issues/tofsjonas/sortable) ![NPM Version](https://img.shields.io/npm/v/sortable-tablesort) ![NPM Downloads](https://img.shields.io/npm/dw/sortable-tablesort) ![GitHub Repo stars](https://img.shields.io/github/stars/tofsjonas/sortable) [![jsdelivr](https://data.jsdelivr.com/v1/package/gh/tofsjonas/sortable/badge)](https://www.jsdelivr.com/package/gh/tofsjonas/sortable)

Makes any table with **class="sortable"**, er, sortable. The user can click on a table header and change the sorting of the table rows.

Just include the JavaScript and it will work. No function calls are needed, everything is handled by an **eventListener**.

Demo

You can find a simple demo on

Table of Contents

- [Factoids](#factoids)
- ["Installation"](#installation)
- [1. link to jsDelivr](#1-link-to-jsdelivr)
- [2. copy file to assets folder](#2-copy-file-to-assets-folder)
- [3. npm package](#3-npm-package)
- [a) use links in the html](#a-use-links-in-the-html)
- [b) import files in javascript](#b-import-files-in-javascript)
- [Non-sortable field](#non-sortable-field)
- [...using `class="no-sort"`](#using-classno-sort)
- [...using `CSS`](#using-css)
- [...using `td` instead of `th`](#using-td-instead-of-th)
- [Indicators/arrows on the left side](#indicatorsarrows-on-the-left-side)
- [NOTE ABOUT CSS/SCSS](#note-about-cssscss)
- [Sorting sizes, dates and such](#sorting-sizes-dates-and-such)
- [Alternative sorting](#alternative-sorting)
- [Colspans/Sort on specific column](#colspanssort-on-specific-column)
- [Concerning `rowspan`](#concerning-rowspan)
- [Ascending sort](#ascending-sort)
- [Tiebreaker / secondary sort](#tiebreaker--secondary-sort)
- [Empty/null rows always last](#emptynull-rows-always-last)
- [Accessibility](#accessibility)
- [Sort on load](#sort-on-load)
- [Thank you...](#thank-you)

## Factoids

- **1148 bytes** minified. (619 bytes gzipped)

- Works with **JavaScript generated tables**. (since we are using an eventListener)

- **Lightning fast**. _Huge_ tables will make it slow and may freeze the browser, especially for mobiles, so you know...

- Requires **thead** and **tbody**.

- **rowspan** is not supported 😒

- **cross browser**, ~~ie9+~~ No longer ie9 compatible. Then again, maybe it already wasn't 🀷

- NOT tested with React, Angular, Vue, etc.

- Works with [Svelte](https://svelte.dev/)!

## "Installation"

There are three ways to use sortable, all of which have their pros and cons. [S Anand](https://github.com/sanand0) and [dkhgh](https://github.com/dkhgh) had some [interesting thoughts](https://github.com/tofsjonas/sortable/issues/28) about it.

1. Include a link to [jsDelivr](https://www.jsdelivr.com/package/gh/tofsjonas/sortable). (easiest)

2. Copy the file from [jsDelivr](https://www.jsdelivr.com/package/gh/tofsjonas/sortable) or [Github](https://github.com/tofsjonas/sortable) and put it in your assets folder. (in between)

3. Install the [npm package](https://www.npmjs.com/package/sortable-tablesort). (most reliable)

### 1. link to jsDelivr

```html



Role
Name




Genius
Rick


Sidekick
Morty

```

The `span` on line four is just there to prove that you can have elements inside `th`!

⚠️ _If you are concerned about bugs, I recommend using version numbers instead of "latest"._

### 2. copy file to assets folder

Same as above, but link to your own files

```html
...

...
```

### 3. npm package

First,

```bash
npm install sortable-tablesort
# yarn add sortable-tablesort
# pnpm install sortable-tablesort
```

Now you can

#### a) use links in the html

Same as above, with links to files

```html
...

...
```

or

#### b) import files in javascript

```javascript
// main.js
import 'sortable-tablesort/sortable.min.css'
import 'sortable-tablesort/sortable.min.js'
```

## Non-sortable field

### ...using `class="no-sort"`

If you wish to disable sorting for a specific field, the easiest (and best) way is to add `class="no-sort"` to it, like so:

```html


Role
Name

```

Sorting will not be triggered if you click on "Role".

### ...using `CSS`

This is a bit trickier, but it doesn't require any changes to the html, so I guess it could be worth it in some cases.

```css
/* the first column in every sortable table should not be sortable*/
.sortable th:nth-child(1) {
pointer-events: none;
}

/* the seventh column in the second .sortable table should not be sortable*/
.sortable:nth-of-type(2) th:nth-child(7) {
pointer-events: none;
}
```

### ...using `td` instead of `th`

The eventListener only triggers on `th`, not `td`, so this would disable sorting for "Role":

```html


Role
Name

```

⚠️ _Since `th` and `td` are not the same thing, you would most likely still have to use CSS to make them look the way you want. (It might also mess with accessibility.) In **some** cases it could be worth it, but I recommend the `.no-sort` alternative_.

## Indicators/arrows on the left side

If you have text that is aligned on the right side, you may want to have the arrows on the left side.

This is solved by adding a class to the css and using `::before` instead of `::after`.

(You can of course use a pure css solution, without class names - just like with the [non-sortable field](#non-sortable-field) - but _that_ I will leave for you to figure out.)

```css
.sortable th.indicator-left::after {
content: '';
}
.sortable th.indicator-left::before {
margin-right: 3px;
content: 'β–Έ';
}
/* etc. */
```

> _Full example: [CSS](https://github.com/tofsjonas/sortable/blob/main/sortable-base.css), [SCSS](https://github.com/tofsjonas/sortable/blob/main/src/sortable-base.scss)_

## NOTE ABOUT CSS/SCSS

The `css/scss` in this repo was only ever meant as an example. It was never intended to be actually _used_.

That said, if you're feeling lazy, here are two stylesheets you can use:

```html

```

## Sorting sizes, dates and such

Using the `data-sort` attribute in `tbody` > `td` you can have one visible value and one sortable value. This is useful in case you have for instance sizes like kb, Mb, GB, or really weird date formats. πŸ˜‰

```html



Movie Name
Size
Release date




Zack Snyder's Justice League
900MB
03/18/2021


The Sound of Music
1.5GB
12/09/1965

```

## Alternative sorting

If you click on a table header while holding **shift** or **alt** an alternative
`data-sort-alt` attribute will override `data-sort`.

```html



Movie Name
Size
Release date




Something
A
B
C


Something else
D
E
F

```

## Colspans/Sort on specific column

Using the `data-sort-col` attribute in `thead` > `th`, you can sort on a different column than the one that was clicked. For instance if you want to have colspans. Like so:

```html



Category
Show
Overall
On Our Dates
First Sold Out


Β 
Comedy
Show 1
18/25
72%
3/4
75%
2022-07-30

...

```

## Concerning `rowspan`

Rowspans are not supported. Maybe I could do a half-assed implementation, but I don't think it would be worth it. You can read my justification in [Issue 71](https://github.com/tofsjonas/sortable/issues/71)

If you have a good idea, please let me know!

## Ascending sort

By adding `asc` to `table`, the default sorting direction will be **ascending** instead of descending

```html


...


...

```

## Tiebreaker / secondary sort

If you wish to sort by a different column when two values are equal, you can use the `data-sort-tbr` attribute, like so:

```html



Year
Month
Day




2010
07
25


2010
11
12


2010
04
25

```

When clicking **Year**, if they are the same, we will sort on **Month**.

## Empty/null rows always last

Adding `class="n-last"` to `` will make empty/null values always be sorted last, similar to what SQL does with `ORDER BY foo NULLS LAST`.

```html



Text
Number




jkl
0.4


This will always be sorted after the others



abc
0


def
0.2

```

⚠️ _Note that a string of blank spaces is **not** considered null/empty. `` will be sorted normally._

## Accessibility

Sortable is not very accessible in its raw form. It does not support screen readers, and it does not have any keyboard support. Including `sortable.a11y.min.js` in your project will add some basic accessibility features.

```html

...

```

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:

```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:

```html



Movie Name
Size
Release date



...

window.addEventListener('load', function () {
const el = document.getElementById('movie-size')
// without id:
// const el = document.querySelector('.sortable th:first-child')
// const el = document.querySelector('.sortable th:nth-child(2)')
// const el = document.querySelectorAll('.sortable')[3].querySelector('th:nth-child(7)')
// etc.
if (el) {
el.click()
}
})

```

Combine this with `` to reverse the sort order. Or do `el.click()` twice!

## Thank you...

- ...[Nikita Dunajevs](https://github.com/dunajevs) for the [ascending sort](#ascending-sort) idea!

- ...[wodny](https://github.com/wodny) for the [alternative sorting](#alternative-sorting) idea!

- ...[Nick Kocharhook](https://github.com/nk9) for the [colspan sorting](#colspanssort-on-specific-column) idea!

- ...[mxve](https://github.com/mxve) for the **nested elements** inside `th` fix!

- ...[Christian Petersson](https://github.com/Issen007) and [Abit Salihu](https://github.com/abitsalihu) for the [sort on load](#sort-on-load) example!

- ...[GazHay](https://github.com/gazhay) for the idea to sort multiple ``!

- ...[Gordan Ratkovic](https://github.com/GordanRatkovic) for the [tiebreaker / secondary sort](#tiebreaker--secondary-sort) idea!

- ...[chatcoda](https://github.com/chatcoda) for the `` / `0` sorting bug fix!

- ...[Christian Garbs](https://github.com/mmitch) for fixing the `dataset` bug!

- ...[Witold Baryluk](https://github.com/baryluk) for pointing out some inefficiencies!

- ...[Nick](https://github.com/data-handler) for raising a whole bunch of issues! 🀯️

- ...[James Pudson](https://github.com/nepsilon) for the [empty last](#emptynull-rows-always-last) suggestion, AND for finding the "`data-sort` ignored when empty" bug! πŸ₯³οΈ

- ...[Jojo-IO](https://github.com/Jojo-IO) for the finding the "`parseFloat` messes up time values" bug!

- ...[Steve Wirt](https://github.com/swirtSJW) for lifting the Accessibility issue! 🦾️