facebook google plus twitter
Webucator's Free Developing Mobile Websites Tutorial

Lesson: jQuery Mobile

Welcome to our free Developing Mobile Websites tutorial. This tutorial is based on Webucator's Responsive Web Design Training course.

In this lesson, we explore jQuery Mobile, a JavaScript framework that makes easy the process of creating Web sites for a wide range of popular mobile platforms.

Lesson Goals

  • Learn how to use jQuery Mobile to create sites optimized to work for all major mobile platforms.
  • Learn how to use Intel Open Source Technology Center's Rapid Interface Builder to rapidly prototype pages.
  • Learn how to use JavaScript to handle touch and orientation events.

Mobile Focus

jQuery Mobile is "is a HTML5-based user interface system designed to make responsive websites and apps that are accessible on all smartphone, tablet and desktop devices." With thoroughly tested code that works consistently across all major phone platforms, support for touch and other gestures, and an Ajax-based page transition model, jQuery Mobile offers an easy way to build highly mobile-optimized sites and Web applications.

jQuery Mobile is a user-interface library built on top of the popular jQuery JavaScript library. To use jQuery Mobile, you must include jQuery first before including jQuery Mobile.

jQuery Mobile makes building mobile websites and mobile Web applications quicker and easier, with WYSIWYG builders, code tested on lots of devices, and easy-to-add UI widgets. But one need not, of course, use jQuery Mobile to use jQuery in mobile development, and one need not use jQuery at all to develop sites optimized for mobile viewing.

Does jQuery Mobile work for all devices - desktop, tablet, and mobile? jQuery Mobile is certainly more mobile centric than most other frameworks; you'll have to decide if jQuery's strategy - "A unified user interface system that works seamlessly across all popular mobile device platforms, built on the rock-solid jQuery and jQuery UI foundation" - works for your site or application on desktops as well. Sites built with jQuery Mobile will certainly work on desktops; the library has been tested on all major desktop browsers.

jQuery UI is a similar user-interface library, built on top of jQuery, aimed at desktops. Learn more at jqueryui.com.

Supported Platforms

jQuery Mobile offers support for a wide range of platforms; they categorize browsers according to A-, B-, and C-level groupings, as below.

jQuery Mobile Graded Browser Support
Browser Grade Functionality
A-grade Full enhanced experience with Ajax-based animated page transitions
B-grade Enhanced experience except without Ajax navigation features
C-grade Basic, non-enhanced HTML experience that is still functional

See the jQuery Mobile docs for a full list of supported devices.

The Basics

The Page Model

Pages in jQuery Mobile site are represented by <div data-role="page"> with jQuery Mobile enabling Ajax-based transition between pages. You can organize pages into different files or all in the same file (with multiple <div data-role="page">s); regardless, jQuery Mobile will enable Ajax transitions between the different pages.

UI Elements

Lists, filters, buttons, grids - jQuery Mobile comes with a useful array of user-interface elements. Adding class="ui-btn" to a link turns it into a button; data-role="listview" turns an unordered list into a listview widget.

A First Example

Let's look at a simple jQuery Mobile-based demonstration: we'll rig up a low-fi page from which users can filter and select from a few jazz clubs, as shown on the left. Tapping the club brings the user to a detail page, with map, as shown on the right:

Jazz Calendar - jQuery Mobile on iPhone

Open the file jQueryMobile/Demos/jazz/index.html in your browser (preferably from a smartphone) and in your file editor.

Code Sample:

jQueryMobile/Demos/jazz/index.html
<!DOCTYPE html> 
<html> 
	<head> 
	<title>Jazz Calendar</title> 
	<meta name="viewport" content="width=device-width, initial-scale=1"> 
	<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" />
	<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
	<script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
</head> 
<body> 

<div data-role="page">

	<div data-role="header">
		<h1>Jazz Calendar</h1>
	</div>

	<div class="ui-content" role="main">
		<p>Use the filter below to find concerts near you:</p>
		<form class="ui-filterable">
			<input id="filter-input" data-type="search">
		</form>
		<ul data-role="listview" data-filter="true" data-input="#filter-input">
			<li><a href="bakers-keyboard-lounge.html">Baker's Keyboard Lounge</a></li>
			<li><a href="blues-alley.html">Blues Alley</a></li>
			<li><a href="el-chapultepec.html">El Chapultepec</a></li>
			<li><a href="village-vanguard.html">Village Vanguard</a></li>
		</ul>
	</div>

