jQuery Mobile: Part II - Mobile - HTML5, JavaScript and jQuery (Programmer to Programmer) - 2015

HTML5, JavaScript and jQuery (Programmer to Programmer) - 2015

Part V Mobile

Lesson 40 jQuery Mobile: Part II

In this lesson, you will continue with the creation of a jQuery Mobile web application but shift your focus away from pages and navigation and toward mobile-specific UI components and mobile-based events. As mentioned in the previous lesson, mobile devices naturally lend themselves to different approaches from traditional desktops and laptops, and this can impact both the UI components used and the event listeners registered.

UI Components

Mobile phone platforms such as iOS and Android each support a toolkit of UI components (commonly referred to as widgets). Many of these, such as text fields, mirror HTML elements extremely closely. Several others, however, are intended to address the unique needs of mobile devices and do not match corresponding HTML elements.

In order to address this discrepancy, the jQuery Mobile library provides a wide variety of UI components that match those commonly found in native toolkits. You have already encountered several of these in the previous lesson: This included buttons, control groups, pages, tables, headers and footers, and you will continue looking at several others in this section.

The components you have seen so far have all been based on conventional HTML elements such as the table or select elements, but have been transformed into components by jQuery Mobile based on their data attributes and CSS classes.

In fact, in many cases you are using jQuery Mobile components even without realizing it. If you view the Add contact page, you will notice that the select element has been customized specifically for mobile devices, as shown in Figure 40.1. This looks similar to the components you will see in native mobile applications, and follows the same basic design philosophy.

image

Figure 40.1

You will also notice that the appearance of this component has been significantly modified from the native Chrome select element, as shown in Figure 40.2, despite the fact that no jQuery Mobile specific attributes or classes were provided.

image

Figure 40.2

If you inspect the HTML for the web page, you will see that jQuery Mobile has achieved this partly via CSS classes, but more importantly, it has added a whole new set of elements to the DOM, as you can see in Figure 40.3.

image

Figure 40.3

The top two div elements shown in Figure 40.3 have been added by jQuery Mobile itself and provide a way of modifying the appearance and behavior of the select element contained within it.

Not only does this approach allow jQuery Mobile to create more mobile-friendly components that are easier to interact with using your finger, it means that you can maintain a consistent look and feel across different mobile browsers and platforms.

All jQuery Mobile components, even those based on conventional HTML elements, support a wide array of properties and methods, and therefore act more like the feature-rich UI components found in native frameworks.

For instance, if you open the Add contact screen and type the following:

$('select' ).selectmenu('disable');

the select component will be immediately disabled.

Each UI component is associated with a jQuery Mobile method. As you can see, select boxes are associated with the selectmenu method, and this line of code therefore invokes a method called disable on a selectmenu component.

Conversely, you can convert a jQuery Mobile component back into a conventional HTML component by invoking destroy on it:

$('select').selectmenu('destroy')

You can also programmatically construct components by invoking the relevant method on them and passing an optional object with any options:

$('select').selectmenu({'icon': 'star'});

The options passed can almost always also be provided via the data attributes investigated in the previous lesson, but there are times when it makes sense to programmatically construct components, particularly when they are added to the page after the page has loaded. In fact, because the contacts are loaded into the main table after jQuery Mobile had initialized, it was necessary to manually initialize the components inside the table body with the following code:

$(screen).find('table').table("refresh");

$(screen).find('[data-role="controlgroup"]').controlgroup();

Note

The full list of options and methods supported by the various jQuery Mobile components is beyond the scope of this book, but be sure to browse the jQuery Mobile documentation at api.jquerymobile.com to gain a greater understanding of the power and flexibility of these UI components.

Collapsible Components

Let's begin this look at new components by adding a final page to the web application. This page will be used to contain any settings or configuration tools required by the web application. The code for this page is as follows:

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

<div data-role="header">

<h1>Settings</h1>

<a href="#contactListPage" data-role="button" data-icon="home" data-transition="slidedown" class="ui-btn-right">Home</a>

</div>

<div data-role="content">

<div data-role="collapsible-set">

<div data-role="collapsible" data-collapsed="false">

<h3>Import contacts</h3>

<p>

<label for="importJSONFile">Import contacts</label>

<input type="file" id="importJSONFile" name="importJSONFile">

</p>

</div>

<div data-role="collapsible">

<h3>Import from server</h3>

<p>

<a id="importFromServer" data-role="button"

href="#">Import from server</a>

</p>

</div>

</div>

</div>

</div>

The structure and heading of this page should look very familiar, but the content contains a new type of component called a collapsible set. This component functions like a set of vertical tabs: Each entry in the set is assigned a header (indicated by an h3 tag) and a details section (indicated by a p tag), and when a header is selected, its detail section is displayed, as shown in Figure 40.4.

image

Figure 40.4

