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">
    <title>CSS3 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">
    <h1>Shape</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

<h4>Shapes</h4>
<ul data-role="listview" data-inset="true">
    <li><a 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">
    <h3>Header & Icon</h3>
    <p>Collapsible 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.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • CD Smith

    Great article…I have not been able to find any information on how to change the various elements such as the listview, buttons, etc..

    For example, the listview buttons span the width of the screen, how can you shorten them and position them else where?

    I am familiar with CSS but it would be great to know where to go within the JQuery Mobile CSS to have full control over the screen elements..

  • http://3easy.org Paul Bridgestock

    If you go the jQuery Mobile website, check out the Docs and Demos, then click on Buttons in the Components section, you’ll have arrived at some of the information you need.

    You can achieve a button that is only as wide as the Text and Icon it contains, by adding data-inline="true" to the markup. Its as simple as that, no CSS is required for that one.

    It is important to note that the direction the framework is promoting, as far as I can tell, is to use the data attributes for everything related to layout. That’s how it appears to me.

    If you had unusual positioning requirements, it might be worth looking at the Docs on Content Formatting in general, and Layout Grids in particular. Almost any layout can be achieved.

    For styling, the approach is to use the Theme Framework. Essentially you would create a new Swatch of your own, following the CSS pattern suggested by the framework.

  • John Guerin

    I have MAMP in the applications folder … what do you have to do to run it from the sites folder.

    John

  • http://3easy.org Paul Bridgestock

    Hello John,

    Open up the MAMP application, not just the Dashboard Widget if you happen to use that, but the application itself from the Applications folder.

    Click on the Preferences button, choose the Apache tab, and you should be presented with the Document Root, where you can select a new location.

    Choose /Users/YouAndYour/Sites, click OK and MAMP should restart with the new settings. You should be go to go.

    From here, my practice is to create a new folder in Sites for each project. I also go a couple of extra steps and add a Virtual Host for those project folders…

  • http://www.wordpressguru.com.au Wordpress Developer

    Hi Paul,
    I am Jquery Mobile Newbie … I am looking to add my own custom css and overwrite most of default css rather than using theme a- e… Reading at some articles I came to know that if I use a div to wrap the element I want to stylise I can do that ..
    Is there any better way to just add new css and read it …