</div>

</body>
</html>

Code Explanation:

We include three external files - a stylesheet and two JavaScript files, for jQuery and jQuery Mobile. These three files are all hosted externally, at code.jquery.com. We could, of course, download and host these files ourselves, locally - we would need to do this if working without an internet connection.

Three divs wrap our content:

  1. <div data-role="page"> is the outermost wrapper;
  2. <div data-role="header"> wraps the header of the page;
  3. <div class="ui-content" role="main"> wraps the main content for the page.

These specific attribute values for the various <div>s are significant and specific for jQuery Mobile - using them ensures that jQuery Mobile's CSS and JavaScript functionality works in a self-consistent manner.

The form and unordered list markup in index.html enables the filter-as-you-type functionality, limiting the results shown to those items whose display text matches the typed text. Each individual list item is a link to a club-specific detail page.

Tapping the link to any of the detail pages shows the title of the page, the venue's address, a map of the location, and a link ("Home") back to the main page. Let's take a look at code from one of those pages:

Code Sample:

jQueryMobile/Demos/jazz/bakers-keyboard-lounge.html
<!DOCTYPE html> 
<html> 
	<head> 
	<title>Jazz Calendar: Baker's Keyboard Lounge</title> 
	<meta name="viewport" content="width=device-width, initial-scale=1"> 
	<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" />
	<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
	<script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
</head> 
<body> 

<div data-role="page">

	<div data-role="header">
		<h1>Baker's Keyboard Lounge</h1>
	</div>

	<div class="ui-content" role="main">
		<address>2050 Livernois Ave
		<br>Detroit, Michigan 48221</address>
		<img src="https://maps.googleapis.com/maps/api/staticmap?center=2050%20Livernois%20Ave,%20Detroit,%20MI&zoom=14&size=288x200&markers=2050%20Livernois%20Ave,%20Detroit,%20MI&sensor=false" height="200" width="288" />
		<a href="index.html" class="ui-btn ui-icon-home ui-btn-icon-left">Home</a>
	</div>

</div>

</body>
</html>

Code Explanation:

Again, divs denoting the "page", "header", and "content", respectively, mark up our content. We exploit the convenient Google Maps static-map-from-address image: supplying GET parameters for the center of the map and the marker to show allows us to easily render a useful map of the location. Setting class="ui-btn ui-icon-home ui-btn-icon-left" for the link back to the "Home" page displays the bottom link as a mobile-friendly button (from class ui-btn); the latter two classes sets the icon for the button as jQuery Mobile's canned "home" icon.

Drag-and-Drop Code Builder

A useful tool in learning to write jQuery Mobile code is Intel's Rapid Interface Builder; note that the tool requires the use of the Chrome browser. You can create a page (or multiple pages) using the drop-and-drop interface, preview to test it out, and view/export the resulting code. It's a good way, especially if you are just starting out with jQuery Mobile, to both rapidly design various widgets and themes, and to explore the code that would render your desired elements.

Intel RIB

Gestures

Like all JavaScript frameworks, jQuery Mobile offers support for event handling - convenient ways to respond programmatically to user interaction with our pages. Usefully, this includes touch events - responding to finger taps and swipes to change pages, open dialogs, etc. Here are the touch events, from the jQuery Mobile docs:

jQuery Mobile Touch Events
Event Details
tap Triggers after a quick, complete touch event
taphold Triggers after a held complete touch event
swipe Triggered when a horizontal drag of 30px or more (and less than 75px vertically) occurs within 1 second duration
swipeleft Triggered when a swipe event occurs moving in the left direction
swiperight Triggered when a swipe event occurs moving in the right direction

Let's take a look at an example.

Swiping to Change Pages

We'll extend our find-a-jazz-club pages from the previous example to allow the user to swipe right and left to navigate from one detail page to the next, rather than having to return to the home screen each time. Open jQueryMobile/Demos/jazz-touch/index.html from a smartphone or emulator, and take a look at the code in your file editor.

Code Sample:

