You are on page 1of 257

(This page intentionally left blank)

Unit 1:
Unit 1: Introducing the Course

About the Course


Fast Track to Intel XDK New is designed to
teach experienced web developers and
designers how to design, implement, and
package web applications for mobile devices.
The course is task-based, with you learning by
performing a series of hands-on tasks. Over the
next four hours you will create a web
application named Friends with Beer that
enables users to create a themed contact
manager that uses many mobile-specific
features such as calculating geoposition, video
playback, push notifications, phone dialing,
sending emails, and more!
Along with covering the basics of the Intel
XDK New, the course focuses on best practices
and design, stressing the importance of
usability, optimization, and maintainability of
cross-device compatible applications.
Lab instructions are designed for Windows or Figure 1: The app
OS/X users who have an Android phone. that you'll build in this
course.

2013 Intel Corporation 1-1


Fast Track to Intel XDK New

Introducing Intel XDK New


Intel XDK NEW, enables you to easily create, test, and package cross-
device compatible HTML5-based mobile apps. Intel XDK New runs on
Windows 7,8, OS/X and Ubuntu Linux desktops. It seamlessly integrates
many best-of-breed mobile web development technologies into an easy-to-
use, integrated development environment.

Figure 2: The Intel XDK New GUI

Choose a Framework

You can develop your apps using popular HTML5 mobile


frameworks including
Bootstrap a popular front-end framework for faster
and easier web development.
jQuery Mobile the write less, do more library for
rapidly coding mobile apps.
Intel's App Framework - an open source HTML5 UI
framework
Topcoat a fast-performing CSS framework from Adobe that includes
icons, fonts, and themed components for mobile devices.

1-2 2013 Intel Corporation.


Unit 1: Introducing the Course

Develop visually, code fast and furiously

Intel XDK NEW integrates an easy-to-use, drag & drop app designer
with Brackets, a highly-regarded, open-source editor with syntax helpers
and auto-completion.

Figure 3: The integrated Brackets code editor.

Emulate popular devices

Use the built-in Apache Ripple device emulator to simulate your app
running on multiple devices, from different geographic locations, varying
bandwidth conditions, and changing orientations. Use the integrated
Google Chrome Dev Tools to troubleshoot runtime issues.

Figure 4: Using the built-in device emulator.

2013 Intel Corporation. 1-3


Fast Track to Intel XDK New

Trust, But Verify

By loading Intel App Preview onto your mobile devices, you'll be able to
easily:
Run your app on physical devices without rebuilding
Debug your app while it's running on the device, using the integrated
weinre remote debugger.
Conduct performance profiling
Check out demo apps.
Intel App Preview is available for iOS, Android, and Windows Phone.

Figure 5: Test your app on physical devices with Intel App Preview

1-4 2013 Intel Corporation.


Unit 1: Introducing the Course

Package for App Stores

After you've completed your testing, use Intel XDK's integrated Apache
Cordova framework to build native apps for all the popular mobile
platforms.

Integrate native features and add cloud support

The Intel XDK API that includes features not currently available in
Cordova, including:
Facebook login API
Android multi-touch
Oauth support
Enhanced audio
Accelerated canvas
In addition, you can quickly add cloud-based features from appMobi to
such as push notification support, user management, e-commerce, and
cloud hosting.

2013 Intel Corporation. 1-5


Fast Track to Intel XDK New

Reviewing the Course Objectives


After completing this course, you should be able to:
Develop web and native apps for mobile devices
Visually design and implement a graphical user interface.
Create input forms that read and submit data to/from an application
server
Request JSON data from an application server
Integrate mapping, geolocation, and push notifications into a mobile
app.
Deploy audio and video assets
Theme your application to meet branding standards
Test and package your app to run natively on Android and iPhone
devices.

Reviewing the Course Prerequisites


The knowledge prerequisites for this course are:
Prior experience with HTML 5
A casual understanding of CSS
Intermediate JavaScript coding skills and, in particular, familiarity with
JavaScript Object Notation

Required Software
The following software is REQUIRED to be installed on your computer:

Intel XDK
http://xdk-software.intel.com/
Fast Track to Intel XDK student files
http://www.xdktraining.com/student.zip

The following software is REQUIRED to be installed on your mobile


device:

Intel App Preview


Available on iOS, Android, and Microsoft stores.

1-6 2013 Intel Corporation.


Unit 1: Introducing the Course

Reviewing the Course Format


This course is divided into ten units, each of which presents new
information and contains demonstrations, walkthroughs, and a lab. At the
end of each unit, you will find a summary and a short review to test your
knowledge of the units content.
The following icons are used throughout the guide:

Concepts introduce new information.

Demonstrations illustrate new concepts.

Walkthroughs guide you, with the instructors assistance, through


procedures in a hands-on context.

Labs let you practice new skills on your own.

Summaries provide a brief synopsis of the units content.

Reviews test how well you remember the concepts from the unit.

Best Practices provide you with helpful insights and information.

2013 Intel Corporation. 1-7


Fast Track to Intel XDK New

Outlining the Course Content


Unit 1: Introducing the Course

Unit 2: Getting Started


Introducing the Intel XDK New
Reviewing the features and benefits of HTML5 / CSS3
Using Debugging Techniques
Getting Help

Unit 3: Designing Views


Defining Pages
Using Layout Controls
Linking to Pages
Adding text and images

Unit 4: Working with Data


Using jQuery to make data requests via AJAX
Outputting structured data into a List
Reading Data from the Contact's list
Storing data on the Device with WebSQL

Unit 5: Implementing Forms


Using the Forms Widgets
Implementing Data Validation
Saving Form Data

Unit 6: Implementing GEO Features


Geocoding Addresses
Acquiring the Device Position
Calculating Distance to Targets
Visualizing Data on a Map

1-8 2013 Intel Corporation.


Unit 1: Introducing the Course

Unit 7: Using Device Features


Dialing the Phone
Sending Email
Launching Turn By Turn Directions
Using the Accelerometer
Handling Push Notifications

Unit 8: Handing Multimedia


Understanding the features and capabilities of HTML5
Playing Audio
Playing Video

Unit 9: Theming your App


Using CSS3 Features and Capabilities
Applying CSS3 Backgrounds
Using ThemeRoller to theme your UI components

Unit 10: Going Native


Creating Production Web Builds
Creating Native Builds for iOS
Exercise: Packaging a Native iOS Build

2013 Intel Corporation. 1-9


Fast Track to Intel XDK New

Demonstration 1-1: Viewing the Applications


Observe as your instructor introduces the applications that you will be
building during the exercises:

You will build the Friends with Beer mobile application during your
instructor-led walkthroughs in the following order:
About Friends with Beer (Home Page)
Beer List
Friends with Beer Contact List
Friends with Beer Contact Data Entry Form
Friends with Beer Contact Detail
Friends with Beer Video

Reviewing the Application Intro Screens

The Friends with Beer Home Page The Beers List displays a list of
contains simple html markup. It's beers that were downloaded from a
designed to help you get comfortable REST-based web service and
using the Intel XDK visual designer. cached into an HTML5 WebSQL
database.

1 - 10 2013 Intel Corporation.


Unit 1: Introducing the Course

The Contact List is driven from data The Contact form enables you to
stored in a WebSQL database. Clicking edit information about your
on the button in the top-left corner contacts. It also converts their
enables you to import data from your street address to a lat/lng position
phone's native contacts app. Users can on-the-fly and has client-side data
actually shake the device to select a validation.
friend at random.

2013 Intel Corporation. 1 - 11


Fast Track to Intel XDK New

Reviewing the Application Using Device Features

The Friends with Beer Detail Page The Video page displays a
enables the user to activate the device's streaming video from Vimeo and
phone dialer, email application, and an mp4 from a web server so that
navigation app. It also uses Google the user will never have to feel like
Maps to display real-time traffic they're drinking alone.
conditions around your friend's
location.

1 - 12 2013 Intel Corporation.


Unit 1: Introducing the Course

Walkthrough 1-1: Installing the Courseware


In this lab, you will perform the following tasks:

Install Intel XDK New on your desktop


Install Intel App Preview on your mobile device
Download and install the course files

Steps

Download and Install Intel XDK


1. Open a web browser to the following URL:
http://xdk-software.intel.com/
2. Click the Download Intel XDK New button.

OS/X Users:
3. Open the downloaded .dmg file
4. Double-click on the .pkg file
5. Complete the steps in the installation wizard.
6. Select Go > Applications and verify that XDK New is present.

Microsoft Windows 7+ Users:


7. Open the downloaded .exe file
8. Complete the steps in the installation wizard
9. Verify that Intel XDK New appears in your Start menu.

Log into Intel XDK


10. Launch Intel XDK New
11. Click on Need to sign up for an Account?
12. Fill out the form, entering your name, email address, password, and
country. Note the following:
Passwords must be between 8-15 characters in length
Passwords must contain at least one alpha character
Passwords may not contain non-English characters
Passwords must contain at least one number
Passwords must contain at least one special character (!@#$%)
13. Check the Terms and Conditions checkbox.
14. Sign up for the newsletters.

2013 Intel Corporation. 1 - 13


Fast Track to Intel XDK New

15. Click the Submit button.


16. Enter your username and password.
17. Turn on the checkbox labeled Keep me logged in on this computer.
18. Click Submit.

Install Intel App Preview on your Mobile Device


19. Configure your mobile device to be on the same wireless network as
your computer.
20. Open Google Play on your Android phone.
21. Search for Intel App Preview
22. Tap on Intel App Preview
23. Tap on the Install button.
24. Tap the Accept button.
25. When the installation process as completed, tap the open button.
26. Sign into the app using the Intel XDK credentials that you created
earlier in this exercise.

Download and Unzip the Exercise Files


27. Download the exercise files from
http://www.xdktraining.com/exercises.zip
28. Unzip the files into your home/documents folder.

End of Walkthrough --

1 - 14 2013 Intel Corporation.


Unit 1: Introducing the Course

Unit Summary
The course is presented through a combination of lectures and hands-
on exercises.
The course has been designed assuming that you already understand
HTML, CSS, and some Javascript.
The course consists of 10 units that cover the essentials of developing
mobile apps with Intel XDK New.
The course focuses on developing web and native applications for
mobile devices.
You will build a web application to keep track of your friends with
beer.

2013 Intel Corporation. 1 - 15


(This page intentionally left blank)
Unit 2:
Getting Started with Intel XDK New

Unit Objectives
After completing this unit, you should be able to:
Understand the features and capabilities of Intel XDK New
Use the visual designer to create a Hello World page in your app.
Use the code editor to add JavaScript to your app.
Test your app on the simulator and your mobile device.
Package your app as a native application for distribution on App stores.

Unit Topics
Introducing Intel XDK New
Debugging Your Apps
Getting Help

2-1

2013 Intel Corporation.


Fast Track to Intel XDK New

Introducing Intel XDK New


The Intel XDK NEW development system is for those developers who
wish to use their HTML5 expertise to build hybrid HTML5 apps for
mobile devices (e.g., phones and tablets) and other platforms that host
HTML5 web apps (such as a Google Chrome* extension or a mobile web
site).

Going with an HTML 5 Solution

Developers and corporate IT increasingly turn to HTML5 as a solution to


meet the critical, time-sensitive demands of their organizations.
Developing mobile apps with HTML5 offers several key advantages over
native app development:
Native apps are developed to run on a single device platform whereas
HTML5 apps use the same codebase to run on multiple devices and
operating systems.
Native apps are typically distributed via app stores, however, HTML5
apps can also be deployed as mobile web sites that run in a user's
mobile web browser.
HTML5 apps use open-source technologies.
Native OS apps can get lost among the hundreds of thousands of
apps in app stores. Mobile web apps are crawlable by search engines.
Mobile web apps are instantly updatable on a web server.
Instead of having to learn Java or Objective-C, web developers can
leverage their existing skill sets to rapidly create mobile apps.
HTML5-based apps tend to be less affected by changes in the mobile
operating system.

Navigating the Tooling Quagmire

Historically, one of the biggest challenges faced by mobile web app


developers has been dealing with the lack of a truly integrated development
environment. Most developers spend their days toggling between an html
design tools, a javascript code editor, a CSS editor, web browser,
debugger, command-line build utilities, FTP, mobile simulators, and more.
Intel XDK NEW is the first truly integrated development environment that
application consists of a set of best-of-breed tools that help you code,
debug, test and build mobile web apps and hybrid HTML5 apps for
multiple target platforms.

2-2
2013 Intel Corporation.
Getting Started with Intel XDK New

Reviewing the Intel XDK New Interface

Intel XDK New is organized around the sequence that HTML app
developers follow when they create and package an application:
1. Develop
Use the visual designer to prototype your graphical user interface and
handle user interactions by hand-coding javascript with the built-in
Brackets editor.
2. Emulate
Validate that your application looks and functions properly across
multiple screen resolutions, under varying bandwidth conditions, and
from different geographic locations by using the embedded Apache
Ripple emulator. Debug application errors with the integrated Google
debugger.
3. Test
Verify that your app performs as expected by running from Intel's App
Preview container. Debug the app and chart its performance as it runs
on your device by using the embedded weinre remote debugger.
4. Build
Package the app for distribution via app stores or the web using the
integrated Apache Cordova toolkit. Test device-specific features.
5. Services
Integrate cloud-based services into your app from appMobi, including
push-notifications, e-commerce, live updates, in-app purchasing, and
hosting.

2-3
2013 Intel Corporation.
Fast Track to Intel XDK New

Designing Apps

As depicted in Figure 1, Develop mode enables you to visually prototype


the look and feel of your application.

Figure 1: Develop / Design View

The Project Selector enables you to load pre-existing projects or


create new projects into the Intel XDK GUI.
Your app's views appear in the Project Files panel.
While in Design view, you can drag and drop components from the
UI Controls Palette onto the Design Canvas.
UI controls that you've dropped onto the Design Canvas may be
configured by changing settings in the Property Editor.
The Product Version indicator alerts you as to the release version
of the XDK that is currently in use.

2-4
2013 Intel Corporation.
Getting Started with Intel XDK New

Developing Apps

As depicted in Figure 2, toggling to Code view enables you to modify the


code generated by the visual designer, as well as edit javascript and css
application assets. Code hints appear as you type.

Figure 2: Using the integrated Brackets editor to hand-code your app

Running Your App in an Emulator

As illustrated in Figure 3, clicking on the Emulate tab runs your app in the
Apache Ripple emulator.

Figure 3: Simulate your app running on multiple devices.

The emulator enables you to simulate your app running on multiple devices
under varying environmental conditions:
2-5
2013 Intel Corporation.
Fast Track to Intel XDK New

The Devices panel allows you to simulate your app running on a


variety of popular devices including the iPad, iPhone, Google Nexus,
Microsoft Surface Pro, Motorola Droid 2, Nokia Lumina 920,
Samsung Galaxy S, and Samsung Galaxy tab.
The Information panel provides
you with metrics regarding your
selected device, including OS,
screen resolution, pixel density, and
the http user agent that's transmitted
on each request.
The Accelerometer panel enables
you to simulate moving the device
along its x, y, and z axis. This is
vital for testing movement-based
controls. You can also have it
virtually shake the device.
The Live Update Service panel
simulates your app receiving an
update service request from
appMobi.
The Device & Network Settings
panel enables you to simulate
Figure 4: Testing accelerometer-
different degrees of network based controls.
throughput (from WiFi to no
connection), as well as toggle locales from English to French or
German.
The Geo Location panel allows you to simulate how your app would
behave if it were running from different physical locations. You can
also configure heading, speed, altitude, GPS accuracy, and GPS
timeout. You can even have it replay a route that was saved to a GPS
Exchange Format (GPX) file.
The PushMobi panel allows you to inspect how your application
would behave if it received a push-notification message.

2-6
2013 Intel Corporation.
Getting Started with Intel XDK New

Testing your app on a device

The Test module, depicted in Figure 5, enables you to easily upload your
application to a testing server. You can then launch it on any device that's
running the Intel App Preview mobile application.

Figure 5: Upload your app and test it on devices using Intel App Preview

You'll typically test apps on physical devices


by completing the following steps:
1. In Intel XDK New, click on the Test tab.
2. Click on the Push Files button
3. Open Intel App Preview on your mobile
device.
4. Tap on the Server Apps tab.
5. Tap on the camera icon, located in the
top-right corner of the app.
6. Scan the QR code in the XDK with your
phone's camera.
Once the QR code has been scanned, the app
will be automatically downloaded and
executed.
You can debug the app as it's running on yourFigure 6: Intel App Preview
device by using the built-in weinre remote
debugger.

2-7
2013 Intel Corporation.
Fast Track to Intel XDK New

Generating Production Builds

The Build tab, as depicted in Figure 7, uploads your app to a cordova-


based build server, packaging your code as a native app for distribution
across popular app stores or for distribution within your enterprise. Options
include:

iOS Ad-Hoc iOS App Store Android


Distribution
Windows Phone 8 Tizen
Windows 8 Store
Amazon Nook

Figure 7: Intel XDK uses Apache Cordova to convert your web app into
native apps for all popular platforms.

2-8
2013 Intel Corporation.
Getting Started with Intel XDK New

As illustrated by Figure 8, some vendors will require you to upload


distribution certificates and/or supply authentication credentials.

Figure 8: Uploading certificates and a provisioning profile for an iOS App


Store production build

You can also have XDK New create a distribution package for deployment
across the following web platforms:
WebApp
Enables you to post your code on a local or remote web server, or host
in AppMobi. (Your code may be downloaded as a .zip file)
Chrome
Packages your app for distribution in the Google Chrome store.
Facebook
Packages your app for distribution via the Facebook social network.

2-9
2013 Intel Corporation.
Fast Track to Intel XDK New

Using Cloud Services

As illustrated by Figure 9, Intel XDK New features tight integration with


appMobi cloud services.

Figure 9: Using the appMobi hosting service

While you are not obligated to use appMobi, it is a convenient resource for
providing the following application support resources:
HostMobi can host your app in a PHP, .NET, or Node.js server
environment. Edge-cached hosting delivers the best performance for
on-the-go web apps, and hostMobi provides that through our
partnership with Amazon's Elastic Computing Cloud, (which now
spans the entire globe).
Live Update enables you to notify users that a new version of your
app is available. You have the option to push app updates immediately
instead of waiting for your users to upgrade at their leisure.
Storeview is a cloud-based reporting service that aggregates detailed
app analytics from the most popular app stores and displays them in an
interactive dashboard.
Pushmobi enables you to send push notifications to your subscribers.
You can target messages to a particular user target users based on
search filters.
1Touch is an in-app purchase (IAP) cloud service, that allows you to
interface with various app stores using a single line of javascript.
1Touch takes away the pain of integrating with the various app stores
and payment providers. With a single function call you can sell in-app
items on IOS, Android, Windows8, Windows8 Phone, Facebook and
the Chrome Store.

2 - 10
2013 Intel Corporation.
Getting Started with Intel XDK New

Walkthrough 2-1: Getting Started


In this lab, you will perform the following tasks:

Log into Intel XDK


Create a new project
Design a hello world page
Test your app in the emulator
Package your app for distribution
Install your app on your Android device

Steps

Create a New Project


1. Launch Intel XDK New
2. Click on the Start a New Project button
3. Click on Start with App Designer
4. Enter a project name of MyHelloWorld
5. Click the Create button.
6. Click the No Thanks button.
7. Click the Let's Go! button.
8. In the left panel, click on index.html. The Select a Framework dialog
box will appear.
9. Click on the jQuery Mobile radio button.
10. Click on the Select button.

Design a Page
11. From the Controls panel, drag a Header and drop it onto the design
canvas.
12. In the Header Settings panel, turn on the checkbox adjacent to the Title
property and enter the following title:
Friends with Beer

13. Turn on the Fixed checkbox.


14. From the Controls > Media panel, drag a Text control and drop it
underneath the Header on the Design canvas.

2 - 11
2013 Intel Corporation.
Fast Track to Intel XDK New

15. In the Text Settings panel, change the text to the following:
Welcome to Friends with Beer!

Display your page in the Emulator


16. Click on the Emulate tab.
17. In the Devices panel, select Google Nexus 4.
18. In the Devices panel, toggle the orientation of the emulated device by
clicking on the landscape orientation button.
19. In the Device & Network Settings panel, note that you can emulate
different network lag conditions.

Run Your App on Your Mobile Device


20. Click on the Test tab.
21. Click the Sync button.
22. Open Intel App Preview on your mobile device.
23. Tap the Server Apps button.
24. Tap the Camera button located in the top right corner of the GUI.
25. Scan the QR code on your desktop.
26. Tap OK. Your app should launch.

Build your App for Native Distribution


27. Return to XDK New on your desktop.
28. Click the Build tab.
29. Click the Android Build button.
30. Click the Build App Now button.
31. Click the Download Build button and save the generated .apk file to
your desktop.
32. Email the .apk file to yourself.
33. Open the email on your Android phone.
34. Tap on the .apk file attachment.
35. Click on the Install button.
36. Click Open. Your app should open.

Congratulations. You've just built a native mobile app!

2 - 12
2013 Intel Corporation.
Getting Started with Intel XDK New

Debugging Your Apps


As you develop your apps, you'll inadvertently insert bugs into your
program which will need to be eradicated as quickly and efficiently as
possible. Most of your bugs will likely appear when you run your app in
the emulator. Others may not show up until you run the app on a physical
device. Fortunately, XDK New has both of these scenarios covered.

Debugging in the Emulator

Intel XDK New


features an integrated
Chromium developer
that you can invoke by
clicking the debugger
button from Emulate
mode, as depicted in
Figure 10.
The debugger enables
you to inspect the
DOM of your Figure 10: Activating the Debugger
application, review all
HTTP requests, read the contents of cookies and HTML5 local storage, and
can even provide hints as to how to optimize your application's
performance.
Most importantly, it enables you to set breakpoints and step through your
code interactively while monitoring the contents of variables.

Figure 11: The integrated Chromium debugger.

2 - 13
2013 Intel Corporation.
Fast Track to Intel XDK New

The debugger is partitioned into the following seven segments:

Label Description

Elements Enables you to click on any area in your browser and


inspect its markup. It also displays all the CSS applied to
the element and allows you to selectively enable, disable,
and modify individual styles.

Resources Enables you to review the contents of HTML5 local


database (SqlLite), HTML5 Local Storage, HTML5 Session
Storage, HTTP cookies, and the HTML5 Application
Cache.

Network Displays all HTTP communications. This is particularly


useful for troubleshooting AJAX requests. Displays both
data transmitted via the HTTP header to the server as well
as the content returned from the server.

Sources Displays all of the JavaScript files that were loaded into the
browser as part of the request. You can set breakpoints and
step through your code one line at a time. You can also
define watch expressions to keep an eye on the contents of
your variables.

Timeline Displays the time to download files from the server, the
time to execute scripts, and the time to render the output.
Use the timeline to develop insights into where your
bottlenecks might be in your code as well as benchmark
your changes.

Profiles Similar to the timeline, the Profiles panel captures the


execution of your application and then displays the
percentage of CPU utilization that was required to execute
specific methods or handle events. You can also profile the
performance of your CSS to see how long selector matching
took and take a heap snapshot to understand memory
distribution among your page's Javascript objects and
related DOM nodes.

Audits Evaluates the performance of your application and provides


helpful optimization tips.

Console Displays error messages as well as the output from


executing console.log() statements. You can also execute
javascript code interactively in this view.

2 - 14
2013 Intel Corporation.
Getting Started with Intel XDK New

Programmatically Setting Breakpoints

You can set programmatic breakpoints by inserting the following command


into your JavaScript:
debugger;

If the Chromium debugger is active when this statement is encountered,


execution of your app will pause and your script will appear in the Sources
section as depicted in Figure 12).

Figure 12: Active breakpoint

As depicted in Figure
13, you can use the
debugger controls to
interactively step
through your code.
You can also set watch
expressions in order to
view how your code
changes the contents of
your variables.

Figure 13: Using the debugger's step controls

2 - 15
2013 Intel Corporation.
Fast Track to Intel XDK New

Outputting Variables to the Debugger Console

Use the console.log() command to dump the contents of Javascript


variables to the Chromium debugger console as illustrated below:
<script type="application/javascript">
function init() {
$('#debugBtn').bind('click', function(e) {
debugger;
for (var i=0; i<5; i++) {
console.log(i);
}
});
}
</script>

Figure 14: Variables that are output via console.log appear in the Chromium
debugger Console view

Programmatically Interacting with Your Application

The Chromium debugger can do far more than just report errors and output
the results of console.log() statements. You can actually use it to interact
with your application in real-time, use it to experiment with invoking
javascript api methods, and change the contents of variables on-the-fly.
As depicted in figure 15, you can even fire events on application elements
and see the result in the emulator!

Figure 15: Invoking application methods from the Chromium console view.

2 - 16
2013 Intel Corporation.
Getting Started with Intel XDK New

Debugging on the Device

If your application invokes methods from the Cordova API, or uses device
features that are not natively supported by Javascript, you may find
yourself in a situation when it's most effective to troubleshoot the app when
it's actually running on a physical device.
Using a desktop debugger to inspect an app running on a device is a
process called remote debugging. Remote debugging is supported by the
Intel XDK via the weinre remote debugger.

Figure 16: Add the <script> from the Test tab onto all html pages that you
need to remotely debug.

For remote debugging to work properly, you must:


1. Embed the following code into your HTML files:
<script
src="http://debug-software.intel.com/target/target-script-
min.js#{unique identifer}"></script>

Where {unique identifier} is indicated on the Intel XDK New Test


panel.
2. Launch the app on the device via App Preview.
3. Click on the Begin Debugging on Device button in the Intel XDK New
Test panel.

2 - 17
2013 Intel Corporation.
Fast Track to Intel XDK New

As depicted in figure 17, after you click the Begin Debugging on Device
button, the weinre extension for the Chromium browser appears, enabling
you to troubleshoot your app as it's runs on your device. The debugger
functions nearly identically to the one that you used in the Emulate panel.

Figure 17: Invoking the weinre remote debugger.

In a manner similar to the Chromium debugger, you can inspect the


browser's DOM, review network traffic, review runtime errors, and even
interact directly with the app through the debugger's Console view.

Figure 18: Using the weinre remote debugger.

2 - 18
2013 Intel Corporation.
Getting Started with Intel XDK New

Walkthrough 2-2: Debugging your Applications


In this lab, you will perform the following tasks:

Use Javascript's debugger; and console.log() methods to aid you in


your debugging efforts.
Use the Chromium debugger to step through your code on an emulated
device.
Use the weinre debugger to step through code in your app running on a
physical device.

Steps

Open a Project
1. Open Intel XDK New
2. Click on the word PROJECTS in the top-left corner of the GUI.
3. Click the Open a Project button.
4. Select the following file:
/ftIntelXdkNew/walk/walk2_2/walk2_2.xdk

5. Click the open button.

Add JavaScript Debugging Statements


6. Click on the Develop tab.
7. In the project's file browser, click on the index.html file.
8. Click on the CODE button.
9. On line 32, insert the following statement to establish a programmatic
breakpoint:
debugger;

