Whizu

jQuery Mobile in Java

View project on GitHub
Whizu Download
jQuery Mobile widgets
Pages Accordions Buttons Collapsibles

jQuery Mobile Pages

The page is the primary unit of interaction in jQuery Mobile and is used to group content into logical views that can be animated in and out of view with page transitions. A basic HTML document may start with a single 'page' and the AJAX navigation system will load additional pages on demand into the DOM as users navigate around. Alternatively, a HTML document can be built with multiple 'pages' inside it and the framework will transition between these local views with no need to request content from the server.

How to create a jQuery Mobile application with Whizu

A jQuery Mobile application consists of at lease one page. Creating a jQuery Mobile application with Whizu consisting of one or more pages is simple. The following code is the absolute minimum you need to implement.

import org.whizu.annotation.App;
import org.whizu.jquery.mobile.JQueryMobile;
import org.whizu.jquery.mobile.Page;

@App("/whizu/page/url")
public class MyJQueryMobileApplication implements JQueryMobile {

    @Override
    public void onLoad(Page page) {
        //implement this
    }
}

To summarize you need to do two things to create a jQuery Mobile application with Whizu.

Annotate your class with the @App annotation

The @App(“url) annotation specifies at which url your jQuery Mobile application will be served. You need to make sure that your url is being sent through the WhizuFilter by verifying that your WEB-INF/web.xml file contains a servlet-filter and filter-mapping url that matches your application's url. See the getting started guide for more information. Here's a sample WEB-INF/web.xml deployment descriptor file.

