JQuery

How to sort alphanumeric values with jQuery and C#

on October 25, 2012 by Programming, Web Programming & Development with 0 comments

Sorting values on the server side is usually pretty trivial. There are a lot of tools at your disposal, not the least of which is the data query itself. When it comes to sorting an element on the front end however, it can sometimes take a little bit of clever data value usage to accomplish your goal, especially if you don’t want to make another call to the server.

For this example, let’s assume that we have a list of visitors staying at a hotel. Each visitor has a visit with basic data describing that visit, such as their name, room number, length of stay, etc. Imagine that you are laying out each of those current visits on a web application dashboard for a quick view of who is staying at the hotel at the moment. Each visit might be represented by a 200 x 200 block of data that we might call a ‘card’. Initially these cards might be sorted by Last Name but say you want to change that sort order so that it is ordered by Room Number instead. If your room numbers are plain integers this is pretty easy, but what if they consist of letters,numbers, and other special characters? For example, 407 W to represent the west wing of the building.

When I need to do some element sorting using jQuery I turn to TinySort, the fantastic plugin by Ron Valstar. It is very flexible, well documented, and at just 1kB gzipped, tiny. Out of the box, TinySort does some very good sorting, even on mixed literal and numeric strings. For example (from the TinySort docs):

mixed literal and numeral

In a normal sort the order would be a1,a11,a2 while you’d really want it to be a1,a2,a11. TinySort corrects this:

$(".visit-list ul li").tsort();
  • eed140ler111
  • eil26viu117
  • omi111jea23
  • uin115oem6
  • uin1oem121
  • uin37oem109
  • uin84oem57
  • uin84oem78
  • uin84oem88

In my use however, I was unable to get the proper sort order when numbers were followed by a blank space, then a letter, i.e “407 W”. To correct this, and to gain more control of how the objects would be sorted, I decided to use TinySort’s ability to specify what attribute I’d like to sort on. I created a custom HTML5 data element called data-room and told TinySort to use the value of that attribute when sorting:

$(".visit-list ul li").tsort({ attr: 'data-room'});

Then in my HTML I use that data element on the objects I want to sort:

<div class="visit-list">
    <ul>
        <li data-room="404 W">
            Visit Details
        </li>
    </ul>
 </div>

The next step is to control the value of that data-room attribute more precisely. In this example I’m using C#.NET MVC 4 with the Razor view engine on the server side. I want to convert the room number into a more basic form, in my case I decided to turn everything into a decimal for easy sorting. To do this, I created an extension method so that I’d have access to it conveniently throughout my application. The extension method looks like this:

        public static decimal ToSortableDecimal(this string str)
        {
            if (String.IsNullOrWhiteSpace(str))
                return 0;

            char[] alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();

            StringBuilder sb = new StringBuilder();
            foreach (var c in str.ToUpper().ToCharArray())
            {
                int result;
                if (int.TryParse(c.ToString(), out result))
                {
                    sb.Append(c);
                }
                else
                {
                    if (c == ' ' || Array.IndexOf(alpha, c) == -1)
                    { //ignore
                    }
                    else
                    {
                        if (!sb.ToString().Contains('.'))
                            sb.Append(".");

                        sb.Append(Array.IndexOf(alpha, c));
                    }
                }
            }
            return decimal.Parse(sb.ToString());
        }

When you pass a string through this function, several things happen:

  • All non alphanumeric characters are eliminated
  • If a numeric character is encountered, it is added to the decimal at the current position
  • If a letter is encountered, a decimal is added if one does not yet exist
  • If a letter is encountered, it’s position in the alphabet is determined and that index position is used in place of the letter

For example, “0965 D” becomes “965.3″ which is much easier to sort and a lot more clear in terms of how the sort will behave.

Now you just need to use this room number conversion in the HTML:

<div class="visit-list">
    <ul>
        @foreach (var visit in Model.Visits)
        {
            <li data-room="@visit.RoomNumber.ToSortableDecimal()">
                Visit Details
            </li>
        }
    </ul>
</div>

When you trigger TinySort on those elements, you will get a nice, tidy decimal sort.

The following two tabs change content below.

Matthew Mombrea

Matt is a longtime entrepreneur and software engineer. He is a founder of Cypress North, and chief technology officer. Matt also contributes to the community as a columnist on ITworld.com.

Leave a Reply