Zend certified PHP/Magento developer

BuildMobile: jQuery Mobile Components

Hello. This is the second in a short run of articles aimed at explaining the basics of jQuery Mobile. In the introductory article Hello jQuery Mobile we covered getting set up, page structures, navigation, transitions and basic list views.

In so doing, we built out a reference site, which demonstrates the use of CSS to create shapes without images. This article continues development of that CSS3 Shapes reference site, and continues to refer to our new best friend as jQM, but this time around we’ll take a whistle stop tour of Components.

On the Cutting Edge

When we introduced you to jQM it was noted the code was in an Alpha state. Since then the first jQM Beta hit the streets. There are many ways to keep abreast of such developments, which we’ll come back to in a moment. For the hardcore there is, of course, the jQuery Mobile GitHub repository.

I am attracted to the GitHub repo because, as noted in the README.md, you can have the docs demos running locally, with the double benefit of an up-to-the-minute jQM build. We are going to clone a copy of the repository. If you’re not on the Git bandwagon by now, shame on you. It’s not too late.

You need a local web server. I am using MAMP configured to run in the “Sites” folder on Mac OS X, so I’ll create a new ‘jQueryMobile’ folder in ‘Sites’. Then enter the following commands in Terminal, one at a time. Admittedly, this is particular to my environment, so you may need to make minor tweaks.

Clone the jQM Repo

cd ~/sites/jquerymobile
git clone git://github.com/jquery/jquery-mobile.git
cd jquery-mobile
make

That is all. Point your browser to our new jquerymobile/jquery-mobile/ folder, behold the local docs and demos! The project is inside the jquery-mobile folder, which gets created during the clone. This is awesome for doing some development at the park or cafe, and its quicker to browse.

As a result of the make command you will have a folder called compiled, which contains fresh as a daisy copies of the *.js and *.css files. Copy the new files into the jqm folder of our reference project, update the links in the head and we are right on the cutting edge.

Note, the images in the first Beta are the same as the Alpha but if they did change, or you are doing this for the first time, add or update /images/ with those from /themes/default/images/. Finally, note that jQuery is up to 1.6.1 and the jQM project uses it, so update that file as well.

Keeping Abreast of Developments

It’s important to keep abreast of developments. Besides GitHub, read the jQuery Mobile Blog, and follow the developers on Twitter, wherein folks like @scottjehl announce updates and suggest required reading. This is especially important because jQM is developing quite rapidly right now.

For example, pinch-to-zoom was disabled up to Alpha and has been restored in the Beta, for various reasons as explained in the Beta 1 Release Post. From now on, developers must add the meta viewport tag to the markup, where before it was inserted dynamically.

All In The Head

head
    meta charset="utf-8" /
    meta name="viewport" content="width=device-width, initial-scale=1"
    titleCSS3 Shapes/title
    link rel="stylesheet" href="jqm/jquery.mobile-1.0b2pre.min.css" /
    script src="jqm/jquery-1.6.1.min.js"/script
    script src="jqm/jquery.mobile-1.0b2pre.min.js"/script
/head

With these additions to the head, our reference site will now scale properly, wherein the column width is narrow but the text and icons remain full size. The friendly developers help where they can, but make sure you stay up to date where you can, especially whilst the jQM project incubates.

No Going Back

At this stage we have the original reference project, with updated jQM code files in the /jqm/ folder and an updated meta viewport tag. Fire up your reference site, and note the lack of ‘Back’ button on pages beyond the home page or index.html. The “Back” button is now off by default, as predicted.

A simple fix is to add data-add-back-btn="true" to each data-role="page" element, which restores the ‘Back’ button. This button ignores the href and goes back one history entry. The equivalent manual code would be a href="index.html" data-icon="arrow-l" data-rel="back"Back/a

But let’s think about this manual code, because it presents some complexity when you are coding links all over your site. The docs say you should provide a meaningful href for C grade browsers that actually points back to the referring page. This means you need to write code to dynamically populate the href to point back to the previous page.

When the buttons are added programatically using the data-add-back-btn="true" attribute, jQM adds a simple href="#". That’s fine for jQM, because if it adds something using Javascript then it can assume there won’t be an issue using Javascript to take care of the back button. Graceful fallbacks for C grade browsers or a lack of JS, will require a dynamic href attribute.

