Contents
- Abstract
- Introduction
- What Natural Sorting is
- Discussing problems
- The birth of a new feature in jqGrid
- Implementation
- jqGrid code
- Data for sorting
- Data after string sorting
- Data after Natural Sorting
- What next
- Closing Notes
This entire article is discussing an actual problem and all about how the new feature "Natural Sorting" is requested and added to jqGrid. As a case study we need to implement Natural Sorting using JqGrid with ASP.NET. Through-out this project we will see how to implement it in JqGrid.
Introduction
In the current version of JqGrid we have the ability to sort our columns in a natural way. Earlier versions of JqGrid did not have that capability. In this article, we will see how this feature has been implemented in JqGrid and how to use it.
In future sections we will see how the request has been made for this new feature and how Natural Sorting works with jqGrid.
What Natural Soring is
Before going into the details of the implementation, let's first understand the term Natural Sorting. So, what is Natural Sorting?
- //Needs to sort
- 1 3 10 11 1A AA AB 2 A1
- //Alphanumeric sorting also known as string sorting
- 1 10 1A 11 2 3 AA A1 AB
- //Natural sorting
- 1 1A 2 3 10 11 A1 AA AB
Discussing the problem
Now to return to the original problem. :) I was saying, it's not possible sort our data in NaturalSort order using jqGrid before its current release version 4.6.0.
I was the main lead for the project and need to solve this issue any how and the challenge is we were not allowed to replace a jqGrid with other jQuery plugins that have a builtin NaturalSort algorithm.
I started research and found some interesting things, I found:
The preceding is only the solution for our issue, I was very excited and started the implementation, I used a custom formula with jqGrid and unfortunately it was not supported.
The birth of a new feature in jqGrid
I posted the issue in many forms and publishing/article places, including stack overflow.
Unfortunately, I did not get a solution for this issue. And then I approached Tony Move, the creator of jqGrid. Afterwards, I logged a bug for this issue at here: NaturalSort.
I do not want to to feed my own custom function into jqGrid source file(s). I can't do that; the reason is simple, it will be automatically washed-out.
When someone upgrades the jqGrid version. We have only option to wait and see when this issue will be fixed and is available with the new release of jqGrid.
Finally, on February 08, 2014, Tony Move announced the new feature here. It will make my life easier, I was very happy and waiting for the new release of jqGrid.
Implementation
This new feature has the ability to add our custom sort function; in my case I need this:
- //3 parmeters comapre values a,b and direction 1 for ascending -1 for descending
- /*
- * Natural Sort algorithm for JavaScript - Version 0.7 - Released under MIT license
- * Author: Jim Palmer (based on chunking idea from Dave Koelle)
- */
- function naturalSort (a, b, d) {
- if(d===undefined) { d=1; }
- var re = /(^-?[0-9]+(\.?[0-9]*)[df]?e?[0-9]?$|^0x[0-9a-f]+$|[0-9]+)/gi,
- sre = /(^[ ]*|[ ]*$)/g,
- dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/,
- hre = /^0x[0-9a-f]+$/i,
- ore = /^0/,
- i = function(s) { return naturalSort.insensitive && (''+s).toLowerCase() || ''+s },
- // convert all to strings strip whitespace
- x = i(a).replace(sre, '') || '',
- y = i(b).replace(sre, '') || '',
- // chunk/tokenize
- xN = x.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'),
- yN = y.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'),
- // numeric, hex or date detection
- xD = parseInt(x.match(hre)) || (xN.length != 1 && x.match(dre) && Date.parse(x)),
- yD = parseInt(y.match(hre)) || xD && y.match(dre) && Date.parse(y) || null,
- oFxNcL, oFyNcL;
- // first try and sort Hex codes or Dates
- if (yD)
- if ( xD < yD ) return -d;
- else if ( xD > yD ) return d;
- // natural sorting through split numeric strings and default strings
- for(var cLoc=0, numS=Math.max(xN.length, yN.length); cLoc < numS; cLoc++) {
- // find floats not starting with '0', string or 0 if not defined (Clint Priest)
- oFxNcL = !(xN[cLoc] || '').match(ore) && parseFloat(xN[cLoc]) || xN[cLoc] || 0;
- oFyNcL = !(yN[cLoc] || '').match(ore) && parseFloat(yN[cLoc]) || yN[cLoc] || 0;
- // handle numeric vs string comparison - number < string - (Kyle Adams)
- if (isNaN(oFxNcL) !== isNaN(oFyNcL)) { return (isNaN(oFxNcL)) ? d : -d; }
- // rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
- else if (typeof oFxNcL !== typeof oFyNcL) {
- oFxNcL += '';
- oFyNcL += '';
- }
- if (oFxNcL < oFyNcL) return -d;
- if (oFxNcL > oFyNcL) return d;
- }
- return 0;
- }
Hereunder, I will describe the following simple procedure to use this JavaScript function with jqGrid (I used Visual Studio 2013, also added a simple HTML file, so if you want you can just use the HTML file):
- Open Visual Studio.
- Choose the template of your choice (I chose ASP.Net project).
- Add the latest version of jqGrid using Nuget Packages, it will automatically add support for jQuery files.
- Add the preceding JavaScript function as an inline function in the same file or in a separate file.
- Add the code of jqgrid to call and make a call to this function.
jqgrid code
The following snippet is what the jqGrid code looks like:
- <script type="text/javascript">
- jQuery(document).ready(function () {
- jQuery("#list4").jqGrid({
- datatype: "local",
- height: 250,
- colNames: ['Inv No', 'Date', 'Natural Sort order', 'Amount', 'Tax', 'Total', 'String Sort'],
- colModel: [{ name: 'id', index: 'id', width: 60, sorttype: "int" },
- { name: 'invdate', index: 'invdate', width: 90, sorttype: "date" },
- { name: 'name', index: 'name', width: 150, sortfunc: naturalSort },
- { name: 'amount', index: 'amount', width: 80, align: "right", sorttype: "float" },
- { name: 'tax', index: 'tax', width: 80, align: "right", sorttype: "float" },
- { name: 'total', index: 'total', width: 80, align: "right", sorttype: "float" },
- { name: 'note', index: 'note', width: 150, sortable: "string" }],
- multiselect: true,
- caption: "NaturalSortOrder using jqrid"
- });
- var mydata = [
- { id: "1", invdate: "2013-10-01", name: "atest", note: "atest", amount: "200.00", tax: "10.00", total: "210.00" },
- { id: "2", invdate: "2013-10-02", name: "Atest", note: "Atest", amount: "300.00", tax: "20.00", total: "320.00" },
- { id: "3", invdate: "2013-09-01", name: "test2", note: "test2", amount: "400.00", tax: "30.00", total: "430.00" },
- { id: "4", invdate: "2013-10-04", name: "test", note: "test", amount: "200.00", tax: "10.00", total: "210.00" },
- { id: "5", invdate: "2013-10-05", name: "test2A", note: "test2A", amount: "300.00", tax: "20.00", total: "320.00" },
- { id: "6", invdate: "2013-09-06", name: "test2a", note: "test2a", amount: "400.00", tax: "30.00", total: "430.00" },
- { id: "7", invdate: "2013-10-04", name: "Test", note: "Test", amount: "200.00", tax: "10.00", total: "210.00" },
- { id: "8", invdate: "2013-10-03", name: "2", note: "2", amount: "300.00", tax: "20.00", total: "320.00" },
- { id: "9", invdate: "2013-09-01", name: "1", note: "1", amount: "400.00", tax: "30.00", total: "430.00" },
- { id: "10", invdate: "2013-09-01", name: "test34", note: "test34", amount: "400.00", tax: "30.00", total: "430.00" },
- { id: "9", invdate: "2013-09-01", name: "1test", note: "1test", amount: "400.00", tax: "30.00", total: "430.00" },
- { id: "11", invdate: "2013-09-01", name: "10", note: "10", amount: "400.00", tax: "30.00", total: "430.00" },
- { id: "12", invdate: "2013-09-01", name: "test33", note: "test33", amount: "400.00", tax: "30.00", total: "430.00" },
- { id: "13", invdate: "2013-09-01", name: "Test1", note: "Test1", amount: "400.00", tax: "30.00", total: "430.00" },
- { id: "14", invdate: "2013-09-01", name: "BTest", note: "BTest", amount: "400.00", tax: "30.00", total: "430.00" },
- { id: "15", invdate: "2013-09-01", name: "3", note: "3", amount: "400.00", tax: "30.00", total: "430.00" }];
- for (var i = 0; i <= mydata.length; i++)
- jQuery("#list4").jqGrid('addRowData', i + 1, mydata[i]);
- });
- </script>
Data for sorting
We have the following data that needs to be sorted the Natural way:

Data after string sorting
After String Sorting we have the following data:

Data after Natural Sorting
Here is data after Natural Sorting with the new feature of jqGrid:

To use a natural sort with jqgrid, we need to write it this way:
- { name: 'name', index: 'name', width: 150, sortfunc: naturalSort }
See in the sortfunc above, it is telling jqGrid that we need to use a naturalSort for our custom sort function. Isn't it easy?
What to do next?
See the latest release and its documentation, here:
The full source code is shown here, it is available at: jqGridNaturalSortOrder.
Closing Notes
- In this entire article we saw how Natural sorting was invented as a new feature in jqGrid.
- How to use it.
- How it works.

Shuby AroraPosted Feb 5, 2015, 2:30 PM
short and good one
Gaurav Kumar AroraPosted Jan 24, 2015, 1:12 PM
Manish Kumar Choudhary thanks glad to read you liked it.
Manish Kumar ChoudharyPosted Jan 24, 2015, 9:38 AM
Nice and very helpful article for me. Thanks for sharing Gaurav Kumar Arora sir.