jQueryMobile/Demos/jazz-touch/index.html
<!DOCTYPE html> 
<html> 
	<head> 
	<title>Jazz Calendar</title> 
	<meta name="viewport" content="width=device-width, initial-scale=1"> 
	<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" />
	<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
	<script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
	<script type="text/javascript">
		$(document).on('swiperight', "#bakerskeyboardlounge", function() {
			$( "body" ).pagecontainer( "change", "#villagevanguard" );
		});
		$(document).on('swipeleft', "#bakerskeyboardlounge", function() {
			$( "body" ).pagecontainer( "change", "#bluesalley" );
		});
		$(document).on('swiperight', "#bluesalley", function() {
			$( "body" ).pagecontainer( "change", "#bakerskeyboardlounge" );
		});
		$(document).on('swipeleft', "#bluesalley", function() {
			$( "body" ).pagecontainer( "change", "#elchapultepec" );
		});
		$(document).on('swiperight', "#elchapultepec", function() {
			$( "body" ).pagecontainer( "change", "#bluesalley" );
		});
		$(document).on('swipeleft', "#elchapultepec", function() {
			$( "body" ).pagecontainer( "change", "#villagevanguard" );
		});
		$(document).on('swiperight', "#villagevanguard", function() {
			$( "body" ).pagecontainer( "change", "#elchapultepec" );
		});
		$(document).on('swipeleft', "#villagevanguard", function() {
			$( "body" ).pagecontainer( "change", "#bakerskeyboardlounge" );
		});
	</script>
</head> 
<body> 

<div data-role="page" id="home">
	<div data-role="header">
		<h1>Jazz Calendar</h1>
	</div>

	<div class="ui-content" role="main">
		<p>Use the filter below to find concerts near you:</p>
		<form class="ui-filterable">
			<input id="filter-input" data-type="search">
		</form>
		<ul data-role="listview" data-filter="true" data-input="#filter-input">
			<li><a href="#bakerskeyboardlounge">Baker's Keyboard Lounge</a></li>
			<li><a href="#bluesalley">Blues Alley</a></li>
			<li><a href="#elchapultepec">El Chapultepec</a></li>
			<li><a href="#villagevanguard">Village Vanguard</a></li>
		</ul>
	</div>

</div>

<div data-role="page" id="bakerskeyboardlounge">

	<div data-role="header">
		<h1>Baker's Keyboard Lounge</h1>
	</div>

	<div class="ui-content" role="main">
		<address>2050 Livernois Ave
		<br>Detroit, Michigan 48221</address>
		<img src="https://maps.googleapis.com/maps/api/staticmap?center=2050%20Livernois%20Ave,%20Detroit,%20MI&zoom=14&size=288x200&markers=2050%20Livernois%20Ave,%20Detroit,%20MI&sensor=false" height="200" width="288" />
		<a href="index.html" class="ui-btn ui-icon-home ui-btn-icon-left">Home</a>
	</div>

</div>

<div data-role="page" id="bluesalley">

	<div data-role="header">
		<h1>Blues Alley</h1>
	</div>

	<div class="ui-content" role="main">
		<address>1073 Wisconsin Ave. NW
		<br>Washington, DC 20007</address>
		<img src="https://maps.googleapis.com/maps/api/staticmap?center=1073%20Wisconsin%20Ave.%20NW%20Washington,%20DC&zoom=14&size=288x200&markers=1073%20Wisconsin%20Ave.%20NW%20Washington,%20DC&sensor=false" height="200" width="288" />
		<a href="index.html" class="ui-btn ui-icon-home ui-btn-icon-left">Home</a>
	</div>

</div>

<div data-role="page" id="elchapultepec">

	<div data-role="header">
		<h1>El Chapultepec</h1>
	</div>

	<div class="ui-content" role="main">
		<address>1962 Market St
		<br>Denver, CO 80202</address>
		<img src="https://maps.googleapis.com/maps/api/staticmap?center=1962%20Market%20St.%20Denver,%20CO&zoom=14&size=288x200&markers=1962%20Market%20St.%20Denver,%20CO&sensor=false" height="200" width="288" />
		<a href="index.html" class="ui-btn ui-icon-home ui-btn-icon-left">Home</a>
	</div>

</div>