Header Toolbar Buttons

There is a slot for buttons either side of the the text in a data-role="header" element, so that’s two in a standard configuration. The jQM header plugin looks for immediate children of the data-role="header", the first link it finds goes to the left, and the second goes to the right.

Once we have left the home page, let’s add a “Home” button to the header, by adding a href="#shapes" data-icon="home"Home/a inside the data-role="header" element. With that, and that alone, you’ll wonder where our “Back” button has gone. Take control of position by adding class="ui-btn-right", and the “Back” button returns to view because the “Home” button is out of its way to the right.

If we add the data-rel="back" to the “Home” button link, jQM will remove one item from the history stack and reverse the transition, when it is touched or clicked. Adding data-iconpos="notext" removes the text from the button, but we can leave the text in the markup regardless.

Home Button

header data-role="header"
    h1Shape/h1
    a href="#shapes" class="ui-btn-right" data-rel="back"Home/a
/header

This is fine when we’re one step away from the ‘Home’ page, but when we’re two steps away on a ‘CSS’ page the markup will have to change, because data-rel="back" will go back to a ‘Shape’ page instead of ‘Home’. So we’ll use a meaningful href and data-direction="reverse", which means we get the left-to-right slide, and the mental model remains intact.

Note, there is a bug where class="ui-btn-active" is not properly removed such that revisiting a page after returning home shows the ‘Home’ button still active. There are short term solutions, using additional Javascript to work around the bug, suggested in the comments.

Footer Toolbar Fixed Positioning

Essentially the same rules that apply to data-role="header" apply to data-role="footer". The primary difference is that there is less structure, such that buttons are not placed left and right, instead they are all inline.

A cool feature is to keep data-role="footer" firmly in place between transitions, by using a common data-id="". Note, this requires that the data-role="header" and data-role="footer" use fixed positioning.

To take advantage of native scrolling and have the toolbars re-appear after a scroll, use data-position="fixed". Add this snippet to all of the data-role="header" and data-role="footer" elements in the code.

Now we can add a persistent footer, by adding a common data-id="footer" to every data-role="footer" element. Note, the data-position="fixed" set on all data-role="footer" elements means it is global element. Now we have a fixed position footer that remains static during page transitions. Cool.

Persistent Footer

footer data-role="footer" data-position="fixed" data-id="footer"
    ...
/footer

Dialogs Data Icons

Since our data-role="footer" is a global element, we’ll put something global in there like a page about the web app. We’ll make our page about the app present itself as a dialog, to demonstrate the code and talk about the implications. First thing to note, dialogs are not included in the hash state history tracking.

Create a new data-role="page" element at the bottom of the source, to maintain sensible source order. This page has a slightly different structure, a simple data-role="page" and data-role="header" including our ‘Home’ button. There is no data-position="fixed" applied to the data-role="header" because that would destroy the modal dialog. There is no data-role="footer" at all because that, too, would destroy the modal dialog.

Next, in the data-role="footer" element of all standard data-role="page" elements, add a link to the new dialog. Add data-rel="dialog" to the link to ensure the linked page will present as a dialog. We’ll choose a data-icon="" for the button image, we are using data-icon="gear".

The default transition for a modal dialog is a data-transition="pop" otherwise it is recommended to use slideup or flip to make it feel more dialog-like. Padding is off by default, so we need to add it back in for buttons, navbars and other widgets. Add class="ui-bar" to all data-role="footer" elements, when using them this way.

Dialog Gear

footer data-role="footer" data-position="fixed" data-id="footer" class="ui-bar"
    a href="#about" data-rel="dialog" data-icon="gear" data-transition="pop"About/a
/footer

Buttons

We can style any anchor link as a button by adding data-role="button". By default the buttons fill the available screen width. Make buttons compact, and only as wide as the text and icons they contain by using the data-inline="true" attribute. Set buttons side by side by wrapping them in a containing element with the data-inline="true" attribute applied.

Group buttons in a block by wrapping them in a container with the data-role="controlgroup" attribute applied. Stacked vertically by default, change to a horizontal group by adding data-type="horizontal" to the data-role="controlgroup" element.