This component is ideal for mobile web applications because it allows various options to be presented on the same page without the detail of each option distracting the user. Notice also that jQuery Mobile automatically takes care of assigning appropriate icons to each option: The plus icon indicates that the details can be shown, whereas the minus icon indicates that the option is currently selected.

It is also possible to use collapsible components outside the collapsible-set component. In this case, the component functions identically to the summary and details elements you encountered earlier in the book, but has the advantage of working consistently across all browsers.

Popups

An alternative way of implementing the Settings screen would be as a popup. A popup leaves the user in the context of the current page, and means users do not need to navigate back to where they came from once they complete their action.

In order to implement a page as a popup, you need to start by changing the data-role of the div from page to popup:

<div id="settingsPage" data-role="popup">

It is also necessary to move the markup for the page so that it sits inside the contactListPage element, preferably just before the closing section tag.

You will also remove the header from the Settings page when it appears as a popup, and replace it with a Close button on the right-hand side of the popup. This can be achieved by replacing the header with the following:

<a href="#" data-rel="back" data-role="button" data-icon="delete" data-iconpos="notext" class="ui-btn-right">Close</a>

The final change is to add data-rel=”popup” to the link that opens the settings page so that the page opens as a popup:

<a href="#settingsPage" data-rel="popup" data-role="button" data-icon="gear" class="ui-btn-right" data-transition="slideup">Settings</a>

If you reload the web page and press the Settings button, the page will be displayed as a popup over top of the current page.

Selection

jQuery Mobile also supports a widely used mobile component called a list. This provides a mechanism for the user to select a single option from a list of options, usually with the intention of viewing additional information.

This component could have provided an additional mechanism for arranging the Contact list screen. For instance, the contacts could be arranged in a list as follows:

<div data-role="content">

<ul data-role="listview">

<li><a href="#" data-contact-id="1">Dane Cameron</a></li>

<li><a href="#" data-contact-id="2">James Cook</a></li>

<li><a href="#" data-contact-id="3">William Pitt</a></li>

</ul>

</div>

This is a conventional unordered list, as encountered earlier in the book, except the ul element has been tagged with the data-role=”listview” attribute, and each list item contains a link to the relevant contact. When viewed, this appears as you see in Figure 40.5.

image

Figure 40.5

Each element in the list could then be clicked to load the details and notes of the contact. Because it is only possible to select a single action per row, the delete functionality would need to be managed in an alternative manner, such as a button on the Contacts Notes screen.

Lists are often used as an alternative to tables in mobile web applications because they tend to adjust more easily to small resolutions.

Flip-Switch

The final component we will address is a called a flip-switch. A flip-switch is used for selecting between two possible states, and is therefore similar to the checkboxes commonly used in HTML forms. In order to demonstrate this, add the following to the form on the Add contact screen:

<div class="ui-field-contain">

<label for="followUp"Follow up required</label>

<input name="followUp" id="followUp" type="checkbox" data-role="flipswitch" />

</div>

This component is modeled as a conventional checkbox, but assigned the attribute data-role=”flipswitch”. This constructs the component shown in Figure 40.6.

image

Figure 40.6

Like many of these components, the main reason flip-switches are preferred over checkboxes is that they are more “touch-friendly.” It feels more intuitive for a finger to slide a switch and see its state toggled because the action mirrors real-world switches such as light and socket switches. Pressing your finger inside a square and seeing a check appear, by contrast, does not mirror a real-world activity.

Events

Our mobile web application now resembles a native mobile application in many ways, but there is still one core feature to add: mobile events.

The events generated by mobile devices are fundamentally different from traditional desktops in three basic ways:

· The user is holding the device; therefore they can convey meaning by moving the device. For instance, shaking an iOS-enabled device triggers an undo operation.

· The device (usually) supports touch screen; therefore the user can interact with the device by touching it with his or her fingers, and using “gestures.”

· As you have seen, navigation is typically implemented differently in mobile web applications; therefore, mobile devices support a class of events linked to navigation.

Unfortunately, it is not possible to respond to the first class of events with mobile web applications because the API is only available to native web applications, but the next lesson looks at a workaround. This section addresses the other two classes of events.

Gestures

jQuery Mobile supports event listeners for four special types of events:

· Swipe: The swipe event involves the user moving a finger horizontally across the screen for 30 pixels or more within a time-range of 1 second. It is possible to listen for any swipe, swipes to the left (swipeleft), or swipes to the right (swiperight).

· Tap: The tap event is triggered by the user quickly touching the screen with a single finger. This event type is very similar to (and often confused with) a click event, and, in fact, mobile browsers will generate click events when the user taps the screen.

You may be wondering why you need to specifically listen for tap events when click events are generated automatically. The main reason is performance: There is often a significant lag between when the tap event is generated and when the click event is generated so if you want to create a responsive web application, you need to ensure you register tap event listeners.