<div data-role="page" id="villagevanguard">

	<div data-role="header">
		<h1>Village Vanguard</h1>
	</div>

	<div class="ui-content" role="main">
		<address>178 7th Avenue South, New York, NY 10014
		<br></address>
		<img src="https://maps.googleapis.com/maps/api/staticmap?center=178%207th%20Avenue%20South,%20New%20York,%20NY&zoom=14&size=288x200&markers=178%207th%20Avenue%20South,%20New%20York,%20NY&sensor=false" height="200" width="288" />
		<a href="index.html" class="ui-btn ui-icon-home ui-btn-icon-left">Home</a>
	</div>

</div>

</body>
</html>

The first thing you notice is that there's only one file here. We've changed the file architecture from the last example: where the previous demo code presented each individual-venue page as a separate file, we now present each individual-venue page as separate divs, each with data-role="page", in the same index.html file. Note that each page div has a unique id, which we'll use to reference the "page" in links. To the user, this is transparent - jQuery Mobile's Ajax-based page transitions hide this implementation detail.

In the head of the page, we create rules for each page's swipeleft and swiperight event: swiping right on the #bakerskeyboardlounge, for instance, brings the user to the #bluesalley page. The code $.mobile.changePage('#bluesalley') effects this.

One can see that this process - detailing the right- and left-swipe page links for each page - might get pretty onerous as the number of pages grows. Let's see if we can handle this a little more elegantly.

Using data Attributes

For a next iteration of the swipe-able pages, we'll use HTML5 data- attributes. HTML5, unlike earlier HTML versions, now formally allows - encourages, even - parameter information passing via attributes named data-* on any element. For our purposes here, this means each venue's div can hold information about the pages to which swiping right and left should bring the user:

<div data-role="page" data-next-page="#elchapultepec" data-prev-page="#bakerskeyboardlounge" id="bluesalley">

Using the data attributes, we can write JavaScript event-handling code that is clearer and more concise. Also, this strategy would be much easier to implement if the page for each venue were produced by a content management system.

Open jQueryMobile/Demos/jazz-touch/index-attribute.html from a mobile device or emulator; check out the code with a file editor.

Code Sample:

jQueryMobile/Demos/jazz-touch/index-attribute.html
<!DOCTYPE html> 
<html> 
	<head> 
	<title>Jazz Calendar</title> 
	<meta name="viewport" content="width=device-width, initial-scale=1"> 
	<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" />
	<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
	<script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
	<script type="text/javascript">
		
		$(document).on('swiperight', ".swipeablepage", function() {
			$( "body" ).pagecontainer( "change", $(this).attr('data-prev-page') );
		});
		
		$(document).on('swipeleft', ".swipeablepage", function() {
			$( "body" ).pagecontainer( "change", $(this).attr('data-next-page') );
		});

	</script>
</head> 
<body> 

<div data-role="page" id="home">
	<div data-role="header">
		<h1>Jazz Calendar</h1>
	</div>

	<div class="ui-content" role="main">
		<p>Use the filter below to find concerts near you:</p>
		<form class="ui-filterable">
			<input id="filter-input" data-type="search">
		</form>
		<ul data-role="listview" data-filter="true" data-input="#filter-input">
			<li><a href="#bakerskeyboardlounge">Baker's Keyboard Lounge</a></li>
			<li><a href="#bluesalley">Blues Alley</a></li>
			<li><a href="#elchapultepec">El Chapultepec</a></li>
			<li><a href="#villagevanguard">Village Vanguard</a></li>
		</ul>
	</div>

</div>

<div data-role="page" data-next-page="#bluesalley" data-prev-page="#villagevanguard" class="swipeablepage" id="bakerskeyboardlounge">

	<div data-role="header">
		<h1>Baker's Keyboard Lounge</h1>
	</div>

	<div class="ui-content" role="main">
		<address>2050 Livernois Ave
		<br>Detroit, Michigan 48221</address>
		<img src="https://maps.googleapis.com/maps/api/staticmap?center=2050%20Livernois%20Ave,%20Detroit,%20MI&zoom=14&size=288x200&markers=2050%20Livernois%20Ave,%20Detroit,%20MI&sensor=false" height="200" width="288" />
		<a href="#home" class="ui-btn ui-icon-home ui-btn-icon-left">Home</a>
	</div>

