jQuery Mobile, Django and Collapsible
November 12, 2010
This article follows on from two previous ones, available at http://drumcoder.co.uk/blog/2010/nov/12/jquery-mobile-basics/ and http://drumcoder.co.uk/blog/2010/nov/12/jquery-mobile-and-django/. Please read both those first.
This article covers the results page. This is a Django generated list of contest results for a given band, with collapsible details underneath, working like an Accordion.
Band Links
The links in the band list page go to:
<li><a href="/bands/{{band.slug}}/">{{band.name}}</a></li>
So we now need to add an entry into the band application's url.py for this:
(r'^([\w-]*)/$', 'mobile.bands.views.band'),
This links to the band view:
def band(request, pBandSlug): """ Show a specific band """ try: lBand = Band.objects.filter(slug=pBandSlug).select_related()[0] except IndexError: raise Http404() return render_auth(request, 'bands/results.htm', {"Band" : lBand, "ContestResults" : lBand.contestresult_set.all() })
The results.htm template contains:
{% load humanize %} <div data-role="page"> <div data-role="header"> <h1>Results</h1> <a data-icon="arrow-u" class="ui-btn-right" href="#home">Home</a> </div> <div data-role="content"> <h2>{{Band.name}}</h2> <h3>{{Band.region.name}}</h3> <div data-role="collapsible-set"> {% for result in ContestResults %} <div data-role="collapsible"> <h3>{{result.results_position|ordinal}} - {{result.contest_event.contest.name}} {{result.contest_event.event_date}}</h3> <p>Competed as: {{result.band_name}}</p> <p>Conductor: <a href="/conductors/{{result.conductor.slug}}/">{{result.conductor.name}}</a></p> <p>Draw: {{result.draw}}</p> {% if result.points %}<p>Points: {{result.points}}</p>{% endif %} {% if result.test_piece %} <p>Test Piece: <a href="/pieces/{{result.test_piece.slug}}/">{{result.test_piece.name}}</a></p> {% endif %} </div> {% endfor %} </div> </div> <div data-role="footer"> <h4>Footer</h4> </div>
Collapsible
The collapsible behaviour is the key thing to note about this HTML.
Here's how it renders normally:
And here's what happens if you click on one of the plus symbols:
If you click a different plus, then the one that is open is closed first.
The generated HTML for the first two rows looks something like this:
<div data-role="collapsible-set"> <div data-role="collapsible"> <h3>8th - Fife Charities Band Assocation Contest 3rd Oct 2009</h3> <p>Collapsed Content Is Here</p> </div> <div data-role="collapsible"> <h3>7th - Northern Counties Open Contest 24th May 2009</h3> <p>Collapsed Content Is Here</p> </div> </div>
The outer div defines data-role="collapsible-set"
which indicates that the collapsible sub div's should be treated as one group, with only one open at a time.
Each inner div has data-role="collapsible"
which adds the plus/minus button (this can also be used outside a set)
By default, jQuery mobile hides anything after the header, and by default the last one is open. To specify they should all be closed, add data-collapsed="true"
to the collapsible div.
<div data-role="collapsible" data-collapsed="true">