Ordering sequence plugin
I recently had an interesting question from a developer who wanted to show their end users a visual representation of the ordering sequence applied to a DataTable when multi-column ordering. For example, if you have two columns in the ordering, it can be useful to know which one DataTables is using for the primary order, and which for the secondary.
DataTable's default styling does include shading for cells in an ordered column, but the difference between primary and secondary ordering is intentionally subtle. To make it stand out more, I came up with the idea of showing a number label next to the order indicator. In the example below the first and second columns are used for primary and secondary ordering respectively and you can see the number at the top of each column:
Name | Position | Office | Salary |
---|---|---|---|
Tiger Nixon | System Architect | Edinburgh | $320,800 |
Garrett Winters | Accountant | Tokyo | $170,750 |
Ashton Cox | Junior Technical Author | San Francisco | $86,000 |
Cedric Kelly | Senior Javascript Developer | Edinburgh | $433,060 |
Airi Satou | Accountant | Tokyo | $162,700 |
Brielle Williamson | Integration Specialist | New York | $372,000 |
Herrod Chandler | Sales Assistant | San Francisco | $137,500 |
Rhona Davidson | Integration Specialist | Tokyo | $327,900 |
Colleen Hurst | Javascript Developer | San Francisco | $205,500 |
Sonya Frost | Software Engineer | Edinburgh | $103,600 |
Jena Gaines | Office Manager | London | $90,560 |
Quinn Flynn | Support Lead | Edinburgh | $342,000 |
Charde Marshall | Regional Director | San Francisco | $470,600 |
Haley Kennedy | Senior Marketing Designer | London | $313,500 |
Tatyana Fitzpatrick | Regional Director | London | $385,750 |
Michael Silva | Marketing Designer | London | $198,500 |
Paul Byrd | Chief Financial Officer (CFO) | New York | $725,000 |
Gloria Little | Systems Administrator | New York | $237,500 |
Bradley Greer | Software Engineer | London | $132,000 |
Dai Rios | Personnel Lead | Edinburgh | $217,500 |
Jenette Caldwell | Development Lead | New York | $345,000 |
Yuri Berry | Chief Marketing Officer (CMO) | New York | $675,000 |
Caesar Vance | Pre-Sales Support | New York | $106,450 |
Doris Wilder | Sales Assistant | Sydney | $85,600 |
Angelica Ramos | Chief Executive Officer (CEO) | London | $1,200,000 |
Gavin Joyce | Developer | Edinburgh | $92,575 |
Jennifer Chang | Regional Director | Singapore | $357,650 |
Brenden Wagner | Software Engineer | San Francisco | $206,850 |
Fiona Green | Chief Operating Officer (COO) | San Francisco | $850,000 |
Shou Itou | Regional Marketing | Tokyo | $163,000 |
Michelle House | Integration Specialist | Sydney | $95,400 |
Suki Burks | Developer | London | $114,500 |
Prescott Bartlett | Technical Author | London | $145,000 |
Gavin Cortez | Team Leader | San Francisco | $235,500 |
Martena Mccray | Post-Sales support | Edinburgh | $324,050 |
Unity Butler | Marketing Designer | San Francisco | $85,675 |
Howard Hatfield | Office Manager | San Francisco | $164,500 |
Hope Fuentes | Secretary | San Francisco | $109,850 |
Vivian Harrell | Financial Controller | San Francisco | $452,500 |
Timothy Mooney | Office Manager | London | $136,200 |
Jackson Bradshaw | Director | New York | $645,750 |
Olivia Liang | Support Engineer | Singapore | $234,500 |
Bruno Nash | Software Engineer | London | $163,500 |
Sakura Yamamoto | Support Engineer | Tokyo | $139,575 |
Thor Walton | Developer | New York | $98,540 |
Finn Camacho | Support Engineer | San Francisco | $87,500 |
Serge Baldwin | Data Coordinator | Singapore | $138,575 |
Zenaida Frank | Software Engineer | New York | $125,250 |
Zorita Serrano | Software Engineer | San Francisco | $115,000 |
Jennifer Acosta | Junior Javascript Developer | Edinburgh | $75,650 |
Cara Stevens | Sales Assistant | New York | $145,600 |
Hermione Butler | Regional Director | London | $356,250 |
Lael Greer | Systems Administrator | London | $103,500 |
Jonas Alexander | Developer | San Francisco | $86,500 |
Shad Decker | Regional Director | Edinburgh | $183,000 |
Michael Bruce | Javascript Developer | Singapore | $183,000 |
Donna Snider | Customer Support | New York | $112,000 |
Use shift click on the column headers to trigger multi-column ordering on the table, and note the indicators change. When ordering is applied to a single column only, no additional indicator is shown.
Usage
Before detailing how this effect is created, let's explore how to use the OrderNumber plugin.
Initialisation
The initialisation of this example is done quite simply by enabling the new orderNumbers
option in the DataTables configuration:
new DataTable('#myTable', {
orderNumbers: true
});
And that's it!
Sources
The distribution files to include directly on your page are available on the DataTables CDN:
If you are using a bundler, this plugin is available on npm as datatables.net-feature-ordernumbers
. To use it with ES Modules, simply include the package and it will register itself as available as a feature:
import DataTable from 'datatables.net-dt';
import 'datatables.net-feature-ordernumbers';
new DataTable('#myTable', {
orderNumbers: true
});
This StackBlitz example demonstrates the new plugin being used in a Typescript + Vite build environment.
The sources for this plugin are available in the DataTables plugins git repo and are released under the MIT license.
Styling
The default CSS for the order numbers is fairly bold, as well as being black and white, with styles for both dark and light modes. You may very well wish to modify the styling to suit your own colour scheme. This can readily be done in a stylesheet with CSS variables.
OrderNumbers defines four variables that it will use to customise the colours of the indicators:
table {
--dt-order-numbers-light-color: white;
--dt-order-numbers-light-background: #555;
--dt-order-numbers-dark-color: black;
--dt-order-numbers-dark-background: #d3d3d3;
}
Modify and include in your own CSS as needed.
Creating the plugin
This plugin is primarily driven by the draw
event - listen for that on the host DataTable and insert elements into the header cells when ordering is performed on them. We can get the current order using order()
. So the plugin really boils down to:
table.on('draw', function () {
var order = table.order();
if (order.length > 1) {
for (var i = 0; i < order.length; i++) {
var col = table.column(order[i][0]);
var cell = col.header();
if (! col.visible()) {
continue;
}
$('<span>')
.addClass('dt-order-number')
.text(i + 1)
.appendTo(cell);
}
}
});
Here we loop over the 2D array given by order
and for each entry get the column in question. Line 9 confirms that the column is actually visible before displaying the number, the lines 13-16 create a simple span
and insert it into the column's header cell (given by column().header()
- line 7).
As well as creating new elements we also need to remove them. On each draw we can use a single line of jQuery to select the old elements from the header (table().header()
) and remove them from the document:
$('span.dt-order-number', table.table().header()).remove();
The only missing piece is to listen for DataTables being initialised, so we can check the initialisation options and see if we should add the draw
event listener. This we do with a init
listener on the document
, so we know when any DataTable has been initialised. Next, check if orderNumbers
was in the initialisation object (init()
) or is enabled by default - and if so, add the listener:
$(document).on('init.dt', function (e, settings) {
var api = new DataTable.Api(settings);
var enable = api.init().orderNumbers || DataTable.defaults.orderNumbers;
if (enable) {
orderNumbers(api);
}
});
Creating your own plugins
It is a fun little plugin this one, hopefully, an interesting starting point if you fancy trying your hand at your own customisations for DataTables. Perhaps it will spark an idea of what you would like to see. If it does, get in touch and share it with the community!