</div>



<div data-role="page" data-next-page="#elchapultepec" data-prev-page="#bakerskeyboardlounge" class="swipeablepage" id="bluesalley">

	<div data-role="header">
		<h1>Blues Alley</h1>
	</div>

	<div class="ui-content" role="main">
		<address>1073 Wisconsin Ave. NW
		<br>Washington, DC 20007</address>
		<img src="https://maps.googleapis.com/maps/api/staticmap?center=1073%20Wisconsin%20Ave.%20NW%20Washington,%20DC&zoom=14&size=288x200&markers=1073%20Wisconsin%20Ave.%20NW%20Washington,%20DC&sensor=false" height="200" width="288" />
		<a href="#home" class="ui-btn ui-icon-home ui-btn-icon-left">Home</a>
	</div>

</div>

<div data-role="page" data-next-page="#villagevanguard" data-prev-page="#bluesalley" class="swipeablepage" id="elchapultepec">

	<div data-role="header">
		<h1>El Chapultepec</h1>
	</div>

	<div class="ui-content" role="main">
		<address>1962 Market St
		<br>Denver, CO 80202</address>
		<img src="https://maps.googleapis.com/maps/api/staticmap?center=1962%20Market%20St.%20Denver,%20CO&zoom=14&size=288x200&markers=1962%20Market%20St.%20Denver,%20CO&sensor=false" height="200" width="288" />
		<a href="#home" class="ui-btn ui-icon-home ui-btn-icon-left">Home</a>
	</div>

</div>

<div data-role="page" data-next-page="#bakerskeyboardlounge" data-prev-page="#elchapultepec" class="swipeablepage" id="villagevanguard">

	<div data-role="header">
		<h1>Village Vanguard</h1>
	</div>

	<div class="ui-content" role="main">
		<address>178 7th Avenue South, New York, NY 10014
		<br></address>
		<img src="https://maps.googleapis.com/maps/api/staticmap?center=178%207th%20Avenue%20South,%20New%20York,%20NY&zoom=14&size=288x200&markers=178%207th%20Avenue%20South,%20New%20York,%20NY&sensor=false" height="200" width="288" />
		<a href="#home" class="ui-btn ui-icon-home ui-btn-icon-left">Home</a>
	</div>

</div>

</body>
</html>

Code Explanation:

Note that the JavaScript handling the swipe events is much more brief. We bind the swipeleft and swiperight to any div of class swipeablepage - we've chosen not to offer swiping from the home page, though of course we could.

For each swipe event, bring the user to the page represented by the id contained in the respective div's data-next-page (or -prev-page): $( "body" ).pagecontainer( "change", $(this).attr('data-prev-page') )

Handling Orientation Change

Mobile phones, unlike desktops and laptops, often change orientation: we tilt our phones from vertical (portrait) to horizontal (landscape) orientation. Web pages and apps that respond to orientation changes are more useful and more interesting.

jQuery Mobile makes easy the handling of these events with the orientationchange event; see the jQuery Mobile docs for more info:

jQuery Mobile Orientation Event
Event Details
orientationchange Triggers when a device orientation changes (by turning it vertically or horizontally). When bound to this event, your callback function can leverage a second argument, which contains an orientation property equal to either "portrait" or "landscape". These values are also added as classes to the HTML element, allowing you to leverage them in your CSS selectors. Note that we currently bind to the resize event when orientationchange is not natively supported, or when $.mobile.orientationChangeEnabled is set to false.

Showing/hiding content, changing a side-by-side layout into a stacked vertical layout, and other orientation-state reactions are enhancements to your pages that your mobile users will appreciate.

Let's look at an example with the Jazz Calendar site: open jQueryMobile/Demos/jazz-orientation/index.html in a phone browser and with a file editor to check the code.

Code Sample:

