# sortable - a tiny, vanilla JS table sorter
Makes any table with **class="sortable"**, er, sortable. That is 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 needed, all is done with an **eventListener**.
(the CSS is not strictly needed, but makes it ~pretty and user friendly)
- [sortable - a tiny, vanilla JS table sorter](#sortable---a-tiny-vanilla-js-table-sorter)
- [Factoids](#factoids)
- [...with a little help from my friends](#with-a-little-help-from-my-friends)
- [Demo](#demo)
- [A basic example](#a-basic-example)
- [Non-sortable field](#non-sortable-field)
- [...using `class` and `css`](#using-class-and-css)
- [...using `css` only](#using-css-only)
- [Indicators/arrows on the left side](#indicatorsarrows-on-the-left-side)
- [Note about css/scss](#note-about-cssscss)
- [Sort on value other than the one shown](#sort-on-value-other-than-the-one-shown)
- [Alternative sorting](#alternative-sorting)
- [Specify which column should be sorted](#specify-which-column-should-be-sorted)
- [Ascending sort](#ascending-sort)
- [Sort on load](#sort-on-load)
## Factoids
- **954 bytes** minified. (545 bytes gzipped) Still under 1k! 🥳
- 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**.
- **cross browser**, ie9+ (I think, there have been a _whole_ bunch of changes since I last tested it on ie9 🤷)
- ~~eventListeners attached to the rows _WILL_ be removed~~
- eventListeners are no longer removed! 😊
- NOT tested with React, Angular, Vue, etc.
- Works with [Svelte](https://svelte.dev/)!
### ...with a little help from my friends
- `
` let's you [sort ascending](#ascending-sort) by default. Thanks [
Nikita Dunajevs](https://github.com/dunajevs)!
- `data-sort-alt` in `tbody` > `td` allows for [alternative sorting](#alternative-sorting) while holding `shift` or `alt`. Thanks [wodny](https://github.com/wodny)!
- `data-sort-col` in `thead` > `th` allows you to [specify which column should be sorted](#specify-which-column-should-be-sorted), in case you are using `colspan`, for instance. Thanks [Nick Kocharhook](https://github.com/nk9)!
- **Nested elements** inside `th` now works. Thanks [mxve](https://github.com/mxve)!
- [Sort on load](#sort-on-load) example. Thanks [Christian Petersson](https://github.com/Issen007) and [Abit Salihu](https://github.com/abitsalihu)!
- Thanks to [chatcoda](https://github.com/chatcoda) for the `
` / `
0
` sorting bug fix!
- If you have more than one ``, they will all be sorted. (Multiple ``s are not "allowed".) Thanks [GazHay](https://github.com/gazhay)!
## Demo
You can find a simple demo on
## A basic example
```html
```
_(The `span` is just there to prove that elements inside `th` works)_
## Non-sortable field
### ...using `class` and `css`
If you wish to disable sorting for a specific field, the easiest way is to add a class to it, like so:
```html
Role
Name
```
and then use css to block clicks. like so:
```css
.sortable th.no-sort {
pointer-events: none;
}
```
### ...using `css` only
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;
}
```
## 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/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
```
## Sort on value other than the one shown
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, etc.
```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
```
## Specify which column should be sorted
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
...
```
## Ascending sort
By adding `asc` to `table`, the default sorting direction will be **ascending** instead of descending
```html
...
...
```
## 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
...
```
Combine this with `
` to reverse the sort order. Or do `el.click()` twice!
[![jsdelivr](https://data.jsdelivr.com/v1/package/gh/tofsjonas/sortable/badge)](https://www.jsdelivr.com/package/gh/tofsjonas/sortable)