Using the autodivider feature in jQuery Mobile (take two)

This post is more than 2 years old.

Almost a year ago I blogged about using the autodivider feature in jQuery Mobile. This is a simple feature that enhances list views with dividers. It makes content a bit easier to parse when working with a large list.

One of my readers, Fher (who has a cool name - I kind of imagine her/him as a fire-breathing wolf), asked if there was a way to add a bubble count to the dividers. You can see an example of this on the docs for listview, but this is what the feature looks like:

So, the short answer is no, you can't do this with autodividers. Why? While the feature allows you to build a function to create dynamic dividers, it only lets you specify the text for the divider, not random HTML. However, if you are willing to give up having the "pretty bubble" effect, you can simply use it as part of the label. To make that work, I modified my code a bit from the previous demo (and again, you can read that here, I'd suggest checking it out just so you can see the context). Here is the complete JavaScript code. (The HTML didn't change.)

$(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>");	
	}

	/*
	Create a generic func to return the label
	*/
	var getLabel = function(d) {
		return (d.getMonth()+1)+ "/" + d.getDate() + "/" + d.getFullYear();
	}
			
	/*
	Now that we have a func, use it to generate a label to count hash
	*/
	var dateCount = {};
	for(var i=0, len=dates.length; i<len; i++) {
		var l = getLabel(new Date(dates[i]));
		if(dateCount.hasOwnProperty(l)) {
			dateCount[l]++;
		} else {
			dateCount[l] = 1;
		}
	}
			
	dateList.listview({
		autodividers:true,
		autodividersSelector: function ( li ) {
			var d = new Date(li.text());
			var label = getLabel(d);
			
			return label + " (" +dateCount[label] +")";
		}
	}).listview("refresh");

});

The first change was to abstract out the code used to generate the divider - basically turning the date value into a label. Once I have that, I iterate over my data to figure out how many unique date labels I have. This is done with a simple object and a counter. Finally, my autodividersSelector function is modified to make use of this count. Here is the result.

There you go. Not exactly rocket science, but hopefully helpful. It is possible to create dividers with list bubbles, just not quite as simply as this entry demonstrates. I'll show that tomorrow.

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 Fher posted on 11/19/2014 at 3:30 AM

Thank you very much, Raymound. These and other posts are helpful for me I am going to visit them too, I am sure!!!

Comment 2 by Raymond Camden posted on 11/19/2014 at 3:31 AM

This is off topic, but it's my blog - what does your name mean? What is the nationality? By the way, it is a personal question so do *not* feel like you have to answer.

Comment 3 by Ty Whalin posted on 11/19/2014 at 6:14 AM

Looks like it might stand for F**K Her or the man named the Fher Hail. LOL...

Comment 4 by Anthony M. Powers posted on 11/19/2014 at 7:20 AM

Just for your information, list-dividers support the JQM native "bubble count" code. Here's how: http://jsfiddle.net/tehrave...

Comment 5 by Raymond Camden posted on 11/19/2014 at 7:24 AM

Well, my point was that it wasn't supported "out of the box" - but obviously it can be done by DOM manipulation as you did here. And... this is *far* simpler than what I was planning for my next post, so you just ruined that. ;)

Seriously though - nice - that is slick.

Comment 6 by Fher posted on 11/19/2014 at 7:38 PM

What is the problem? I guess the language I dont speak English. Raymond, I am from Quito, I am a Junior Programmer I am a male. I am doing a mobil application based in Cordova and Html5. That is all. Thank You!!! I try to be getlemen? I must to take a new English Course...

Comment 7 by Raymond Camden posted on 11/19/2014 at 7:59 PM

@Fhre: There is absolutely no problem! Sorry if I implied that. I was honestly just curious about your name. It is very interesting. You weren't rude or anything at all. :)

Comment 8 by Fher posted on 11/19/2014 at 10:16 PM

Thank you, for responds: I try it:

$actualtab.append("<li data-icon='plus'> <a href='#map-page3'> <img width='64px' height='64px' style='margin-left: 5px; margin-top: 7px; ' src='"+img+"' alt='Emergencia' class='ui-li-con ui-corner-none'>"+
"<p id='date'>"+fecha+"</p>"+
"<p>13:30 P.M.</p>"+
"<p>"+nombre+"</p>"+
"</a></li>");

$actualtab.on("afterRefresh", function(){
$(this).find("li.ui-li-divider").each(function(){

var number = $(this).nextUntil(':not(.ui-btn)').length;

$(this).addClass('ui-li-has-count').append('<span class="ui-li-count ui-btn-up-c ui-btn-corner-all">' + number + '</span>');

});
}) ;

$actualtab.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
var d= li.find("p[id='date']").text();
return d ;
}
}).listview("refresh").trigger("afterRefresh");

If have ideas please!!

Comment 9 by rachelr posted on 8/10/2015 at 2:16 AM

Hmm, ever come across custom dividers for items you want grouped in a list (but the divider text not specifically within the list items?) So in your date example, extracting the date into the divider and any json object array with that particular date becomes a list item?

Your example:
12/16/2013 as the divider with 12:00:00 and 14:00:00 as list items. I'm trying to figure out the best way to handle this type of situation.

Comment 10 (In reply to #9) by Raymond Camden posted on 8/10/2015 at 2:56 AM

I'm sorry - but I've read your comment a few times and I just don't get it. Maybe you can write it again?

Comment 11 (In reply to #10) by rachelr posted on 8/10/2015 at 5:15 PM

Sorry - I'm thinking in terms of a returned JSON object. I'd like to base the auto-divider on a property within the JSON object but not necessarily show that as a list item. For example, if I had two JSON entries and they each had a .project="Rachel" with other attributes like .subject and .message. I'd want the .project to be the list divider of "Rachel" and then two list items under that divider with their subject and message attributes. The way I'm thinking it has to be done is through manual creation of the dividers - first reading the json .project property and if it's new, creating a new divider and then appending the list items for items within the array with the same .project property. Was just hoping for an easy way to auto divide them with out have to do the if/then logic! And if this is still confusing you, I apologize haha I'm going to try and figure it out today/tomorrow and I can link my result.

Comment 12 (In reply to #11) by Raymond Camden posted on 8/10/2015 at 9:16 PM

It sounds like you could use the same code as my demo here. The difference here is that getLabel would get the project value. Make sense?

Comment 13 (In reply to #12) by rachelr posted on 8/16/2015 at 7:08 PM

I'm not quite there. This is what my list items look like:

$.each(results, function(i,message){
$('#messageList').append('<li>

<h1>'
+ message.project +'</h1><h2>'
+ message.from_user + '</h2>

'
+ message.title + '

'
+ message.text + '

'
+ message.time_created + '

</li>');
});

$('#messageList').listview('refresh');

I'd rather the message.project not even show in the list item and only show in the list divider. Is that a possibility? Or does it have to be in the list item so that the .text call can find?

Comment 14 (In reply to #13) by Raymond Camden posted on 8/17/2015 at 1:34 AM

It doesn't need to be in the list body afaik.