jQueryMobile/Demos/jazz-orientation/index.html
<!DOCTYPE html> 
<html> 
	<head> 
	<title>Jazz Calendar</title> 
	<meta name="viewport" content="width=device-width, initial-scale=1"> 
	<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css" />
	<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
	<script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
	<script type="text/javascript">
		
		$(document).on('swiperight', ".swipeablepage", function() {
			$( "body" ).pagecontainer( "change", $(this).attr('data-prev-page') );
		});
		
		$(document).on('swipeleft', ".swipeablepage", function() {
			$( "body" ).pagecontainer( "change", $(this).attr('data-next-page') );
		});

		$(window).on('orientationchange', function(event) {
 			setContent(event.orientation);
		});

		$(document).on('pagecreate', function() {
			setContent(window.orientation);
		});

		function setContent(orien) {
			// desktops will return undefined for window.orientation, so handle that:
			if (orien != undefined) {
				// on page load, window.orientation returns 0, 90, -90, 180, so translate to 'portrait' or 'landscape'
				if (orien == '0' || orien == '180') {
					orien = 'portrait';
				} else if (orien == '90' || orien == '-90') {
					orien = 'landscape';
				}
				
				//hide extra content for portrait view
				if (orien == 'portrait') {
					$('p.info').hide();
				} else if (orien == 'landscape') {
					$('p.info').show();
				}
			}
		}

	</script>
</head> 
<body> 

<div data-role="page" class="page" id="home">
	<div data-role="header">
		<h1>Jazz Calendar - Attribute</h1>
	</div>

	<div class="ui-content" role="main">
		<p>Use the filter below to find concerts near you:</p>
		<form class="ui-filterable">
			<input id="filter-input" data-type="search">
		</form>
		<ul data-role="listview" data-filter="true" data-input="#filter-input">
			<li><a href="#bakerskeyboardlounge">Baker's Keyboard Lounge</a></li>
			<li><a href="#bluesalley">Blues Alley</a></li>
			<li><a href="#elchapultepec">El Chapultepec</a></li>
			<li><a href="#villagevanguard">Village Vanguard</a></li>
		</ul>
	</div>

</div>

<div data-role="page" data-next-page="#bluesalley" data-prev-page="#villagevanguard" class="swipeablepage" id="bakerskeyboardlounge">

	<div data-role="header">
		<h1>Baker's Keyboard Lounge</h1>
	</div>

	<div class="ui-content" role="main">
		<address>2050 Livernois Ave
		<br>Detroit, Michigan 48221</address>
		<img src="https://maps.googleapis.com/maps/api/staticmap?center=2050%20Livernois%20Ave,%20Detroit,%20MI&zoom=14&size=288x200&markers=2050%20Livernois%20Ave,%20Detroit,%20MI&sensor=false" height="200" width="288" />
		<a href="#home" class="ui-btn ui-icon-home ui-btn-icon-left">Home</a>
		<p class="info">Baker's is noted for its long history of presenting local and major jazz acts, its excellent acoustics, its intimacy - seating only 99, its Art Deco furnishings, including a distinctive, piano-shaped bar painted with a keyboard motif.</p>
	</div>

</div>

<div data-role="page" data-next-page="#elchapultepec" data-prev-page="#bakerskeyboardlounge" class="swipeablepage" id="bluesalley">

	<div data-role="header">
		<h1>Blues Alley</h1>
	</div>

	<div class="ui-content" role="main">
		<address>1073 Wisconsin Ave. NW
		<br>Washington, DC 20007</address>
		<img src="https://maps.googleapis.com/maps/api/staticmap?center=1073%20Wisconsin%20Ave.%20NW%20Washington,%20DC&zoom=14&size=288x200&markers=1073%20Wisconsin%20Ave.%20NW%20Washington,%20DC&sensor=false" height="200" width="288" />
		<a href="#home" class="ui-btn ui-icon-home ui-btn-icon-left">Home</a>
		<p class="info">Founded in 1965, Blues Alley is the nation's oldest continuing jazz supper club, having showcased internationally renowned concert hall artists such as Dizzy Gillespie, Sarah Vaughan, Nancy Wilson, Grover Washington Jr., Ramsey Lewis, Charlie Byrd, Maynard Ferguson and Eva Cassidy in a small intimate setting. <a href="http://www.bluesalley.com/visit.cfm">More Info</a></p>
	</div>

</div>

