Blog

How to use jQuery to sort and reorganize your content

Hello!

Recently we were tasked with finding ways to re-organize search results on a Drupal page in such a way that we could prioritize, group and sort the results in a coherent way.

The simplest way to look at organizing in general, especially content that is dynamically generated, is to either adjust the query that actually produces the results (back-end) OR adjust the results with jQuery (front-end).

There are advantages and reasons why one way may be more advantageous over the other. Adjusting the query that produces the results may produce the sorted results quicker however the downside might be that making further adjustments or improvements requires extra overhead since building and executing database queries (for example) requires additional testing, QA and all that sort of stuff.

Alternatively, if you sort the content / results on your page with jQuery, it is much more flexible and easier to manipulate the results as the needs and requirements of your site or your client may change. The time to test and implement sorting and reorganizing content with jQuery is significantly lower as a result. You are also potentially reducing load off the database by executing less “expensive” queries.

So jQuery was the route to move forward with!

Make your HTML markup sort-able by jQuery

Before getting into the actual sorting and reorganizing, we need to take a look at the content to understand how to parse and shuffle it around. The best way to go about doing this is to establish a data field for each content.

In our example, the content itself is displayed on the page in the form of a styled unordered list. Below find an example of the list of content :

  • Item 1
  • Item 2
  • Item 3
  • Item 4
  • Item 5
  • Item 6
  • Item 7
  • Item 8

So painfully simple, right? Obviously this is over simplified for a reason. You have to imagine the above list being generated dynamically. In Drupal we build a pretty substantial database query with many conditions across many fields for a specific content type. The results (in our real world scenario) have 3-4 fields and an image. All contained within the li.

When producing the results, we want to be able to sort or group the results based on the taxonomy that was assigned to them. So when producing the HTML markup, we want to have a data field that identifies this. So our markup now becomes this :

  • Item 1
  • Item 2
  • Item 3
  • Item 4
  • Item 5
  • Item 6
  • Item 7
  • Item 8

So now you can see that each list item has a data-category field. We’re going to tell jQuery to use this data field to sort and re-organize our results.

Create a jQuery function to parse your HTML markup

The first thing we want to do is create a simple function that we can use to parse and re-sort all the data-category fields on the page and sort by all the matching data-category fields in ascending or descending order.

function sortMeBy(arg, sel, elem, order) {
        var $selector = $(sel),
        $element = $selector.children(elem);
        $element.sort(function(a, b) {
                var an = parseInt(a.getAttribute(arg)),
                bn = parseInt(b.getAttribute(arg));
                if (order == "asc") {
                        if (an > bn)
                        return 1;
                        if (an < bn)
                        return -1;
                } else if (order == "desc") {
                        if (an < bn)
                        return 1;
                        if (an > bn)
                        return -1;
                }
                return 0;
        });
        $element.detach().appendTo($selector);
}

What does this function do? Well it takes 4 arguments : arg, sel, elem and order. Here’s a breakdown of what each arugment is :

arg : The data-filter to parse for sorting. In our case it would be “data-category”
sel : This will be the parent selector that contains the data filter. In our case it is the class “search-results”
elem : This further narrows down the child elements within the parent selector, which is just a “li” in this case
order : This specifies the sort order. “asc” or “desc” would either be acceptable

What we want to do is trigger the newly created function and store the results in a variable :

var deferred = sortMeBy("data-category", "ul.search-results", "li", "asc");

After the function is executed, everything magically re-sorts! You probably want to encapsulate everything in a document ready function :

jQuery(document).ready(function($) {
    // add function and trigger it here
});

You might be wondering why we stored everything in a variable called “deferred”. This is because we wanted to inject the category name above all the list items that belong in that category.

What we will need to do is identify the first item in the grouped list of items within a particular category. That is because we want to inject html before that first item only (i.e. a category heading title) :

jQuery.when(deferred).done(function() {
        var arr = jQuery("[id^=result-tax]");
        for (var i = 0; i < arr.length; i++) {
                jQuery("#" + arr[i].id).first().addClass("firsttest");
        }
        jQuery(".firsttest").each(function() {
                var datatermname = jQuery(this).data(\'category\');
                jQuery(this).before("
  • " + datatermname + "

  • "); }); });

    Whats happening in the above snippet? Once the deferred variable is finished populating, we parse all the list item id’s with regex filtering “result-tax” and assigning the class “firsttest” to the first one only.

    Then we parse all the list items with the class “firsttest” , pull the category name from the data-category field and inject html before the item. The result is for all the items there will be a heading title of the category name before each grouped list.

    Hopefully this will help someone out there!