Using the autodivider feature in jQuery Mobile

This post is more than 2 years old.

A few days ago a reader asked me an interesting question. He wanted to create a list of dates in jQuery Mobile and group them by date. Turns out, this is fairly easy using the Autodividers feature of the ListView widget.

jQuery Mobile has supported dividers in lists for a while now, but recent editions added support for creating them automatically. Out of the box, jQuery Mobile will create dividers based on the first letter of the list item. Consider this example.

<ul data-role="listview" data-inset="true" data-autodividers="true">
	<li>Benedict</li>
	<li>Bleys</li>
	<li>Brand</li>
	<li>Caine</li>
	<li>Corwin</li>
	<li>Eric</li>
	<li>Gerard</li>
	<li>Julian</li>
	<li>Random</li>
</ul>

By adding autodividers="true" to the list, you get dividers based on the first letter in each name above.

So the obvious next question is - how do you create dividers based on some other form of grouping - like dates? Luckily jQuery Mobile's listview widget gives you an easy way to handle this.

You simply take the listview widget and define a function that returns the "selector" for an item. In abstract, it would look like this:

$("some selector").listview({
	autodividers:true,
	autodividersSelector: function ( li ) {
		// "li" is the list item, you can get the text via li.text()
		// and then you return whatever you want - in text that is
		return li.text().substring(0,1).toUpperCase();
	}
}).listview("refresh");

The method above should work the same as the default behavior. Get the first letter and upper case it. (I typed this without actually running it so if there is a typo above blame my laziness.)

In order to support our date grouping, we can use this method and JavaScript date methods. Let's look at a full example. First, the HTML. Note that I've made an empty list widget that will store my data.

<!DOCTYPE html> 
<html>
    
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1"> 
        <title>Divide Demo</title>
        <link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.css" />
        <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
        <script src="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js"></script>
    </head> 
    
    <body> 
        
        <div data-role="page" id="mainPage" >
            
            <div data-role="header">
                <h1>Our Events</h1>
            </div>
            
            <div data-role="content">
				<ul data-role="listview" data-inset="true" id="dates" data-autodividers="true">
				</ul>
            </div>
            
            <div data-role="footer">
                <h4>Footer content</h4>
            </div>
            
        </div>

		<script src="datestuff.js"></script>

	</body>
</html>

Now let's look at the JavaScript.

/* global $,document,console,quizMaster */
$(document).ready(function() {

	var dates = [
		"12/16/2013 12:00:00",
		"12/16/2013 14:00:00",
		"12/17/2013 12:00:00",
		"12/18/2013 12:00:00",
		"12/19/2013 12:00:00",
		"12/19/2013 16:00:00"
	];
	
	var dateList = $("#dates");
	for(var i=0, len=dates.length; i<len; i++) {
		dateList.append("<li>"+dates[i]+"</li>");	
	}
		
	dateList.listview({
		autodividers:true,
		autodividersSelector: function ( li ) {
			var d = new Date(li.text());
			return (d.getMonth()+1)+ "/" + d.getDate() + "/" + d.getFullYear();
		}
	}).listview("refresh");

});

At the top I've got a set of hard coded dates. These would typically be loaded via Ajax. I loop over them and insert them into the list. Once I've got that I can then initialize my listview and define a custom selector. As I mentioned above, I can use JavaScript date methods to return a string based on just the date portion of the date values I had above. (In other words, ignore the time.) I can also do some formatting on the date to make it look nice. Here is the final result.

You can run a full demo of this below.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Claude Raiola posted on 12/18/2013 at 1:19 PM

Hi Ray,

thanks for this

is it possible just to display the time in the list not repeat the date given the date is already in the divider

Comment 2 by Raymond Camden posted on 12/18/2013 at 5:18 PM

Yes. See my code that loops over the dates and inserts them? Just modify that. The code would be similar to the autodivider code. Ie, get the parts out of the date you want to use.

Comment 3 by Fher posted on 11/18/2014 at 10:59 PM

Hi, How to addd Bubble counts to the dividers? Thanl You.

Comment 4 by Raymond Camden posted on 11/18/2014 at 11:01 PM

It is possible but a bit more complex. The custom function is called for every item. The function returns a unique string that is used for dividers. In order to support what you want, you would need to access the global list, figure out the total for matched items, and return that.

So possible, but need a bit of work in the function.

Comment 5 by Raymond Camden posted on 11/18/2014 at 11:01 PM

Actually, let me work up a demo for this.

Comment 6 by Fher posted on 11/18/2014 at 11:15 PM

Thank you Raymond!! I'm trying.... too!

Comment 7 by Raymond Camden posted on 11/19/2014 at 2:08 AM

Unfortunately, you only get to return the text used in the divider, not the html. So I can make it return "Foo (X)", but X won't be a list bubble like how jQM does elsewhere.

Comment 8 by Fher posted on 11/19/2014 at 2:20 AM

Soo sad...

Comment 9 by Raymond Camden posted on 11/19/2014 at 2:24 AM

Still going to make a demo.

Comment 10 by Raymond Camden posted on 11/19/2014 at 2:43 AM

Note that if you don't use autodividers and generate 'regular' dividers, you can do it that way as well, but it will be more involved.

Comment 11 by Fher posted on 11/19/2014 at 2:52 AM

Ray, please look at this, I am trying by this way,but i dont know how count...

$actualtab.on("afterRefresh", function(){
$(".ui-li-divider").each(function(){
var count = document.createElement('span');
$(count).addClass('ui-li-count');
$(this).append(count);
});
}) ;

$actualtab.listview({
autodividers:true,
autodividersSelector: function ( li ) {

var d= li.find("p[id='date']").text();
return d;
}
}).listview("refresh").trigger("afterRefresh");

Comment 12 by Raymond Camden posted on 11/19/2014 at 2:59 AM

@Fher - I'm literately hitting Submit on the blog post now - see my newest entry.

Comment 13 by Fher posted on 11/19/2014 at 3:13 AM

I am going to try that!!!