<div data-role="page" data-next-page="#villagevanguard" data-prev-page="#bluesalley" class="swipeablepage" id="elchapultepec">

	<div data-role="header">
		<h1>El Chapultepec</h1>
	</div>

	<div class="ui-content" role="main">
		<address>1962 Market St
		<br>Denver, CO 80202</address>
		<img src="https://maps.googleapis.com/maps/api/staticmap?center=1962%20Market%20St.%20Denver,%20CO&zoom=14&size=288x200&markers=1962%20Market%20St.%20Denver,%20CO&sensor=false" height="200" width="288" />
		<a href="#home" class="ui-btn ui-icon-home ui-btn-icon-left">Home</a>
		<p class="info">El Chapultepec, at 20th and Market streets in lower downtown Denver, may look like just a divey little bar. But this jazz club has hosted some of the most legendary artists in music history. <a href="http://www.gocolorado.com/restaurants/bars-pubs/denvers-el-chapultepec-cold-beer-hot-jazz/">More Info</a></p>
	</div>

</div>

<div data-role="page" data-next-page="#bakerskeyboardlounge" data-prev-page="#elchapultepec" class="swipeablepage" id="villagevanguard">

	<div data-role="header">
		<h1>Village Vanguard</h1>
	</div>

	<div class="ui-content" role="main">
		<address>178 7th Avenue South, New York, NY 10014
		<br></address>
		<img src="https://maps.googleapis.com/maps/api/staticmap?center=178%207th%20Avenue%20South,%20New%20York,%20NY&zoom=14&size=288x200&markers=178%207th%20Avenue%20South,%20New%20York,%20NY&sensor=false" height="200" width="288" />
		<a href="#home" class="ui-btn ui-icon-home ui-btn-icon-left">Home</a>
		<p class="info">For 70 years, [our] alliterative name has swung in 4/4 time, marking the center of the known jazz universe to an international circle of musicians and music fans. To the uninitiated, the small club at the bottom of 15 well-trodden steps below street level may seem little more than a cramped, triangular-shaped room. But to a hip populace its where the ghosts of past jazz giants still play, where the best living jazz talent aspire to record, and where sound waves seem to reverberate in a manner unlike any other club, anywhere. <a href="http://www.villagevanguard.com/html/history.html">More Info</a></p>
	</div>

</div>

</body>
</html>

We create a function, setContent, which when executed will check to see if the parameter passed to it (orien) is undefined; if not, then we must be dealing with a device for which orientation makes sense - a phone rather than a desktop.

