jQuery Mobile Filterable Collapsible Listview with Smart Expansion

Wow, that’s a mouthful. Basically, I wanted to make use of the data-filter option to search a listview, but instead of a listview, I wanted it to be a collection of collapsible elements. Do accomplish this I needed some custom CSS to make it look right. Here is the example code with the ID iamalist. The page’s content section ID is iama, which is used in the CSS.

<div data-role="content" id="iama">	
	<ul data-role="listview" id="iamalist" data-inset='true' data-filter="true" data-filter-placeholder="Search term is...">
		<li data-filtertext="keywords">
			<div data-role="collapsible" data-inset='false'><h3>Title</h3>
			<p>Answer.</p></div>
		</li>
		<li data-filtertext="keywords">
			<div data-role="collapsible" data-inset='false'><h3>Title</h3>
			<p>Answer.</p></div>
		</li>
		<li data-filtertext="keywords">
			<div data-role="collapsible" data-inset='false'><h3>Title</h3>
			<p>Answer.</p></div>
		</li>
		<li data-filtertext="keywords">
			<div data-role="collapsible" data-inset='false'><h3>Title</h3>
			<p>Answer.</p></div>
		</li>
		<li data-filtertext="keywords">
			<div data-role="collapsible" data-inset='false'><h3>Title</h3>
			<p>Answer.</p></div>
		</li>
	</ul>
</div>
#iama .ui-listview>.ui-li-static {
	padding: 0em 1em !important;
	margin: -.5em 0em !important;
}
#iama .ui-listview>li h1, .ui-listview>li h2, .ui-listview>li h3, .ui-listview>li h4, .ui-listview>li h5, .ui-listview>li h6 {
	margin: 0 0 .3em 0 !important;
}
#iama .ui-listview>li p {
	overflow: visible !important;
	white-space: normal !important;
	margin-top: 0 !important;
}
#iama .ui-listview>.ui-li-static.ui-last-child, .ui-listview>.ui-li-divider.ui-last-child, .ui-listview>li.ui-last-child>a.ui-btn {
	border-bottom-width: 0;
}

Now that the styling is done, I wanted to add one more feature. When the filter starts working (if 10 items, then when filter reduces that to < 10), I wanted to automatically expand the collapsible content. This is done through the following javascript, which refers to the list's ID iamalist.

$(document).on('pageinit',function(){
	$("#iamalist").on('updatelayout',function(){
		if (($('#iamalist li').length - $('#iamalist .ui-screen-hidden').length) < $('#iamalist li').length){
			$('#iamalist li').each(function(){
				$(this).find('.ui-collapsible-content').removeClass('ui-collapsible-content-collapsed');			
				$(this).find('.ui-icon-plus').addClass('ui-icon-minus');			
				$(this).find('.ui-icon-plus').removeClass('ui-icon-plus');			
			});
		}
	});
});

The magic here is using the .on(‘updatelayout’) to detect when the list changes. Originally, I was using the .on(‘keyup’) of the input[data-type=’search’], but that was causing strange results. The proper way is to use the .on(‘updatelayout’) hook provided by the jQueryMobile API.

You can see this live here: http://readysum.com/#iama

Leave a Reply

Your email address will not be published. Required fields are marked *