Wednesday 22nd October, 2014

Search result highlighting

DataTables' built in search features provide the ability for the end user to very quickly search the data that is contained in a table, filtering the results down into just the relevant results for what they are looking for. However, the user still needs to scan the results in order to locate the specific data they search for. Often this will not be an arduous process for the user, but in complex tables it might take them a few seconds - seconds that we can spare them by highlighting the search term in the result set!

Bartek Szopka has written a jQuery plug-in for highlighting text in any given jQuery collection of nodes which is perfect for our highlighting needs. This blog post details how the highlighting plug-in can be integrated very easily with DataTables, and ultimately creating a reusable feature plug-in for DataTables that can be used on any table very easily.

An example table using this feature plug-in is shown below - an initial search term has been entered to immediately show the results, and as you alter the search term, the highlighting will automatically update.

NamePositionOfficeAgeStart dateSalary
NamePositionOfficeAgeStart dateSalary
Tiger NixonSystem ArchitectEdinburgh612011/04/25$320,800
Garrett WintersAccountantTokyo632011/07/25$170,750
Ashton CoxJunior Technical AuthorSan Francisco662009/01/12$86,000
Cedric KellySenior Javascript DeveloperEdinburgh222012/03/29$433,060
Airi SatouAccountantTokyo332008/11/28$162,700
Brielle WilliamsonIntegration SpecialistNew York612012/12/02$372,000
Herrod ChandlerSales AssistantSan Francisco592012/08/06$137,500
Rhona DavidsonIntegration SpecialistTokyo552010/10/14$327,900
Colleen HurstJavascript DeveloperSan Francisco392009/09/15$205,500
Sonya FrostSoftware EngineerEdinburgh232008/12/13$103,600
Jena GainesOffice ManagerLondon302008/12/19$90,560
Quinn FlynnSupport LeadEdinburgh222013/03/03$342,000
Charde MarshallRegional DirectorSan Francisco362008/10/16$470,600
Haley KennedySenior Marketing DesignerLondon432012/12/18$313,500
Tatyana FitzpatrickRegional DirectorLondon192010/03/17$385,750
Michael SilvaMarketing DesignerLondon662012/11/27$198,500
Paul ByrdChief Financial Officer (CFO)New York642010/06/09$725,000
Gloria LittleSystems AdministratorNew York592009/04/10$237,500
Bradley GreerSoftware EngineerLondon412012/10/13$132,000
Dai RiosPersonnel LeadEdinburgh352012/09/26$217,500
Jenette CaldwellDevelopment LeadNew York302011/09/03$345,000
Yuri BerryChief Marketing Officer (CMO)New York402009/06/25$675,000
Caesar VancePre-Sales SupportNew York212011/12/12$106,450
Doris WilderSales AssistantSidney232010/09/20$85,600
Angelica RamosChief Executive Officer (CEO)London472009/10/09$1,200,000
Gavin JoyceDeveloperEdinburgh422010/12/22$92,575
Jennifer ChangRegional DirectorSingapore282010/11/14$357,650
Brenden WagnerSoftware EngineerSan Francisco282011/06/07$206,850
Fiona GreenChief Operating Officer (COO)San Francisco482010/03/11$850,000
Shou ItouRegional MarketingTokyo202011/08/14$163,000
Michelle HouseIntegration SpecialistSidney372011/06/02$95,400
Suki BurksDeveloperLondon532009/10/22$114,500
Prescott BartlettTechnical AuthorLondon272011/05/07$145,000
Gavin CortezTeam LeaderSan Francisco222008/10/26$235,500
Martena MccrayPost-Sales supportEdinburgh462011/03/09$324,050
Unity ButlerMarketing DesignerSan Francisco472009/12/09$85,675
Howard HatfieldOffice ManagerSan Francisco512008/12/16$164,500
Hope FuentesSecretarySan Francisco412010/02/12$109,850
Vivian HarrellFinancial ControllerSan Francisco622009/02/14$452,500
Timothy MooneyOffice ManagerLondon372008/12/11$136,200
Jackson BradshawDirectorNew York652008/09/26$645,750
Olivia LiangSupport EngineerSingapore642011/02/03$234,500
Bruno NashSoftware EngineerLondon382011/05/03$163,500
Sakura YamamotoSupport EngineerTokyo372009/08/19$139,575
Thor WaltonDeveloperNew York612013/08/11$98,540
Finn CamachoSupport EngineerSan Francisco472009/07/07$87,500
Serge BaldwinData CoordinatorSingapore642012/04/09$138,575
Zenaida FrankSoftware EngineerNew York632010/01/04$125,250
Zorita SerranoSoftware EngineerSan Francisco562012/06/01$115,000
Jennifer AcostaJunior Javascript DeveloperEdinburgh432013/02/01$75,650
Cara StevensSales AssistantNew York462011/12/06$145,600
Hermione ButlerRegional DirectorLondon472011/03/21$356,250
Lael GreerSystems AdministratorLondon212009/02/27$103,500
Jonas AlexanderDeveloperSan Francisco302010/07/14$86,500
Shad DeckerRegional DirectorEdinburgh512008/11/13$183,000
Michael BruceJavascript DeveloperSingapore292011/06/27$183,000
Donna SniderCustomer SupportNew York272011/01/25$112,000

