Friday 26th July, 2024
By Allan Jardine

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:

NamePositionOfficeSalary
Tiger NixonSystem ArchitectEdinburgh$320,800
Garrett WintersAccountantTokyo$170,750
Ashton CoxJunior Technical AuthorSan Francisco$86,000
Cedric KellySenior Javascript DeveloperEdinburgh$433,060
Airi SatouAccountantTokyo$162,700
Brielle WilliamsonIntegration SpecialistNew York$372,000
Herrod ChandlerSales AssistantSan Francisco$137,500
Rhona DavidsonIntegration SpecialistTokyo$327,900
Colleen HurstJavascript DeveloperSan Francisco$205,500
Sonya FrostSoftware EngineerEdinburgh$103,600
Jena GainesOffice ManagerLondon$90,560
Quinn FlynnSupport LeadEdinburgh$342,000
Charde MarshallRegional DirectorSan Francisco$470,600
Haley KennedySenior Marketing DesignerLondon$313,500
Tatyana FitzpatrickRegional DirectorLondon$385,750
Michael SilvaMarketing DesignerLondon$198,500
Paul ByrdChief Financial Officer (CFO)New York$725,000
Gloria LittleSystems AdministratorNew York$237,500
Bradley GreerSoftware EngineerLondon$132,000
Dai RiosPersonnel LeadEdinburgh$217,500
Jenette CaldwellDevelopment LeadNew York$345,000
Yuri BerryChief Marketing Officer (CMO)New York$675,000
Caesar VancePre-Sales SupportNew York$106,450
Doris WilderSales AssistantSydney$85,600
Angelica RamosChief Executive Officer (CEO)London$1,200,000
Gavin JoyceDeveloperEdinburgh$92,575
Jennifer ChangRegional DirectorSingapore$357,650
Brenden WagnerSoftware EngineerSan Francisco$206,850
Fiona GreenChief Operating Officer (COO)San Francisco$850,000
Shou ItouRegional MarketingTokyo$163,000
Michelle HouseIntegration SpecialistSydney$95,400
Suki BurksDeveloperLondon$114,500
Prescott BartlettTechnical AuthorLondon$145,000
Gavin CortezTeam LeaderSan Francisco$235,500
Martena MccrayPost-Sales supportEdinburgh$324,050
Unity ButlerMarketing DesignerSan Francisco$85,675
Howard HatfieldOffice ManagerSan Francisco$164,500
Hope FuentesSecretarySan Francisco$109,850
Vivian HarrellFinancial ControllerSan Francisco$452,500
Timothy MooneyOffice ManagerLondon$136,200
Jackson BradshawDirectorNew York$645,750
Olivia LiangSupport EngineerSingapore$234,500
Bruno NashSoftware EngineerLondon$163,500
Sakura YamamotoSupport EngineerTokyo$139,575
Thor WaltonDeveloperNew York$98,540
Finn CamachoSupport EngineerSan Francisco$87,500
Serge BaldwinData CoordinatorSingapore$138,575
Zenaida FrankSoftware EngineerNew York$125,250
Zorita SerranoSoftware EngineerSan Francisco$115,000
Jennifer AcostaJunior Javascript DeveloperEdinburgh$75,650
Cara StevensSales AssistantNew York$145,600
Hermione ButlerRegional DirectorLondon$356,250
Lael GreerSystems AdministratorLondon$103,500
Jonas AlexanderDeveloperSan Francisco$86,500
Shad DeckerRegional DirectorEdinburgh$183,000
Michael BruceJavascript DeveloperSingapore$183,000
Donna SniderCustomer SupportNew 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:

CSS
JS

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!