Posted on

Opening (and closing) jQuery Mobile Collapsible sections programatically

We use jQuery Mobile for OrderPipe, it’s a fantastic framework and I have a lot of love for it. One thing that has bugged me about the way our settings section works though is after making a change within a collapsible section (like inviting a user for example) the section would be closed afterwards. It was surprisingly easy to fix that and this blog post will run through a quick example of allowing URL’s to map to open sections quickly and easily. It assumes Spring MVC on the server side, but you could do it with any server side technology.

Firstly on the server side, you could do this with query parameters, or URL paths (or cookies if you really wanted I guess) – we use paths, because I think it looks cleaner.

 
@Controller
@RequestMapping(value = "/settings")
public class SettingsController {
 
	@RequestMapping(value = "", method = RequestMethod.GET)
	public String list(Model model) {
		return listSection(null, model);
	}
 
	@RequestMapping(value = "section/{sectionId}", method = RequestMethod.GET)
	public String listSection(@PathVariable String sectionId, Model model) {
 
		// <snip>
		model.addAttribute("section", sectionId);
		return "page/settings";
	}
}

Then in your view (settings.jsp in this case) you want to have the all important javascript to actually determine which section to open, and open it.

<c:if test="${!empty sectionId}">
	<script type="text/javascript">
		setTimeout(function(){$('#<c:out value="${sectionId}" />').trigger('expand')},300);
	</script>
</c:if>

The magic is $('#id').trigger('expand') part, which if you have an id on your collapsible div, will cause it to expand. Likewise you can cause it to collapse with $('#id').trigger('collapse'). I also add a short 300ms delay to this, so that the page has time render before the expand sequence runs.

Just to complete the example, your actual sections will look something like this:

<div id="general-settings" data-role="collapsible" data-collapsed="true">
	<h3>General Settings</h3>
</div>

And then if you redirect a user to /settings/section/general-settings instead of just /settings they’ll find themselves back at the settings page, with the general settings already expanded, showing the changes they just made.