Adding icons to buttons is achieved with the data-icon="" attribute. jQM ships with a couple of sprites that include a selection of icons most often needed for mobile apps, simply specify your icon choice in the attribute. Position is left of the text by default, but the position of the button icon can be controlled using the data-iconpos=""attribute.

For our reference app, we’ll stick to a simple controlgroup with two data-role="button" elements, one for the ‘Shape’ and one for the ‘CSS’. We’ll apply this pattern to each of the ‘Shape’ and ‘CSS’ pages, therein providing a quick toggle between the shape and the code used to produce each.

Shape

nav data-role="controlgroup"
    a data-role="button"Shape/a
    a href="#shape_css" data-role="button" data-transition="pop"CSS/a
/nav

CSS

nav data-role="controlgroup"
    a href="#shape" data-role="button" data-rel="back"Shape/a
    a data-role="button"CSS/a
/nav

Lists

Our good friend jQM includes a wide range of list types and formatting options to cover most common design patterns, all of which are simple to use by adding data items to the markup. We covered a fair amount of the options in the first article Hello jQuery Mobile. But one more quick example.

We’ll add an index for all ‘Shapes’ and all ‘CSS’ pages to our About dialog. Add an h4 to act as a header to each list, then the plain old semantic HTML elements of ul and li sequences for the items. Two additional data items are all we need to add, and they are ul data-role="listview" data-inset="true". This results in two inset lists in the About page.

Inset List

h4Shapes/h4
ul data-role="listview" data-inset="true"
    lia href="#circle"Circle/a/li
    ...
/ul

Content Formatting

jQM takes a gentle approach to content styling, allowing the browser’s native rendering to take precedence, adding just a little bit of padding for comfortable reading. You can use the theming system to take control of typeface and colour. And we’ll save the Theme Framework for a later fireside chat.

Back to layout. jQM provides a simple way to achieve CSS based columns through a convention called ui-grid. Although multiple column layouts are tough in the mobile environment, layout grids can be achieved in a few preset configurations.

For a two column grid, simply add a class="ui-grid-a" to a containing element, and inside that add elements with class="ui-block-a" and class="ui-block-b". A three column grid uses a container with class="ui-grid-b" applied, and expects class="ui-block-a" and class="ui-block-b" and class="ui-block-c" inside it.

Finally, note that multiple row grids can be achieved by adding, say, four child blocks to a two column grid, six or nine blocks to a three column grid. Cycle through class="ui-block-a" and class="ui-block-b" and so on as applicable to your desired layout

Multiple Row Grid

div class="ui-grid-b"
    div class="ui-block-a"Row 1 Cell 1/div
    div class="ui-block-b"Row 1 Cell 2/div
    div class="ui-block-c"Row 1 Cell 3/div
    div class="ui-block-a"Row 2 Cell 1/div
    div class="ui-block-b"Row 2 Cell 2/div
    div class="ui-block-c"Row 2 Cell 3/div
/div

And the content formatting fun just keeps coming, with collapsible blocks. Collapsible content blocks are created by adding a data-role="collapsible" attribute to a container, wherein jQM will add a “+/–” icon to a heading element placed immediately inside the container.

Add a heading element of h1 through an h6, which remains visible with the expansion icon, then markup the remainder of the content inside the data-role="collapsible" container, whose visibility can then be toggled on and off with the heading.

Collapsible

div data-role="collapsible"
    h3Header  Icon/h3
    pCollapsible Content/p
/div

As we head for the finish line, a quick note that the content area of a page should take the majority of its styles from the data-theme="x" attribute applied to the data-role="page" element. There is a comprehensive object oriented CSS framework within jQM that you can take and make in your own image.

Closing Comments

Thus far, we have covered the basics of getting up and running with jQM followed by a whistlestop tour of the components you can use simply by adding to your markup. Everything we have done has been achieved with markup alone.

There is great depth to be discovered, and we have barely scratched the surface. If you are lucky enough to start courting jQM you might discover her rich APIs, which relate to events, methods and utilities, the responsive layout and the theme framework.

Check out the complete reference site at 3Easy. Please leave your thoughts and questions in the comments, and be so bold as to request where you might like to go next. Thanks for stopping by, for now I bid you farewell. I got a date with jQM.