<filter>
  <filter-name>WhizuFilter</filter-name>
  <filter-class>org.whizu.server.WhizuFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>WhizuFilter</filter-name>
  <url-pattern>/whizu/*</url-pattern>
</filter-mapping>

Implement the JQueryMobile interface

Having your class implement the JQueryMobile interface tells Whizu that your application is a jQuery Mobile application. Additionally the JQueryMobile interface will force you to implement the following method.

@Override
public void onLoad(Page page) {
    //implement this
}

The page argument of the onLoad method corresponds to the initial jQuery Mobile Page called 'index' that is to be initialized after loading the application.

The default Whizu mobile page structure

A jQuery Mobile site must start with an HTML5 doctype to take full advantage of all of the framework's features. Older devices with browsers that don't understand HTML5 will safely ignore the 'doctype' and various custom attributes.

In the head, references to jQuery, jQuery Mobile and the mobile theme CSS are all required to start things off. jQuery Mobile 1.3.2 works with versions of jQuery core from 1.7.0 to 1.9.1. The easiest way to get started is to link to files hosted on the jQuery CDN or for best performance, build a custom bundle.

By default Whizu generates the following page structure.

<!DOCTYPE html> 
<html>
<head>
    <title>${title}</title>
    <meta name="description" content="${description}">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="${servlet-context-path}/whizu/stylesheet/whizu.css"/>
    <link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.css"/>
    <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js"></script>
</head>
<body>
    <div data-role='page' id='index'>
        <div data-role='content' id='whizu'></div>
    </div> 
</body>
</html>

Notice that by default a page called 'index' is being generated that correspondes to the page argument of the onLoad method of your jQuery Mobile application.

@Override
public void onLoad(Page page) {
    //implement this
}

Setting a custom title and description

To customize the page title ${title} and page description ${description} meta tag, the @Title and @Description annotations are available. Here's an example of their usage.

import org.whizu.annotation.App;
import org.whizu.annotation.Description;
import org.whizu.annotation.Title;
import org.whizu.jquery.mobile.JQueryMobile;
import org.whizu.jquery.mobile.Page;

@App("/whizu/page/url")
@Title("My page title")
@Description("My page description")
public class MyJQueryMobileApplication implements JQueryMobile {

    @Override
    public void onLoad(Page page) {
        //implement this
    }
}

Viewport meta tag

Note above that there is a meta viewport tag in the head to specify how the browser should display the page zoom level and dimensions. If this isn't set, many mobile browsers will use a 'virtual' page width around 900 pixels to make it work well with existing desktop sites but the screens may look zoomed out and too wide. By setting the viewport attributes to content=“width=device-width, initial-scale=1”, the width will be set to the pixel width of the device screen.

<meta name="viewport" content="width=device-width, initial-scale=1">

These settings do not disable the user's ability to zoom the pages, which is nice from an accessibility perspective. There is a minor issue in iOS that doesn't properly set the width when changing orientations with these viewport settings, but this will hopefully be fixed in a future release. You can set other viewport values to disable zooming if required since this is part of your page content, not the library.

Inside the tag, each view or 'page' on the mobile device is identified with an element (usually a div) with the data-role='page' attribute.

<div data-role="page">
    ...
</div>

Within the 'page' container, any valid HTML markup can be used, but for typical pages in jQuery Mobile, the immediate children of a 'page' are divs with data-roles of 'header', 'content', and 'footer'.

<div data-role="page">
    <div data-role="header">...</div>
    <div data-role="content">...</div>
    <div data-role="footer">...</div>
</div>

Putting it together: Basic single page template

Putting it all together, this is the standard boilerplate application and single page template you should start with on a new project.

import org.whizu.annotation.App;
import org.whizu.annotation.Description;
import org.whizu.annotation.Title;
import org.whizu.jquery.mobile.JQueryMobile;
import org.whizu.jquery.mobile.Page;

@App("/whizu/page/url")
@Title("My page title")
@Description("My page description")
public class MyJQueryMobileApplication implements JQueryMobile {

    @Override
    public void onLoad(Page page) {
        page.header("My Page Title");
        page.p("Page content goes here.");
        page.footer("My Page Footer");
    }
}

The corresponding application will look like this:

Basic jQuery Mobile Application

While here's the corresponding HTML markup being generated inside the 'body' tag:

<body>
    <div data-role='page' id='index'>
        <div data-role='header'>
            <h1>My Page Title</h1>
        </div>
        <div data-role='content' id='whizu'>
            <p>Page content goes here.</p>
        </div>
        <div data-role='footer' data-theme='e'>
            <h4>My Page Footer</h4>
        </div>
    </div>
</body>

Multi-page template structure

A single jQuery Mobile HTML document can contain multiple 'pages' that are loaded together by stacking multiple divs with a data-role of 'page'. Each 'page' block needs a unique id (id='foo') that will be used to link internally between 'pages' (href='#foo'). When a link is clicked, the framework will look for an internal 'page' with the id and transition it into view.

Whizu allows you to create additional pages using the PageBuilder API.

import org.whizu.jquery.mobile.Page;
import org.whizu.jquery.mobile.PageBuilder;

Page foo = PageBuilder.createWithId("foo").build();

Here is an example of a two 'page' site built with two jQuery Mobile divs navigated by linking to an id placed on each page wrapper. Note that the ids on the page wrappers are only needed to support the internal page linking, and are optional if each page is a separate HTML document. Here's the Java code. Have a look at the PageBuilder class providing you with a fluent builder API to create a new Page.

import org.whizu.annotation.App;
import org.whizu.annotation.Description;
import org.whizu.annotation.Title;
import org.whizu.jquery.mobile.JQueryMobile;
import org.whizu.jquery.mobile.Page;
import org.whizu.jquery.mobile.PageBuilder;

@App("/whizu/multipage")
@Title("My page title")
@Description("My page description")
public class MultiPageTemplate implements JQueryMobile {

    @Override
    public void onLoad(Page foo) {
        Page bar = createBar(foo);
        foo.header("Foo");
        foo.p("I'm first in the source so I'm shown as the page.");
        foo.p("View internal page called {}", bar);
        foo.footer("My Page Footer");
    }

    private Page createBar(Page foo) {
        // @formatter:off
        Page bar = PageBuilder
                .createWithId("bar")
                .header("Bar")
                .p("I'm the second in the source so I'm hidden when 
                    the page loads. I'm just shown if a link that 
                    references my id is being clicked.")
                .p("Back to {}", foo)
                .footer("Page footer")
                .build();
        return bar;
        // @formatter:on
    }
}

The browser will show the following. The hyperlink 'bar' takes you to the second page.

Here's the second page, the 'index' link takes you back to the home page.

Here is what the generated markup for two pages looks like inside the 'body' element.

<body>
<!-- Start of first page -->
<div data-role="page" id="index">

    <div data-role="header">
        <h1>Foo</h1>
    </div><!-- /header -->

    <div data-role="content" id="whizu">
        <p>I'm first in the source so I'm shown as the page.</p>
        <p>View internal page called <a href="#bar">bar</a></p>
    </div><!-- /content -->

    <div data-role="footer">
        <h4>Page Footer</h4>
    </div><!-- /footer -->
</div><!-- /page -->

<!-- Start of second page -->
<div data-role="page" id="bar">

    <div data-role="header">
        <h1>Bar</h1>
    </div><!-- /header -->

    <div data-role="content">
        <p>
            I'm the second in the source so I'm hidden when 
            the page loads. I'm just shown if a link that references 
            my id is beeing clicked.
        </p>
        <p><a href="#index">Back to foo</a></p>
    </div><!-- /content -->

    <div data-role="footer">
        <h4>Page Footer</h4>
    </div><!-- /footer -->
</div><!-- /page -->
</body>

PLEASE NOTE: Since jQuery Mobile is using the hash to track navigation history for all the AJAX 'pages', it's not currently possible to deep link to an anchor (index.html#foo) on a page in jQuery Mobile, because the framework will look for a 'page' with an id of #foo instead of the native behavior of scrolling to the content with that id.

The id attribute of all your elements must be not only unique on a given page, but also unique across the pages in a site. This is because jQuery Mobile's single-page navigation model allows many different 'pages' to be present in the DOM at the same time. This also applies when using a multi-page template, since all 'pages' on the template are loaded at once.

Javadoc API reference

The core classes, interfaces and annotations involved in creating jQuery Mobile applications and pages with Whizu are the following.

Some related API's include:

Of course, don't forget that for any of this to function you need to have added the WhizuFilter servlet filter-mapping to your WEB-INF/web.xml deployment descriptor.

Written by Rudy D'hauwe | Copyright © 2013 | All rights reserved.