setContent can be invoked in two different ways. When the page initially loads ($(document).on('pagecreate', '.page', function()), we pass the value of window.orientation to setContent - this has a value of 90 or -90 (for landscape orientations) or 0 or 180 (for portrait orientations).

We also check for orientation-state changes ($(window).on('orientationchange', function(event)) after the page has loaded, passing the value of event.orientation to setContent. This parameter has a value of "landscape" or "portrait".

If its parameter has one of the numeric values, function setContent translates the value into "landscape" or "portrait". It then uses jQuery's hide() and show() functions to hide or show any paragraph of class info - showing the content for landscape and hiding it for portrait:

portrait orientation

landscape orientation

Pickup Soccer with jQuery Mobile

Duration: 25 to 35 minutes.

Let's use the Rapid Interface Builder to create a mobile-optimized page for the Pickup Soccer site. We'll add a simple header and footer, style with the page with one of the stock jQuery themes, and use some collapsible elements to let the user pick from a few different content choices:

Rapid Interface Builder Pickup Soccer

  1. Visit the Rapid Interface Builder from a Chrome browser;
  2. If prompted, click OK to allow 01.org to "store large data on your computer" - the prototyping tool uses local storage to save your work on your browser;
  3. Edit the "Header" and "Footer" titles (by double-clicking on them) to present appropriate content;
  4. Drag three "Collapsible Section" elements to the center portion of the layout window - select "jQuery Mobile" from the "Widget Sets" category in the "Widget Categories" at upper right, if needed;
  5. Change the title of each "Collapsible Area" (again, by double-clicking) to an appropriate word or phrase;
  6. Add content to each collapsible area: add plain text, add an image (you can upload an image from your computer/network), or try out some of the other jQuery Mobile-specific elements like button groups, grids, or accordions.
  7. Optionally, change the "theme" property of any element (or all elements) to see how using the stock jQuery Mobile themes - lettered from "a" to "e" - to change the appearance of your page;
  8. When you are satisfied with your page, click Preview at upper left to view your design - you can switch between "Layout" and "Preview" mode to make and view changes;
  9. Click Code at upper left to view the code that rendered your final design;
  10. Click Export at upper right to export (choose "zip" format) a copy of the finished project; if possible, save the project files to a web-accessible server and view on a smartphone to test it out with an actual mobile device;
  11. Open the file in an editor to check the code.

Solution:

jQueryMobile/Solutions/soccer/index.html
<!DOCTYPE html>
<html>
    
    <head>
        <title>title</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <script src="lib/jquery-1.6.4.js"></script>
        <script src="lib/jquery.mobile-1.1.0.js"></script>
        <link href="src/css/jquery.mobile.structure-1.1.0.css" rel="stylesheet">
        <link href="src/css/jquery.mobile.theme-1.1.0.css" rel="stylesheet">
    </head>
    
    <body>
        <div data-role="page" id="page1">
            <div data-role="header" data-theme="e">
                <h1>Pickup Soccer</h1>
            </div>
            <div data-role="content">
                <div data-role="collapsible" data-theme="e" data-content-theme="e">
                    <h1>Schedule</h1>
                    <div class="ui-grid-a">
                        <div class="ui-block-a">
                            <span>Sat 1/25</span>
                        </div>
                        <div class="ui-block-b">
                            <span>Barry Park - 1 pm</span>
                        </div>
                        <div class="ui-block-a">
                            <span>Sun 1/26</span>
                        </div>
                        <div class="ui-block-b">
                            <span>PS 122 - 2 pm</span>
                        </div>
                        <div class="ui-block-a">
                            <span>Mon 1/27</span>
                        </div>
                        <div class="ui-block-b">
                            <span>PS 122 - 7 pm</span>
                        </div>
                    </div>
                </div>
                <div data-role="collapsible" data-theme="e" data-content-theme="e">
                    <h1>About Us</h1>
                    <span>Perfect for any ability, Pickup Soccer offers informal games at set times across
                        our community.</span>
                    <img src="images/twolegsball.jpg">
                </div>
                <div data-role="collapsible" data-theme="e" data-content-theme="e">
                    <h1>Contact</h1>
                    <span>123 Fake Street, Anywhere, USA</span>
                </div>
            </div>
            <div data-role="footer" data-theme="e">
                <h1>Find a Game. Now.</h1>
            </div>
        </div>
    </body>

</html>

Code Explanation:

Not much coding to do here - none, really! The Rapid Interface Builder has done all the work for us. Of course, the WYSIWYG builder has its limitations - more advanced behaviors would require some custom coding. In addition, the tool renders code from an older (but certainly still viable) version of jQuery Mobile. But a nice way to start!

As you dig through the code from our solution, note that we used a jQuery Mobile "grid" element for the "schedule" content and that we used theme "e" for all elements, giving the header, footer, and various widgets a yellow color scheme.

Note, too, that the Rapid Interface Builder gathers together all of the files we need for our mobile-optimized page into directories: source for the jQuery and jQuery Mobile libraries, images for any images, etc.

What about Desktops?

As mentioned above, jQuery Mobile is a mobile-centric library, emphasizing UI widgets and presentation specifically for smartphones and tablets. But (as also mentioned above), jQuery Mobile certainly works fine for desktop browsers. Offering a better desktop experience is easy enough with the addition of some CSS3 media queries.

Consider the jQuery Mobile main documentation page. When viewed on a desktop at a browser width greater than 650 pixels, the main navigation element sits to the left of the main content:

jQuery Mobile Docs page - wide browser

At browser widths narrower than 650 pixels, the design moves to a one-column layout, with the nav on top of the main content:

jQuery Mobile Docs page - narrow browser

The site accomplishes this with a custom stylesheet. A custom CSS stylesheet - that is, a CSS file the authors of the site have added themselves, separate from the standard jQuery Mobile stylesheet - directs the div layer holding the nav to float left when the browser is wider than 650 pixels:

@media all and (min-width: 650px){
			/* some code omitted */
			.content-secondary {
				text-align: left;
				float: left;
				width: 45%;
				background: none;
			}
			/* some code omitted */
		}

As designers and developers, we can add whatever custom styles we want to our jQuery Mobile sites, enhancing the user experience for visitors who view our sites and Web applications on desktop browsers.