Collapsible content and Ajax loading with jQuery Mobile

John sent me an interesting question. He wants to make use of jQuery Mobile but needed a way to get sets of content on a page that would load only when requested. He tried using a list view but this failed to render properly for his needs. Turns out - there are all kinds of nice gems within jQuery Mobile, one of them being collapsible content items.

They are - like most things in jQuery Mobile - incredibly simple to use. Just wrap your content in a specially marked div and you get a collapsible item:

<div data-role="collapsible">   
    	<h1>Item One</h1>
    	<p>
    	This is my content.
    	</p>
</div>

And that's it. Really. If you want to make the content default to collapsed, you have to write a bunch of JavaScript code... nah, I'm kidding, you just add an argument:

<div data-role="collapsible" data-collapsed="true">   
    	<h1>Item One</h1>
    	<p>
    	This is my content.
    	</p>
</div>

Ok, so that's incredibly trivial. What isn't so trivial is how to make the actual content something you load via Ajax. The docs don't discuss this, but a Google search turned up this forum posting that says an event is fired when your div is collapsed or expanded. The example they provide is this:

$('div').live('expand', function(){
    console.log('expand');
  }).live('collapse', function(){
    console.log('collapse');
});

Easy enough, right? So I whipped up a super simple static front page:

<!DOCTYPE html> 
<html> 
	<head> 
	<title>Page Title</title> 
	<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a4/jquery.mobile-1.0a4.min.css" />
	<script src="http://code.jquery.com/jquery-1.5.2.min.js"></script>
	<script src="http://code.jquery.com/mobile/1.0a4/jquery.mobile-1.0a4.min.js"></script>
	<script>

	$('div.info').live('expand', function(){
		//get the ID for this record
		var record = $(this).data("record");
	    console.log('expanded '+record);
		$(".detail", this).load("test2.cfm?record="+record);
	  });

	</script>
</head> 
<body> 

<div data-role="page">

	<div data-role="header">
		<h1>Page Title</h1>
	</div>

	<div data-role="content">	

		<div data-role="collapsible" data-collapsed="true" class="info" data-record="1">   
	    	<h1>Item One</h1>
			<div class="detail"></div>   
	    </div>

		<div data-role="collapsible" data-collapsed="true" class="info" data-record="2">    
	    	<h1>Item Two</h1>    
			<div class="detail"></div>  
	    </div>
	
	</div>

	<div data-role="footer">
		<h4>Page Footer</h4>
	</div>

</div>

</body>
</html>

I've got two collapsible items here - hard coded. Normally this would probably be database driven. Note that I've applied a class to them as well as a data item called record. If you go up to the JavaScript, you can see I've modified the selector to be more specific. It only picks up divs with the info class. I also only care about expansion so I didn't bother with a collapse handler. Once one of my divs is opened, I grab the record value (imagine this is a database table primary key) and call a load event. test2.cfm isn't doing anything interesting but here it is anyway:

<cfparam name="url.record" default="">

<cfoutput>
This is dynamic data for record #url.record#
</cfoutput>

Raymond Camden's Picture

About Raymond Camden

Raymond is a developer advocate for Extend by Auth0. He focuses on serverless and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support.

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

Comments