If you are supporting mobile and non-mobile devices, you also need to ensure you register click listeners, of course. In order to make this process easier, jQuery Mobile supports a special event type called vclick (virtual click), which ensures the appropriate event listener is registered for the device.

· Tap hold: The taphold event is triggered when the user taps an area of the screen with one finger, and holds his finger in that spot for a sustained period (750 milliseconds by default). This event type is commonly used as an alternative to right-mouse clicks in mobile applications, and commonly produces a popup menu listing possible options from the context of the click.

Although this event has its uses, the main drawback of it is that the user may not be aware the functionality behind this event exists.

· Scroll: jQuery Mobile supports two scroll-based events: scrollstart and scrollstop. These events fire as the user scrolls a page with her finger.

jQuery Mobile event listeners are registered in an identical manner to conventional jQuery events. For instance, consider a case where you want a swipe on the Add contact screen to take the user back to the Contact list screen. This can be achieved with the following event listener:

$('#contactDetailsPage').on('swipe', function(evt) {

$(":mobile-pagecontainer").pagecontainer("change", "#contactListPage", { transition: 'slide', direction: 'reverse' });

});

The event listener itself is registered on the entire page, meaning that the user can swipe anywhere on the screen, and the event will be captured.

Lifecycle Events

The other major class of event is related to jQuery Mobile lifecycle and page navigation. Because the user changes pages without loading a new HTML page, it is sometimes necessary to ensure a page is initialized appropriately when a user navigates to it for the first time, or that it is refreshed when the user navigates to it on subsequent occasions.

Just as jQuery supports a ready event, jQuery Mobile supports a mobileinit event: This method is invoked once per page refresh and indicates that jQuery Mobile has completed its initialization of the page. This event listener should be registered directly on the document—for instance:

$( document ).on( "mobileinit", function() {});

Just as the entire mobile web application is initialized, each page is also initialized once, on demand when the user first navigates to it. It is at this point that jQuery Mobile constructs the relevant UI components required by the page. It is possible to register an event listener that will be fired when this process completes. For instance, if you want to execute specific code after the Settings page is constructed, you can register the following event listener:

$(document).on('pagecreate','#settingsPage', function(){

console.log('Settings page is being created');

});

Most of the other events are navigation related and therefore relate specifically to the pagecontainer component, which is the container holding all other pages. These events follow the lifecycle that occurs in jQuery Mobile as a page change is completed:

· An event is fired on the page that will be hidden, but while it is still visible.

· An event will be fired on the page that will be displayed, but before it is visible.

· An event is fired on the page that has been hidden, after it has been hidden.

· An event will be fired on the new page displayed, once it is visible.

Event listeners can be registered with this component as follows:

$(document).on("pagecontainerbeforechange", function( event, ui ) {

console.log('Before change event fired');

});

The event listener is always passed two objects: The first is the event object you are familiar with from jQuery. In this particular case, because the page change has not occurred yet, you are afforded the opportunity to veto the page change by invokingevent.preventDefault().

The second object provides context about the UI event. For instance, it contains a toPage property indicating the page that the user is navigating to, and a prevPage property indicating the current page.

The other events that occur during the page navigation lifecycle are (in order):

· pagecontainerbeforeshow

· pagecontainerhide

· pagecontainerload

It is also possible to register an event listener that simply fires whenever a page transition completes; this can be accomplished by registering a listener with the pagecontainertransition event.

Try It

When developing mobile web applications, it is essential to have a fast turnaround between making code changes and seeing the results on a mobile device.

In order to ease this process, it is common to turn to mobile phone emulators. As you have seen, Chrome comes built in with a simple emulator, but in this Try It, you will install and use a more complex emulator called Ripple.

Lesson Requirements

In this lesson, you will need the Chrome web browser and a version of the CRM mobile web applications you have developed in this lesson.

Step-by-Step

1. Open the Chrome browser and browse to chrome://apps. From here, click the Web Store link at the bottom of the page.

2. Change the Types filter to “Extensions,” and search for “Ripple.” The result should return the app shown in Figure 40.7.image

Figure 40.7

3. Select to install the Ripple application by clicking the + FREE button. The application will automatically be installed without a restart.

4. Open the mobile_contacts.html page through your web server. You will notice a small green button to the right of the toolbar, as shown in Figure 40.8. Click this, and then select Enable.image

Figure 40.8

5. You will be prompted with a list of platforms that you wish to emulate; choose Mobile web (default).

6. You will be presented with a full screen emulator. Not only does this allow you to see how the mobile web application will look in various devices, but it allows you to manually set features such as the current location and the angle the phone is pointing.

7. In the top-left hand corner, select Devices and choose HTC Legend. The emulation should immediately change to show how the web application would appear in this particular phone.

8. Select to change the orientation of the phone to landscape mode.

9. Select the Platforms option and choose WebWorks. Press the Change Platform button. This will now show you how your web application will appear on a BlackBerry.