Simple integration

The jQuery Highlight plug-in's basic operation is very simple - there are two methods:

  • $().highlight() - Highlight a search term
  • $().unhighlight() - Remove existing highlights

Only a couple of DataTables API methods and a single event are required to create an almost complete integration:

  • draw - When the table is redrawn this event will trigger and we can perform the highlighting required
  • search() - Get the search term
  • table().body() - Got the table's tbody element.

Using this we can construct:

$(document).ready( function () {
    var table = $('#myTable').DataTable();

    table.on( 'draw', function () {
        var body = $( table.table().body() );

        body.unhighlight();
        body.highlight( table.search() );   
    } );
} );

In the above code:

  • Line 2: Create a DataTable
  • Line 4: Listen for the draw event
  • Line 5: Get a reference to the table tbody node, since only nodes in this element should be highlighted.
  • Line 7: Remove any existing highlighting from a previous search
  • Line 8: Use search() to get the search term and highlight it.

For completeness a listener for the column-visibility event should also be added as column visibility toggling does not need to trigger a draw and we would want the highlighting to be applied to any column that is made visible.

Finally, the DataTables "No records found" message shouldn't be highlighted if the user enters a search term such as "records" and no rows are found! This can be done using the rows() method with the selector-modifier set to include only filtered rows in the result set:

body.unhighlight();

if ( table.rows( { filter: 'applied' } ).data().length ) {
    body.highlight( table.search() );
}

Feature plug-in

While it would be perfectly possibly to stop at this point, us software engineers hate needing to copy and paste code to reuse a feature (and rightly so, since it makes for a maintenance nightmare in future!), so now let's wrap the above code into a reusable feature plug-in for DataTables.

For this another DataTables event can be used: the init event which is triggered whenever a new DataTable is created. This event bubbles up through the DOM so a listener on the document will see every newly created DataTable in the document - i.e.:

$(document).on( 'init.dt', function (e, settings, json) {
    ...
} );

The next step is to check if the table should have row highlighting enabled on it, and if so, run the highlighting code developed above.

There are three methods by which this plug-in can be activated:

  • Adding the class searchHighlight to the HTML table
  • Setting the searchHighlight parameter in the DataTables initialisation to be true
  • Setting the searchHighlight parameter to be true in the DataTables defaults (thus causing all tables to have this feature) - i.e. $.fn.dataTable.defaults.searchHighlight = true.

Extending the init code from above to achieve this:

$(document).on( 'init.dt.dth', function (e, settings, json) {
    var table = new $.fn.dataTable.Api( settings );
    var body = $( table.table().body() );

    if (
        $( table.table().node() ).hasClass( 'searchHighlight' ) || // table has class
        settings.oInit.searchHighlight                          || // option specified
        $.fn.dataTable.defaults.searchHighlight                    // default set
    ) {
       ...
    }
} );
  • Line 1: Listen for the initialisation of a DataTable
  • Line 2: Get an DataTables API instance from the DataTable.Settings object passed into the event
  • Line 3: Get the table's body tag since we will be using it
  • Line 6: Check if the table has the class searchHighlight
  • Line 7: Check if the initialisation options had searchHighlight (a public API for this will be forthcoming)
  • Line 8: Check if the defaults have searchHighlight set
  • Line 10: Run the highlight code from above

Initialisation

In its simplest form, to activate highlighting of search terms in a table, now all we need to do is specify the searchHighlight term when initialising the table:

$(document).ready( function () {
    $('#example').DataTable( {
        searchHighlight: true
    } );
} );

The other options for giving a default or using a class name, as defined above, will also work nicely.

Released code

The code for the feature plug-in developed here is available on the DataTables CDN for immediate use:

JS
CSS

Recall also that this plug-in depends upon the jQUery Highlight plug-in:

JS

It is also hosted in the DataTables plug-ins repository on GitHub. Forks, pull requests, etc are all very welcome!