10. After the code that you inserted from the prior step, insert a for loop
that loops from 0 to 4:
for (var i=0; i<5; i++) {

11. Inside the for loop, insert a statement that outputs the value of the
variable i to the debugging console:
console.log(i);

12. Select File > Save from the code editor's menu.

2 - 19
2013 Intel Corporation.
Fast Track to Intel XDK New

Inspect the app in the Emulator


13. Click on the Emulate tab
14. Click on the Debug button
15. Click on the Debug Me button within the app running in the emulator.
The sources panel of the debugger should activate.
16. Click on the [+] button in the Watch Expressions title bar.
17. Enter i as the expression and press [Enter]
18. Click the debugger's Step Over button to advance the program
execution through the for loop. Notice how the value for the variable I
changes in the Watch panel.
19. Mouse-over the variable i, located in the console.log() statement.
Hovering your mouse over the variable should display its value.
20. Open the Scope Variables panel and review the contents of the
variables that are present.
21. Click the Resume Script Execution button to allow your scripts to run
to completion.
22. Click on the debugger's Console tab. You should see the results from
executing your console.log() statement.

Use the Remote Debugger


23. In the Intel XDK New, click on the Test tab.
24. Scroll down the page to the On Device Debugging section.
25. Copy the script tag displayed at the bottom of the page to your
clipboard.
26. Click on the Develop tab.
27. Open the index.html file in Code view.
28. Paste the <script> tag just above the </head> tag.
29. From the code editing menu bar, select File > Save.
30. Click the Test tab.
31. Click on the Push Files button.
32. Run Intel App Preview on your mobile device.
33. Tap on the Camera button and scan the QR code from the Test tab.
34. On your mobile device, tap OK to launch the app.
35. In the Intel XDK Test tab, click on the Begin Debugging on Device
button.
36. Click on the hyperlinked target reference.
37. In the weinre debugger, click on the Console button.
38. In the app running on your mobile device, tap the Debug Me button.

2 - 20
2013 Intel Corporation.
Getting Started with Intel XDK New
39. Note that the console output from your mobile app running on your
device appears in the weinre remote debugger console view.
40. Click on the End Debugging Button to end your remote debugging
session.

End of Walkthrough --

2 - 21
2013 Intel Corporation.
Fast Track to Intel XDK New

Getting Help
Intel XDK New ships with online documentation and sample applications,
and has community support resources available as well. As illustrated by
Figure 19, help features are available by clicking on the yellow question
mark button.

Figure 19: Accessing help resources.

Using the XDK Documentation

Selecting the Visit the Help Page link opens your web browser to the Intel
Developer Zone at http://software.intel.com/en-us/html5/articles/xdkdocs.
From here, you can get quick access to Intel's App Framework docs, the
Apache Cordova API docs, jQuery API, and Google Chrome Dev Tools
docs

Figure 20: The Intel XDK New Help Page

2 - 22
2013 Intel Corporation.
Getting Started with Intel XDK New
Perhaps the most relevant documentation for this course is the Intel XDK
API documentation, which contains information about available javaScript
methods in the intel.xdk namespace. You can access these resources
directly from:
http://www.html5dev-software.intel.com/documentation/jsAPI/index.html

Figure 21: Documation for the intel.xdk javascript package

This package documents methods that enable you to access the following
resources:
Mobile device physical resources, including the camera and
accelerometer
Facebook API support
Supporting multitouch on Android devices
oAuth authentication methods
Interacting with the accelerated Canvas App Game interface plugin

2 - 23
2013 Intel Corporation.
Fast Track to Intel XDK New

Using the Forums

The Intel XDK New developer forum, depicted in Figure 22, is a great
resource for interfacing with other developers and the Intel XDK
development team. Post your technical support questions here and receive
quick responses from other developers as well as members of Intel's XDK
New development team.

Figure 22: The Intel XDK New developer forum.

2 - 24
2013 Intel Corporation.
Getting Started with Intel XDK New

Reviewing the Sample Applications

As depicted in Figure 23, Intel XDK New ships with 14 separate sample
applications that aptly demonstrate how to use commonly requested mobile
app features. Documentation for each example, accessed by pressing the
document button, highlights the specific API calls that were critical in
producing the desired outcome.

Figure 23: Opening a sample application

The examples include the following:

Name Description

Rolling Can Captures a devices accelerometer data and animates an


HTML element using CSS transformations.

Flood Puzzle A simple puzzle game implemented as a Single Page


App that illustrates how to use Javascript to modify CSS
styles based on user interactions.

Springboard A jQuery-Mobile based application that demonstrates


custom styling techniques which adapt to various screen
sizes and rotations, and achieve a different look and feel
than JQM defaults.

Buttons A basic example of that reads the touchStart and


touchEnd JavaScript events in order to provide a
responsive visual cue to the user that a button is being
pressed.

2 - 25
2013 Intel Corporation.
Fast Track to Intel XDK New

Name Description

App A simple app that demonstrates how to use various Intel


Framework App Framework UI components.

Geolocation Plots the user's geolocation on a Google Map, updating


every five seconds.

Tab Nav A multi-page JQM scaffold using tab-based navigation. It


demonstrates how to create a custom options menu
widget that maintains state across page transitions and
how to dynamically inject widgets into the DOM.

RPN A themable stack-based calculator that uses different


Calculator color schemes, styles, and button animations.

Basic Hybrid Demonstrates how to use the intel.xdk library to access


App native device features.

Hello World The classic. You know it, you love it.

PhoneGap Uses a Cordova media object to record and playback


Audio audio.

Towers of Uses CSS and jQuery to animate solving the classic


Hanoi Towers of Hanoi puzzle.

Counting A simple HTML5-based game that teaches young


Beads children how to count up to 50.

IQM List A JQM-based app that uses the Rotten Tomatoes API to
View create a paginated list of DVD rentals. It demonstrates
how to populate a list view with live data and
dynamically generate pages.

2 - 26
2013 Intel Corporation.
Getting Started with Intel XDK New

Walkthrough 2-3: Using a Starter App


In this lab, you will perform the following tasks:

Review the Tab Nav sample application


The Friends with Beer application that you're going to create uses a similar
navigational structure. You'll review and learn how to apply the techniques
used to create this app later in the course.

Steps

Create a New Project from a Sample


1. Open Intel XDK New
2. Click on the word Projects in the top left corner of the GUI.
3. Click the Start a New Project button.
4. Click on the Work with a Demo tab.
5. Click on the IQM Tab Nav app.
6. Click Next.
7. Enter the following information:

Name your project: walk2_3


Project Location: /path/to/ftIntelXdkNew/walk/walk2_3
8. Click the Create button.
9. Click No Thanks
10. Click Let's Go

Review the App


11. Click on the Emulate tab and review how the application runs on-
screen. Note the tab-based navigation that's docked to the bottom of the
screen.
12. Click on the Develop tab.
13. Click on the index.html file.
14. Review the structure of the HTML. Note that each page is represented
by a set of logical pages, set off by a <div> tag with data-role=page.
15. Review the structure of the tab bar which manifests from the
<div data-role=footer> markup.
16. Open the file app/tabbedImages.js and review the code. Note that jQM
pages fire an event named pageshow when they appear to a user.
End of Walkthrough --

2 - 27
2013 Intel Corporation.
Fast Track to Intel XDK New

Unit Summary
Designing and developing applications for handheld devices is a
completely different process than writing for desktop browsers
Intel XDK New is an integrated development environment for creating
mobile applications built on web standards HTML 5, JavaScript, and
CSS3.
Intel XDK New integrates many best-of-breed HTML5 development
tools including the following:

MobiOne WYSIWYG visual interface designer


Brackets code editor
Google Chromium Debugger
Apache Ripple Emulator
Intel App Preview mobile app launcher
weinre remote debugger
Apache Cordova native app packager
appMobi cloud services
You can develop your application using a variety of Javascript
frameworks including jQuery Mobile, TopCoat, Bootstrap, and Intel's
App Framework.
Intel's App Framework API extends Apache Cordova features.
The Chromium debugger and weinre remote debugger provide you
powerful troubleshooting capabilities and optimization tips.
Intel XDK New ships with over a dozen sample apps that demonstrate
frequently requested mobile application features.

2 - 28
2013 Intel Corporation.
Getting Started with Intel XDK New

Unit Review
1. Do you need to install any software other than Intel XDK New in order
to develop, test, build, and deploy a mobile app?

2. What are some advantages to developing a mobile app using web


standards instead of using Objective-C or Java?

3. Which physical device features can you test with the Emulator?

4. You must develop mobile apps using Intel's App Framework


(true/false)

5. List two programmatic techniques for inspecting the contents of a


javascript variable.

2 - 29
2013 Intel Corporation.
(This page intentionally left blank)
Unit 3:
Page Layout

Unit Objectives
After completing this unit, you should be able to:
Define logical pages in your application
Use layout controls to position elements on a page
Implement your app's navigational controls
Enable animated transitions between pages
Add text and image content to your application

Unit Topics
Defining Pages
Adding Content

3-1

2013 Intel Corporation.


Fast Track to Intel XDK New

Defining Pages
jQuery mobile uses a combination of HTML tags and HTML5 custom data
properties to implement a page-based architecture for layout. An HTML
file may contain either a single page widget, or multiple page widgets.
Pages are typically indicated by <div> tags with a data-role property equal
to page. Most jQuery Mobile pages, therefore use the the following
structure:
<div data-role="page" id="page1">

<!-- fixed page header -->

<-- page body -->

<!-- fixed page footer -->

</div>

Note: The Intel XDK New visual wysiwyg designer does not support
defining multiple pages within a single .html file.

You'll typically define pages with the following attributes:

Attribute Description

data-dom-cache Determines whether to keep the page in the


DOM when the user navigates away from it.

data-theme Sets the theme that will be used to render the


page.

In most transactional-based apps, you'll also need to write an event handler


that executes when a page is instantiated in the DOM. Typically your event
handler will download .JSON data from a REST-based webservice or
static .JSON file and use it to populate the contents of the page.
The structure of your page creation event listener will resemble the
following:
$("#page1").on("pagecreate", function( event, ui ) {

// page initialization logic goes here.

});

3-2
2013 Intel Corporation.
Page Layout

Adding New Pages in Intel XDK

You can add new pages to


your app by right/cmd-
clicking in the files panel as
indicated in figure 1.

Figure 1: Adding new files to your project

As indicated by Figure 2, you''ll be prompted to select a mobile Javascript


framework for each new .html file that you add to your project.

Figure 2: You must select a framework for each html file.

3-3
2013 Intel Corporation.
Fast Track to Intel XDK New

Defining Page Headers

The page header typically displays a page title and can display up to two
buttons which are aligned to the left and right of the title, respectively.
Headers are usually placed in a fixed position at either the top or bottom of
a page.
The title text is normally an H1 heading element but it's possible to use any
heading level (H1-H6) to allow for semantic flexibility.
The basic syntax for implementing a header or resembles the following:
<div data-role="page" id="page1">

<div data-role="header" data-position="fixed">


<h1>Friends with Beer</h1>
</div>

<-- page body goes here -->

<div data-role="footer" data-position="fixed">


<!-- footer goes here -->
</div>

</div>

Adding Buttons to Headers

The header container automatically sets the first child link to the left button
slot and the second child link in the right as depicted by the following
example:
<div data-role="header">
<a href="#" data-icon="delete">Cancel</a>
<h1>Edit Contact</h1>
<a href="#" data-icon="check">Save</a>
</div>

You can also set button position by applying the ui-btn-right and ui-btn-left
style classes. This is particularly useful if you need to place a single button
on the right of a header as illustrated by the following example:

<div data-role="header">
<h1>Edit Contact</h1>
<a id="btnSave"
data-icon="check"
class="ui-btn-right">Save</a>
</div>

3-4
2013 Intel Corporation.
Page Layout

Adding Back Buttons

Jquery Mobile will


automatically add a back
button on a header if the
following conditions exist:
The page must have the
data-add-back-btn=true
property.
Using the data-rel=back
property on an anchor.
The data-rel=back property
causes the default href action to
Figure 3: Automatic back button support
be ignored in favor of
mimicking the browser's back
button behavior, going back one history entry.
<div data-role="page"
id="editForm"
data-add-back-btn="true">

<div data-role="header"
data-position="fixed">

<a data-rel="back"
data-role="button"
data-icon="back">Back</a>

<h1>Edit Friend Info</h1>

<button
id="btnSaveFriend"
data-icon="save"
class="ui-btn-right">Save</a>
</div>

</div>

3-5
2013 Intel Corporation.
Fast Track to Intel XDK New

Defining Navigation Bars with the NavBar widget

The NavBar widget enables you to place a navigation bar containing up to


five buttons, within a header or footer by using the following syntax:

Figure 4: Implementing a Nav Bar

<div data-role="footer">
<div data-role="navbar">
<ul>
<li><a href="#">About</a></li>
<li><a href="#">Contacts</a></li>
<li><a href="#">Beers</a></li>
<li><a href="#">Drink!</a></li>
</ul>
</div>
</div>

Buttons are automatically sized to occupy the available width/height of


their container.

3-6
2013 Intel Corporation.
Page Layout

Setting the Default Button State

To set an item to be active by default, add class="ui-btn-active" to


the corresponding anchor. Add a class of ui-state-persist to make the
jQuery automatically restore the active state each time the page is shown.
For instance, a nav bar on the index.html page should resemble the
following:
<div data-role="footer">
<div data-role="navbar">
<ul>
<li><a
href="index.html"
class="ui-btn-active ui-state-persist"
>About</a>
</li>
<li><a href="contacts.html">Contacts</a></li>
<li><a href="beers.html">Beers</a></li>
<li><a href="drink.html">Drink!</a></li>
</ul>
</div>
</div>

Adding Page Transitions

Add the data-transition property to each anchor tag in order to apply


a transition animation when a user taps on a navbar button.

<div data-role="footer">
<div data-role="navbar">
<ul>
<li><a
href="index.html"
class="ui-btn-active ui-state-persist"
>About</a>
</li>
<li><a href="contacts.html"
data-transition="slide">Contacts</a></li>
<li><a href="beers.html"
data-transition="fade">Beers</a></li>
<li><a href="drink.html"
data-transition="none">Drink!</a></li>
</ul>
</div>
</div>

Supported transitions include the following:


fade turn slide
pop flow slideup
flip slidefade slidedown
none

3-7
2013 Intel Corporation.
Fast Track to Intel XDK New

Defining Navigation Bars with the Button Group Widget

The ControlGroup widget groups


buttons together so that they look
similar to a navigation component.
The effect is generated by
applying a
data-role=controlgroup property
to a <div> tag that wraps a series
of anchor-based buttons as Figure 5: Control Group Buttons
illustrated by the following code
snippet:
<div data-role="controlgroup">
<a href="#" data-role="button">Click Me!</a>
<a href="#" data-role="button">No, Click me!</a>
<a href="#" data-role="button">Always click me!</a>
</div>

You can set the buttons to display horizontally by adding the data-
type=horizontal attribute to the controlgroup container as illustrated
below:

Figure 6: A horizontally aligned button group.

<div data-role="controlgroup" data-type="horizontal">


<a href="#" data-role="button">Click Me!</a>
<a href="#" data-role="button">No, Click me!</a>
<a href="#" data-role="button">Always click me!</a>
</div>

Other configuration properties for the controlgroup widget include:

Property Description

data-corners Boolean. Sets whether to draw the controlgroup with


rounded corners. Defaults to true.

data-mini Boolean. Controls whether to display more compact


buttons that use less space. Defaults to false.

3-8
2013 Intel Corporation.
Page Layout

Defining Buttons

Buttons are coded with standard HTML anchor and input elements, then
enhanced by jQuery Mobile to make them more attractive and useable on a
mobile device. You'll typically use anchor links to define navigation
buttons, reserving input or button elements for form submission.
As previously described, the basic syntax for defining a button is the
following:

<a href="index.html" data-role="button">Home</a>

You can add icons to buttons by applying the data-icon property to the
anchor tag as illustrated below:
<a
href="index.html"
data-role="button"
data-icon="home">Home</a>

The complete set of bundled icons is illustrated in Figure 7:

Figure 7: jQuery Mobile Icons

Icons may be positioned at the top, left, bottom, or right of the button's text
by setting the data-iconpos property:
<a
href="index.html"
data-role="button"
data-icon="home"
data-icon-pos="top">Home</a>

You can change the button's theme, causing it to display with either a light
background and dark text or a dark background and light text by applying
the data-theme property:

<a
href="index.html"
data-role="button"
data-theme="b"
>Home</a>

3-9
2013 Intel Corporation.
Fast Track to Intel XDK New

Creating Button Groups with the WYSIWYG Designer

As depicted in Figure 8, you can drag a controlgroup widget to the center


of a footer, and then style each button individually through the properties
panel.

Figure 8: Using the controlgroup widget and styling buttons in the


WYSIWYG designer

Navigating Between HTML Files

jQuery Mobile automatically ''hijacks standard links and form


submissions, converting them into an AJAX requests.
Whenever a link is clicked or a form is submitted, that event is
automatically intercepted by the AJAX nav system. An AJAX request
based on the href or form action is issued instead of reloading the page.
While the framework waits for the AJAX response, a loader overlay is
displayed.
When the requested page loads, jQuery Mobile parses the document for an
element with the data-role="page" attribute and inserts that code into the
DOM of the original page. Any widgets in the incoming page are enhanced
to apply all the styles and behavior. The title of the incoming page is noted
and the home page is updated when the new page is transitioned into
view.
NOTE: The rest of the incoming page is discarded so any scripts,
stylesheets or other information will not be included.

3 - 10
2013 Intel Corporation.
Page Layout

Walkthrough 3-1: Designing Pages


In this lab, you will perform the following tasks:

Define your application pages


Implement a basic header and footer
Implement the app's basic navigational structure

Figure 9: During this lab, you'll Implement tab-style navigation and create
placeholder pages.

Steps

Open a Project
1. Open Intel XDK New
2. Click on the word PROJECTS in the top-left corner of the GUI.
3. Click the Open a Project button.
4. Select the following file:
/ftIntelXdkNew/walk/walk3_1/walk3_1.xdk

5. Click the open button.

Design the Page Footer


6. Open the index.html file in Design view.
7. Drag a FOOTER control from the Controls-Layout panel and drop it
onto the design canvas.
8. Drag a BUTTON GROUP control from the Controls-Form panel and
drop it onto the center of the footer.
9. Click on the first button on the left in the control group.

3 - 11
2013 Intel Corporation.
Fast Track to Intel XDK New

10. In the Button Settings panel, configure the following properties:

Label : Home
Theme: (b) dark
Icon: home
Icon position: top

11. Click on the button adjacent to the Home button and configure the
following properties:

Label : Friends
Icon: user
Icon position: top

12. Click on the button adjacent to the Friends button and configure the
following properties:

Label : Beers
Icon: heart
Icon position: top

13. Drag an additional button from the Controls > Form panel and drop it
to the far right of the controlgroup in the footer.
14. Configure the following properties:

Label : Drink!
Icon: video
Icon position: top
15. Go to Code view and add the following attributes to the Home
button:

href : index.html
data-transition: slide
16. Add the following attributes to the Friends button:

href: friends.html
data-transition: slide
17. Add the following attributes to the Beers button:

href: beers.html
data-transition: slide
18. Add the following attributes to the Drink button:

href: drink.html
data-transition: fade
19. Save the file.

3 - 12
2013 Intel Corporation.
Page Layout
20. Click on the Emulate tab. The footer should appear similar to Figure
10 .

Figure 10: The completed page footer.

Create the Contacts, Beers, and Drink! Placeholders


21. Return to Develop mode.
22. In the Files panel, right/cmd-click on index.html and select New File.
23. Enter the following file name:
friends.html

24. When prompted, select the jQuery Mobile framework and click
Select.
25. Return to the index.html file
26. Enter Code View
27. Copy the contents of the entire page to your clipboard
28. Return to friends.html
29. Enter Code view
30. Paste the contents of your clipboard into the friends.html file.
31. Cut the following code to your clipboard and paste it into the anchor
tag that points to contacts.html:
data-theme="b"

32. Return to Design mode.


33. Click on the page header.
34. In the Header Settings panel, change the title to the following:
Friends

35. Save the file.


36. Repeat steps 21-35 for the following files, changing the page header
and footer as appropriate:

beers.html
drink.html
37. Click the Emulate tab.

3 - 13
2013 Intel Corporation.
Fast Track to Intel XDK New

38. Confirm that you can navigate between the pages by clicking/tapping
on the footer's navigation bar.

End of Walkthrough

3 - 14
2013 Intel Corporation.
Page Layout

Adding Content
You'll typically implement the page content area as a <div> tag with the
attribute data-role="content", placing it between the page header and
footer as illustrated below:

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

<div data-role="header" data-position="fixed">


<h1>Friends with Beer</h1>
</div>

<div data-role="content">
Hello World
</div>

<div data-role="footer" data-position="fixed">


<!-- footer goes here -->
</div>

</div>

As illustrated in Figure 11, the Intel XDK New WYWIWYG designer


enables you to quickly lay out your content into a series of columns and
rows by dragging and dropping the Column and Row widgets onto the
design canvas.

Figure 11: Drag and dropping rows and columns into the content area

Note that as you drag widgets from the Controls pallette, valid drop targets
become highlighted with a cyan colored background in the design canvas.
When you hover over a valid drop target, its color changes to orange.

3 - 15
2013 Intel Corporation.
Fast Track to Intel XDK New

The designer generates a series of styled <div> elements, as illustrated by


the following code snippet:
<div class="upage-content">
<div class="grid grid-pad urow uib_row_1 row-height-1"
data-uib="layout/row">
<div class="col uib_col_4 col-0_6-12"
data-uib="layout/col">
<div class="widget-container content-area vertical-col">
<div class="widget uib_w_3 d-margins"
data-uib="media/text">
<div class="widget-container left-receptacle"/>
<div class="widget-container right-receptacle"/>
<div>
<p>Column 1</p>
</div>
</div>
<span class="uib_shim"></span>
</div>
</div>

<div class="col uib_col_5 col-0_6-12"


data-uib="layout/col">
<div class="widget-container content-area vertical-col">
<div class="widget uib_w_4 d-margins"
data-uib="media/text">
<div class="widget-container left-receptacle" />
<div class="widget-container right-receptacle"/>
<div>
<p>Column 2</p>
</div>
</div>
<span class="uib_shim"/>
</div>
</div>

<span class="uib_shim"></span>
</div>

<div class="grid grid-pad urow uib_row_2 row-height-2"


data-uib="layout/row">
<div class="col uib_col_6 col-0_12-12"
data-uib="layout/col">
<div class="widget-container content-area vertical-col">
<div class="widget uib_w_5 d-margins"
data-uib="media/text">
<div class="widget-container left-receptacle"/>
<div class="widget-container right-receptacle" />
<div>
<p>This row spans both columns</p>
</div>
</div>
<span class="uib_shim"></span>
</div>
</div>
<span class="uib_shim"></span>
</div>
</div>

3 - 16
2013 Intel Corporation.
Page Layout

Adding Text

As depicted in Figure 12, you can add text to page by dragging and
dropping the Text widget from the Controls-Media panel and dropping it
onto the design canvas.

Figure 12: Adding text to an app page.

The Text Settings panel enables you to perform the following functions:
Replace the Lorum ipsum placeholder text
Set the id property of the generated <div> element.
Set display and visibility properties
Define CSS Styles for text and margins
Create define media queries that apply styles based on screen
resolution (covered in unit 9)

3 - 17
2013 Intel Corporation.
Fast Track to Intel XDK New

Applying Typographic Styles

As illustrated in Figure 13, the


WYSIWYG interface enables you to
define typographic styles for your page
elements. Configurable options include:
Font Size
Font Style
Font Weight
Color
Font Family
Text Decoration
Text Align
Figure 13: Defining typographic
Line Height styles
Style classes that are defined for one element can be applied to other
elements in the WYSIWYG designer.
You'll learn how to extend these styling capabilities via Code View in unit
9.

Adding Images

The IMG widget enables you to add


jpg, png, or gif images to your
content. As depicted in Figure 14,
any images that have been placed in
your project's folder structure may be
selected from the drop-down list in
the IMG Settings panel. You can also
configure Alt text (to meet section
508 accessibility requirements), edit
a visible caption, and set the
generated elements DOM identifier.
Figure 14: Configuring an IMG
widget

3 - 18
2013 Intel Corporation.
Page Layout

Walkthrough 3-2: Adding Content


In this lab, you will perform the following
tasks:

Add text content to the home page.


Define typographic styles.
Add an image to the home page.

Steps

Open a Project
1. Open Intel XDK New
2. Click on the word PROJECTS in the top-
left corner of the GUI.
Figure 15: Your goal
3. Click the Open a Project button.
4. Select the following file:
/ftIntelXdkNew/walk/walk3_2/walk3_2.xdk

5. Click the open button.

Add Text
6. From the Controls > Media panel, drag a Text widget and drop it onto
the design canvas, placing it between the header and footer.
7. Open walk3_2/resources/homepagetext.txt in Code view.
8. Copy the contents of the first paragraph of homepagetext.txt to your
clipboard.
9. Open index.html in Design view.
10. In the Design canvas, click on the Text widget.
11. In the Text Settings panel, paste the contents of your clipboard into the
Text field.

Define Typographic Styles


12. In the Text Settings panel, click on the Text button and select New...
13. Enter a style class name of homepage
14. Enter the following properties:

Font-Size: 0.9em
Font-Family: sans-serif
Line-Height: normal

3 - 19
2013 Intel Corporation.
Fast Track to Intel XDK New

Add an Image
15. From the Controls > Media panel, drag an IMG widget and drop it
underneath the Text block on the Design Canvas.
16. Configure the following IMG settings:

Src: Resources/Beer.jpg
Alt: Beer: The cause and solution to all of our problems

Add a Second Text Widget


17. From the Controls > Media panel, drag a Text widget and drop it onto
the design canvas, placing it directly underneath the image.
18. Open walk3_2/resources/homepagetext.txt in Code view.
19. Starting with the second paragraph, copy the contents of
homepagetext.txt to your clipboard.
20. Open index.html in Design view.
21. In the Design canvas, click on the Text widget.
22. In the Text Settings panel, paste the contents of your clipboard into the
Text field.

Apply the homepagetext Text Style


23. In the Text Settings > Styles panel, click on the Text menu and select
homepagetext as illustrated below:

24. Save the file


25. Click the Emulate button. Your app should appear similar to Figure 15
on the previous page.

End of Walkthrough --

3 - 20
2013 Intel Corporation.
Page Layout

Unit Summary
jQuery mobile uses a combination of HTML tags and HTML5 custom
data properties to implement a page-based architecture for layout.
jQuery mobile behaviors are typically defined by adding custom data
properties to html elements.
When pages are created in the mobile browser's DOM, the
pagecreate event is fired.
Every html page in your app must be linked to a mobile JavaScript
framework.
Page headers and footers can be docked into a fixed position.
JQM can automatically add a back button on a header.
Use the ButtonGroup widget to easily add navigation to your apps.
JQM supports slide and fade transitions between pages.
Buttons may be styled with icons and themes.
The Intel XDK App Designer enables you to lay out your pages using a
rows/column metaphor.
Style classes that are defined for an element can be applied to other
elements within your app.
The App Designer will automatically locate all images that have been
placed within your project folder.

3 - 21
2013 Intel Corporation.
Fast Track to Intel XDK New

Unit Review
1. Pages do not need to be linked to a mobile javascript framework
(true/false)

2. You cannot define custom icons for your buttons (true/false)

3. An HTML file may only contain a single page view (true/false)

4. The App Designer generates HTML table markup to ensure


compatibility with the broadest range of browsers (true/false)

5. How can you impement a page transition animation?

3 - 22
2013 Intel Corporation.
Unit 4:
Working with Data

Unit Objectives
After completing this unit, you should be able to:
Use jQuery Mobile to make asynchronous data requests
Output structured data into a ListView
Transfer data read from an application server into an HTML5 Local
SQL Database
Read data from the device's Contacts list

Unit Topics
Making External Data Requests
Working with the ListView
Caching Data in a Local Database
Importing Data from the Contacts List

4-1

2013 Intel Corporation.


Fast Track to Intel XDK New

Making External Data Requests


Jquery mobile supports making two different types of data requests from a
web browser:
Use the $.ajax() method to read and post external data using
Javascript's native XmlHttpRequest() method.
Use the $.getJSON() method to read structured data in JavaScript
Object Notation format (JSON) from a remote domain by dynamically
injecting a <script> tag into your application's DOM.

Making AJAX Data Requests from JQM

You can make AJAX requests to a server using the $.ajax() method
illustrated below. $.ajax() should be used whenever you need to retrieve
external data that's not in JSON format or if you need to POST data to a
server.

$.ajax({
url: 'myservice.cfc?method=getdata',
type: 'GET',
dataType: 'json',
error : function (){ alert('there was an error'); },
success: function (data) {
console.log(data);
// debugger;
}
});

Note the following:


The callback to the success or error handler is executed
asynchronously.
The success handler receives the data as a javascript object. You do not
need to use the eval() method or an equivalent to parse the JSON into a
native JavaScript object.
Use the console.log() method to output results to your debugger.
Alternately, you can use the debugger; command to set a programmatic
breakpoint.
Web apps will not be able to make cross-domain requests unless the
remote host supports cross-origin resource sharing (CORS)
Cordova-based apps will need to whitelist all external domains
(covered in unit 10).

4-2
2013 Intel Corporation.
Working with Data

Making JSONP Requests from JQM

You can make cross-domain JSON-P requests from jQuery using the
$getJSON method illustrated below:
var url='http://someurl/someAppServerService.php?';

$.getJSON(url + 'method=somemethod&callback=?',
function(data) {
console.log(data);
}
);

Note that the ? Used in the callback url is replaced at runtime by a jQuery
with a randomly generated set of numbers. JSONP GET requests
therefore typically resemble the following:

Figure 1: A typical JSONP Request.

Use $.getJSON() whenever you need to retrieve JSON data from a remote
domain that does not support CORS.

4-3
2013 Intel Corporation.
Fast Track to Intel XDK New

Deferring Data Requests Until Page Activation

One of the challenges that you will have with building larger, more
complicated JQM apps is minimizing the amount of memory that your app
consumes. One strategy for managing memory is to not load data until it is
absolutely needed. For instance, if a data request is required to populate a
list view, you might want to defer making the request until such time as the
page is requested by the user.
The typical pattern to trigger the execution of code on page visibility is the
following:

$(document).bind('pageinit', function() {
$(document).on( "pagechange", function(event,page) {
switch(page.toPage[0].id) {
case 'page1' :
// initialize page 1
break;
case 'page2' :
// initialize page 2
break;
};
});
});

In the preceding code snippet, the pageinit event is triggered once the
index.html page has completed loading in the browser. In jQuery Mobile,
listening for pageinit event should be used in lieu of document.onready().
The pagechange event is triggered whenever an anchor tag is activated by
a user, causing jQM to intercept the request and load the requested html
page. You can parse the second argument returned to the pagechange event
handler to determine the id property contained within the div tag
containing the data-role=page attribute as illustrated below:

<div class="upage" data-role="page" id="page1">

4-4
2013 Intel Corporation.
Working with Data

Developing Javascript Classes to Encapsulate Event Handlers

As your application grows in size, you may find it useful to bundle all of a
page's event listeners into a single Javascript object. This approach has
several benefits:
Encapsulation
Protected variable scoping
Code Reuse
The general approach to implement this coding style is to define a global
javascript object in your index.html file for each page of your app. For
example, you might define a Javascript object container for your beers-
page related subroutines as illustrated by the following:
var BeersPage = {

};

Inside of the JavaScript object, you'll place all of the page's dynamic
properties and methods:
var BeersPage = {
initialized: false,
init: function() {
this.initialized = true;
}
}

Note that in the preceding case, the init() method refers to the initialized
variable using the this scope as both the init() method and the initialized
property are both members of the same object.
You could then invoke the init() method for beersPage through the
following syntax:
BeersPage.init();

You will use this development methodology throughout this course.

4-5
2013 Intel Corporation.
Fast Track to Intel XDK New

Caching Data In a Local Variable

From a performance perspective, HTTP transactions from mobile devices


are very costly. You can reduce external calls by caching data in memory,
html5 local storage, or html5 local database.
It's relatively straightforward to extend our class system in order to persist
remote data in a local variable. In the following code, we've extended the
Beers class described on the prior page by adding an additional property
named data. Once the JSON-P data has been successfully read from the
server, it's placed into the data property where it can be referred for the
duration that the app remains running. A strategically placed if() condition
prevents the remote data from being fetched more than once.
var Beers = {

initialized: false,
data : null,

init: function() {
var me = this; // use closure to retain scope
if (me.data === null && !me.initialized) {
me.initialized = true;
var url= "http://xdktraining.com/ftxdknew/data/beer.cfc";
$.getJSON(url + "?method=getBeerList&callback=?",
function(data) {
me.data = data;
}
);
}
}
}

4-6
2013 Intel Corporation.
Working with Data

Walkthrough 4-1: Making External Data Requests


In this walkthrough, you will start developing the Beer List feature of the
application.

Make a local data request to retrieve a list of Beers that's encoded in


JSON format.
Display the results from the transaction in the debugger.

Steps

Open the Project


1. Open Intel XDK New
2. Click on the word PROJECTS in the top-left corner of the GUI.
3. Click the Open a Project button.
4. Select the following file:
/ftIntelXdkNew/walk/walk4_1/walk4_1.xdk

Define a pageinit Event Listener


5. Open the following URL and review the output:
http://xdktraining.com/ftxdknew/data/beer.cfc?
method=getBeerList

6. Open the index.html file in Code view.


7. Immediately prior to the closing <head> tag, insert a Javascript block:
<script type=text/javascript>

</script>

8. Inside the <script>, listen for the pageinit event to be triggered by the
index page:

Your code should appear similar to the following:


<script type="text/javascript">
$(document).bind('pageinit', function() {

});
</script>

4-7
2013 Intel Corporation.
Fast Track to Intel XDK New

9. Inside the event handler function, define a variable named page that
retrieves the file name of the current url. Your code should resemble
the following:
var page = event.target.baseURI.split('/');
page = page[page.length - 1];

10. After the code that you inserted from the prior step, check for the
existence of the global variable App.initialized. If the variable has bot
been defined, set it equal to true and call a method named App.init()
which you will define later in this exercise.
$(document).bind('pageinit', function(event,obj) {

var page = event.target.baseURI.split('/');


page = page[page.length - 1];

if (!App.initialized) {
App.initialized = true;
App.init();
}
}

11. After the code that you inserted from the prior step, insert a switch/case
statement that evaluates the contents of the page variable and checks it
against each of your application's pages.
switch (page) {
case 'index.html' :
break;
case 'beers.html' :
break;
case 'friends.html' :
break;
case 'drink.html' :
break;
}

Create the App Class and Get the Data


12. Where indicated by the comment, define an object named App with
the following properties:

initialized: false
beers: null
13. Verify that your code appears as follows:
var App = {
initialized: false,
beers: null
}

4-8
2013 Intel Corporation.
Working with Data

Retrieve and Cache the Data


14. Define two method for the App object named init() and cacheBeers().
var App = {

initialized: false,
beers: null,

init: function() {

},
cacheBeers: function() {

}
}

15. Invoke the cacheBeers() method from the init() method as illustrated
below:

var App = {

initialized: false,
beers: null,

init: function() {
this.cacheBeers();
},
cacheBeers: function() {

}
}

Make a JSON-P Request


16. Inside the cacheBeers method, define a local variable named me that
points to the Beers class and set the initialized property to true.
var me = this;

17. Immediately after the code that you inserted from the prior step, make
a JSON-P request to the following URL, placing the result in the Beers
class data property and dumping its results to the debugging console.
http://xdktraining.com/ftxdknew/data/beer.cfc?
method=getBeerList&callback=?

18. Verify that your code appears similar to the following:


cacheBeers: function() {
var me = this;
var url = "http://xdktraining.com/ftxdknew/data/beer.cfc";
$.getJSON(url + "?method=getBeerList&callback=?",
function(data) {
me.beers = data;
console.log(data);
}
);
}

19. Save the file.

4-9
2013 Intel Corporation.
Fast Track to Intel XDK New

20. Click on the Emulate tab.


21. Open the debugger. You should see the array output from the data
request as illustrated in Figure 2:

Figure 2: Inspecting the results of the JSON-P request.

22. Type the following code in the debugger's console view to output the
list of Beers:
App.beers

--End of Walkthrough--

4 - 10
2013 Intel Corporation.
Working with Data

Working with the ListView


Use the ListView widget, depicted in Figure 3, to display the contents of
either unordered or ordered lists.
Add a data-role=listview property to a
<ul> or <ol> entity in order to instantiate
a ListView:
<ul data-role="listview">
<li><h3>Aaron</h3></li>
<li><h3>Adam</h3></li>
<li><h3>Alexander</h3></li>
</ul> Figure 3: A simple listview

Grouping Lists

You can create grouped lists as illustrated in Figure 4 by applying the


data-autodividers="true" property to the <ul> entity as illustrated below.
Note the following:
Grouped items must be placed in alphabetical order.
By default, the group name will be the uppercased first character of the
item's text.

<ul
data-role="listview"
data-autodividers="true">

<li><h3>Drucker, Aidan</h3></li>
<li><h3>Drucker, Dylan</h3></li>
<li><h3>Drucker, Steve</h3></li>
<li><h3>Gallerizzo, David</h3>
</li>
</ul>
Figure 4: Using autodividers

4 - 11
2013 Intel Corporation.
Fast Track to Intel XDK New

Defining Custom Group Names

The following code snippets illustrate


how to define custom group names by
completing the following steps:
Add a custom data attribute to your
<li> entities that define the group
name.
Define an autodividersSelector
method that dynamically returns the
group name based on list item
properties.
Programmatically refresh the list
Figure 5: Defining custom group
names
Markup:
<ul data-role="listview" id="personsList">
<li data-lastname="Drucker"><h3>Drucker, Aidan</h3></li>
<li data-lastname="Drucker"><h3>Drucker, Dylan</h3></li>
<li data-lastname="Drucker"><h3>Drucker, Steve</h3></li>
<li data-lastname="Watts"><h3>Watts, David</h3></li>
<li data-lastname="Watts"><h3>Watts, Tiberius</h3></li>
</ul>

Script:
$("#personsList").listview({
autodividers: true,
autodividersSelector: function(li) {
return li.attr("data-lastname");
}
});
$("#personsList").listview("refresh");

Dynamically Populating a List from JSON

In most use cases you'll need to dynamically construct a list from data that
was returned from an AJAX or JSON-P call. In order to pull this off, you'll
usually need to perform the following tasks:
Dynamically sort the array returned from the AJAX/JSON-P call.
Construct a template for generating list item markup.
Generating html markup for each item and append to the ListView.
Refresh the ListView.

4 - 12
2013 Intel Corporation.
Working with Data
Dynamically Sorting an Array

Use Javascript's array.sort() method to sort an array of objects so that it


may be grouped correctly into a list.
Passing a function as an argument to the sort() method enables you to sort
based on two or more fields typically the field that you're grouping on,
and the label for each list item. In this context, Javascript automatically
passes in two objects to your custom function. The function, in turn, must
return the following:
-1 if a < b
0 if a == b
1 if b > a
The following code snippet illustrates an ascending alphabetical sort for a
group-based sort.
data.sort(function(a,b) {
if(a.groupfield == b.groupfield) {
return (a.label < b.label) ? -1 :(a.label > b.label) ? 1:0;
} else {
return (a.groupfield < b.groupfield) ? -1 : 1;
}
});

Constructing a Template

Using templates improves code readability while reducing syntax errors


that inevitably result from performing complex multi-variable string
concatenation with the + operator.
While, jQuery 1.x no longer supports built-in template methods, but you
can easily add a substitute by extending JavaScript's String class as
illustrated by the following snippet:
String.prototype.format = function () {
var args = arguments;
return this.replace(
/\{(\d+)\}/g,
function (m, n) { return args[n]; }
);
};

This String.format() method enables you to easily perform dynamic string


replacement of placeholders through the following invocation:
var template = "The rain in {0} falls mostly on the {1}";
template.format("Spain","plain");

// output: The rain in Spain falls mostly on the plain

4 - 13
2013 Intel Corporation.
Fast Track to Intel XDK New

Dynamically Generating List Items

The problem with using the aforementioned syntax, however, is that


creating a multi-line template remains somewhat error-prone since you
can't insert line breaks within a Javascript string. Sharing the template
across multiple applications would also be problematic.
The solution is to break the template out into a separate script as illustrated
below:
<script type="text/template" id="tplListItem">
<li data-value="{0}">
<h3>{1}</h3>
</li>
</script>

You can then convert the contents of the script to an HTML string using
jQuery's html() method:
var itemTemplate = $("#tplListItem").html();

Now that you've got your template in place, you can easily loop through
your dataset, appending markup to your list. Note that once you have
completed adding list items, you must programmatically refresh the list as
illustrated by the following example:
var list = $('ul#personsList');

list.empty(); // remove all items

for (var i=0; i< data.length; i++) {


var item = data[i];
var str = itemTemplate.format(item.id, item.name);
list.append(str);
}

// redraw the list absolutely REQUIRED!!!


list.listview("refresh");

4 - 14
2013 Intel Corporation.
Working with Data

Adding a Search Filter

Adding the data-filter="true" property


to a list causes the jQuery Mobile
framework to prepend a search box that
filters out list items that don't contain
the text that the user types into the box.
The input's placeholder text defaults to
"Filter items..."
<ul
data-role="listview"
id="personsList" Figure 6: Adding a Search Filter
data-filter="true" >
<li data-lastname="Drucker"><h3>Drucker, Aidan</h3></li>
<li data-lastname="Drucker"><h3>Drucker, Dylan</h3></li>
<li data-lastname="Drucker"><h3>Drucker, Steve</h3></li>
<li data-lastname="Watts"><h3>Watts, David</h3></li>
<li data-lastname="Watts"><h3>Watts, Tiberius</h3></li>
</ul>

Displaying Counts and Carats in a List

The framework includes text formatting


conventions for common list patterns like
header/descriptions, secondary
information and counts through semantic
HTML markup.
To add a count indicator to the right
of the list item, wrap the number in an
element with a class of ui-li-count
To add a carat indicator, insert the following into each list item:
<span
class="ui-icon ui-icon-arrow-r ui-icon-shadow">&nbsp;</span>

Listening for a Tap Event

Listen for tap events on list items by using the bind() method as illustrated
below:
$('#personsList > li').bind('tap', function(e) {
var targetValue = this.getAttribute('data-lastname');
alert("You selected the " + targetValue + " family");
});

4 - 15
2013 Intel Corporation.
Fast Track to Intel XDK New

Walkthrough 4-2: Dynamically


Generating Lists
In this walkthrough, you will enhance your
application by outputting the data that you
retrieved in the previous walkthrough into a
ListView.

Generate a list view


Sort an array of records
Output records into a grouped list

Steps

Open the Project


1. Open Intel XDK New
Figure 7: Output a list of
2. Click on the word PROJECTS in the Beers, grouped by country of
top-left corner of the GUI. origin.
3. Click the Open a Project button.
4. Select the following file:
/ftIntelXdkNew/walk/walk4_2/walk4_2.xdk

Sort the Dataset


5. Where indicated by the comment, sort the dataset.
Group on the country field
Sort by the name field
6. Your code should appear similar to the following:
data.sort(function(a,b) {
if(a.country == b.country) {
return (a.name < b.name) ? -1 : (a.name > b.name) ? 1 : 0;
} else {
return (a.country < b.country) ? -1 : 1;
}
});

7. Save the file and run the app in the emulator.


8. Open the debugger's console view.
9. Inspect the results from the console.log(). You should see that the data
retrieved from the getJSON() method has been sorted by country name
and beer name.
10. Click on the Develop tab.

4 - 16
2013 Intel Corporation.
Working with Data
Create the List
11. Open the Beers.html file in Design mode.
12. From the Controls > Widgets panel, drag a ListView widget and drop it
onto the design canvas between the page's header and footer.
13. In the ListView Settings panel, turn on the following checkboxes:

Filter
Auto Dividers
id
14. Enter the following id for the ListView:
beerslist

15. Save the file and test the application in the emulator. The list should
appear.

Define a List Item Template


16. Where indicated by the comment, define a template for the list items
that you need to dynamically instantiate. Assign an id property to the
template of tplBeerItem The output from the template needs to
contain markup similar to the following:
<li data-value="1" country="United States">
<h3>Samuel Adams Boston Lager</h3>
<span class="ui-li-count">0</span>
</li>

17. Verify that your code appears similar to the following:


<script type="text/template" id="tplBeerItem">
<li data-value="{0}" country="{1}">
<h3>{2}</h3>
<span class="ui-li-count">{3}</span>
</li>
</script>

Populate the List


18. Return to Develop mode.
19. Open index.html in Code view.
20. Inside the populateList() method, define a variable named list that
points to the ListView component.
var list = $('#beerslist > ul');

21. Clear the default list items from the list. Your code should appear
similar to the following:
list.empty();

22. After the code that you inserted from the prior step, define a variable
named beerTemplate that points to the html in the tplBeerItem element.
var beerTemplate = $("#tplBeerItem").html();

4 - 17
2013 Intel Corporation.
Fast Track to Intel XDK New

23. After the code that you inserted from the prior step, loop through the
data retrieved from the JSON-P transaction. Your code should appear
similar to the following:

for (var i=0; i<App.beers.length; i++) {


var item = App.beers[i];
}

24. Inside the for-loop, use the String.format() method to generate a


dynamic list item and then append the result to the list.

for (var i=0; i<App.beers.length; i++) {


var item = App.beers[i];
list.append(beerTemplate.format(
item.id, item.country, item.name, 0));
}

25. After the for-loop, insert code to refresh the list.


list.listview("refresh");

26. Save the file and test the application in the emulator. You will need to
test the app by launching the index.html file and then clicking on the
Beers button in the footer. Note that the dividers are not displaying
correctly.

Configure Custom AutoDividers


27. Return to Develop mode.
28. Open index.html in code view.
29. In the populateList() method, immediately after the variable
declaration of the variable list , define a custom autodivider selector
that is generated from the value of the country attribute from each list
item. Your code should appear similar to the following:
list.listview({
autodividers: true,
autodividersSelector: function ( li ) {
return li.attr('country');
}
});

30. Save the file and re-test in the emulator. Your list dividers should now
contain the names of the countries from where the beers were made.

End of Walkthrough --

4 - 18
2013 Intel Corporation.
Working with Data

Caching Data in a Local Database


The HTML 5 specification defines database-agnostic SQL for accessing
local databases. Most mobile browsers have implemented SqlLite, enabling
you to use define database tables to store and retrieve structured data.
The amount of space allocated for local databases is configurable through
the browser. You can allocate up to 5MB per app without needing to
prompt the user to allocate more space.

Creating / Opening a Local Database

The following access methods are supported for opening a database


connection:

Method Description

window.openDatabase() Creates / opens a local database

WorkerUtils.openDatabase() Creates / opens a local database using


web workers (threads)

WorkerUtils.openDatabaseSync() Synchronizes database information

Each of the aforementioned methods require the following arguments


(listed in order). Items in bold are required:

Type Description

string Database name. Will create new, empty database if the


specified name does not exist.

string Database version.

string Display name

long Estimated size in bytes of the database size

function A callback to be invoked if the database has not yet


been created. The callback function, in turn, must
invoke the changeVersion() function to set the version
id for the database. If a callback is not specified, the
database will be created and version set to the value
specified by the second argument. Note that
changeVersion() is not implemented in all browsers.

4 - 19
2013 Intel Corporation.
Fast Track to Intel XDK New

The following example illustrates the creation of a local database


containing a single table:
<script>
Cart = {
db : null,

dbOpen : function() {
this.db = openDatabase('cart',
'1.0',
'Cafe Townsend Shopping Cart',
5*1024*1024
);

this.db.transaction(function(tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS cart(id
INTEGER PRIMARY KEY ASC, desc TEXT, qty INT, unitprice NUM)',
[], this.onSuccess, this.onError);
});
},

onError : function(tx, e) {alert("Error: " + e.message);}

onSuccess : function(e) {alert("Success"); }

}
</script>

<body onload="Cart.dbOpen()">

Performing Database Transactions

You can perform database transactions using the transaction() method of


your web database to define a transaction and then using the executeSql()
method of a transaction to process your queries.
The executeSql() method accepts four arguments, listed in order:

Arg Description

1 The SQL that you wish to execute

2 Optional bind parameters

3 Optional success handler function

4 Optional error handler function

4 - 20
2013 Intel Corporation.
Working with Data

The following example illustrates using a combination of hardcoded and


bind parameters, represented by question marks, to insert data into the cart
table:

Cart.db.transaction(function(tx) {

var desc = "Roasted Tomato Soup";


var qty = "5";
var unitprice = "4.5";

tx.executeSql('INSERT INTO cart (id, desc, qty, unitprice)


VALUES (1,?,?,?)',
[desc,qty,unitprice],
function() {alert('success')},
function() {alert('failed')});
});

Similarly, an update statement might resemble the following:


Cart.db.transaction(function(tx) {
var desc = "Steak";
tx.executeSql('update cart set qty = qty + 1
where desc = ?', [desc]);
});

Delete statements may be handled in a similar fashion:


Cart.db.transaction(function(tx) {
var id = 1
tx.executeSql('delete from cart where id= ?', [id]);
});

Retrieving Data from the Database

The executeSql() method passes a SQLResultSet object into its success


callback function.
SQLResultSet has the following read-only attributes:

Attribute Description

insertId Returns the row ID of the data inserted into


the database

rowsAffected The number of rows affected by the operation

rows A SQLResultSetRowList object. representing


the rows returned, in the order returned by the
database. If no rows were returned, it will be
empty (zero-length).

4 - 21
2013 Intel Corporation.
Fast Track to Intel XDK New

The SQLResultSetRowList object contains a readonly attribute - length


which contains the number of rows returned. It also contains a getter
method named item(). Passing a row number to the item() method returns a
structure representing the row's column data.
The following example illustrates the process of retrieving and looping
through a SQLResultSetRowList object:

function getData(db) {
db.transaction(function(tx) {
tx.executeSql(
'SELECT * FROM cart',
[],
function (tx, results) {
var len = results.rows.length;
for (var i = 0; i < len; i++)
{
alert(results.rows.item(i).desc);
}
});
})
}

Handling Database Errors

When an error occurs, either a SQLError or a SQLException object is


passed to your handler. Both objects have similar structures, containing the
following attributes:

Attribute Description

code A numeric error code, described below

message A string containing the error message, localized to


the user's language

The following error codes may be returned:

Constant Code Description

UNKNOWN_ERR 0 Transaction failed for reasons not related


to the database.

DATABASE_ERR 1 Operation failed due to the database, but


not covered by the other error types

VERSION_ERR 2 Operation failed because the database


version did not match with the expected
version

4 - 22
2013 Intel Corporation.
Working with Data

Constant Code Description

TOO_LARGE_ERR 3 The dataset returned from the database


was too large

QUOTA_ERR 4 Not enough disk space allocated

SYNTAX_ERR 5 Failed due to a syntax error, or a


mismatch on the number of bind
parameters.

CONTRAINT_ERR 6 Failed due to a referential integrity


constraint.

TIMEOUT_ERR 7 Could not establish a transaction lock in a


reasonable amount of time

The following code snippet illustrates handling a database exception:

db.transaction(function(tx) {
var desc = "Roasted Tomato Soup";
var qty = "5";
var unitprice = "4.5";

tx.executeSql(
''.concat('INSERT INTO cart (id, desc, qty, unitprice)',
' VALUES (1,?,?,?)'
),
[desc,qty,unitprice],
function() {
alert('success');
},
function(tx,e) {
alert('Error code: ' + e.code + ':' + e.message);
}
);
});

4 - 23
2013 Intel Corporation.
Fast Track to Intel XDK New

Manually Verifying Database Transactions

You can manually validate that your data has been manipulated in the local
database by opening the Chromium debugger, clicking on the Resources
tab, and inspecting the contents of the Web SQL assets as indicated in
figure 8.

Figure 8: Reviewing the contents of a WebSQL table.

4 - 24
2013 Intel Corporation.
Working with Data

Walkthrough 4-3: Working with


WebSQL
In this walkthrough, you will refactor your
application by caching the list of beers that
you retrieved in the previous walkthrough
into a webSQL database.

Generate a WebSQL database


Review code that inserts, updates, and
deletes from a WebSQL Database
Select data from a WebSQL table and
output it to a ListView

Steps

Open the Project


Figure 9: Store, retrieve, and
1. Open Intel XDK New output data from a local
2. Click on the word PROJECTS in the database
top-left corner of the GUI.
3. Click the Open a Project button.
4. Select the following file:
/ftIntelXdkNew/walk/walk4_3/walk4_3.xdk

Review the WebSQL Database API


5. Open walk4-3/js/localdb.js. Review the code. This JavaScript class
defines a singleton that will handle all basic SQL operations within
your application. Note that this library could be easily repurposed for
use in other applications.

The init() method defines two local database tables - beer which
will hold a cached list of beers and friend which will store
extended contact information for your friends.
The runQuery() method executes the structured query language
(SQL) code that you pass into it, passing the results to a callback
function.
The writeRecord() method performs insert and update operations
on the specified table.
The importTable() method copies an array of objects into the
specified database table.

4 - 25
2013 Intel Corporation.
Fast Track to Intel XDK New

Cache data in WebSQL


6. Open walk4-3/index.html in Code View
7. Inside the getJSON callback function, invoke the
FriendsWithBeerDB.importTable() method to transfer the json data
into the Beer table.
var App = {
cacheBeers : function() {
var url = "http://xdktraining.com/ftxdknew/data/beer.cfc";
$.getJSON(url + "?method=getBeerList&callback=?",
function(data) {
FriendsWithBeerDB.importTable('beer',data);
}
);
}
};

8. Save the file.


9. Open the emulator.
10. Open the debugger and click on the Resources panel.
11. Open Web SQL > Friends with Beer.
12. Click on the Beer table. You should see data in the panel.

Retrieve Data from WebSQL and Output to a ListView


13. Return to the index.html in Code view.
14. Review the refactored Beers class.
15. Where indicated by the comment, call the
FriendsWithBeerDB.runQuery() method to execute the SQL
statement defined on the previous line. Your code should appear
similar to the following:
FriendsWithBeerDB.runQuery(sql, function(records) {

});

16. Inside the SQL callback function, loop through the data returned from
the sql transaction:
FriendsWithBeerDB.runQuery(sql, function(records) {
for (var i=0; i<records.length; i++) {

}
});

4 - 26
2013 Intel Corporation.
Working with Data

17. Inside the for-loop, append dynamically generated list items to the
ListView. Your code should appear as follows:
FriendsWithBeerDB.runQuery(sql, function(records) {
for (var i=0; i<records.length; i++) {
var item = records[i];
list.append(
beerTemplate.format(
item.id,
item.country,
item.name,
item.thecount
)
);
}
});

18. Immediately after the for-loop, refresh the list.


list.listview("refresh");

19. Save the file and test the app in the emulator. You should see the full
list of beers appear on the Beers tab.

End of Walkthrough

4 - 27
2013 Intel Corporation.
Fast Track to Intel XDK New

Importing Data from the Contacts List


Intel XDK New supports Apache Cordova, which acts as a bridge that
enables you to use Javascript to access native device resources. One of
those resources is the device's contacts list.
Since contact information is generally considered to be private and
personal, your app's privacy policy should discuss how your app uses this
data and whether it will be shared with other parties. You should also
strongly consider providing a just-in-time notice prior to your app
accessing or using contact data (if the device operating system doesn't do
so already).
The Cordova API enables you to both read and write to the device's
Contacts list.
Full documentation on this API is at the following URL:
http://cordova.apache.org/docs/en/2.9.0/cordova_contacts_contacts.md.htm
l#Contacts

Loading the Cordova Library

You'll need to load the Cordova javascript library, cordova.js, in order to


access Cordova's Contacts List API.
The cordova.js file is dynamically injected into the root of your application
during the BUILD process. All you need to do is add the following element
to the top of your index.html file's <head> section:
<script type="text/javascript" src="cordova.js"></script>

Handling Time-Intensive Asynchronous Operations

Retrieving contacts can be a time-intensive operation, depending on the


speed of the device and the number of contacts that the user has stored.
When dealing with asynchronous operations, it is often useful to provide
the user with feedback that they should wait for a function to complete
before proceeding. Jquery's Loader widget works well in these scenarios.
Instantiate the loader using the following syntax:
$.mobile.loading( 'show', {
text: "Please Wait",
textVisible: true,
theme: "a",
textonly: false,
html: ""
});

Use the following syntax to hide the loader:


$.mobile.loading( "hide" );

4 - 28
2013 Intel Corporation.
Working with Data

Retrieving Contact Records

Contacts.find() queries the device contacts database asynchronously and


returns an array of Contact objects which are passed to a callback function.
The basic syntax is:
navigator.contacts.find(
contactFields, //array of field names to search (required)
contactSuccess, // success callback function (required)
contactError, // failure callback function (optional)
searchOptions // Options to filter contacts (optional)
);

Note the following:


Only the fields specified in the contactFields parameter will be
returned as properties of the Contact objects that are passed to the
contactSuccess callback function.
A contactFields value of ["*"] will return all contact fields.
A zero-length contactFields parameter is invalid and will result in a
ContactError.INVALID_ARGUMENT_ERROR.

The following example returns contacts named Steve:


var options = new ContactFindOptions();
options.filter="Steve";

var fields = ["displayName", "name"];

navigator.contacts.find(
fields,
function(contacts) {
alert(contacts.length + " records found!");
for (var i=0; i<contacts.length; i++) {
alert("Display Name = " + contacts[i].displayName);
}
},
function(err) {
alert("Import Failed");
},
options
);

4 - 29
2013 Intel Corporation.
Fast Track to Intel XDK New

Working with Contact Data

You can read the following fields for each contact record:

Field Description

id String. A globally unique identifier

displayName String. The name of the Contact, suitable for display


to end-users

name Object An object containing all components of a


persons name.

nickname String. A casual name to address the contact.

addresses Array. All of the contact's addresses.

phoneNumbers Array. Contact's phone numbers

emails Array. All of the contact's email addresses

ims Array. All of the contact's instant messaging addresses

organizations Array. All of the contact's organizations

birthday Date. The contact's birthday.

note String. General remarks about the contact.

photos Array. The contact's photos.

categories Array. All of the contact's user-defined categories.

urls Array. An array of web url's associated with the


contact.

You would use the following syntax to output a contact's display name to
an alert box:
onSuccess: function(contacts) {
for (var i=0; i<contacts.length; i++) {
window.alert(contacts[i].displayName);
}
}

4 - 30
2013 Intel Corporation.
Working with Data

Parsing the Contact Name

The Contact Name is a javascript object containing the following


properties:

Field Description

formatted String. The complete name of the contact.

familyName String. The contact's family name.

givenName String. The contact's given name.

middleName String. The contact's middle name.

honorificPrefix String. The contact's prefix (Mr. / Dr. / Mrs. / etc)

honorificSuffix String. The contact's suffix, e.g. Esq, DDS, MD

To output a contact's first name followed by their last name, you would use
the following syntax:
onSuccess: function(contacts) {
for (var i=0; i<contacts.length; i++) {
window.alert(
''.concat(
contacts[i].name.givenName,
' ',
contacts[i].name.familyName
)
)
}
}

4 - 31
2013 Intel Corporation.
Fast Track to Intel XDK New

Parsing the Contact's Addresses

Each ContactAddress object has the following properties:

Property Description

pref Boolean. True if the contact's preferred address.

type String. Indicates type of address, e.g. 'home'

formatted String. The full address, formatted for display.

streetAddress String. The full street address.

locality String. The city or locality.

region String. The state or region.

postalCode String The zip code or postal code.

country String. The country name.

To determine the preferred address, you'll need to loop through the


contact's addresses array as illustrated by the following snippet:
onSuccess: function(contacts) {
for (var i=0; i<contacts.length; i++) {
var address = "";
for (var j=0; j<contacts[i].addresses.length; j++) {
if (contacts[i].addresses[j].pref) {
address = contacts[i].addresses[j];
break;
}
}
alert(address.formatted);
}
}

4 - 32
2013 Intel Corporation.
Working with Data

Parsing the Contact's Email Addresses and Phone Numbers

Email addresses and phone numbers are stored in a ContactField objects


which contains the following properties:

Property Description

type String. The type of field, e.g. 'home','work','mobile'

value String. The email address or phone number

pref Boolean. If true, represents the preferred value.

The following example illustrates how to retrieve the preferred phone


number:
onSuccess: function(contacts) {
for (var i=0; i<contacts.length; i++) {
var phone = "";
for (var j=0; j<contacts[i].phoneNumbers.length; j++) {
if (contacts[i].phoneNumbers[j].pref) {
phone = contacts[i].phoneNumbers[j].value;
break;
}
}
alert(phone);
}
}

4 - 33
2013 Intel Corporation.
Fast Track to Intel XDK New

Testing Contact Features

Accessing the Contact's list is a device-specific feature. You will not be


able to access this functionality through either the emulator or Intel App
Preview. You can only test your code by creating a native build.
Also, note that in the Details configuration tab of the Build panel, you'll
need to turn on the option labeled This App Accesses the User's Contacts
as illustrated in Figure 10.

Figure 10: Including the Contacts library in your native build.

4 - 34
2013 Intel Corporation.
Working with Data

Walkthrough 4-4: Loading Contacts


In this walkthrough, you will add a button to the Friends screen that
enables a user to import their device's contacts into the Friends with Beer
app.

Access device contacts


Transfer contact data into a WebSQL table
Use the weinre debugger to verify your work

Steps

Open the Project


1. Open Intel XDK New
2. Click on the word PROJECTS in the top-left corner of the GUI.
3. Click the Open a Project button.
4. Select the following file:
/ftIntelXdkNew/walk/walk4_4/walk4_4.xdk

Add the Import Button


5. Open Contacts.html in Design View
6. From the Controls > Form palette, drag a Button widget and drop it on
the left edge of the Friends header.
7. Configure the following Button properties:

Label: Import
Icon: ui-icon-user
Icon Position: icon only
id: btnImportContacts

Load the Cordova API


8. Open index.html in Code View
9. Where indicated by the comment, insert a <script> tag to load the file
cordova.js

Review the Contacts Object


10. Where indicated by the comment, review the Contacts object and its
method's associated comments.

4 - 35
2013 Intel Corporation.
Fast Track to Intel XDK New

11. Inside the Contacts init() method, define an event listener for the tap
event on the btnImportContacts button.
init: function() {

$("#btnImportContacts").bind("tap", function(e) {

12. Inside the tap event handler, insert an if-else block that determines
whether the navigator.contacts object exists.

If navigator.contacts does not exist, display an alert() message that


informs the user that the feature is not available.

init: function() {
this.initialized = true;
$("#btnImportContacts").bind("tap", function(e) {
if (navigator.contacts) {

} else {
alert("Function not available");
}
}
}

13. Inside the if-block, insert a window.prompt() that asks the user for the
name of the contact that they want to import. If the user enters a
response, pass it along to the importContacts method of the Contacts
object.
init: function() {
this.initialized = true;
$("#btnImportContacts").bind("tap", function(e) {
if (navigator.contacts) {
var friendName = window.prompt(
"Enter your friend's name",
""
);
if (friendName != null) {
Contacts.importContacts(friendName);
}
} else {
alert("Function not available");
}
}
}

14. Save the file and test in the Emulator. You should see a Function not
available message when attempting to import contacts from the
emulator.

4 - 36
2013 Intel Corporation.
Working with Data

Search for Contacts


15. Return to Develop mode.
16. Inside the importContacts function, display a Please Wait message
to the user.
$.mobile.loading( 'show', {
text: "Please Wait",
textVisible: true,
theme: "a",
textonly: false,
html: ""
});

17. After the code that you inserted in the prior step, define a local variable
named options that is a new ContactFindOptions object.
var options = new ContactFindOptions();

18. Set the filter property of the options object to the value of the
argument that was passed into the function.
options.filter=friendName;

19. Set the multiple property of the options object to retrieve multiple
contact records.
options.multiple = true;

20. Define a local variable named fields that contains an array of strings
for the contact information that you need to retrieve (name, address,
phone, email):
var fields = [
"displayName",
"name",
"addresses",
"phoneNumbers",
"emails"
];

21. Invoke the navigator.contacts.find() method as illustrated below:


navigator.contacts.find(fields,
this.onImport,
this.onImportError,
options);

Define the Contact's Search Success Handler


22. Inside the onImport method, hide the Please Wait message.
$.mobile.loading( "hide" );

23. After the code that you inserted in the prior step, define the following
local variables:
address = null
phone = null
email = null
count = 0
friend = null

4 - 37
2013 Intel Corporation.
Fast Track to Intel XDK New

24. After the code that you inserted in the prior step, insert a for-loop to
iterate through the contacts data returned to the function.
for (var i=0; i<contacts.length; i++) {

25. Inside the for-loop, insert an if() block that checks if the contact's given
name is not undefined.
if (contacts[i].name.givenName != undefined) {

26. Inside the for-loop, increment the count variable by 1.


if (contacts[i].name.givenName != undefined) {
count++;

Retrieve the Contact's Name


27. After the code that you inserted from the prior step, set the variable
friend equal to an array containing two objects with two properties
name and value.

In the first object, the name should be equal to firstName and the
value property should equal the contact's given name.
In the second object, the name should be equal to lastName and
the value property should equal the contact's family name.

for (var i=0; i<contacts.length; i++) {


if (contacts[i].name.givenName != undefined) {
count++;
var friend = [
{
name: "firstName",
value: contacts[i].name.givenName
},
{
name: "lastName",
value: contacts[i].name.familyName
}
];
}
}

Capture the Primary Contact Address


28. After the code that you inserted in the prior step, insert a conditional
that checks for the existence of a contact's address.
if (contacts[i].addresses) {

4 - 38
2013 Intel Corporation.
Working with Data
29. Inside the if() block, set the address variable equal to the result from
calling the Contacts.getPreferred() method, passing in the contact's
addresses.
if (contacts[i].addresses) {
address = Contacts.getPreferred(contacts[i].addresses);
}

30. Immediately after the code that you inserted in the prior step, add the
resulting street address and zipcode to the friends array as indicated
below:
if (contacts[i].addresses) {

address = Contacts.getPreferred(contacts[i].addresses);
friend.push(
{ name: "address", value: address.streetAddress}
);
friend.push(
{ name: "zipcode", value: address.postalCode}
);
}

Get the Contact's Primary Phone Number


31. After the contact's IF block, insert another conditional that evaluates
whether or not any phone numbers exist for the contact.
if (contacts[i].phoneNumbers) {

32. Inside the if() block, push another object onto the friend array that
contains the contact's preferred phone number.
if (contacts[i].phoneNumbers) {
friend.push(
{
name: "phone",
value:
Contacts.getPreferred(contacts[i].phoneNumbers).value});
}
)
}

Get the Contact's Preferred Email Address


33. After the if() block that you inserted from the prior steps, insert another
conditional that evaluates whether the contact object has an emails
property.
if (contacts[i].emails) {

4 - 39
2013 Intel Corporation.
Fast Track to Intel XDK New

34. Inside the if() block, push another object containing user's preferred
email address onto the friend array.
if (contacts[i].emails) {
friend.push(
{
name: "email",
value: Contacts.getPreferred(contacts[i].emails).value});
}
)
}

Save the Friend Object to the Database


35. Immediately after the last if() block, write the data from the friend
object to your WebSQL database.

FriendsWithBeerDB.writeRecord('friend',null, friend);

36. Immediately outside the for-loop in the onImport() method, output the
value from the count variable to the user in an alert box.
alert(count + " Contacts Imported");

Test your Work on Your Device


37. Save the file.
38. Click on the Test tab.
39. Click the Push Files button.
40. Open Intel App Preview on your phone.
41. Click the Camera icon and focus the camera on the QR code.
42. Click OK.
43. Click the Friends button.
44. Click the Import Contacts button.
45. Enter the first or last name of one of your friends who are in your
device's Contacts list.
46. Tap OK.
47. Return to Intel XDK New
48. Click Begin Debugging on Device.
49. Click on the Target hyperlink
50. Click on the Resources tab.
51. Open the FriendsWithBeer database and confirm that data is present in
the Friend table.

End of Walkthrough --

4 - 40
2013 Intel Corporation.
Working with Data

Unit Summary
jQuery Mobile enables you to make external data requests to remote
services using either AJAX or JSON-P protocols.
All data requests are handled asynchronously.
Verify that data was retrieved correctly by outputting the server
response to the debugger using console.log()
Web apps will not be able to make cross-domain requests unless the
remote host supports cross-origin resource sharing (CORS)
Most data requests should be deferred until they are specifically
requested by the user.
Compartmentalize your code by attaching properties and methods to
Javascript objects.
Remote data can be cached in browser memory or persisted in html5
localStorage or WebSQL databases.
Use the ListView widget to output lists of data.
You can listen for tap events on list items and then programmatically
retrieve properties associated with the item that was tapped.
The Cordova API gives you access to hardware resources, including
the Contacts list.
Most Cordova API functionality must be tested on physical devices
and may not function properly in the emulator.

4 - 41
2013 Intel Corporation.
Fast Track to Intel XDK New

Unit Review
1. AJAX requests can only be made to the same domain that a web app is
hosted on (true/false).

2. JSON-P requests cannot read XML data (true/false)

3. You can POST data via JSON-P (true/false).

4. The ListView search filter can only search for data that's visible to the
user.

5. String.format() is a native Javascript method (true/false)?

6. Why do data requests typically require that you supply a callback


function?

7. Which hardware resources can only be accessed via the Cordova API?

4 - 42
2013 Intel Corporation.
Working with Data

Lab 4: Working with Lists and WebSQL


During this lab you will read data from your WebSQL database and display
it in a dynamically populated list view.

Objectives

After completing this lab, you should be able to:


Read data from a WebSQL database
Dynamically construct a list view

Steps

1. Open /lab/lab4/lab4.xdk
2. Open contacts.html
3. Drag a LISTVIEW widget onto the design canvas and configure its
properties.
4. Return to index.html
5. Modify the Contact's displayList() method to output data from the
WebSQL table into the LISTVIEW that you defined from step 3.
6. Modify the onImport() method to refresh the LISTVIEW after your
contacts have been imported.

End of Lab --

4 - 43
2013 Intel Corporation.
(This page intentionally left blank)
Unit 5:
Creating Input Forms

Unit Objectives
After completing this unit, you should be able to:
Create a data entry form
Pre-fill form fields with data
Populate a <select> control with data from a webservice
Validate data input
Transmit form data to an application server
Save form data to a WebSQL database.

Unit Topics
Creating Forms
Validating Form Input
Persisting Form Data

5-1

2013 Intel Corporation.


Fast Track to Intel XDK New

Creating Forms
Intel XDK New supports the following types of form fields:

Checkbox Date Number


Checkbox Group Email Address Datetime
Flip Switch Telephone Number Month
Text Password URL
Hidden Search Radio
Slider Select Radio Group
Text Area

Working with Text Fields

HTML5 extends the standard textfield from HTML 4.01 by adding the
following easily deployed features:
Automatically set focus
Specify placeholder text
Validate that data was input in a specific format

Figure 1: Configuring Text Fields with Intel XDK New

Some of these capabilities are directly supported by the Intel XDK New
GUI as depicted in Figure 1. Others you will need to add using code view.

5-2
2013 Intel Corporation.
Creating Input Forms
Automatically Setting Focus

The HTML 5 autofocus attribute enables you to set focus to a specific form
field as soon as the form is rendered in your browser. In HTML 4 this
could only be accomplished by using JavaScript's focus() method.

The following example sets focus to a text field:

<form>
<label for="myfield">
This field will automatically have cursor focus:
</label>
<input type="text" name="myfield" autofocus />
</form>

Specifying Placeholder Text

Placeholder text helps you make your forms more intuitive and usable by
allowing for descriptive text to be placed inside of a text field via the
placeholder attribute. Once the field has focus or has a value, the
placeholder text is removed.
<form>
<label for="lastname">Enter your last name:</label>
<input type="text"
name="lastname"
placeholder="Last Name" />
</form>

As depicted in Figure 2, the placeholder is frequently used in lieu of a label


in order to conserve space. You can quickly implement this feature by
turning on the placeholder checkbox in the XDK New interface.

Figure 2: Placeholders help you conserve space.

5-3
2013 Intel Corporation.
Fast Track to Intel XDK New

Capturing Email Addresses

Using <input type=email> automatically adjust the user's on-screen


keyboard to facilitate data entry.
<form>
<label for="myemail">Enter your e-mail address:</label>
<input type="email" name="myemail"
placeholder="me@mycompany.com" />
<input type="submit">
</form>

As depicted in Figure 2, you can define an email field by dragging an input


widget onto the design canvas and then specifying email as its type.

Figure 3: Defining an email input field.

Inputting Phone Numbers

Use <input type=tel> to enable a user to


easily enter a telephone number. Mobile browsers
automatically present the user with a phone keypad
to facilitate input into this field type.

<form>
<input
type="tel"
name="phone"
placeholder="Tel" />
<input type="submit">
</form>

Figure 4: The tel field


in iOS

5-4
2013 Intel Corporation.
Creating Input Forms

Using Select Menus

The select menu hides the default html


<select> control and replaces it with a
custom-styled select button that matches
the look and feel of the jQuery Mobile
framework. The select menu is fully
accessible to people with disabilities.
When pressed, select menu options will
render using the native format of the
device. When a value is selected and the
menu closes, the custom button's text is
updated to match the selected value.
The syntax generating a jQuery Select
Menu is the same as generating a standard
HTML <select> control:

<select name="beerid"
id="beerid">
Figure 5: A jQM Select Menu.
<option value="1">Amstel</option>
<option value="2">Budweiser</option>
<option value="3">Chimay Rouge</option>
<option value="4">Corona Extra</option>
</select>

Adding a Placeholder Option

You'll typically want to include a "null" option in your select element to


force a user to choose an option. Placeholder options are automatically
hidden by jQM in the overlay menu, thereby ensuring that only valid
choices are presented to the user. Placeholders are recognized as:
An option with no value attribute or an empty value attribute
An option with no text node
An option with a data-placeholder="true" attribute.
The following example illustrates using a placeholder:
<select name="beerid" id="beerid">
<option>Select a Beer</option>
<option value="1">Amstel</option>
<option value="2">Budweiser</option>
<option value="3">Chimay Rouge</option>
<option value="4">Corona Extra</option>
</select>

5-5
2013 Intel Corporation.
Fast Track to Intel XDK New

Dynamically Adding Options to a Select Menu

Adding dynamic options to a Select menu is quite similar to adding


dynamic rows to a ListView widget. As illustrated by the following code
snippet, use jQuery's append() method to attach dynamically created
<option> elements to a <select> control and then invoke the widget's
refresh() method to have those changes appear on-screen.
var beers = [
{
label: "Amstel Light",
value: 1
},
{
label: "Corona Extra",
value: 2
}
];

var MySelect = $("select#beerid");

var tpl = '<option value="{0}">{1}</option>';

// remove all items


MySelect.empty();

// add placeholder
MySelect.append(tpl.format('','Please Select'));

// add data items


for (var i=0; i<beers.length; i++) {
MySelect.append(tpl.format(
ships[i].value,
ships[i].label
));
}

// important: refresh the list!!!


MySelect.selectmenu("refresh", true);

5-6
2013 Intel Corporation.
Creating Input Forms

Walkthrough 5-1: Designing a Form


In this walkthrough, you will start developing a
data input form to enable the user to edit their
contacts and link their contacts to a specific
brand of beer.

Design a form
Dynamically populate a <select> list
Implement a Back button
Respond to button taps

Steps

Open the Project Figure 6: The data entry


1. Open Intel XDK New form that you will create
during this exercise
2. Click on the word PROJECTS in the top-
left corner of the GUI.
3. Click the Open a Project button.
4. Select the following file:
/ftIntelXdkNew/walk/walk5_1/walk5_1.xdk

Define the Header Buttons


5. Open the contactform.html file in Design mode.
6. From the Controls > Form palette, drag a button widget and drop it on
the left edge of the page header.
7. Configure the following properties:

Icon: ui-icon-back
Icon position: icon only
id: btnBack
8. Go to Code mode.
9. Locate the anchor tag that was generated for the back button and add
the following attribute:
data-rel="back"

10. Return to Design mode.


11. From the Controls > Form palette, drag a button widget and drop it on
the right edge of the page header.

5-7
2013 Intel Corporation.
Fast Track to Intel XDK New

12. Configure the following properties:

Icon: ui-icon-check
Icon Position: Icon only
id: btnSave

Define the Form


13. From the Controls > Layout panel, drag a Row widget and drop it
onto the center of the design canvas.
14. Configure the following property:

is Form: checked

Define the Contact Fields


15. From the Controls > Form palette, drag an Input widget and drop it
onto the Row widget in the Design Canvas.
16. Configure the following properties:

Label: (unchecked)
Type: text
Placeholder: First Name
Name: firstName
id: firstName
17. From the Controls > Form palette, drag an Input widget and drop it
directly underneath the First Name field on the Design Canvas.
18. Configure the following properties:

Label: (unchecked)
Type: text
Placeholder: Last Name
Name: lastName
id: lastName
19. From the Controls > Form palette, drag an Input widget and drop it
directly underneath the Last Name field on the Design Canvas.
20. Configure the following properties:

Label: (unchecked)
Type: text
Placeholder: Street Address
Name: address
id: address

21. From the Controls > Form palette, drag an Input widget and drop it
directly underneath the Address field on the Design Canvas.
22. Configure the following properties:

Label: (unchecked)

5-8
2013 Intel Corporation.
Creating Input Forms
Type: number
Placeholder: Zip Code
Name: zipcode
id: zipcode

23. From the Controls > Form palette, drag an Input widget and drop it
directly underneath the Zip Code field on the Design Canvas.
24. Configure the following properties:

Label: (unchecked)
Type: email
Placeholder: you@you.com
Name: email
id: email
25. From the Controls > Form palette, drag an Input widget and drop it
directly underneath the email field on the Design Canvas.
26. Configure the following properties:

Label: (unchecked)
Type: telephone
Placeholder: Tel
Name: phone
id: phone

Create a Dynamically Populated Select List


27. From the Controls > Form palette, drag a Select widget and drop it
directly underneath the telephone field on the Design Canvas.
28. Configure the following properties:

Label: (unchecked)
Options: Select a Beer
Name: beerId
id: beerId
29. Save the file
30. Open index.html in Code mode.
31. Where indicated by the comment, define a JavaScript object named
ContactForm.
var ContactForm = { };

32. Define the following property on the ContactForm object:


friendId: null;

33. Add the following methods to the ContactForm object:

init
populateBeerField

34. Review your code to ensure that it appears similar to the following:

5-9
2013 Intel Corporation.
Fast Track to Intel XDK New

var ContactForm = {
friendId: null,
init: function() {

},
populateBeerField : function() {

}
};

35. Inside the initialize() method, call the populateBeerField method.


var ContactForm = {
init: function() {
this.populateBeerField();
},
populateBeerField : function() {

}
};

36. Inside the populateBeerField() method, define a local variable named


beerField that points to the beerid select widget in the form. Your code
should appear similar to the following:
var beerField = $("select#beerId");

37. After the code that you inserted from the prior step, insert a for-loop
that loops through the beer data that's cached in the variable App.beers.
populateBeerField : function() {
var beerField = $("select#beerId");
for (var i=0; i< App.beers.length; i++) {

}
}

38. Inside the for-loop, insert code that dynamically outputs the data from
App.beers as <option> elements inside of the select widget.
populateBeerField : function() {
var beerField = $("select#beerId");
for (var i=0; i< App.beers.length; i++) {
beerField.append(
'<option value="{0}">{1}</option>'.format(
App.beers[i].id,
App.beers[i].name
)
);
}
}

39. After the for-loop, insert a statement to refresh the display of the select
widget.
beerField.selectmenu("refresh", true);

40. Save the file.

Add a Add Contact button to the Contacts List


41. Open the contacts.html page in Design mode.

5 - 10
2013 Intel Corporation.
Creating Input Forms
42. From the Controls > Form palette, drag a button widget and drop it on
the right edge of the page header.

43. Configure the following properties:

Icon: ui-icon-plus
Icon Position: Icon only
id: btnAdd
44. Go to Code mode and locate the generated markup for the button.
45. Add the following attributes to the anchor tag that wraps the add
button:

href=contactform.html
data-transition=flip
46. Save the file.
47. Return to index.html in Code mode.
48. In the Contacts object, at the end of the init() method, bind a tap event
handler to the Add Contact button.
$("#btnAdd").bind("tap", function(e) {

});

49. Inside the button tap callback function, set the friendId property in the
ContactForm object to null.
$("#btnAdd").bind("tap", function(e) {
ContactForm.friendId = null;
});

50. Save the file and test in the emulator.

End of Walkthrough --

5 - 11
2013 Intel Corporation.
Fast Track to Intel XDK New

Validating Form Input


Unfortunately, mobile browsers do not support the native form field
validation properties that are stipulated as part of the HTML5 specification.
You can adapt the jQuery Validation Plugin, however, to easily ensure that
users are entering data in the format that you intended.
The jQuery Validation Plugin is maintained by Jrn Zaefferer, a member
of thejQuery team, lead developer on the jQuery UI team and maintainer of
QUnit. It was started back in the early days of jQuery in 2006, and updated
and improved since then.
The plugin comes bundled with a useful set of validation methods,
including URL and email validation, while providing an API to write your
own methods. All bundled methods come with default error messages in
english and translations into 37 other languages.
It's free to use under an MIT license and hosted at
http://jqueryvalidation.org/
The plugin validates the following patterns for correctness:

Type Description

required Makes data input required.

remote Requests a resource check the element for validity.

minlength Requires strings to be a specified minimum length

rangelength Requires strings to be within a specified size range.

email Requires the string to be a properly formatted email


address.

url Requires the input string to be a properly formatted url.

date Requires the input string to be a valid date.

dateISO Requires the input to be a properly formatted ISO date

number Requires the input to be a decimal number

digits Makes the element require numeric values only.

creditcard Validates that the creditcard number has been properly


formatted.

equalTo Requires the input data in one field be identical to the


input data in another field.
It also comes with extensions to validate other data types as well, including
US phone numbers.

5 - 12
2013 Intel Corporation.
Creating Input Forms

Loading the Library

You can load the jQuery Validation Library (jquery.validate.js) by simply


inserting a <script> tag into your document's <head> section:
<head>
...
<script type="text/javascript"
src="js/jquery.min.js"></script>

<script type="text/javascript"
src="jqm/jquery.mobile-min.js"></script>

<script type="text/javascript"
src="js/jquery.validate.js"></script>
</head>

Adding Validation Rules to Form Fields

You can add validation rules to fields by invoking the form.validate()


method which requires a javascript object that defines rules, behaviors, and
other options.
Typical validate() invocations appear as follows:
$( "#myform" ).validate({
submitHandler: function(form) {
$(form).ajaxSubmit();
},
invalidHandler: function(event,validator) {
var errors = validator.numberOfInvalids();
alert("Invalid data in " + errors + " fields");
},
rules: {
lastName: {
required: true
}
},
messages: {
lastName: "Please enter you family name"
}
});

In the preceding snippet, note the following:


The submitHandler is invoked when the the user presses the form's
submit button and all form fields pass validation.
The invalidHandler is called when the form is submitted when the
user presses the form's submit button but not all fields have passed
validation.
The rules object defines data validation rules on form fields. In this
case, lastName is the id of a text field.
The messages object enables you to define custom validation error
messages.

5 - 13
2013 Intel Corporation.
Fast Track to Intel XDK New

Requiring Data Input

You can require data input on a field by adding the required attribute to any
<input> field as illustrated below:
<label class="narrow-control" for="lastName"></label>

<input class="wide-control"
placeholder="Last Name"
type="text"
name="lastName"
id="lastName"
required >

You can also attach the required validation rule to a field by invoking a
form's validate() method (injected by the plugin):
$( "#myform" ).validate({
rules: {
lastName: {
required: true
}
}
});

Validating Email Addresses

Require that a properly formatted email address be entered into a form field
by applying the following validation rules:
<label class="narrow-control" for="email"></label>

<input class="wide-control"
placeholder="me@myemailaddress.com"
type="text"
name="useremail"
id="userEmail">

$( "#myform" ).validate({
rules: {
userEmail: {
required: true,
email: true
}
}
});

5 - 14
2013 Intel Corporation.
Creating Input Forms

Validating String Length

You can set validation on string field length by using the rangelength
validator as illustrated below:
<label class="narrow-control" for="lastName"></label>

<input class="wide-control"
placeholder="Last Name"
type="text"
name="lastName"
id="lastName">

$( "#myform" ).validate({
rules: {
lastName: {
required: true,
rangelength: [2,20]
}
}
});

Validating Numeric Input

Require that input data may only contain characters in the range of 0-9 by
applying the digits rule as noted below:
<label class="narrow-control" for="zip"></label>

<input class="wide-control"
placeholder="zip code"
type="text"
name="zipcode"
id="zipcode">

$( "#myform" ).validate({
rules: {
zipcode: {
required: true,
digits: true
}
}
});

Programmatically Execute Validation Rules

You can invoke form field validating programmatically by invoking the


validator.form() method as illustrated below.
var validator = $("form#contactform").validate();
validator.form();

5 - 15
2013 Intel Corporation.
Fast Track to Intel XDK New

Configuring Validation Message Placement and Theming

By default, error validation messages are injected into the form field's
<label> element. You can modify this behavior on a field-level basis by
specifying an errorPlacement method. The following example moves the
validation method into a parent <div> for a <select> element with an id of
beerid:
var form = $("form#contactform");

form.validate({
errorPlacement: function(error, element) {
if (element.attr("name") === "beerid") {
error.insertAfter($(element).parent());
} else {
error.insertAfter(element);
}
}
});

As illustrated in the following snippet, you can style the error message by
defining a css class on the label.error selector.
label.error {
float: left;
color: red;
padding-top: .5em;
vertical-align: top;
font-weight:bold
}

5 - 16
2013 Intel Corporation.
Creating Input Forms

Walkthrough 5-2: Implementing Form Validation


In this walkthrough you will add data input
validation rules to the contact form.

Load the jQuery Validation plugin.


Define validation rules for form fields
Customize the display of error messages
Programmatically trigger form validation

Steps

Open the Project


1. Open Intel XDK New
2. Click on the word PROJECTS in the top-left corner of the GUI.
3. Click the Open a Project button.
4. Select the following file:
/ftIntelXdkNew/walk/walk5_2/walk5_2.xdk

Add an ID Property to Your Form


5. Open the contactform.html file in Code view.
6. Add the following attribute to the <form> element:
id="contactform"

Define the Validation Rules


7. Open the index.html file in Code mode.
8. On line 34, insert a <script> tag to load the jQuery Validation library.
<script type="text/javascript"
src="js/jquery.validate.js"></script>

9. Inside the ContactForm object, underneath the populateBeerField


method, define a function named initValidation.
10. Inside the initValidation method, define a local variable named form
that points to the form that you defined in the prior walkthrough.
var form = $("form#contactform");

5 - 17
2013 Intel Corporation.
Fast Track to Intel XDK New

11. After the code that you inserted in the prior step, invoke form.validate
and configure the following rules:

Data input for the lastName field is required


Data input for the lastName field must have between 2 and 20
characters
Data input on the firstName field is required
Data input on the address field is required
Data input for the zipcode field may only be digits

12. Review your code to ensure it appears similar to the following:


initValidation: function() {
var form = $("form#contactform");
form.validate({
rules: {
lastName: {
required: true,
rangelength: [2,20]
},
firstName: {
required: true
},
address: {
required: true
},
zipcode: {
required: true,
digits: true
}
}
});
}

13. Inside the init() method of the ContactForm object, invoke the
initValidation() method.
var ContactForm = {

init: function() {
this.populateBeerField();
this.initValidation();
},
populateBeerField: function() {
// omitted for brevity
},
initValidation: function() {
// omitted for brevity
}
}

5 - 18
2013 Intel Corporation.
Creating Input Forms

Programmatically Validate the Form


14. Define an additional method of the ContactForm class named
submitForm()
15. Inside the submitForm() method, execute the validation rules that you
defined in step 9 and output the number of errors to an alert box. Your
code should appear similar to the following:
submitForm: function() {
var validator = $("form#contactform").validate();
validator.form();
alert(validator.numberOfInvalids());
}

16. Save the file

Link the Save button to the submitForm Method


17. Open contactform.html in Design mode.
18. Click on the button to the right of the Friends with Beer header and
configure the following property:

id: btnSave

19. Save the file.


20. Return to index.html in Code view.
21. Inside the init() method of the ContactForm object, define a tap event
handler for the save button that invokes the submitForm method. Your
code should appear similar to the following:
init: function() {
this.initialized=true;
this.populateBeerField();
this.initValidation();
var me = this;
$("#btnSave").bind("tap", function(e) {
me.submitForm();
});
}

22. Save the file and test the app in the emulator. Clicking the save button
should trigger the display of the error validation messages.

Theme the Error Messages


23. Return to index.html in Code mode.
24. Add the following style definition to the <style> block on line 14.
label.error {
float: left;
color: red;
padding-top: .5em;
vertical-align: top;
font-weight:bold
}

5 - 19
2013 Intel Corporation.
Fast Track to Intel XDK New

25. Save the file and re-test the app in the emulator. You should see that
your error messages are now formatted.

End of Walkthrough --

5 - 20
2013 Intel Corporation.
Creating Input Forms

Persisting Form Data


Transactional CRUD interfaces require that you support four major
functions:
Create new records
Read and display records
Update pre-existing records
Delete records
In order to update pre-existing records, you'll typically need to populate a
form with data, allow the user to edit the record, and then post it back to
the server.

Dynamically Setting Form Field Values

To programmatically set the value of an input field, invoke the field's .val()
method as illustrated below:
$("#firstName").val("Steve");

To programmatically set the value of other types of JQM form controls,


you must first manipulate the native control and then use the widget's
refresh method to synchronize the enhanced control with its native html
counterpart as illustrated by the following examples:
// updating checkboxes
var myCheckbox = $("input[type='checkbox']#check1")
myCheckbox.prop("checked",true).checkboxradio("refresh");

// updating radio buttons


var myRB = $("input[type='radio']#rb1")
myRB.prop("checked",true).checkboxradio("refresh");

// select controls
var myselect = $("select#beerid");
myselect.selectedIndex = 1;
myselect.selectmenu("refresh");

Dynamically Getting All Form Field Values

The form.serializeArray() method creates a JavaScript array of objects


consisting of your form field names and their associated input values.
var formData = $("form#contactform").serializeArray();

5 - 21
2013 Intel Corporation.
Fast Track to Intel XDK New

Posting Data to an Application Server

In jQuery Mobile, form submissions are automatically handled using Ajax


whenever possible, resulting in a smooth transition between the form and
the result page. If left unspecified, a form's method will default to get and
its action will default to the current page's relative path
($.mobile.path.get())
Note that forms accept attributes for transitions just like anchors, so you
can attach a data-transition="pop" and data-
direction="reverse".
If you do not want a page transition to occur or simply want more control
over the submission process, you'll need to invoke the $.ajax() method as
illustrated by the following example:

submitForm: function() {

var form = $("form#contactform");


var validator = form.validate();
validator.form();

if (validator.numberOfInvalids() == 0) {
$.ajax({
type: "POST",
url: "http://www.xdktraining.com/savecontact.cfm",
data: form.serialize(),
success: function(data) {
alert("Record Saved");
},
error: function(XMLHttpRequest, textStatus, err){
var msg = ''.concat(
'status:', XMLHttpRequest.status, '\n',
'status text: ', XMLHttpRequest.statusText
);
alert(msg);
}
});
}
}

Note the following from the preceding example:


Call the form.serialize() method to retrieve all form field values and
serialize them into a single encoded string for posting to the app server.
You should always include a failure handler in your AJAX transactions

5 - 22
2013 Intel Corporation.
Creating Input Forms

Walkthrough 5-3: Inserting and Updating Records


In this walkthrough you will add data
input validation rules to the contact
form.

Insert contact records into the


WebSQL database
Set the values of form fields
Update contact records in the
WebSQL database
Programmatically load pages

Steps

Open the Project


1. Open Intel XDK New
2. Click on the word PROJECTS in the top-left corner of the GUI.
3. Click the Open a Project button.
4. Select the following file:
/ftIntelXdkNew/walk/walk5_3/walk5_3.xdk

Add Disabled Lat/Lng Fields to the Form


5. Open contactform.html in Design mode.
6. Drag an Input widget from the Controls > Form palette and drop it
directly underneath the beers select box on the design canvas.
7. Configure the following properties:

Label: Lat (unchecked)


Placeholder: Latitude
Name: lat
id: lat
8. Drag an Input widget from the Controls > Form palette and drop it
directly underneath the beers select box on the design canvas.
9. Configure the following properties:

Label: Lng (unchecked)


Placeholder: Longitude
Name: lng
id: lng
10. Go to code mode and add a disabled property to the lat and lng fields.

5 - 23
2013 Intel Corporation.
Fast Track to Intel XDK New

Create a New Record


11. Open the index.html file in Code mode.
12. Refactor the ContactForm.submitForm() method as indicated below:
submitForm: function() {
var form = $("form#contactform");
var validator = form.validate();
validator.form();
if (validator.numberOfInvalids() == 0) {

} else {
alert("Invalid data input");
}
}

13. Inside the if() block, use the form.serializeArray() method to serialize
all of the form fields into a local variable named fields.
var fields = form.serializeArray();

14. Immediately after the code that you inserted in the last step, append the
values of the disabled lat and lng fields to the fields array.
fields[fields.length] = {
name: 'lat',
value: $('#lat').val()
};

fields[fields.length] = {
name: 'lng',
value: $('#lng').val()
};

15. Immediately after the code that you inserted in the last step, invoke the
FriendsWithBeerDB.writeRecord() method to transfer the data from
the fields variable into your webSQL database.
FriendsWithBeerDB.writeRecord(
'friend',
this.friendId,
fields,
function() {

}
);

16. Inside the writeRecord() callback function, use the alert() method to
output a message to the user and then reload the contacts.html page.

5 - 24
2013 Intel Corporation.
Creating Input Forms

17. Review your submitForm() method to ensure that it appears similar to


the following:
if (validator.numberOfInvalids() == 0) {
var fields = form.serializeArray();
fields[fields.length] = {
name: 'lat',
value: $('#lat').val()
};
fields[fields.length] = {
name: 'lng',
value: $('#lng').val()
};
FriendsWithBeerDB.writeRecord(
'friend',
this.friendId,
fields,
function() {
alert("Record Saved");
$.mobile.changePage('friends.html');
}
);
}
}

18. Save the file and test the application in the emulator. You should now
be able to create new contact records!

Attach a tap event listener to the List Items in the


Friends List
19. In the FriendsList.displayList() method, where indicated by the
comment, attach a tap event listener to the list items.
$('#friendsList > li').bind('tap', function(e) {

});

20. Inside the event handler, retrieve the numeric identifier in the list item
and transfer its value to the ContactForm.friendId property.
$('#friendsList > li').bind('tap', function(e) {
ContactForm.friendId = this.getAttribute('data-value');
});

21. Immediately after the code that you inserted in the prior step,
programmatically change the page to contactform.html
$('#friendsList li').bind('tap', function(e) {
var ContactForm.friendId = this.getAttribute(
'data-value');
$.mobile.changePage('contactform.html');
});

22. Save the file and test in the emulator. Clicking on an item in the
Friends list should now transfer control to the data entry form.

Load Data Into the Form


23. Add a new method named loadRecord to the ContactForm object.

5 - 25
2013 Intel Corporation.
Fast Track to Intel XDK New

24. Inside the loadRecord() method, define an if() block that evaluates
whether the value of the ContactForm.friendId property is null.
loadRecord: function() {
if (this.friendId != null) {

}
}

25. Inside the if() block, invoke the FriendsWithBeerDB.runQuery()


method to retrieve the record from the WebSQL friends table where the
friendId is equal to the friendId stored in the ContactForm object.
loadRecord: function() {
if (this.friendId != null) {
var sql = "select * from friend where id = {0}";
sql.format(this.friendId);
FriendsWithBeerDB.runQuery(sql, function(records) {

});
}
}

26. Inside the runQuery callback function, loop through the properties of
the first record that was returned from the database query, transferring
the values from the query result into the form.
loadRecord: function() {
if (this.friendId != null) {
var sql = "select * from friend where id = {0}";
sql.format(this.friendId);
FriendsWithBeerDB.runQuery(sql, function(records) {
var rec = records[0];
for (var i in rec) {
$("#" + i).val(rec[i]);
}
});
}
}

27. Immediately after the for-loop that you entered in the prior step, refresh
the beerId select menu.
$("#beerId").selectmenu("refresh", true);

Invoke the loadRecord() method


28. Inside the ContactForm.init() method, invoke the
ContactForm.loadRecord() method.
init: function() {

this.initialized=true;
this.populateBeerField();
this.initValidation();
this.loadRecord();
var me = this;
$("#btnSave").bind("tap", function(e) {
me.submitForm();
});
}

5 - 26
2013 Intel Corporation.
Creating Input Forms
29. Save the file.
30. Test the application. You should now be able to edit existing contact
records.

End of Walkthrough --

5 - 27
2013 Intel Corporation.
Fast Track to Intel XDK New

Unit Summary
Intel XDK New and jQuery Mobile support all HTML5 form element
types.
jQuery Mobile replaces standard checkbox, radio button, and select
field controls with controls that have been optimized for a mobile
device.
Native HTML5 form field validation is not supported by most mobile
browsers.
You can easily adapt the jQuery Validation Plugin to work with jQuery
mobile.
The jQuery Validation Plugin supports validating basic patterns
including email address, required data input, string length, numeric
input, and more.
You can persist data in memory, transmit form information to an
application server, or store it in WebSQL or HTML5 localStorage.

5 - 28
2013 Intel Corporation.
Creating Input Forms

Unit Review
1. The name and id properties of an input field should always be identical
(true/false)

2. Which method do you invoke in order to get the value of a form field?

3. Which method do you invoke in order to set the value of a form field?

4. You must call the refresh method of a text input field after changing its
value (true/false)

5. Which method can you invoke to easily combine the values from all of
your form fields in order to transmit them to a server?

6. What are the relative advantages/disadvantages to storing information


locally in WebSQL instead of posting it to an application server?

7. Describe how to populate a <select> control with options that are read
dynamically from an application server.

5 - 29
2013 Intel Corporation.
(This page intentionally left blank)
Unit 6:
Adding GEO Features

Unit Objectives
After completing this unit, you should be able to:
Load the Google API
Instantiate a map
Programmatically geocode an address from data input by the user
Programmatically center a map and understand the basic Google map
configuration options
Add overlays to a map

Unit Topics
Getting Started with Google Maps
Deploying a Simple Map
Programmatically Geocoding Addresses
Adding Overlays and Map Markers

6-1

2013 Intel Corporation.


Fast Track to Intel XDK New

Getting Started with Google Maps


The Google Maps Javascript API is a free service that lets you embed
Google Maps in your own web pages. Version 3 of the API was
specifically designed to support mobile devices as well as traditional
desktop browser applications. It includes a number of utilities for
manipulating maps and adding content to the map through a variety of
collateral services.

To facilitate the integration of Google Maps into a jQM-based app, use the
Google Maps v3 plug-in for jQuery and jQM, available at
http://code.google.com/p/jquery-ui-map/.

Working with the Google Maps Javascript API

The Google Maps Javascript API V3 now comes in three different


versions. All versions support the same features, however, they are limited
in the number of requests that they will process during a 24-hour period.
In the current model each of these API versions is limited to a number of
Page Views a day and a max number of queries per second (QPS). Google
considers a Page View to be an instance of the Maps Javascript API
being loaded in the browser or a single request for a static map. It is
important to note that the API contains many different web services and
that making request to those collateral services (e.g. the Google Geocoding
service) will also count against your Page View limit.
Page View Limitations for the Google Maps Javascript API V3 are as
follows:
1. The Free Version Limited to 1000 Page Views a day per
individual IP address, across all services
2. Purchased Key Version Users of the API can purchase an
overall daily Page View quota, that is not limited by IP address
3. Google Maps for Business API 100,000 Page Views a day per
each different service all different API services:
Directions API
Distance Matrix API
Elevation API
Geocoding API
Places API
Regardless of whether you use the free or paid-for versions of the API you
will be limited to a maximum of 10 queries per second per API. You can
purchase more bandwidth on an as-needed basis.

6-2
2013 Intel Corporation.
Adding GEO Features

Using the Purchased Key Version of Google Maps

The free version of Google Maps v3 enables you to load the API using the
following syntax:
<!--- load maps API --->
<script type="text/javascript"
src="http://maps.googleapis.com/maps/api/js?
sensor=SET_TO_TRUE_OR_FALSE">
</script>

However, if you wish to track map usage or you need a larger number of
daily Page Views then utilizing the Purchased Key Version. API keys are
tied to both your Google account and the domain name from where your
application will be hosted. The process to obtain an API key can be found
at the following URL:

https://developers.google.com/maps/documentation/javascript/tutorial#api_
key
As noted in the instructions, you are allowed to use the key from any
domain, but it is strongly encouraged to restrict the usage from the
domain(s) you manage.

Your Purchased Key license comes with the following restrictions:


1. 25,000 per Page View per day limit on map loads.
2. The Maps API does not include advertising.
3. Your service must be freely accessible to end users. Read terms of use
for details governing this.
4. You may not alter or obscure the logos or attribution on the map.
5. Maps should not be used to display illegal activity or reveal personal
information

6-3
2013 Intel Corporation.
Fast Track to Intel XDK New

Working with the Purchased Key Version of Google Maps

When you sign up for a paid API key, you'll be prompted to register a new
Project ID. This allows multiple Google services to be tied to a single
project/API key for tracking purposes.

Figure 1: Registering a Google Map project


After registering you'll be presented with the following screen which
contains your API key.

Figure 2: Generating the Google Maps API Key

Take the API key and inject it into the script tag that loads the maps API as
illustrated below:
<!--- load maps API --->
<script type="text/javascript"
src="http://maps.googleapis.com/maps/api/js?
key=YOUR_API_KEY&sensor=SET_TO_TRUE_OR_FALSE">
</script>

For additional licensing information, please see:


https://developers.google.com/maps/documentation/javascript/usage

6-4
2013 Intel Corporation.
Adding GEO Features

Deploying a Simple Map


Deploy a Google map in your app by completing the following steps:
Load the Maps JavaScript library
Load the plug-in for jQuery and JQM
Position your map on a page
Place a marker on your map that identifies a location

Loading the Google Maps API

The following is a simple example of loading the Google Maps Javascript


API V3:
<!--- load maps API --->
<script type="text/javascript"
src="http://maps.googleapis.com/maps/api/js?
key=3474828372366&sensor=FALSE">
</script>

As explained previously, Google Maps Javascript API V3 now allows you


to implement a mapping solution without requiring an API key. If you are
using an API Key is it important to note the following:
If Maps services are restricted to a specific set of domains, and the
load request if performed from a domain that is NOT in that set,
you will receive errors upon calling any function from the library.
You must specific true or false for the sensor URL parameter,
depending on if the device has Geospatial System (GS) capabilities
or not. You should set this to TRUE for mobile apps..
For cases where you are using the Free Version of the Google Maps
Javascript API V3, the following call would suffice for most solutions:
<!--- load maps API --->
<script type="text/javascript"
src="http://maps.googleapis.com/maps/api/js?
&sensor=FALSE">
</script>

6-5
2013 Intel Corporation.
Fast Track to Intel XDK New

Loading the Google Maps V3 plugin for jQuery and JQM

The Google Maps V3 plug-in for jQuery and JQM is a very flexible, highly
customizable, lightweight (3.2kB or 3.9kB for the full) library One of its
best features is that you can populate a map from microformats, RDFa or
micro-data on your site, which can be used as a fallback if a user doesn't
have Javascript enabled.
The plug-in is well-documented and acts as an abstraction library for the
most commonly used functionality available from Google Maps. The
jQuery Google Maps plug-in documentation integrates links to Google
Maps Javascript V3 APIs, classes and methods, shortening the learning
curve for including Google Maps in a mobile web app.

The Google Maps V3 plug-in for jQuery and JQM comes with a variety of
libraries, in both full source and minified versions. Depending on your
implementation you may use one or more of these:
jquery.ui.map.js Main library file
jquery.ui.map.extensions.js Used with Geocoding
jquery.ui.map.microdata.js Used for microdata
implementations
jquery.ui.map.microformat.js Used with microformats
jquery.ui.map.overlays.js Used with shapes and KML
jquery.ui.map.rdfa.js Used with RDFa data
jquery.ui.map.services.js Used with Directions and Street view
Each of these libraries has an associated minified version for you to work
with. When implementing for JQM you will use a special minified version
of the main library file jquery.ui.map.full.min.js.
To handle the most basic of map implementations your to implement the
plug-in will look like the following:
<!--- Google Maps / JQuery Plugin --->
<script type="text/javascript"
src="ui/jquery.ui.map.full.min.js">
</script>

6-6
2013 Intel Corporation.
Adding GEO Features

Placing your map on a page

You can instantiate a map into any HTML element that has a unique
identifier (typically a <div>). The map will conform to the defined size of
the container. A typical map container would resemble the following:

<div id="map_canvas"></div>

In order to style the map you will either provide in-line styles for the
<div> tag or provide some parameters for the div to constrain the size. In
this example, you could include a <style> block at the top of the file, or
place the style within a CSS file. The entry for the ID 'map_canvas' could
look like this:
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0; padding: 0 }
#map_canvas { width: 100%; height: 380px }
</style>

When implementing for mobile you will want pay particular attention to
the map canvas parameters. Depending on how the styles have been
implemented with the application you may have to push the map into a
fixed height.

Instantiating a map with the JQM Google Maps plugin typically requires
you to call a constructor named gmap() as illustrated below. Note the use
of #map_canvas which is used to point the map to our map_canvas
<div> and the use of the mapOptions variable to set some basic
parameters for the map,.
<!-- loading a Google Map using jQuery -->
<script type="text/javascript">

var mapOptions = {
'center': '38.986000000, -76.940131000',
'zoom': 15,
disableDefaultUI: false
};

$('#map_canvas').gmap({
center: mapOptions.center,
mapTypeId: google.maps.MapTypeId.SATELLITE,
zoom: mapOptions.zoom,
disableDefaultUI: mapOptions.disableDefaultUI
});
</script>

6-7
2013 Intel Corporation.
Fast Track to Intel XDK New

Setting Options for your Map

The Google Maps Javascript API Map class supports over 30 different
configuration properties, generally referred to as MapOptions. A full
listing can be found here:
https://developers.google.com/maps/documentation/javascript/reference#M
apOptions
At a minimum, the following options must be included when instantiating
a new Map object:
zoom (type int) max zoom value is 19
mapTypeId indicates the type of map to display
center center point on the map, in
Latitude/Longitude

Refreshing the Map

In some user-cases, as illustrated by Figure 3, your


map may only partially instantiate. To handle this
glitch, invoke the gmap refresh() method after a brief
delay to allow the map to initialize.
var loc = new google.maps.LatLng(
"38.908696", "-77.036527");

$mapContainer.gmap({
center: loc,
zoom: 16, Figure 3: Partially
mapTypeId:google.maps.MapTypeId.SATELLITE rendered map.
});

setTimeout("$('#map').gmap('refresh')",500);

6-8
2013 Intel Corporation.
Adding GEO Features

Geocoding a starting position

One of the most important MapOptions is the the center option. This
option gives the map its starting center latitude and longitude coordinates.
You can manually geocode a starting address by going to http://geocoder.us

Figure 4: Manually convert street addresses to lat/lng positions

Using Different Map Types

One of the main features of Google Maps are the different map types. In
the example below we used a MapOption called MapTypeID to name of
the map type displayed. These are defined in the Google API
documentation as follows:
ROADMAP (Default) - displays the normal, default 2D tiles of
Google Maps.
SATELLITE - displays photographic tiles.
HYBRID - displays a mix of photographic tiles and a tile layer for
prominent features (roads, city names).
TERRAIN - displays physical relief tiles for displaying elevation and
water features (mountains, rivers, etc.).
The value of the map type is case sensitive and coincides with the different
map types you can choose from the standard maps UI.
<!-- Instantiating a map using the Satellite Map type -->

$('#map_canvas').gmap({
'center': mapOptions.center,
'mapTypeId': google.maps.MapTypeId.SATELLITE,
'zoom': mapOptions.zoom,
'disableDefaultUI': mapOptions.disableDefaultUI
});

6-9
2013 Intel Corporation.
Fast Track to Intel XDK New

Customizing the look/feel of a map

Another set of commonly used MapOptions are the controls. Google Maps
allows you to customize the various controls within your maps. In our
example on the previous page we set the disableDefaultUI option to false.
This enables the zoom, map type, and street view controls by default.
Other supported controls, which allow you more granularity, include the
following:

Property Description

streetViewControl Boolean. The initial enabled/disabled state of the


Street View control. This control is part of the
default UI, and should be set to false when
displaying a map type on which the Street View
road overlay should not appear (e.g. a non-Earth
map type).

panControl Boolean. The enabled/disabled state of the Pan


control.

scaleControl Boolean. The initial enabled/disabled state of the


Scale control.

mapTypeControl Boolean. Buttons that let the user toggle between


map types (such as Map and Satellite). There are
several levels of sub options for controlling the
position and style if the map type controls that can
be defined here.

overviewMapControl Boolean. A collapsible overview map in the corner


of the screen

6 - 10
2013 Intel Corporation.
Adding GEO Features

Walkthrough 6-1: Getting Started with Maps


In this walkthrough you will manually geocode
an address and center a map on that location
using the JQM Plug-in and Google Maps
Javascript API V3.

Steps

Open the Project


1. Open Intel XDK New
2. Click on the word PROJECTS in the top-
left corner of the GUI.
3. Click the Open a Project button.
4. Select the following file:
/ftIntelXdkNew/walk/walk6_1/walk6_1.xdk

Manually Geocode a Location


5. Open a web browser to http://geocoder.us
6. Enter your address and click search.
7. Note the latitude and longitude of your address.

Load Google Maps and the Google JQM Maps Plugin


8. Open index.html in code view.
9. Where indicated by the comment, insert the script declarations to
initialize the Google Maps Javacript API V3 library. Your code should
resemble the following:

<script type="text/javascript"
src="http://maps.googleapis.com/maps/api/js?
sensor=true></script>

10. After the code that you inserted in the prior step, add a <script> tag
that loads the jQuery Google Map plugin.

<script type="text/javascript"
src="js/jquery.ui.map.js"></script>

Reserve a Space for the Map


11. Open contactdetail.html in Design mode.
12. From the Controls > Layout palette, drag a ROW widget and drop it
onto the middle of the Design Canvas

6 - 11
2013 Intel Corporation.
Fast Track to Intel XDK New

13. From the Controls > Layout palette, drag a ROW widget and drop it
directly underneath the row that you inserted in the prior step.
14. Go to Code view.
15. Locate the markup that was generated for the second row widget and
add an id property with a value of map as illustrated below:
<div class="grid grid-pad urow uib_row_2 row-height-2"
data-uib="layout/row"
id="map">

16. Save the file.

Render the Map


17. Open index.html in code view. Note that a ContactDetail object has
been defined for you.
18. Inside the ContactDetail object, define an init() method.
19. Inside the init() method, define a local variable named $mapContainer
that points to the map row that you defined in step 15.
var $mapContainer = $("#map");

20. After the code that you inserted in the previous step, use the gmap()
method to instantiate a map that's centered on the lat/lng position that
you noted from step 7.
21. Review your code to ensure that it appears similar to the following:
var ContactDetail = {
friendId: null,
gMap: null,
init: function() {
var $mapContainer = $("#map");
this.gMap = $mapContainer.gmap({
center: new google.maps.LatLng ("38.908696",
"-77.036527"),
zoom: 16
});
}
}

22. Save the file.

Invoke the ContactDetail Page


23. In the Contacts.displayList() method, modify the tap event listener for
the friendsList list items to load the contactDetail.html page. Your code
should appear as follows:
$('#friendsList li').bind('tap', function(e) {
ContactForm.friendId = this.getAttribute('data-value');
ContactDetail.friendId = ContactForm.friendId;
$.mobile.changePage('contactdetail.html');
});

24. Save the file and test. Tapping on a list item should display a small
sliver map on the ContactDetail page.

6 - 12
2013 Intel Corporation.
Adding GEO Features
Adjust Map Rendering
25. Return to index.html in CODE mode.
26. At the bottom of the ContactDetail.init() method, use jQuery to set the
height of the map to be the height of the document body minus 300
pixels (to account for the header, footer, and top row).
$mapContainer.height ($("body").height() - 200);

27. Save the file and test in the Emulator. You should see a larger map,
however that still doesn't quite render correctly.
28. Return to index.html in CODE mode.
29. At the bottom of the ContactDetail.init() method, insert a setTimeout()
method that refreshes the map after 500 milliseconds.
setTimeout("$('#map').gmap('refresh')",500);

30. Save the file and test the application in the emulator.

End of Walkthrough --

6 - 13
2013 Intel Corporation.
Fast Track to Intel XDK New

Programmatically Geocoding Addresses


In order to plot a position on a map, you must know its geocode, or
latitude/longitude. You can programmatically determine the geocode of an
address by using the geocode() method of the google.maps.Geocoder
object. Note the following:
The use of the geocode() method is restricted daily based on your
Google Maps API license levels.
For best results, store geocodes of specific locations in your
database. Note that Google's license terms specifically forbid
storing positions generated by Google's geocoder in a database.
When calling the geocode() method, you must specify a callback
function that will receive the calculated coordinates
The geocode() method is called asynchronously. As such you will
not be able to pass variables out of the callback function. If you
need to pass the coded data out you will need to chain your
functions together.
The latitude/longitude is returned within a geometry structure
within a results array. You can access the information by calling
the lat() and lng() methods..

In the following example illustrates Geocoding and address and storing the
resulting lat/long into a variable. The map is then centered on the specified
position.

<!-- get lat and lng of address -->

var geocoder = new google.maps.Geocoder();


geocoder.geocode(
{
address : '1600 Pennsylvania Ave Washington DC'
},
function(results, status) {
var location;
if(status != google.maps.GeocoderStatus.OK) {
alert("Address not found");
} else {
location = results[0].geometry.location;
}
$('#map_canvas').gmap({
center: location,
zoom: 15,
disableDefaultUI: false
});
});

6 - 14
2013 Intel Corporation.
Adding GEO Features

Walkthrough 6-2: Geocoding Addresses


In this walkthrough you will programmatically
geocode your contact's address.
Define disabled input fields
Attach event listeners to form fields
Geocode a street address

Steps

Open the Project


1. Open Intel XDK New
2. Click on the word PROJECTS in the top-left corner of the GUI.
3. Click the Open a Project button.
4. Select the following file:
/ftIntelXdkNew/walk/walk6_2/walk6_2.xdk

Add Buttons to the ContactDetail Page


5. Open contactdetail.html in Design mode.
6. Add a back button to the page header by dragging a Button widget
from the Controls > Forms panel and dropping it on the leftmost
position of the header toolbar.
7. Configure the following Button properties:
Label: Back (unchecked)
Icon: ui-icon-back (checked)
Icon Position: icon only
8. Go into code view and add the following property to the Back
button:
data-rel="back"

9. Return to Design mode.


10. Add an Edit button to the page header by dragging a Button widget
from the Controls > Forms panel and dropping it on the right-most
position of the header toolbar.
11. Configure the following Button properties:

Label: Edit (unchecked)


Icon: ui-icon-edit (checked)
Icon Position: icon only

6 - 15
2013 Intel Corporation.
Fast Track to Intel XDK New

Geocode the Address


12. Go to code view and add the following property to the edit button's
anchor tag:

href=contactform.html
13. Save the file and test the application in your emulator.

Geocode the Address


14. Open index.html in Code mode.
15. Add a method to the ContactForm object named geoCode.
16. Inside the geoCode function, create a variable named geocoder that
instantiates the Google Maps Geocoder object.
var geocoder = new google.maps.Geocoder();

17. Directly under the code that you inserted from the prior step, call the
geocoder.Geocode method, passing it the address and zip code that the
user entered in the form.
geoCode: function() {
var geocoder = new google.maps.Geocoder();
geocoder.geocode({
address : $('#address').val() + " " + $('#zipcode').val()
}, function(results,status) {

});
}

18. Inside the geocoder callback function, insert code to populate the lat
and lng text fields with the resulting geocode data. If the geocding
failed, set the values of the lat and lng field to the empty string. Your
code should appear similar to the following:
geoCode: function() {
var geocoder = new google.maps.Geocoder();
geocoder.geocode({
address : $('#address').val() + " " + $('#zipcode').val()
}, function(results,status) {
if(status != google.maps.GeocoderStatus.OK) {
alert("Address not found");
$("#lat").val('');
$("#lng").val('');
} else {
$("#lat").val(results[0].geometry.location.lat());
$("#lng").val(results[0].geometry.location.lng());
}
});
}

6 - 16
2013 Intel Corporation.
Adding GEO Features

Attach Event Listeners to the Address and ZipCode


Fields
19. At the bottom of the ContactForm.init() method, create event listeners
for the change event on the address and zipcode fields that fire the
geocode method.
$("#address").bind("change", this.geoCode);
$("#zipcode").bind("change", this.geoCode);

20. Save the file and test the app in the Emulator. Editing a contact record
should cause the address to be geocoded with the results getting placed
into the lat/lng input fields.

-- End of Walkthrough --

6 - 17
2013 Intel Corporation.
Fast Track to Intel XDK New

Adding Overlays and Map Markers


Overlays are map objects that indicate points, lines, areas, or objects which
are tied to specific lat/lng coordinates. There are a number of canned
overlays, such as the Google Maps Traffic Layer, that you can easily add to
your map. Map markers, identifying specific positions on your map, are a
form of custom overlay.

Using Overlays

Google Maps enables you to add transparency layers to your map that
visualize the following datasets:

Layer Description

KmlLayer Renders KML and GeoRSS elements into a Maps


API V3 tile overlay.

HeatmapLayer Renders geographic data using a Heatmap


visualization

FusionTablesLayer Renders data contained in Google Fusion Tables.

TrafficLayer Renders a layer depicting traffic conditions and


overlays representing traffic.

TransitLayer Displays the public transport network of your city


on the map.

WeatherLayer and Allow you to add weather forecasts and cloud


CloudLayer imagery to your map.

BicyclingLayer Renders a layer of bike paths and/or bicycle-


specific overlays into a common layer. This layer is
returned by default within the DirectionsRenderer
when requesting directions of travel mode
BICYCLING.

PanoramioLayer Adds photos from Panoramio as a layer.

DemographicsLayer Renders United States demographic information as


a layer, and is available to Google Maps API for
Business customers only. It is contained within the
visualizationlibrary.

6 - 18
2013 Intel Corporation.
Adding GEO Features

Displaying the Current Traffic Conditions

Instantiate the traffic layer using the google.maps.TrafficLayer()


constructor. In order to apply it to a map, you must call the setMap()
method of the resulting object.
The following code snippet illustrates how to add traffic map overlay to a
Google Map. Note that the use of the callback method which receives a
pointer to the google map instance created by the jQuery Maps plugin.
var $mapContainer = $("#map");

$mapContainer.gmap({
center: new google.maps.LatLng ("38.908696", "-77.036527"),
zoom: 16,
callback: function(map) {
var trafficLayer = new google.maps.TrafficLayer();
trafficLayer.setMap(map);
}
});

Displaying the Panoramio Layer

Loading the Panoramio layer requires you to modify the url of the <script>
tag that loads the Google Maps API as illustrated by the following
example:
<script
src="https://maps.googleapis.com/maps/api/js?
v=3.exp&sensor=true&libraries=panoramio">

</script>

With the Panoramio version of the Google Maps API loaded, it becomes a
simple matter to instantiate the map with local photos:

var $mapContainer = $("#map");

$mapContainer.gmap({
center: new google.maps.LatLng ("38.908696", "-77.036527"),
zoom: 16,
callback: function(map) {
var trafficLayer = new google.maps.TrafficLayer();
trafficLayer.setMap(map);

var pl = new google.maps.panoramio.PanoramioLayer();


pl.setMap(map);
}
});

6 - 19
2013 Intel Corporation.
Fast Track to Intel XDK New

Adding Map Markers

Markers identify points on a map and inherit from the same base class as
overlays. They are assigned a position on a map, and can be assigned a
number of properties, including tooltips and custom icons for display.
Using the Google Maps plug-in for jQuery and JQM you can add a marker
to an existing map with the following block of code:
$('#map_canvas').gmap('addMarker', {
position: '42.345573,-71.098326',
bounds: false
});

Note the following:


The position attribute determines where the marker should be placed
on the map.
The bounds attribute identifies whether or not you want the map to
automatically zoom in on the marker when the marker is instantiated.

Adding a Marker to the Center of the Map

In most use-cases, you'll want to place a maker on the map to identify the
center point. As illustrated by the following code snippet, you can easily
implement this in the callback handler that executes during the map
instantiation process.
var $mapContainer = $("#map");

$mapContainer.gmap({
center: new google.maps.LatLng ("38.908696", "-77.036527"),
zoom: 16,
callback: function(map) {
var trafficLayer = new google.maps.TrafficLayer();
trafficLayer.setMap(map);

var pl = new google.maps.panoramio.PanoramioLayer();


pl.setMap(map);

this.addMarker({
position: map.getCenter()
})
}
});

6 - 20
2013 Intel Corporation.
Adding GEO Features

Walkthrough 6-3: Defining Markers


In this walkthrough you will change your
map instantiation to center the map on your
friend's location and display a map marker.
Retrieve data from a WebSQL database
Center the map on a lat/lng position that
was saved to a WebSQL database
Add a marker to the map

Steps

Open the Project


1. Open Intel XDK New
2. Click on the word PROJECTS in the
top-left corner of the GUI.
3. Click the Open a Project button.
4. Select the following file:
/ftIntelXdkNew/walk/walk6_3/walk6_3.xdk

Retrieve and Cache Contact Information from WebSQL


5. Add the following properties to the ContactDetail object:
contactData
mapCenter
6. Inside the init() method, define a local variable named me and set it
equal to the ContactData object.
var me = this;

7. At the end of the init() method, use WebSQL to retrieve the


information for the friend whose primary key value is stored in the
ContactDetail.friendId property.
FriendsWithBeerDB.runQuery(
"select * from friend where id = " + this.friendId,
function(records) {

}
);

8. Inside the WebSQL callback function, set the


ContactDetail.contactData property equal to the record that was
returned from the sql query.
me.contactData = records[0];

6 - 21
2013 Intel Corporation.
Fast Track to Intel XDK New

9. After the code that you inserted in the prior walkthrough, set the
ContactDetail.mapCenter property equal to the a Google LatLng object
that's set to the lat/lng position retrieved from the database query.
me.mapCenter = new google.maps.LatLng (
records[0].lat, records[0].lng
);

10. Invoke the initMap() method from the WebSQL function callback.

Center the Map and Add Overlays


11. Inside the ContactDetail.initMap() method, configure the map instance
to center on ContactDetail.mapCenter.
this.gMap = $mapContainer.gmap({
center: this.mapCenter,
zoom: 16
});

12. Inside the $mapContainer.gmap() configuration object, add a callback


method.
this.gMap = $mapContainer.gmap({
center: this.mapCenter,
zoom: 16,
callback: function(map) {

}
});

13. Inside the callback function, instantiate the traffic and panoramio
layers and apply them to the map.
this.gMap = $mapContainer.gmap({
center: this.mapCenter,
zoom: 16,
callback: function(map) {

var trafficLayer = new google.maps.TrafficLayer();


trafficLayer.setMap(map);

var panoramioLayer = new


google.maps.panoramio.PanoramioLayer();
panoramioLayer.setMap(map);

}
});

6 - 22
2013 Intel Corporation.
Adding GEO Features

Add a Marker to the Map


14. At the bottom of the map instance callback function, add a map marker
to the center of the map.
this.gMap = $mapContainer.gmap({
center: this.mapCenter,
zoom: 16,
callback: function(map) {
me.map = map;
var trafficLayer = new google.maps.TrafficLayer();
trafficLayer.setMap(map);
var panoramioLayer = new
google.maps.panoramio.PanoramioLayer();
panoramioLayer.setMap(map);
this.addMarker({
position: map.getCenter()
});
}
});

15. Save the file and test in the emulator using a friend record that has
been successfully geocoded.

-- End of Walkthrough --

6 - 23
2013 Intel Corporation.
Fast Track to Intel XDK New

Unit Summary
There are multiple licensing options for the Google Maps Javascript
API V3, including a paid for subscription model
Use the JavaScript loader to dynamically load Google API's at runtime
To facilitate using Google Maps with jQuery and JQM you can use the
Google Maps V3 plugin for jQuery and jQuery Mobile
Use the google.maps.Map() object to instantiate maps on your pages in
basic Javascript
Use $(#map_canvas).gmap() to instantiate maps using the plugin for
jQuery mobile
Use jQuery to loop through a returned dataset to programmatically
populate a map overlay components.
Create map markers using the google.maps.Marker() or addMarker()
and assign them to overlays

6 - 24
2013 Intel Corporation.
Adding GEO Features

Unit Review
1. What do you need to get started using the Google Maps API?

2. Describe the process for placing a map on a web page

3. Describe the steps for geocoding an address

4. What are the types of overlays that you can place on a Google Map?

5. You cannot configure the look of a map marker? (true/false)

6 - 25
2013 Intel Corporation.
(This page intentionally left blank)
Unit 7:
Using Device Features

Unit Objectives
After completing this unit, you should be able to:
Retrieving the device's current location
Programmatically activate the phone dialer
Launch the device's email client with the subject, body, and to: fields
pre-filled
Prompt the user to launch the device's built-in navigation app
Create an event listener for the accelerometer so that an action is
performed when the user shakes their device.
Listen for push notifications

Unit Topics
Retrieving the Device's Current Location
Launching the Phone, Email, and Navigation Apps
Listening to the Accelerometer
Listening for Push Notifications

7-1

2013 Intel Corporation.


Fast Track to Intel XDK New

Retrieving the Device's Current Location


Use the navigator.geolocation class to retrieve the user's current position
from its GPS sensor.

Getting the Latitude and Longitude

As illustrated by the following code sample, determining a device's


position is an asynchronous event due to the latency associated with
locating the proper satellites from which to calculate a "fix". When the
position of the device has been calculated, the callback handler will be
executed.
Note that you should always provide an error handler as this feature may
fail if the user moves to a location where line-of-sight to the satellites and a
wifi connection are both unavailable.
navigator.geolocation.getCurrentPosition(

function(position) {
var pos = new google.maps.LatLng(
position.coords.latitude,
position.coords.longitude);
},

function (error) {
var msg = "";
switch(error.code) {
case error.PERMISSION_DENIED:
msg="User denied the request for Geolocation."
break;
case error.POSITION_UNAVAILABLE:
msg="Position is unavailable."
break;
case error.TIMEOUT:
msg="The GPS request timed out";
break;
case error.UNKNOWN_ERROR:
msg = "An unknown error occurred getting your position"
break;
}
alert(msg);
}
);

7-2
2013 Intel Corporation.
Using Device Features

Retrieving Additional Information from the GPS Sensor

In addition to the latitude and longitude, most device browsers will also
return the following information as properties of the position.coords object.

Property Description

accuracy The accuracy of the position

altitude The altitude (in meters) above sea level

altitudeAccuracy The accuracy of the altitude query

heading The user's heading, specified in degrees clockwise from


North

speed The speed (in meters per second)

timestamp The date/time of the last successful request

Calculating Distance to Target

You can calculate the distance between two points by using either the
Haversine formula or the Spherical Law of Cosines. The following
function represents a JavaScript implementation of the Haversine formula:

var calcDistance = function(lat1,lng1,lat2,lng2) {

var R = 3959; // use 3959 for miles or 6371 for km


var dLat = (lat2-lat1) * Math.PI / 180 ;
var dLon = (lng2-lng1)* Math.PI / 180;
var lat1 = lat1 * Math.PI / 180;
var lat2 = lat2 * Math.PI / 180;

var a = Math.sin(dLat/2) * Math.sin(dLat/2) +


Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) *
Math.cos(lat2);

var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

return R * c;

7-3
2013 Intel Corporation.
Fast Track to Intel XDK New

Enabling Permissions to Access the GPS Sensor

As illustrated in Figure 1, you will need to turn on permissions to the GPS


sensor prior to producing a native build. Android apps that attempt to
access the gps sensor without the proper permissions will fail silently.

Figure 1: Configuring GeoLocation Permission

7-4
2013 Intel Corporation.
Using Device Features

Walkthrough 7-1: Getting the Device Location


In this walkthrough you will get the device's
current position and calculate the distance
between the device and your selected friend.
Implement a multi-column layout
Format WebSQL data using a Template
Get the device's current position
Calculate range to target

Steps

Open the Project


1. Open Intel XDK New
2. Click on the word PROJECTS in the top-
left corner of the GUI. Figure 2: Output contact
info and distance to
3. Click the Open a Project button. target.
4. Select the following file:
/ftIntelXdkNew/walk/walk7_1/walk7_1.xdk

Modify the Contact Detail Layout


5. Open contactdetail.html in Design mode.
6. From the Controls > Layout palette, drag a
Column widget and drop it to the left of
the top row of page layout.
7. Drag the left column's right-divider to the
right until your layout appears similar to
Figure 3.
Figure 3: ContactDetail
8. Go to Code View page layout
9. Add an id=contactdetails property to the column that you just added.
Your code should resemble the following:
<div class="col uib_col_4 col-0_6-12" data-uib="layout/col">
<div class="widget-container content-area vertical-col"
id="contactdetails">
<span class="uib_shim"></span>
</div>
</div>

10. Save the file

7-5
2013 Intel Corporation.
Fast Track to Intel XDK New

Output Contact Information


11. Open index.html in Code view.
12. Where indicated by the comment, define a template that contains
placeholders for the contact's first name ({0}), last name ({1}), address
({2}), and favorite beer ({3}) as well as a <span> tag from where the
distance will be output.
<script type="text/template" id="tplContact">
<div class="contactname">{0} {1}</div>
<div class="contactaddress">{2}</div>
<div class="contactdistance">{3} is only <span
id="distancetofriend"></span> away!</div>
</script>

13. Define a method in the ContactDetail object named outputDetails().


14. Inside the outputDetails() method, define a local variable named
tplContact that contains the html from the template that you defined
from step 12.
var tplContact = $("#tplContact").html();

15. After the code that you added in the prior step, define a local variable
named html that processes the contact's information through the
template.
var html = tplContact.format(
this.contactData.firstName,
this.contactData.lastName,
this.contactData.address,
this.contactData.beername
);

16. After the code that you inserted in the prior step, output the contents of
the html variable to the #contactdetails <div> element.
$("#contactdetails").html(html);

17. Where indicated by the comment, invoke the


ContactDetail.outputDetails() method.
18. Save the file and test in the emulator. Tapping on a contact name
should now display the contact's name, address, and favorite beer in an
area positioned immediately above the map.

Get the Device's Current Position


19. Return to index.html in Code mode.
20. Add an additional method named outputDistance() to the
ContactDetail object.
21. Inside the outputDistance() method, define a variable named me that
points to the current scope.
var me = this;

7-6
2013 Intel Corporation.
Using Device Features
22. Invoke the navigator.geolocation.getCurrentPosition() method,
defining success and error callback functions. Your code should
appear similar to the following:
navigator.geolocation.getCurrentPosition(
function(position) {

},
function(error) {

}
);

23. Inside the success callback function, convert the device's latitude and
longitude coordinates to a google maps lat/lng object and store the
resulting object into the ContactDetail.currentPosition property.
navigator.geolocation.getCurrentPosition(
function(position) {

me.currentPosition =
new google.maps.LatLng(
position.coords.latitude,
position.coords.longitude
);

},
function(error) {

}
);

24. After the code that you inserted in the prior step, define a local variable
named miles that contains the calculated distance between the device
and the selected friend.

Note: The calcDistance function is defined on line 102 of index.html


var miles = calcDistance(
me.mapCenter.lat(),
me.mapCenter.lng(),
position.coords.latitude,
position.coords.longitude
);

25. Immediately after the code that you inserted in the prior step, output
the value from miles into the <span id=contactdistance> element.
$("#distancetofriend").html(miles + " miles ");

26. Inside the error function callback, output an alert() that indicates that
an error occurred in retrieving the device's coordinates.
27. Where indicated by the comment inside of the ContactDetail.init()
method, invoke the outputDistance function.
28. Save the file and test. Tapping on a contact should now display the
distance between the device and the contact's address as illustrated by
the screenshot in Figure 2.
End of Walkthrough --

7-7
2013 Intel Corporation.
Fast Track to Intel XDK New

Launching the Phone, Email, and Navigation Apps


You can execute the device's phone dialer, email, and navigation apps by
programmatically setting location.href to a specially encoded url link as
illustrated below:
// launch mail-compose
location.href='mailto:sdrucker@figleaf.com';

Activating the Phone Dialer

Use the tel URL scheme to launch the device's phone dialer and initiate
dialing of the specified phone number. Whether or not the user is prompted
to dial or the dialing occurs automatically is dependent on the type of
mobile operating system being used.
The javascript syntax to activate the native Phone app is:
location.href="tel:555-555-5555";

Note that the iOS browser will automatically try to detect and hyperlink
strings that match a phone number pattern. You can disable this behavior
by adding the following meta tag to your html:
<meta name = "format-detection" content = "telephone=no">

Activating the Email Client

Use the mailto: url scheme to launch the mail app's compose feature and
programmatically fill the following fields:

Syntax Description

mailto: Receipient or recipients (comma-separated list)

&cc= The carbon copy recipients (comma-separated list)

&bcc= The blind carbon copy recipients (comma-separated list)

&subject The subject of the email, url encoded using JavaScript's


escape() method.

&body= The body of the message (including line breaks), url


encoded using Javascript's escape() method.

7-8
2013 Intel Corporation.
Using Device Features

To launch the mail client, dynamically assemble the url and


programmatically click it as illustrated by the following code snippet:
var mailLink = "mailto:{0}?subject={1}&body={2}";
mailLink = mailLink.format(
"sdrucker@figleaf.com",
escape("Can I come over now?"),
escape("Hey good buddy, can I come over?")
);
location.href = mailLink;

Branching your code for Turn-by-Turn Directions

The techniques for launching turn-by-turn directions in iOS and Android


vary significantly, therefore you'll need to branch your code by inspecting
the contents of the navigator.userAgent property as illustrated below:
if( /Android/i.test(navigator.userAgent) ) {

// android-specific code

} else if (/iPhone|iPad|iPod/i.test(navigator.userAgent)) {

// ios specific code

Activating the Navigation App on iOS

On iOS, the maps URL scheme can open the native Apple maps app to
show geographical locations as well as generate driving directions between
two points.
On iOS, maps links are specified using a special maps:// uri as illustrated
by the following snippet:

<a href="maps://?daddr=2000 K St 20036&saddr=santa clara,


CA">Directions</a>

You can pass the following parameters to the maps.apple.com url:

Argument Description

q This parameter is treated as if it had been typed into the


query box by the user in the Maps app

near Locates a position near the specified target

ll The latitude and longitude (comma-separated) for the


center point of the map.

7-9
2013 Intel Corporation.
Fast Track to Intel XDK New

Argument Description

sll The latitude and longitude (comma-separated) from where


a business search should be performed.

spn The approximate latitude and longitude span

t The type of map to display

z Zoom level

saddr The source address from which to generate driving


directions

daddr The destination address from which to generate driving


directions.

The following snippet illustrates how to generate a link that, when pressed,
would launch an iOS device's maps app with turn-by-turn directions:
var fromAddr = escape("1400 16th St NW 20036");
var toAddr = escape("2000 K St NW 20036");
var tpl='<a href="maps://?daddr={0}&saddr={1}">Click Me</a>'

location.href = tpl.format(fromAddr,toAddr);

Activating the Navigation App for Android Web Apps

Opening the navigation app on Android can be a little tricky since the
Android webview, which is used to drive native-apps functions slightly
differently than the native Android browser when it's running in standalone
mode.
If running your code as a web app, the browser will respond similarly to
the technique previously described for iOS devices you simply need to
specify the url for maps.google.com as illustrated below:
var fromAddr = escape("1400 16th St NW 20036");
var toAddr = escape("2000 K St NW 20036");
var tpl='<a href="http://maps.google.com/maps?
daddr={0}&saddr={1}">Click Me</a>'

location.href = tpl.format(fromAddr,toAddr);

You can also open the native Google Maps app by using the geo: uri. As
illustrated by the following use case, you can pass a latitude and longitude
as a comma-delimited list. The z argument indicates zoom level on a scale
of 1-23 where 1 is the whole earth and 23 is is the highest zoom level.
<a href="geo://?
saddr=20.544,34.34&daddr=20.866,45.345">Navigate!</a>

7 - 10
2013 Intel Corporation.
Using Device Features
Unfortunately, the Android WebView that is used to run your app in
native mode does not recognize that a maps.google.com url or the geo:
uri should be opened in an external app.

Launching Google Maps in the Cordova InAppBrowser

An alternative to launching the native Google


Maps app on the device is to launch the
maps.google.com web app inside of a
Cordova InAppBrowser.
The InAppBrowser is a web browser that
displays when you invoke the window.open()
method as illustrated below:
var fromAddr =
escape("1400 16th St NW 20036");
var toAddr =
escape("2000 K St NW 20036");

var tpl="http://maps.google.com/maps?
daddr={0}&saddr={1}";

var loc = Figure 4: The Cordova


tpl.format(fromAddr,toAddr); InAppBrowser
var ref = window.open(loc, '_blank', 'location=yes');

Activating the Navigation App for Native Android Apps

Another alternative is to use a Cordova plugin that enables you to launch


and Android intent. An intent is an abstract description of an operation to
be performed which can include launching an activity. In native Android
parlance, an activity is an app.

Detecting Native vs Web

if (document.URL.indexOf( 'http://' ) === -1 &&


document.URL.indexOf( 'https://' ) === -1) {

// PhoneGap application

} else {

// Web page

7 - 11
2013 Intel Corporation.
Fast Track to Intel XDK New

Walkthrough 7-2: Invoking External Apps


In this walkthrough you will enhance the
contactdetail view by adding buttons that
enable the user to telephone, email, or get turn-
by-turn directions to their friend with beer.
Add buttons to a UI
Create a function to programmatically
click a dynamic link
Use special urls to invoke external apps

Steps

Open the Project


1. Open Intel XDK New
2. Click on the word PROJECTS in the top-
left corner of the GUI. Figure 5: Add buttons to
3. Click the Open a Project button. dial, email, and navigate

4. Select the following file:


/ftIntelXdkNew/walk/walk7_2/walk7_2.xdk

Add buttons to the UI


5. Open contactdetail.html in Design mode.
6. From the Controls > Form panel, drag a BUTTON widget and drop it
on the top row, right-column of the page body in the canvas.
7. Configure the following Button properties:

Mini: checked
Icon: ui-icon-phone
Icon Position: Icon only
Id: btnPhone
8. From the Controls > Form panel, drag a BUTTON widget and drop it
onto the design canvas, directly underneath the btnPhone button.
9. Configure the following Button properties:

Mini: checked
Icon: ui-icon-mail
Icon Position: Icon Only
Id: btnMail
10. From the Controls > Form panel, drag a BUTTON widget and drop it
onto the design canvas, directly underneath the btnMail button.
7 - 12
2013 Intel Corporation.
Using Device Features
11. Configure the following Button properties:

Mini: checked
Icon: ui-icon-navigation
Icon Position: Icon Only
Id: btnNav
12. Save the file

Create an Event Listener for the Telephone Button


13. Inside the ContactDetail object, define a method named
configureButtons().
14. In the ContactDetail.init() method, invoke the
ContactDetail.configureButtons() function directly underneath the
outputDetails() invocation.
me.outputDetails();
me.configureButtons();
me.outputDistance();

15. Inside the ConfigureButtons() method, bind a tap event listener to the
btnPhone button so that it launches the user's phone application and
dials their friend's phone number when tapped.
16. Verify that your code appears similar to the following:
$("#btnPhone").bind("tap", function(e) {
var ph = ContactDetail.contactData.phone;
if (ph != "") {
var telLink = "tel:" + ph;
location.href=telLink;
} else {
alert("Phone Number Not Available");
}
});

17. Save the file.


18. Click on the Test tab.
19. Click the Push Files button
20. Launch Intel App Preview on your device, scan the QR code, and test
your app.

Create an Event Listener for the Email Button


21. Return to index.html in Code mode.
22. Underneath the code that you added in step 14, bind a tap event listener
to the btnMail button so that it launches the user's email application
and sets default subject and body text when tapped.

7 - 13
2013 Intel Corporation.
Fast Track to Intel XDK New

23. Verify that your code appears similar to the following:


$("#btnMail").bind("tap", function(e) {
var mailLink = "mailto:{0}?subject={1}&body={2}";
mailLink = mailLink.format(
ContactDetail.contactData.email,
escape("Can I come over now?"),
escape("Need to chat about something big!")
);
location.href = mailLink;
});

24. Launch Intel App Preview on your device, scan the QR code, and test
your app.

Create an Event Listener for the Nav Button


25. After the code that you inserted from step 22, bind a tap event listener
to the #btnNav button. Your code should appear similar to the
following:
$("#btnNav").bind("tap", function(e) {

});

26. Inside the event handler function, insert an if-elseif-else block that
determines whether the user is using an Android device or an iOS
device. If the device is not iOS or Android, output an alert message.

Your code should appear similar to the following:


$("#btnNav").bind("tap", function(e) {
if (/Android/i.test(navigator.userAgent)) {

} else if (/iPhone|iPad|iPod/i.test(navigator.userAgent)) {

} else {
alert('Device not supported');
return;
}
});

27. Inside the if() block for Android, define a local variable named
mapsUrl and set it equal to the google maps url with GET parameters
named daddr and saddr that point to lat/lng placeholders.
if (/Android/i.test(navigator.userAgent)) {
var mapsUrl = "http://maps.google.com/maps?daddr={0},
{1}&saddr={2},{3}";
}

7 - 14
2013 Intel Corporation.
Using Device Features

28. After the code that you inserted in the prior step, replace the
placeholders with the lat/lng coordinates of the contactData and
currentPosition properties of the ContactDetail object.
mapsUrl = mapsUrl.format(
ContactDetail.contactData.lat,
ContactDetail.contactData.lng,
ContactDetail.currentPosition.lat(),
ContactDetail.currentPosition.lng()
);

29. After the code that you inserted from the prior step, launch the url in an
inAppBrowser.
window.open(mapsUrl, '_blank', 'location=yes');

30. Inside the if() block for iOS, define a local variable named mapsUrl
and set it equal to the Apple maps url with GET parameters named
daddr and saddr that point to lat/lng placeholders.
if (/Android/i.test(navigator.userAgent)) {
var mapsUrl = "http://maps.google.com/maps";
} else if (/iPhone|iPad|iPod/i.test(navigator.userAgent)){
var mapsUrl = "maps://?daddr={0},{1}&saddr={2},{3}";
} else {
/* omitted for brevity */
}

31. After the code that you inserted in the prior step, replace the
placeholders with the lat/lng coordinates of the contactData and
currentPosition properties of the ContactDetail object.
mapsUrl = mapsUrl.format(
ContactDetail.contactData.lat,
ContactDetail.contactData.lng,
ContactDetail.currentPosition.lat(),
ContactDetail.currentPosition.lng()
);

32. After the code that you inserted in the prior step, launch the url by
setting the location.href property as illustrated below:
location.href = mapsUrl;

33. Save the file.


34. Click on the Test tab.
35. Click on Push Files.
36. Launch Intel App Preview on your device and test the app.

End of Walkthrough --

7 - 15
2013 Intel Corporation.
Fast Track to Intel XDK New

Listening to the Accelerometer


You can access a device's accelerometer through either JavaScript's
DeviceMotion API or, alternatively, via Cordova's Accelerometer support.
The DeviceMotion API enables you to listen for changes in the device's
orientation as well as changes in movement.
Browsers that currently support the DeviceMotion API include:

iOS Safari 4.2.1 (and above) BlackBerry PlayBook 2.0


Android 4.0.3 (default browser) Firefox for Android
Opera Mobile (Android) FirefoxOS Devices

Detecting Changes to Device Orientation

Before using the DeviceOrientation API, verify that the


DeviceOrientationEvent is supported by your browser as illustrated in the
following snippet:
if (window.DeviceOrientationEvent) {

// insert coolness here

} else {

alert("Aw, Snap! Can't determine device orientation");

You can subsequently add an event listener that is triggered whenever the
user's device changes orientation along different axes. In the following
example, the event handler simply outputs the orientation of the device to
the debugging console.
window.addEventListener('deviceorientation', function(e) {

var out = "alpha: {0}, beta: {1}, gamma: {2}";

console.log(out.format(
e.alpha,
e.beta,
e.gamma
));
});

Note the following:


alpha is the direction that the device is facing.
beta is the angle that the device is tilted from front-to-back.
gamma is the angle that the device is tilted left-to-right.

7 - 16
2013 Intel Corporation.
Using Device Features

Detecting Changes in Device Motion

Listen to the DeviceMotionEvent to poll for the rotation and acceleration


of the device.
Since support for this API varies, you should always verify that the event is
available by including the following code snippet:
if (window.DeviceMotionEvent) {

// bring the awesome here

} else {

alert("Aw, Snap! No shake gesture for you!");

Attach your event handler to the devicemotion event as illustrated below:

window.addEventListener('devicemotion', function(e) {

// get refresh interval:


// e.interval

// acceleration info:
// e.acceleration.x
// e.acceleration.y
// e.acceleration.z

// acceleration info including gravity:


// e.accelerationIncludingGravity.x
// e.accelerationIncludingGravity.y
// e.accelerationIncludingGravity.z

// rotation rate
// e.rotationRate.alpha
// e.rotationRate.beta
// e.rotationRate.gamma

}, false);

Using the Shake.js Library

The Shake.js library, developed by Alex Gibson (http://alxgbsn.co.uk/) and


available under an MIT license, gives you a high-level event that's fired
when the user shakes their device. You can set up the event listener by
simply loading his shake.js script and then listen for a shake event as
illustrated by the following snippet:
window.addEventListener('shake', shakeEventDidOccur, false);

7 - 17
2013 Intel Corporation.
Fast Track to Intel XDK New

Walkthrough 7-3: Listening for a Shake


In this walkthrough you will use the shake.js library to capture a shake
gesture and display information about a randomly selected friend.
Load the shake.js library
Review the devicemotion api
Configure an event listener

Steps

Open the Project


1. Open Intel XDK New
2. Click on the word PROJECTS in the top-left corner of the GUI.
3. Click the Open a Project button.
4. Select the following file:
/ftIntelXdkNew/walk/walk7_3/walk7_3.xdk

5. Open index.html in Code View.


6. Review the getRandomFriend() and handleAppShake() methods of
the App object.

Listen for a Shake Gesture


7. Where indicated by the comment, insert a <script> tag to load the
js/shake/shake.js file.
8. Open the js/shake/shake.js file and review its contents. Note that it uses
the DeviceMotion API.
9. Return to index.html in Code mode.
10. Inside the App.init() method, where indicated by the comment, listen
for a shake event. When triggered, invoke the App.handleshake()
method.
window.addEventListener(
'shake',
App.handleAppShake,
false
);

11. Save the file.

7 - 18
2013 Intel Corporation.
Using Device Features

Test Your Work


12. Test the app using Intel App Preview.

Note: this feature cannot be tested on the emulator at the current time
13. Run the app and shake your phone (be careful not to drop it!). Note
that shaking the phone selects a random friend and displays his/her
detail information.

End of Walkthrough --

7 - 19
2013 Intel Corporation.
Fast Track to Intel XDK New

Listening for Push Notifications


Push notifications transfer messages through a constantly open IP
connection to mobile devices. Notifications may include badges, sounds or
custom text alerts. They can play a vital role in increasing user
engagement.
Each mobile operating system vendor has a gateway from which
notifications are transmitted. You can build your own front-end to these
gateways or use a 3rd party push notification vendor. Typically these
vendors offer GUI and web-service based API's that enable you to target
specific groups of users based on metadata collected by your apps, their
current geographic position, username, and more.

Figure 6: Sending messages to devices from PushMobi

Vendors include, but are not limited to:


AppMobi Cloud Services (PushMobi)
Urban Airship
PushWoosh
Mixpanel
This course details how to receive push notifications from the PushMobi
service to Android devices.

7 - 20
2013 Intel Corporation.
Using Device Features

Registering your App to Receive Notifications

The first step to enabling push notifications is to enable push notification


support for each mobile platform via the BUILD tab in the Intel XDK.
Clicking on the PUSH tab, as illustrated by Figure 7, presents you with an
OS-specific form. Before you can proceed, you'll need to register your app
with the Google Cloud Messaging Service.

Figure 7: Configuring Push notification services for Android

7 - 21
2013 Intel Corporation.
Fast Track to Intel XDK New

Registering with the Google Cloud Messaging Service

In order to enable GCM for your app, you'll need to register your project in
the Google Cloud Console at http://cloud.google.com.

Figure 8: Enabling Google Cloud Messaging


After registering your project, you'll need to click on the APIs & Auth tab
and enable Google Cloud Messaging for Android as illustrated in Figure 8.

Registering the PushMobi App as the Client

Rather counter-intuitively, what you need to register in the next step of the
process is not your android app, but actually a web application since it's
actually the PushMobi service that will be communicating with the GCM
to send messages and PushMobi is a web-based application.

Figure 9: Registering the PushMobi front-end for Friends with Beer

7 - 22
2013 Intel Corporation.
Using Device Features

Getting the Necessary Credentials

In order to configure PushMobi to be able to communicate properly with


GCM, you'll need to retrieve two identifiers from the Google Cloud
Console:
The Web Application's Browser Key
The Project's Identifier
You can retrieve the first item by opening the Browser Key section of your
APIs Web Application detail page as illustrated by Figure 10.

Figure 10: Getting the Browser Key

Once you've copied the browser key to your clipboard, you must paste it
into the Api Key (5d) field in the Intel XDK Build > Push screen as
illustrated in figure 7.

7 - 23
2013 Intel Corporation.
Fast Track to Intel XDK New

The second piece of information the project's identifier, you can get by
clicking on your project's Overview tab as illustrated by figure 11. You'll
need to copy the Project Number and paste it into the Project Id (5C) field
as illustrated in Figure 7.

Figure 11: Getting the Project's ID

Using the intel.xdk.notification API

After you've configured the PushMobi service to communicate with the


Google Cloud Messenger gateway, you can add code to your app to listen
for push notifications and handle them when the occur.
The PushMobi client-side API registers a user (or device) with the push
service and listens for incoming messages. The code is largely boilerplate
and can be easily copied into an app.
Essentially, the process is broken into three steps:
1. Check to see if the user/device is registered with the service
2. Register the user/device if necessary
3. Listen for notifications and handle them when they occur.

Checking Device and User Registration

Invoke the intel.xdk.notification.checkPushUser() method to


determine if a user account has been registered with the PushMobi service.
The general syntax is:
intel.xdk.notification.checkPushUser(
username,
password
);

Note that if your app does not require authentication, you can simply
substitute the device's unique identifer (UUID) for both the username and
password as illustrated below:
intel.xdk.notification.checkPushUser(
intel.xdk.device.uuid,
intel.xdk.device.uuid
);

7 - 24
2013 Intel Corporation.
Using Device Features
When the checkPushUser() method has completed, it will fire an event
named intel.xdk.notification.push.enable and pass in an event
object where you can inspect the result and register the user, if necessary:

var notifications = {
didAdd : false,
register: function(event) {
if(event.success === false) {
if (notifications.didAdd === false) {
notifications.didAdd = true;
intel.xdk.notification.alert(
"Doing addPushUser now...",
"My Message",
"OK"
);

//Try adding the user now - sending unique user id,


//password, and email address.

intel.xdk.notification.addPushUser(
intel.xdk.device.uuid,
intel.xdk.device.uuid,
'no@email.com'
);

//This will fire the push.enable event again,


//so that is why we use didAdd to make sure
//we dont add the user twice if this fails for any reason.
return;
}

intel.xdk.notification.alert(
"Notifications Failed: " + event.message,
"My Message",
"OK"
);
return;
}
var msg = event.message || 'success';
intel.xdk.notification.alert(
"Notifications Enabled: " + msg,
"My Message",
"OK"
);
}

// register event listener


document.addEventListener(
"intel.xdk.notification.push.enable",
notifications.register,
false
);

7 - 25
2013 Intel Corporation.
Fast Track to Intel XDK New

Listening for Notifications

After the user's account has been registered, the receiving of push
notifications will trigger the
intel.xdk.notification.push.receive event. You can code this
handler any way that you wish, although typically you'll use the following
methods to read, parse, and delete messages:
intel.xdk.notification.getNotificationList()
Returns an array of strings that correspond to the identifiers for
received messages.
intel.xdk.notification.getNotificationData(notification id)
Returns an object containing the properties of the specified notification
Object property names include: msg and data.
intel.xdk.notification.deletePushNotifications(notification id)
Deletes the specified notification
A typical notification handler resembles the following snippet:
var notifications = {
receivedPush: function() {
var N = intel.xdk.notification;
var myNotifications=N.getNotificationList();

// It may contain more than one message, so loop!

var len=myNotifications.length;
if(len > 0) {
for(i=0; i < len; i++) {
//Get message id
msgObj=N.getNotificationData(myNotifications[i]);

if(typeof msgObj == "object" &&


msgObj.id == myNotifications[i]){

// Display the message now.


// You can do this however you like -
// it doesn't have to be an alert.

N.alert(msgObj.msg + "\n" + msgObj.data + "\n" +


msgObj.userkey, "pushMobi Message","OK");

// Always mark the messages as read and delete them.


// If you dont, your users will see them repeated

N.deletePushNotifications(msgObj.id);
return;
}
} // for
} // if()
} // function
} // class

// listen for event


document.addEventListener(
"intel.xdk.notification.push.receive",
notifications.receivedPush,
false);

7 - 26
2013 Intel Corporation.
Using Device Features

Testing in the Emulator

You can verify your event handlers and view the result of your push
notification handling by running your app in the Emulator as depicted in
Figure 12. Typing a message into the PUSHMOBI SERVICE panel
simulates the firing of an intel.xdk.notification.push.receive
event.

Figure 12: Sending a test message in the emulator.

7 - 27
2013 Intel Corporation.
Fast Track to Intel XDK New

Testing on a Device

Test your app on a physical device by going through the application build
process, install the app on your device, and then access the PushMobi
service under the XDK Services tab as illustrated in figure 13.

Figure 13: Sending a message via PushMobi

Devices that have properly registered themselves with the PushMobi


service should appear under the User Management tab. Note that the
PushMobi console allows you to target individual users by name, device
platform, or custom filter.

7 - 28
2013 Intel Corporation.
Using Device Features

Walkthrough 7-4: Handling Push Notifications


During this walkthrough you will configure
PushMobi to send messages through the Google
Cloud Messaging Service. You will then add code
to your application to register the device and
handle push notifications. You'll test your work in
the Emulator and on a physical device.
Register a Push Notification App with Google
Configure PushMobi to communicate with
GCM
Listen for push messages to your app

Steps

Figure 14: Handling


Open the Project Push Notifications
1. Open Intel XDK New
2. Click on the word PROJECTS in the top-left corner of the GUI.
3. Click the Open a Project button.
4. Select the following file:
/ftIntelXdkNew/walk/walk7_4/walk7_4.xdk

Configure the Server Push Service


5. Click on the Build Tab
6. Click on Build > Android
7. Click Upload Code
8. Click on the Push tab
9. Click on the radio button labeled Configure this app for push
messaging
10. Click OK.

Configure Google Cloud Messaging (GCM)


11. Open a web browser to the following URL:
http://cloud.google.com/console

12. Click the Create Project button.


13. Enter the following information:

Project Name: Friends with Beer

7 - 29
2013 Intel Corporation.
Fast Track to Intel XDK New

14. Click the Create button.

Proceed through the SMS verification process


15. Click on API's & Auth
16. Turn the Google Cloud Messaging for Android to ON.
17. Click on Registered apps
18. Click on the Register App button and enter the following information:

Name: Friends with Beer


Platform: Web Application

19. Click the Register button.


20. Click on Browser Key
21. Copy the API Key to your clipboard
22. Paste the API Key into the Intel XDK API Key field (5d)
23. Click on Projects
24. Click on Friends with Beer
25. Copy the Project Number to your clipboard
26. Paste the project number into the Intel XDK Project ID field.
27. Click Go to Next Step.

Listen for Push Notification Events


28. Click on the Develop tab.
29. Open index.html in Code mode.
30. Carefully review the Notifications object, its properties, and its
methods that start on line 709.
31. Where indicated by the comment in the onDeviceReady() handler, add
an event listener for the intel.xdk.notification.push.enable event that
invokes the notifications.register event.
var onDeviceReady=function(){
//hide splash screen
intel.xdk.device.hideSplashScreen();
document.addEventListener(
"intel.xdk.notification.push.enable",
notifications.register,
false
);
};

7 - 30
2013 Intel Corporation.
Using Device Features

32. Immediately after the code that you inserted in the prior step, add an
event listener that invokes the notifications.receivedpush method
when an intel.xdk.notification.push.receive event is fired.
var onDeviceReady=function(){
//hide splash screen
intel.xdk.device.hideSplashScreen();
document.addEventListener(
"intel.xdk.notification.push.enable",
notifications.register,
false
);
document.addEventListener(
"intel.xdk.notification.push.receive",
notifications.receivedPush,
false
);
};

33. Immediately after the code that you inserted in the prior step, check to
see if the device is registered with the PushMobi service. Your code
should appear as follows:
var onDeviceReady=function(){
//hide splash screen
intel.xdk.device.hideSplashScreen();
document.addEventListener(
"intel.xdk.notification.push.enable",
notifications.register,
false
);
document.addEventListener(
"intel.xdk.notification.push.receive",
notifications.receivedPush,
false
);
intel.xdk.notification.checkPushUser(
intel.xdk.device.uuid,
intel.xdk.device.uuid
);
};

34. Save the file.

Test the Service in the Emulator


35. Click on the Emulate Tab
36. Send a test message from the PUSHMOBI SERVICE panel.

End of Walkthrough --

7 - 31
2013 Intel Corporation.
Fast Track to Intel XDK New

Unit Summary
You can retrieve a device's current position by using either the Cordova
API or the build-in navigator.geolocation.getCurrentPosition() method.
You can activate the phone dialer and email client by calling special
URI's.
Support for launching the built-in navigation app varies between
platforms and delivery systems
Use the accelerometer to handle changes in orientation to the device.
The devicemotion api enables you to detect changes in how the device
is being handled including shake gestures.
Implement push notifications to enhance user engagement.
You can create your own push notification messaging front-end or
choose from a variety of third-party services.
Intel XDK New directly supports the PushMobi front-end for sending
push notifications.
You will need to configure PushMobi for each of the platforms that
you intend to support (iOS, Android, Windows Mobile)

7 - 32
2013 Intel Corporation.
Using Device Features

Unit Review
1. You must use the Cordova API to access the device's accelerometer
(true/false)?

2. Describe the process for activating the device's phone dialer and
default email application.

3. Which method do you call to get the device's current position?

4. Why should you always include an error callback function when


attempting to get the device's current position?

5. Intel XDK apps can only receive push notifications from the PushMobi
service (true/false)

7 - 33
2013 Intel Corporation.
(This page intentionally left blank)
Unit 8:
Integrating Multimedia

Unit Objectives
After completing this unit, you should be able to:
Add audio to your applications
Integrate video from different sources into your app
Use JavaScript to implement custom player controls for your media

Unit Topics
Playing Audio and Video

8-1

2013 Intel Corporation.


Fast Track to Intel XDK New

Playing Audio and Video


Intel XDK New has design-time widgets for deploying native HTML5
audio and video players. It also has widgets for embedding YouTube videos
and Vimeo presentations within your app.
The goal of the HTML 5 audio/video specification was to natively support
data formats that are royalty-free, have good data compression while not be
cpu-intensive to decode, and a hardware decoder. It states that browsers
should support Theora video and Vorbis audio, as well as the Ogg container
for a placeholder, since these codecs are not affected by any known patents.
Syntactically, the playback of audio and video is handled through the
<video> , <audio>, and <source> commands.

Adding HTML5 Video

You can insert browser-based video into your web page using the <video>
tag. The following attributes are supported:

Attribute Description
autoplay Boolean attribute, causes the user agent to start playing
the media as soon as it is able.
controls Boolean attribute indicating whether the author has not
provided a custom controller using Javascript and would
like to use the native set of controls.
height The height of the control, in pixels
width The width of the control, in pixels
loop Boolean attribute indicating whether the media should
continue playing from the start of the file once it has
reached its end.
preload "none" indicates to the browser that that the author
will probably not need the media resource.
"metadata" hints to the browser that the author will
probably not need the media resource but that pre-
fetching the resource metadata (dimensions, first
frame, duration) is worthwhile.
"auto" hints to the browser that the author expects the
video to be played and therefore it should
optimistically cache the resource.
poster Gives the address of an image file that the user agent can
show while no video data is available. The attribute, if
present, must contain a valid non-empty URL potentially
surrounded by spaces. The image is supposed to be a
representative frame from the video.

8-2
2013 Intel Corporation.
Integrating Multimedia

Attribute Description
src The URL of the media asset. May be overridden by the
use of the <source> element.

The following example illustrates a simple invocation of the <video> tag:

<video
width="320"
height="240"
controls="true"
src="video1.ogg"
preload="auto"
poster="titleframe.jpg">

Get a real browser, yo.

</video>

Reviewing supported file formats

Support for video formats varies, with most vendors supporting either the
WebM or MP4 formats. Ironically, support for Ogg as stipulated in the
HTML5 specification, is only included in the mobile Opera and Firefox
browsers.

Browser WebM MP4

Android Yes Partial

iOS No Yes

Blackberry No Yes

IE Mobile No Yes

Opera Mobile No Yes

Chrome Android Yes Yes

Firefox Android Yes Partial


In order to support all mobile browsers, you'll therefore need to support
both WebM and MP4 formats by using the <source> element as illustrated
below:
<video width="320"
height="240"
controls="true">

<source src="video1.webm" type="video/webm" />


<source src="video1.mp4" type="video/mp4" />

</video>

8-3
2013 Intel Corporation.
Fast Track to Intel XDK New
Inserting Video with Intel XDK New

As illustrated in Figure 1, Intel


XDK New has a Video widget
that enables you to drag and drop
a video into your app.
Supported config properties
include:
Webm Source File
Mp4 Source File
Autoplay
Controls
Loop
Preload Figure 1: Intel XDK New Video Widget
Settings
Video Caption

Building your own controls

The HTML5 media element supports the following properties and methods
from which you could build a custom playback controls:

Read Only Description


Property
paused Returns true if the playback is paused
ended Returns true if playback has ended
readyState Describes whether the video is ready to be
played and/or enough of the video has been
preloaded for it to play without intermediate
pauses.
played Returns a TimeRanges object representing the
range of the media that has been played
seeking Returns true if the user agent is currently seeking
duration Returns the length of the media resource, in
seconds
startTime Returns the earliest possible position, in seconds.
Note that this might not be zero-based if the
resource is being streamed in real-time.
seekable Returns a TimeRanges object that represents the
ranges of the media resource to which it is
possible for the user agent to seek.

8-4
2013 Intel Corporation.
Integrating Multimedia

Read/Write Description
Property
playbackRate Returns the current playback rate
defaultPlaybackRate Returns the default playback rate, where 1.0 is
normal speed.
volume Retuns the current playback volume, in a range
of 0.0 to 1.0 where 0.0 is the quietest and 1.0 is
the loudest.
currentTime Returns the current playback position, in
seconds. Can be set to seek to a specific time.
muted Returns true if the audio is muted, false if not.
Method Description
load() Causes the element to reset and start selecting
and loading a new media resource from scratch.
pause() Sets the paused attribute to true, loads the media
resource if necessary.
play() Sets the paused attribute to false, loads the media
resource, and starts playback.
canPlayType(type) Returns the empty string (a negative response),
"maybe", or "probably" if the user agent
determines that it can play media resources of
the given type.

The following Media events are also available:

ondurationchange onplaying
onemptied onseeked
onerror onseeking
onloadedmetadata onstalled
onloadstart onsuspend
onpause ontimeupdate
onplay onvolumechange
onwaiting

8-5
2013 Intel Corporation.
Fast Track to Intel XDK New

Using these properties and methods, you could create your own
playback/pause button as illustrated by the following snippet:
<head>
<script language="javascript">
enablebuttons = function() {
document.getElementById('playbutton').disabled =
false;
}

playpause = function() {
var objMedia = document.getElementById('mymedia');
var objButton = document.getElementById('playbutton');
if (objMedia.paused) {
objMedia.play();
objButton.value="Pause";
} else {
objMedia.pause();
objButton.value="Play";
}
}
</script>

</head>
<body>

<video
width="320"
height="240"
controls="false"
onCanPlayThrough="enableButtons()"
id="mymedia">

<source src="video1.webm" type="video/webm" />


<source src="video1.mp4" type="video/mp4" />

</video>

<input type="button"
value="Play"
onClick="playpause()"
id="playbutton">
...
</body>

8-6
2013 Intel Corporation.
Integrating Multimedia

Playing Videos from YouTube

You can play YouTube videos from your app by inserting a video's embed
code into your app. The embed code uses an <iframe> and, as illustrated in
Figure 2, the url is located within the Share-Embed block underneath each
video.

Figure 2: Retrieving a YouTube video embed url

8-7
2013 Intel Corporation.
Fast Track to Intel XDK New

Intel XDK New includes a design-time video widget that will insert the
<iframe> code for you you simply need to enter the embed URL into the
YouTube Settings panel as illustrated in figure 3.

Figure 3: Configuring a YouTube video

Embedding Content from Vimeo

Vimeo is a video-sharing website similar in nature to YouTube. Unlike


YouTube, however, it does not play advertisements before, during, or after
your videos. Vimeo has a significant following among the creative and
business communities and is directly supported by Intel XDK New.
You can embed Vimeo videos into your app by using the same <iframe>
technique that had been previously described for embedding YouTube
videos. As illustrated in Figure 4, you can copy the URL to your clipboard
by clicking on a video's Share button and then paste it into the XDK New
Vimeo widget Settings panel.

Figure 4: Getting an embed URL from Vimeo

8-8
2013 Intel Corporation.
Integrating Multimedia

Working with Audio

The <audio> tag functions similarly to the <video> tag in that it enables
you to play a media file without requiring the use of a browser plug-in and
is typically used in mobile apps to play songs and podcasts.
Audio support in mobile browsers remains problematic for use in games.
Timing issues, lags, lack of pre-loading, inability to play multiple clips
simultaneously, and general bugginess make it unsuitable for playing short
sound-effect clips with precision timing. In the near future, the recently
introduced HTML5 Audio API may provide some relief for html5 mobile
game developers.
Supported attributes of the <audio> element include the following:

Attribute Description
autoplay Boolean attribute, causes the user agent to start playing
the media as soon as it is able.
controls Boolean attribute indicating whether the author has not
provided a custom controller using Javascript and would
like to use the native set of controls.
Note that Android devices do not have native audio
controls.
loop Boolean attribute indicating whether the media should
continue playing from the start of the file once it has
reached its end.
preload "none" indicates to the browser that that the author
will probably not need the media resource.
"metadata" hints to the browser that the author will
probably not need the media resource but that pre-
fetching the resource metadata (dimensions, first
frame, duration) is worthwhile.
"auto" hints to the browser that the author expects the
video to be played and therefore it should
optimistically cache the resource.
Note: preload is not supported on most mobile browsers.
src The URL of the media asset. Use the <source> element
to specify alternative file formats for broader user agent
compatibility.
As illustrated below, you should include both mp3 and Ogg Vorbis files in
order to support the broadest range of devices.
<audio
controls="false"
onCanPlayThrough="enableButtons()"
id="mymedia">
<source src="audiofile.mp3" type="audio/mpeg" />
<source src="audiofile.ogg" type="audio/ogg" />
</audio>

8-9
2013 Intel Corporation.
Fast Track to Intel XDK New

Using <audio> Properties

The <audio> element exposes a number of runtime properties that help you
determine the clip's current state:

Property Description

currentTime Number. The playhead position, expressed as seconds

duration Number. Playback time for the clip, in seconds.

muted Boolean. Returns true if volume is muted

paused Boolean. Returns true if media is paused.

volume Float. Volume level, between 0 and 1.

Listening for <audio> Events

You can listen on the following events which are thrown by an Audio
object.

Event Description

canplay The media can be played, but may need to pause while
downloading.

canplaythroug Indicates that the media can be played through without


h pausing.

progress Fires to indicate progress at downloading the media file.


Typically fires every 250 ms but can be unreliable on
mobile devices. For better granularity, call a method
using window.setInterval()

ended The end of the media was reached and playback was
stopped.

play The media has started playing.

volumechange The volume level has been adjusted.

8 - 10
2013 Intel Corporation.
Integrating Multimedia

Futures: Using the HTML5 Audio API

As previously discussed, manipulation of audio in Javascript is quite


limited. A new HTML5 Audio API is under development, however, support
remains limited to the following browsers:
iOS Safari 6.0+ Firefox 25 for Android
Chrome 31 for Android Most desktop browsers
(excluding Microsoft Internet
Explorer)
Features of the HTML5 Audio API include:

An AudioContext class for Scheduling precise sound


managing and playing all sounds. playback for games.
Support for playing multiple Cross-fading between sounds
sound sources simultaneously.
Applying filter effects.
Loading sounds via the
XMLHTTPRequest object with
audio decoding methods.

The following code snippet illustrates how you could use the HTML5
Audio API to load a sound file.
var musicBuffer = null;

// Fix up prefixing
window.AudioContext = window.AudioContext ||
window.webkitAudioContext;
var context = new AudioContext();

function loadSound(url) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';

// Decode asynchronously
request.onload = function() {
context.decodeAudioData(
request.response,
function(buffer) {
musicBuffer = buffer;
},
function (err) {
alert("Could not decode audio file");
}
);
}
request.send();
}

loadSound('100BottlesOfBeerOntheWall.mp3');

Note: See http://www.html5rocks.com/en/tutorials/webaudio/intro/ for a


detailed introduction to the html5 Web Audio API.

8 - 11
2013 Intel Corporation.
Fast Track to Intel XDK New

Walkthrough 8-1: Playing Videos


In this walkthrough you will add streaming video playback from Vimeo to
your application as well as use the native html5 <video> element
Integrate video from Vimeo
Use the HTML5 <video> element to play an MP4 file.

Steps

Open the Project


1. Open Intel XDK New
2. Click on the word PROJECTS in the top-left corner of the GUI.
3. Click the Open a Project button.
4. Select the following file:
/ftIntelXdkNew/walk/walk8_1/walk8_1.xdk

Integrate Video from Vimeo


5. Open drink.html in Design mode.
6. From the Controls > Media panel, drag a Vimeo widget and drop it
onto the center of the Design Canvas.
7. Configure the following Vimeo Settings:

Src: //player.vimeo.com/video/9608723
Autoplay: checked
Loop: checked
8. Click on the TEST tab.
9. Click the Push Files button
10. Test your application on a device using Intel App Preview. You should
be able to play the Vimeo video by tapping on the Drink! tab of the
app.

Integrate WebM/MP4 Video


11. Return to the drink.html file in Intel XDK New's Design mode.
12. Right-click/Cmd-click on the Vimeo video and select Delete.
13. Right-click/Cmd-click on the Column object and select Delete.
14. From the Controls > Media panel, drag a Video widget and drop it onto
the center of the Design Canvas.

8 - 12
2013 Intel Corporation.
Integrating Multimedia
15. Enter the following Video Settings:

Webm Src: //xdktraining.com/ftxdknew/friends.webm


Mp4 Src: //xdktraining.com/ftxdknew/friends.mp4
Autoplay: true
Controls: true
Loop: true
16. Save the file.
17. Click on the TEST tab.
18. Click the Push Files button
19. Test your application on a device using Intel App Preview. You should
be able to play the Vimeo video by tapping on the Drink! tab of the
app.

End of Walkthrough --

8 - 13
2013 Intel Corporation.
Fast Track to Intel XDK New

Unit Summary
You can play audio and video without the user of a plug-in
The HTML5 <audio> and <video> elements have API methods that
you can use to design custom player controls.
You should support both WebM and MP4 video formats to ensure the
highest degree of compatibility.
Intel XDK New has design-time widgets for HTML5 video as well as
playing assets hosted on YouTube.com and Vimeo.com
The <audio> element is not well-suited for playing sound effects in
games.
The HTML5 Audio API contains a very robust set of methods for
handling audio, however, it is not currently supported by the native
Android browser.

8 - 14
2013 Intel Corporation.
Integrating Multimedia

Unit Review
1. What is the purpose of the <video> element's poster property?

2. What video file formats are natively supported by iOS and Android?

3. You cannot programmatically determine where the playhead is at


while a video or audio clip is playing (true/false).

4. The Android browser will automatically output playback controls for


<audio> instances (true/false).

8 - 15
2013 Intel Corporation.
(This page intentionally left blank)
Unit 9:
Theming

Unit Objectives
After completing this unit, you should be able to:
Understand how to work with vendor prefixes
Add web fonts to your application
Enhance your app's typography
Apply background gradients and images
Use ThemeRoller to visually prototype a application widgets

Unit Topics
Working with CSS3 on Mobile Devices
Enhancing Fonts and Typography
Enhancing Backgrounds
Working with ThemeRoller

9-1

2013 Intel Corporation.


Fast Track to Intel XDK New

Working with CSS3 on Mobile Devices


Generally speaking, most advanced features of CSS3 are well-supported by
mobile browsers. CSS3 adds support for many important functions that are
critical for simulating native app behavior and minimizing the use of
hacks that were typically graphics intensive and led to slower download
times and increased memory requirements. Key features include:

Rounded borders Transparency


Downloadable Fonts Better text overflow handling
Enhanced Typography Background sizing and
positioning
Shadowing
CSS-based Keyframe Animation

Handling Vendor Prefixes

Vendor prefixes in CSS generally denote a CSS property that is unique to a


specific browser or may not have been officially ratified by the W3C.
Typical vendor prefixes that you'll encounter in mobile development
include:

Prefix Description

-webkit- Webkit browsers (typically iOS and Android)

-moz- Mobile Firefox

-o- Mobile Opera

-ms- Mobile IE

As illustrated by the following snippet, these vendor prefixes can make


supporting CSS files somewhat laborious as the same declaration must be
repeated multiple times in order to achieve full cross-platform
compatibility:
.box_gradient {
background-color: #c0c0c0; // fallback
background-image: linear-gradient(#ffffff,#c0c0c0);
background-image: -webkit-linear-gradient(#ffffff,#c0c0c0);
background-image: -moz-linear-gradient(#ffffff,#c0c0c0);
background-image: -o-linear-gradient(#ffffff,#c0c0c0);
}

Consequently, most app developers typically use a 3rd party tool to handle
vendor prefixes and make CSS authoring a bit less redundant. Two of those
products are Sass and LESS.

9-2
2013 Intel Corporation.
Theming

About Sass

Sass (Syntactically Awesome Stylesheets) is an extension of CSS that a


allows you to use variables, nested rules, inline imports, with a fully CSS-
compatible syntax. Sass helps keep large stylesheets well-organized, and
get small stylesheets up and running quickly, particularly with the help of
the Compass style library.

Sass is essentially a stylesheet compiler. You author .scss files (Sassy CSS)
which are then converted into production-ready CSS files by a command-
line utility.
Vendor prefixes in Sass are handled through a mechanism called mixins
which are analogous to javascript functions. However, whereas a
JavaScript function typically returns result data based on a set of
parameters, a Sass mixin generates css styles based on passed-in data.
For instance, the following declaration in Sass:
.myCustomClass {
@include border-radius(5px);
}

Generates this CSS output:


.myCustomClass{
-webkit-border-radius:5px;
-moz-border-radius:5px;
-ms-border-radius:5px;
-o-border-radius:5px;
border-radius:5px
}

More information about Sass is available from www.sass-lang.com.

9-3
2013 Intel Corporation.
Fast Track to Intel XDK New

About LESS

LESS is similar to Sass it's a dynamic stylesheet language that's designed


to make CSS authoring more robust and easier to maintain. Less is
actually used behind-the-scenes by Intel XDK New to manage app styles.

LESS also supports the concept of mixins as illustrated by the following


snippet:
.rounded-corners (@radius: 5px) {
-webkit-border-radius: @radius;
-moz-border-radius: @radius;
-ms-border-radius: @radius;
-o-border-radius: @radius;
border-radius: @radius;
}
#header {
.rounded-corners;
}
#footer {
.rounded-corners(10px);
}

Generated CSS code:


#header {
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
border-radius: 5px;
}
#footer {
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
-ms-border-radius: 10px;
-o-border-radius: 10px;
border-radius: 10px;
}

You can find out more about LESS at http://lesscss.org

9-4
2013 Intel Corporation.
Theming

Enhancing Fonts and Typography


Intel iOS webkit browsers supports a large number of fonts, however, very
few of these are also supported by Android's native browser. To ensure that
your applications uses the same font across a wide variety of devices you
should leverage CSS3's support for downloadable fonts.
Google Web Fonts contains over 600 free, open-source fonts that have
been optimized for the web. Adobe Edge Web Fonts contains another 502
fonts. The most difficult part of implementing web fonts is making a
decision about which fonts to use in your apps!

Downloading a Font

CSS3 capable browsers can download fonts and use them to format your
text. Use the @font-face selector to define a font name and associated
download url. You can then reference the font in subsequent style
definitions as indicated below:
@font-face {
font-family: 'Droid Sans';
src: url(fonts/Droid_Sans.ttf);
}

h1{
font-family: 'Droid Sans';
}

Customizing Text Stroke and Fill Color

CSS3 supports the following font-related attributes:

Property Description

text-fill-color Sets the fill color of the text.

text-stroke-color The outline color of the text.

text-stroke-width The thickness of the stroke line.


The following snippet illustrates how to use these properties:

<style>
h1 {
text-fill-color: green;
text-stroke-color: orange;
text-stroke-width: 2px;
font-family: arial;
font-size: 40px;
}
</style>
<h1>This is a test</h1>

9-5
2013 Intel Corporation.
Fast Track to Intel XDK New

Adding Text Shadows

The CSS3 text-shadow property enables you to cast a shadow behind your
text as indicated below:
<style>
p {
font-family:arial;
font-size: 30px;
text-shadow:2px 2px 5px #000;
}
</style>
<p>This is a demonstration of text shadows</p>

As illustrated below, text-shadow takes


four arguments:
1. Right shadow offset
2. Vertical (down) shadow offset
3. Blur radius
4. Shadow color

You can visually prototype text-shadow and box-shadow effects by visiting


http://css3gen.com/text-shadow/ as illustrated in Figure 5.

9-6
2013 Intel Corporation.
Theming

Applying Transparency

CSS 3 allows you to


declare colors as Red,
Green, Blue, and Alpha
transparency. Alpha
transparency is
specified as a numeric value between zero (fully transparent) and one
(opaque). Note that you should also specify a fallback color to use for
browsers that do not support RGBA
<style>
p {
font-family:arial;
font-size: 30px;
color: rgba(255,255,255,0.4);
text-align: center;
padding-top: 30px;
}

#appetizer {
background:url(../images/appetizer.jpg);
width: 475px;
height: 102px
}
</style>

<div id="appetizer"><p>This is a watermark</p></div>

Creating an Inset-Text Effect

Combine color, text-shadow, and rgba transparency to create an insett-


effect as illustrated by the following snippet:
h1 {
color: #3a1515 !important;
text-shadow: 0px 1px rgba(255, 255, 255, 0.3) !important!;
}

9-7
2013 Intel Corporation.
Fast Track to Intel XDK New

Using Ellipsis for Text Overflow

CSS 3 enables you to automatically terminate text with ellipsis if the


content is too large to fit within its parent container.
<style>
#test {
width: 100px;
height: 40px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
</style>

<div id="test">
Lorum Ipsum and more pseudo-latin ridiculousness
</div>

Implementing Newspaper-Style Columns

With CSS3 it is now relatively straightforward to implement multiple


columns of wrapped text using the column-count and column-gap
properties. This technique can be particularly useful when developing apps
for tablets.

<style>
#myarticle{
column-count: 2;
column-gap: 10px;
/* Column-count not implemented yet */
-moz-column-count: 2;
-webkit-column-count: 2;
/* Column-gap not implemented yet */
-moz-column-gap: 22px;
-webkit-column-gap: 22px;
}
</style>

<div id="myarticle">
<p>Lorem Ipsum...and more latin nonsense</p>
</div>

9-8
2013 Intel Corporation.
Theming

Using Google Fonts

As illustrated in Figure 7, Google Fonts has a filter panel in its left column
that enables you to search for fonts based on font type (serif, sans-serif,
display, and handwriting) as well as thickness, slant, and width.
Studies have shown that, on mobile devices, sans-serif and display fonts
are more readable than serif fonts.

After you select a font, the Google Fonts interface generates the <link>
element and font-family css declarations that you'll use to invoke the font
from within your app. It also displays an estimate impact on page load
time.

9-9
2013 Intel Corporation.
Fast Track to Intel XDK New

Using Adobe Edge Fonts

Adobe Edge Web Fonts gives you access to a vast web font library made
possible by contributions from Adobe, Google, and designers around the
world. The fonts are served by Typekit which is a subscription-based
library of hosted, high-quality fonts that was acquired by Adobe in 2011.

The interface for


selecting fonts from
Adobe Edge is not too
dissimilar from
Google Fonts. One
minor difference is
that while Google
uses a <link> tag to
download your
selected fonts, Adobe
Edge uses a <script>
tag as illustrated by
Figure 9.

Figure 9: Load your selected font by including a


<script> tag generated by Adobe Edge Fonts

9 - 10
2013 Intel Corporation.
Theming

Walkthrough 9-1: Applying Typography


In this walkthrough you will replace the
default font with a Google web Font.
Select a web font from Google Fonts
Set the custom default font for text in
your application
Apply an insert effect to the page
headers

Steps

Open the Project


1. Open Intel XDK New
2. Click on the word PROJECTS in the
top-left corner of the GUI.
3. Click the Open a Project button.
4. Select the following file:
/ftIntelXdkNew/walk/walk9_1/walk9_1.xdk

Select a Google Font


5. Open a web browser to Google Fonts at:
http://www.google.com/fonts
6. Type the following font name into the text field:
Rambla

7. Click the Quick Use button.


8. In section 1 (Choose the styles you want), select Bold 700
9. Copy the <link> tag from section 3 to your clipboard and note the font-
family declaration in section 4.

Deploy the Rambla Font


10. Return to Intel XDK New and open index.html in Code view
11. At the top of the file, where indicated by the comment, paste the
<link> tag from your clipboard.

9 - 11
2013 Intel Corporation.
Fast Track to Intel XDK New

12. In the <style> block near the top of the file, add a body and paragraph
tag selector that specifies Rambla as the font-family and bold as the
font-weight.
body, p {
font-family: 'Rambla', sans-serif;
font-weight: bold;
}

13. Save the file and test in the Emulator.

Customize the Page Header Font


14. Return to Code mode in the index.html file.
15. Directly underneath the style that you added in step 12, define a class
named ui-title that increases the font-size for the header text and gives
it an inset effect. Your code should appear similar to the following:
.ui-title {
font-size: 1.5em !important;
color: #000000 !important;
text-shadow: 0px 1px rgba(255, 255, 255, 0.3) !important;
}

16. Save the file and test in the emulator.

End of Walkthrough --

9 - 12
2013 Intel Corporation.
Theming

Enhancing Backgrounds
You can enhance the backgrounds of images in CSS3 by specifiying
background gradients and background images for html elements. If you
plan to use background images, consider base-64 encoding them into your
spreadsheet for improved performance.

Applying a Background Gradient

CSS3 gradients enable you to display smooth transitions between two or


more specified colors. Using gradients offer several advantages over
background images:
Gradients reduce download times and bandwidth usage.
Gradients automatically adjust to running in different screen
resolutions.
Gradients retain their integrity zooms in or out of an area.
As illustrated by the following snippet, gradient definitions are typically
applied through the background-image css property and require the use of
vendor-prefixes. The simplest syntax simply deals with direction of the
transformation (linear, top-bottom), with a color that's specified for the stop
at 0% (the top of the affected area) and a color that's the stop at 100% (the
bottom of the affected area).
body {
background-image: -webkit-linear-gradient(gold, goldenrod);
background-image: -moz-linear-gradient(gold, goldenrod);
background-image: -ms-linear-gradient(gold, goldenrod);
background-image: -o-linear-gradient(gold, goldenrod);
}

An example of a gradient that transitions from red to white to blue using


color stops is illustrated below:

<style>
body {
background-image: -webkit-gradient(
linear, left top, left bottom,
color-stop(0%,#ffffff),
color-stop(50%,#f20e0e),
color-stop(100%,#3e21ff)
);
// other vendor prefixes omitted for brevity
}
</style>

9 - 13
2013 Intel Corporation.
Fast Track to Intel XDK New

Most designers choose to create gradients visually, and many use the
Ultimate CSS Gradient generator depicted in Figure 10.

Applying a Background Image

CSS3 enables you to scale and position a background image two


attributes that are critical for supporting an application that needs to
responds properly to varying screen resolutions.
The basic CSS syntax for specifying a background image is the following:
body {
background: #000000; // black background color
background-image:url('images/beercan.png');
background-repeat: no-repeat;
}

Alternately, you can set all background properties in a single statement:


body {
background:#000000 url('images/beercan.png') no-repeat;
}

9 - 14
2013 Intel Corporation.
Theming

Specifying a background size

Use the background-size property to scale an image to either a


specified pixel size or a percentage of the content area.
You can also specify background-size: cover; which scales the
background image to completely cover the background area, while
mantaining the background image's aspect ratio. Using this option may
result in some parts of the background image being hidden.
Specifying background-size: contain; scales the image such that
both the width and the height of the image fit within the content area.
However, this may result in the background not being fully covered by the
image.
// scale the background image to cover the body

body
{
background:url(beercan.gif);
background-size: cover;
background-repeat:no-repeat;
}

Specifying background-position

Use the background-position property to set the starting position of a


background image.
Valid settings include the following:

Value Description

left top Positions the background image to a relative location


left center within its container.
left bottom
right top
right center
right bottom
center top
center center
center bottom

x% y% Positions the background image to a location specified


as a percentage value along the x/y axis. The right
bottom corner is 100% 100%.

xy Position the background at an absolute location,


typically specified in pixels.

9 - 15
2013 Intel Corporation.
Fast Track to Intel XDK New

Base-64 Encoding a Background Image

Base-64 encoding enables you to take a binary image file and encode it as a
text string that can be included as part of a stylesheet. Encoding images
directly into a stylesheet gives you better startup performance since it
eliminates the need for the browser to make separate http requests for each
image. A drawback, however, is that the process usually increases the
image's data size by approximately 30%.
Websites like www.base64-image.de provide free services for converting
images to base-64.

Figure 11: Use www.base64-image.de to encode your images.

Images encoded into a stylesheet typically appear as follows (note that the
image data has been truncated for brevity):
.body {
background-image: url('data:image/png;base64,iVBORw==');
background-size: cover;
background-repeat: no-repeat;
}

9 - 16
2013 Intel Corporation.
Theming

Combining Multiple Background Images

CSS3 enables you to specify multiple background images that are stacked
on top of each other as transparency layers.
The following examples illustrate the effect of combining a background
images with a radial gradient to produce a glossy-wood effect:

.ui-header-fixed {
background-image: url('resources/headerbackground.png')
}

.ui-header-fixed {
background-image: -webkit-linear-gradient(#9f5628,#5d2f17);
}

.ui-header-fixed {
background-image: url('resources/headerbackground.png'),
-webkit-linear-gradient(#9f5628, #5d2f17) !important;
}

Specifying Background Images

To specify a background image for all pages in your app, attach a


background-image property to the .ui-page class as illustrated below:
.ui-page {
background-image: url('resources/background.png') !
important;
background-size: cover !important;
background-repeat:no-repeat !important;
}

To specify a background image for page headers, attach a background-


image property to the .ui-header-fixed class as illustrated in the previous
section.

9 - 17
2013 Intel Corporation.
Fast Track to Intel XDK New

Walkthrough 9-2: Applying Backgrounds


In this walkthrough you will theme the
header, footer, and body of the app by
applying CSS3 techniques.
Apply a base-64 encoded background
image to the body of the pages.
Apply a background gradient and image
to the header and footer.
Tweak the style of the control bar
buttons.

Steps

Open the Project


1. Open Intel XDK New
2. Click on the word PROJECTS in the
top-left corner of the GUI.
3. Click the Open a Project button. Figure 12: Apply backgrounds
to the header, body, and footer.
4. Select the following file:
/ftIntelXdkNew/walk/walk9_2/walk9_2.xdk

Create a New Stylesheet


5. In the project file listing, right-click on the css folder and select New
File.
6. Rename the new file to custom.css
7. Open the index.html file in code view
8. Where indicated by the comment, insert a <link> element to load the
custom.css file.

Apply a Background to your Pages


9. Open custom.css
10. Define a style class named .ui-page that sets the following properties:

background-image: url('../resources/background.png');
background-size: cover;
11. Save the file and test in the emulator. You should see that there's now
beer in the background in each page of your app.

9 - 18
2013 Intel Corporation.
Theming
Base-64 Encode an Image
12. Open a web browser to the following url:
www.base64-image.de

13. Click the Upload Image button.


14. Upload the following file:
/ftxdknew/walk/walk9-2/resources/background.png

15. Click the encode image button.


16. Copy the background-image property from the CSS Background Image
block onto your clipboard.
17. Return to the custom.css file.
18. Paste the contents of your clipboard into the file, replacing the existing
background-image statement.
19. Save the file and test the app in the emulator. You should see that the
background image still appears in the app.

Theme the Application Header and Footer


20. Return to the custom.css file in your editor.
21. At the beginning of the file, Insert a new class selector named
.ui-header-fixed that has the following property:
background-image:
url('../resources/headerbackground.png'), -webkit-linear-
gradient( #9f5628, #5d2f17) !important;

22. Add another class selector to the definition that you inserted in the
prior step named .ui-footer-fixed. Your code should appear as follows:
.ui-header-fixed, .ui-footer-fixed {
background-image: url('../resources/headerbackground.png'),
-webkit-linear-gradient( #9f5628, #5d2f17) !important;

23. Save the file and test in the emulator. Your header and footer should
now have a glossy-wood background.

Format the Control Bar


24. Return to the custom.css file.
25. At the top of the file insert the following definition to make the button
backgrounds transparent and set the button label style:
.ui-controlgroup-controls .ui-btn {
background: transparent;
color: #000000 !important;
text-shadow: 0px 1px rgba(255, 255, 255, 0.3) !important;
border-color: transparent;
}

26. Save the file and test. Note that the selected button style class remains
inconsistent with the rest of the footer.

9 - 19
2013 Intel Corporation.
Fast Track to Intel XDK New
27. Return to the custom.css file.
28. At the top of the file insert the following definition to make the
selected button style consistent with the rest of the control bar:
.ui-btn.ui-btn-b {
background: transparent !important;
border-color: transparent !important;
color: #DAA520 !important;
text-shadow: 0px 1px rgba(100, 100, 100, 0.3) !
important;
}

29. Save the file and test. Your output should appear similar to figure 9.
Note that the list views in the Friends and Beers list still need to be
themed.

End of Walkthrough --

9 - 20
2013 Intel Corporation.
Theming

Working with ThemeRoller


ThemeRoller for jQuery Mobile is a visual theme designer that enables you
to easily style jQM UI widgets. ThemeRoller also incorporates
complementary color swatches from Adobe Kuler which can assist you in
selecting complementary colors for your app.
A jQuery Mobile theme contains global settings for items such as font and
corner radius as well as up to to 26 "swatches" lettered from A-Z, each
with a unique color scheme that can be mixed and matched in your app.
Each swatch sets the colors, textures and font settings for the primary
elements: toolbar, content block and button. Buttons have 3 interaction
states: normal, hover, pressed.

Getting Started with ThemeRoller

The ThemeRoller interface has 3 major zones: the left column contains the
inspector panel, along the top is the QuickSwatch/Kuler bar, and below this
is the preview window.

Figure 13: jQuery Mobile ThemeRoller

Use the Inspector panel to set global theme settings on the first tab and
tweak the individual style options for each swatch.
When you drag and drop a color from the QuickSwatch panel onto an
element in the preview panel, ThemeRoller automatically calculates
text color and shadow, borders, gradients and button states. The sliders
make it easy to adjust the lightness and saturation of the colors. Use
the Adobe Kuler Swatches to load complementary color palettes from
Adobe's popular color palette sharing site.
The Preview panel shows a sample of common jQuery Mobile
widgets that live update each time you make a change to the theme so
you can quickly test and tweak the theme.

9 - 21
2013 Intel Corporation.
Fast Track to Intel XDK New

Walkthrough 9-3: Using ThemeRoller


In this walkthrough you will create a custom
stylesheet for your application using jQuery
Mobile ThemeRoller.
Use Adobe Kuler to select complementary
colors for your UI controls
Use ThemeRoller to generate a CSS file
Deploy the custom CSS in your app

Steps

Open the Project


1. Open Intel XDK New
2. Click on the word PROJECTS in the top-
left corner of the GUI.
3. Click the Open a Project button. Figure 14: Use ThemeRoller
4. Select the following file: to change the colors of your
JQM widgets
/ftIntelXdkNew/walk/walk9_3/walk9_3.xdk

Theme JQM Components with ThemeRoller


5. Open a browser to http://www.jquerymobile.com/themeroller/
6. Click on the Get Rolling button.
7. Click on the Adobe Kuler swatches link
8. Choose Search Colors from the Adobe Kuler select list.
9. Enter the following search criteria into the Adobe Kuler search box:
beer

10. Click the search button.


11. Drag and drop colors from the various beer color schemes onto the
components in the A swatch.
12. Click the Download button.
13. Enter a theme name of FWB
14. Click the Download Zip button.

Deploy the CSS File


15. Open the zip file
16. Extract the themes/fwb.css file to the /walk9_3/css folder.

9 - 22
2013 Intel Corporation.
Theming
17. Return to Intel XDK New
18. Open index.html in Code mode.
19. Immediately preceeding the <link> tag to custom.css, insert a <link>
tag that points to the css/fwb.css file.
20. Test your app in the emulator. Note that the list of beers and friends are
now themed.

End of Walkthrough --

9 - 23
2013 Intel Corporation.
Fast Track to Intel XDK New

Unit Summary
Some CSS3 style properties require vendor prefixes.
There are a number of 3rd party tools that you can use to help mitigate
vendor-prefix compatibility issues.
CSS3 supports downloadable web fonts.
Google and Adobe offer a combined 1000+ fonts freely available for
download.
You can combine text-shadow and transparancy effects to output an
inset-text effect.
CSS3 enables you to combine background images and gradients to
produce exciting effects.
Base-64 encode your application's images in order to reduce the
number of http requests that must be made and improve app
performance.
You can theme your app by overriding jQuery Mobile CSS classes and
by generating a CSS file from ThemeRoller.

9 - 24
2013 Intel Corporation.
Theming

Unit Review
1. What are the benefits and drawbacks to using base-64 encoding?

2. List three tools that you can use to either visually prototype CSS3
styles or mitigate vendor prefix issues.

3. What are the relative advantages/disadvantages to using ThemeRoller?

4. Which style class can you override to set a background image for all of
the pages in your app?

9 - 25
2013 Intel Corporation.
(This page intentionally left blank)
Unit 10:
Going into Production

Unit Objectives
After completing this unit, you should be able to:

Configure run permissions on an app


Lock the application into a specific device orientation
Implement a custom icon and splash screen
Create a production build for Android
Install a .apk file on your device

Unit Topics
Creating a Production Build for Android

10 - 1

2013 Intel Corporation.


Fast Track to Intel XDK New

Creating a Production Build for Android


You've made it to the finish line! Your app, from all appearances, works
great in the simulator and on Intel App Preview. Now you're ready to create
a production build and test it across multiple physical devices and versions
of Android. After you've completed device testing, you can upload it to
Google Play, the Amazon AppStore, or simply post it to a web server for
download.
Your first step is to click on the Build tab in Intel XDK New as illustrated
in figure 1.

Figure 1: The Overview tab

For Android builds, the overview tab will indicate that your app is ready to
be packaged into a production-ready .apk file. However, while this is
technically a true statement, there are a number of settings that you will
want to modify before you proceed with packaging.
The Details panel allows you to set your application title, version,
permissions, orientation, and codebase.
The Assets panel enables you to configure your application's startup
orientation as well as launch icon and startup screens.
The Plugins panel gives you the ability to upload Cordova plugins for
use in your app.
The Credentials tab lets you enter credentials for working with the
Facebook APIs.
The Push tab configures your app for Push Notification support from
the Google Cloud Messaging Service and PushMobi.

10 - 2
2013 Intel Corporation.
Going into Production

Configuring Build Details

Configure the following information on the Details tab:

Figure 2: Configuring Build Details


Application Name
The name of the application that is displayed to the user when it's
installed on the device.
Application Version ID
The version number of the app (typically 1.0 for your initial release).
Application Permissions
The device resources that your app uses. Note that if your app tries to
access a resource for which it has not been granted permission, it will
usually fail silently.
Device Configuration
Choose the devices that you'll support. You must select Phone+Tablet
for Android builds.
Operating System
This will default to Android 4.2 with backwards compatibility to
Android 2.3
Code Base
There are three options that impact the size (in bytes) of your build-
Gold, Lean, and Lean with App Game Interface. Apps that use
Cordova APIs must choose Gold

10 - 3
2013 Intel Corporation.
Fast Track to Intel XDK New

Configuring Application Assets

The Assets tab, depicted in Figure 3, enables you to add a custom


application icon and splash screens. You can also set the device's initial
start-up orientation.

Figure 3: Define a custom icon and splash screen


Note the following:
The Android Launch Icon must be a 96x96 PNG file
The splash screen for phones must be a 720w x1280h PNG, JPG, or
JFIF.
The tablet splash screen must be a 1600w x 2560h PNG, JPG, or JFIF
During the build process, the launch icon and splash screens will be
automatically resized, while maintaining the same aspect ratio, to support
different device screen resolutions.

10 - 4
2013 Intel Corporation.
Going into Production

Locking the Screen Orientation

You can lock rotation using the intel.xdk bridge library by invoking the
following methods:
Use the intel.xdk.device.setRotateOrientation(str) method to the
preferred orientation (landscape or portrait)
Use the intel.xdk.device.setAutoRotate(bool) method to lock the
orientation.
The following code snippet locks an application into a portrait orientation:
<script type="text/javascript">
intel.xdk.device.setRotateOrientation("portrait");
intel.xdk.device.setAutoRotate(false);
</script>

Adding App Plugins

The plugins tab, as illustrated in Figure 4, enables you to create and upload
cordova API extensions.

Figure 4: Adding Cordova Plugins

Full documentation and examples for writing, packaging, and uploading


plugins is located at the following URL:

http://intel.ly/1dpj1B0

10 - 5
2013 Intel Corporation.
Fast Track to Intel XDK New

Entering App Credentials

As depicted in Figure 5, the App Credentials panel is where you must enter
additional credentials if your app makes use of the Intel XDK native
application Facebook integration.

Figure 5: Adding Facebook Credentials

More information about Facebook integration is located at the following


URL:
http://intel.ly/J5ek5O

10 - 6
2013 Intel Corporation.
Going into Production

Configuring Push Notifications

As described in unit 7, you will need to add information into the Push
notifications panel, in order to receive push notifications from Intel's
PushMobi service.

Figure 6: Configuring PushMobi support

10 - 7
2013 Intel Corporation.
Fast Track to Intel XDK New

Walkthrough 10-1: Packaging an App


In this walkthrough you will create a production app for Android devices.
Lock the application device orientation
Configure application permissions
Upload a custom icon and splash page

Steps

Open the Project


1. Open Intel XDK New
2. Click on the word PROJECTS in the top-left corner of the GUI.
3. Click the Open a Project button.
4. Select the following file:
/ftIntelXdkNew/walk/walk10_1/walk10_1.xdk

Set a Fixed Portrait Orientation


5. Open index.html in Code view.
6. At the top of the onDeviceReady() function, lock the orientation of the
app into portrait mode.
intel.xdk.device.setRotateOrientation("portrait");
intel.xdk.device.setAutoRotate(false);

7. Save the file.

Configure Android Permissions


8. Click on the Build tab
9. Click on the Android Build button.
10. Click the Upload Code button.
11. Click on Details and configure the following properties:

Application Title: FriendswithBeer


Application Version Name: 1.0
This app uses geolocation: Yes
This app accesses the user's contacts: Yes

10 - 8
2013 Intel Corporation.
Going into Production

Upload an Icon and Splash Page


12. Click the browse button adjacent to the Android Launch Icon field.
13. Select the walk10_1/resources/icon.png file.
14. Click the browse button adjacent to the Phone Splash Screen field.
15. Select the walk10_1/resources/splash.png file.

Create a Build
16. Click on the Overview tab.
17. Click the Build App Now button.
18. Click the Download Build button and save the file to your computer.

Test the Build


19. Email the .apk file to yourself.
20. Open the mail client on your Android phone.
21. Open the email that contains your .apk file.
22. Open the apk file on your device, install, and test it.

End of Walkthrough

10 - 9
2013 Intel Corporation.
Fast Track to Intel XDK New

Unit Summary
Accessing some hardware functions require that you grant permissions
to your app.
Application icons and startup images are automatically resized during
the build process in order to support multiple device resolutions.
Use the intel.xdk.device methods to lock the application into using a
specific orientation.
Facebook and Push notification support require that you enter
additional credentials during the build process.
You can email .apk files to your users or post them to a web server.
App distribution does not require uploading your app to Google Play.
Always test your app on a physical device prior to uploading it to an
app store.

10 - 10
2013 Intel Corporation.
Going into Production

Unit Review
1. Which device resource permissions can be set within the Build
process?

2. What is a plugin and why would you need one?

3. App icons and splash screens are automatically scaled in order to


account for varying device resolutions.

4. Describe the process for installing an .apk file on a physical device.

10 - 11
2013 Intel Corporation.