For those of you who don't know this is a rather complex topic. For starters, you're here to learn how to successfully combine jQuery Mobile with PhoneGap, let me first tell you something about them. jQuery mobile framework takes the "write less, do more" mantra to the next level: Instead of writing unique apps for each mobile device or OS, the jQuery mobile framework allows you to design a single highly-branded web site or application that will work on all popular smartphone, tablet, and desktop platforms. everything mentioned here helped it in its rise to popularity. On the other hand, PhoneGap is a free and open source framework that allows you to create mobile apps using standardized web APIs for the platforms you care about. It can/will be used as a native wrapper for your/our mobile applications.
PhoneGap is a distribution of Apache Cordova. You can think of Apache Cordova as the engine that powers PhoneGap, similar to how WebKit is the engine that powers Chrome or Safari. That's why, later in this article, you will need to download Cordova archive but I will still talk about it like it is a PhoneGap. If you want to understand this better read this excellent PhoneGap developers
article.
This article is intended to show you how to successfully combine jQuery Mobile, steer around some implementation obstacles and make it as fast as humanly possible. You have probably heard about the bad performance of PhoneGap applications, because of that, many developers stopped developing any jQuery Mobile PhoneGap applications. Is this a bad combination? Answer is yes and no. jQuery Mobile was never intended to be used in a such way, nor was PhoneGap intended to work with a such complex framework. Thankfully situation is not that bad, this combination can work successfully as long as you ready to learn proper design patterns.
For the test purpose we will create a small hybrid Android jQuery Mobile application from the perspective of Windows OS and Eclipse IDE. If readers show enough interest I will also create a iOS / MacOS combination (
EDIT: I have created MacOS article after several requests, link can be found
here).
Preparations
Download the listed software:
- Install Apache Ant
- Install Java JDK
- Download and extract Eclipse
- Install the Android ADT Plugin for Eclipse
- Install the Android SDK
- Download and extract PhoneGap
Install Apache Ant
Go to the official Apache Ant site and download latest version, or any other if you don't like to use newer versions.
Download link: http://ant.apache.org/bindownload.cgi
Create a new ANT directory (where ever you prefer) and unpack a downloaded archive. It should look something like this:
C:\Android\ANT\apache-ant-1.9.2
Use this location and create a new environment variable called
ANT_HOME , also use this variable and add it to your PATH like this:
%ANT_HOME%\bin . Take a look at this
tutorial if you don't know how to do that, you will find an examples for Windows XP, Windows 2000 and Windows 7.
It should look like this:
Install Java JDK
Go to the official Oracle Java site and download latest Java JDK version, be careful not to download Java JRE instead. You will also need to create an official Oracle account. Be careful to install a correct 32bit or 64 bit version (this
tutorial will show you how to find this information).
Download link: http://www.oracle.com/technetwork/java/javase/downloads/index.html
Install it where ever you want, just remember its location. For example it should look like this:
C:\Program Files\Java\jdk1.7.0_09\
Now, just like with an ANT, create a new environment variable called
JAVA_HOME and add a location to your JAVA installation folder. Then add it to the
PATH . It should look like this:
Install the Android SDK
Go to the official Android SDK site, click
"USE AN EXISTING IDE" and download the latest version.
Download link: http://developer.android.com/sdk/index.html
Install it where ever you want, just remember its location. For example it should look like this:
C:\Android\android-sdk\sdk . Create new environment variable called
ANDROID_HOME and add previously mentioned link. Now add two additional
PATH locations
%ANDROID_HOME%\platform-tools; and
%ANDROID_HOME%\tools; . Everything should look like this:
Download and extract Eclipse
Go to the official Eclipse IDE site and download latest Eclipse Standard version, or Eclipse for Java Developers if you prefer a smaller installation. Again be careful to download correct 32bit or 64bit version.
Download link: http://www.eclipse.org/downloads/
Finally create a new directory and extract Eclipse archive. It should look like this:
C:\Android\Eclipse\ . Open Eclipse directory and create a shortcut if you want, now double click and execute
Eclipse.exe . Close the welcome tab and then select Help -> Install new software, follow images found below and install the ADT Plugin.
When installation ends you will be prompted to restart Eclipse, do so and wait for it to open again. When Eclipse shows again it will open Android SDK manager and offer you to download needed Android versions. I would advise you to download only versions you will use for your development because this step will take a long time to finish.
Click
Install XX packages , select
Accept , read through the
Package Description and License , select
Accept License and click
Install .
Download and extract PhoneGap
Go to the official Apache Cordova site, and download the latest Cordova version.
Download link: http://cordova.apache.org/#download
Extract this archive, warning, it should be extracted in a directory path that don't have spaces. For example it should look like this:
C:\Android\cordova-3.0.0-src\cordova-3.0.0 . Go inside and extract a file named
cordova-android.zip . If you are using older Cordova version this file is going to have a different name, thankfully it always have text
cordova-android inside.
Creating and importing Eclipse project
Open command prompt (cmd.exe) and go to the directory where you have extracted PhoneGap, now open directory bin. It location should look like this:
C:\Android\cordova-3.0.0-src\cordova-3.0.0\bin .
Now we will need to run the create command to create a new project. Before we do that few warnings. Project directory should not exist, create command will create it automatically, second thing, do not do this in an Eclipse workspace directory, this will result in a failure later.
Command line execution should look like this:
C:\Android\cordova-3.0.0-src\cordova-3.0.0\bin>create C:\Android\Project\PhoneGap_example com.test.example projectname
Create command execution should look like this:
Where
C:\Android\Project\PhoneGap_example is our non existent directory,
com.test.example should always be a unique and
projectname is your arbitrary project name.
A new project should/will be created. Check that project was really created. To be sure go to your project directory (C:\Android\Project\PhoneGap_example in my case), if it exist and if there's a content inside you are fine.
Open Eclipse again and press
CTRL-N , select
Android Project from Existing Code -> select your project directory location -> select the new created project and click Finish.
Installation notes
Everything done here can also be done manually in a much shorter way. All you need is Java JDK (configured like above), Android SDK that already comes with Eclipse and ADT Plugin. This method also requires you to manually create and configure your project and that is completely another story. Showed solution require more time for installation and configurations but you will save some much time with automatic project creation process.
Lets build our jQuery Mobile application
jQuery Mobile 1.4 beta has been selected for this application. As previously mentioned, jQuery Mobile don't behave properly when combined with PhoneGap, one of the main reasons for that is heavy use of CSS. This will change with the new jQuery Mobile version. To improve performance developers reduced DOM manipulation as much as possible. Generation of inner markup for elements styled as buttons has been completely removed. In many cases, the framework just adds classes to the native element during enhancement, amount of classes that are added by the framework has also been heavily reduced.
Application will use external JSON source, specifically
themoviedb database. And to make it more interesting, iScroll will be used for more native like scrolling.
HTML
<div data-role="page" id="home">
<div data-theme="a" data-role="header">
<h3>
Movie List
</h3>
</div>
<div data-role="content">
<div class="example-wrapper" data-iscroll>
<ul data-role="listview" id="movie-list" data-theme="a">
</ul>
</div>
</div>
<div data-theme="a" data-role="footer">
<h1>Copyright 2013</h1>
</div>
</div>
<div data-role="page" id="headline">
<div data-theme="a" data-role="header">
<a href="#home" class="ui-btn-left" data-transition="slide" data-direction="reverse">Back</a>
<h3>
Movie Info
</h3>
</div>
<div data-role="content">
<ul data-role="listview" id="movie-data" data-theme="a">
</ul>
</div>
</div>
|
Javascript
$(document).on('pageinit', '#home', function(){
var url = 'http://api.themoviedb.org/3/',
mode = 'search/movie?query=',
movieName = '&query='+encodeURI('Batman'),
key = '&api_key=470fd2ec8853e25d2f8d86f685d2270e';
$.ajax({
url: url + mode + key + movieName ,
dataType: "jsonp",
async: true,
success: function (result) {
ajax.parseJSONP(result);
},
error: function (request,error) {
alert('Network error has occurred please try again!');
}
});
});
$(document).on('pagebeforeshow', '#headline', function(){
$('#movie-data').empty();
$.each(movieInfo.result, function(i, row) {
if(row.id == movieInfo.id) {
$('#movie-data').append('<li><img src="http://d3gtl9l2a4fn1j.cloudfront.net/t/p/w185'+row.poster_path+'"></li>');
$('#movie-data').append('<li>Title: '+row.original_title+'</li>');
$('#movie-data').append('<li>Release date'+row.release_date+'</li>');
$('#movie-data').append('<li>Popularity : '+row.popularity+'</li>');
$('#movie-data').append('<li>Popularity : '+row.vote_average+'</li>');
$('#movie-data').listview('refresh');
}
});
});
$(document).on('vclick', '#movie-list li a', function(){
movieInfo.id = $(this).attr('data-id');
$.mobile.changePage( "#headline", { transition: "slide", changeHash: false });
});
var movieInfo = {
id : null,
result : null
}
var ajax = {
parseJSONP:function(result){
movieInfo.result = result.results;
$.each(result.results, function(i, row) {
console.log(JSON.stringify(row));
$('#movie-list').append('<li><a href="" data-id="' + row.id + '"><img src="http://d3gtl9l2a4fn1j.cloudfront.net/t/p/w185'+row.poster_path+'"/><h3>' + row.title + '</h3><p>' + row.vote_average + '/10</p></a></li>');
});
$('#movie-list').listview('refresh');
}
}
|
CSS
.ui-content {
padding: 0 !important;
}
.ui-listview {
margin: 0 !important;
}
.example-wrapper, .example-wrapper div.iscroll-scroller {
width: 100% !important;
}
|
Working example: http://jsfiddle.net/Gajotres/8uac7/
Lets mix everything up
At this point we have a working Eclipse project and jQuery Mobile example, but before we can proceed we need to create a emulator in which we will simulate a Phone Device. Open Eclipse (if it's not opened already) and click on Window -> Android Virtual Device Manager -> New window will open, click on tab Device Definitions , pick a preselected device, click Create AVD -> change what ever you want and click OK .
Let's create a index.html file from our jsFiddle example, it should look like this:
<!DOCTYPE html>
<html>
<head>
<title>jQM Complex Demo</title>
<meta http-equiv='Content-Type' content='text/html; charset=utf-8'/>
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"/>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.0-beta.1/jquery.mobile-1.4.0-beta.1.min.css"/>
<link rel="stylesheet" href="http://example.gajotres.net/iscrollview/jquery.mobile.iscrollview.css"/>
<link rel="stylesheet" href="http://example.gajotres.net/iscrollview/jquery.mobile.iscrollview-pull.css"/>
<style>
.ui-content {
padding: 0 !important;
}
.ui-listview {
margin: 0 !important;
}
.example-wrapper, .example-wrapper div.iscroll-scroller {
width: 100% !important;
}
</style>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.4.0-beta.1/jquery.mobile-1.4.0-beta.1.min.js"></script>
<script src="http://example.gajotres.net/iscrollview/iscroll.js"></script>
<script src="http://example.gajotres.net/iscrollview/jquery.mobile.iscrollview.js"></script>
<script>
$(document).on('pageinit', '#home', function(){
var url = 'http://api.themoviedb.org/3/',
mode = 'search/movie?query=',
movieName = '&query='+encodeURI('Batman'),
key = '&api_key=470fd2ec8853e25d2f8d86f685d2270e';
$.ajax({
url: url + mode + key + movieName ,
dataType: "jsonp",
async: true,
success: function (result) {
ajax.parseJSONP(result);
},
error: function (request,error) {
alert('Network error has occurred please try again!');
}
});
});
$(document).on('pagebeforeshow', '#headline', function(){
$('#movie-data').empty();
$.each(movieInfo.result, function(i, row) {
if(row.id == movieInfo.id) {
$('#movie-data').append('<li><img src="http://d3gtl9l2a4fn1j.cloudfront.net/t/p/w185'+row.poster_path+'"></li>');
$('#movie-data').append('<li>Title: '+row.original_title+'</li>');
$('#movie-data').append('<li>Release date'+row.release_date+'</li>');
$('#movie-data').append('<li>Popularity : '+row.popularity+'</li>');
$('#movie-data').append('<li>Popularity : '+row.vote_average+'</li>');
$('#movie-data').listview('refresh');
}
});
});
$(document).on('vclick', '#movie-list li a', function(){
movieInfo.id = $(this).attr('data-id');
$.mobile.changePage( "#headline", { transition: "slide", changeHash: false });
});
var movieInfo = {
id : null,
result : null
}
var ajax = {
parseJSONP:function(result){
movieInfo.result = result.results;
$.each(result.results, function(i, row) {
console.log(JSON.stringify(row));
$('#movie-list').append('<li><a href="" data-id="' + row.id + '"><img src="http://d3gtl9l2a4fn1j.cloudfront.net/t/p/w185'+row.poster_path+'"/><h3>' + row.title + '</h3><p>' + row.vote_average + '/10</p></a></li>');
});
$('#movie-list').listview('refresh');
}
}
</script>
</head>
<body>
<div data-role="page" id="home">
<div data-theme="a" data-role="header">
<h3>
Movie List
</h3>
</div>
<div data-role="content">
<div class="example-wrapper" data-iscroll>
<ul data-role="listview" id="movie-list" data-theme="a">
</ul>
</div>
</div>
<div data-theme="a" data-role="footer">
<h1>Copyright 2013</h1>
</div>
</div>
<div data-role="page" id="headline">
<div data-theme="a" data-role="header">
<a href="#home" class="ui-btn-left" data-transition="slide" data-direction="reverse">Back</a>
<h3>
Movie Info
</h3>
</div>
<div data-role="content">
<ul data-role="listview" id="movie-data" data-theme="a">
</ul>
</div>
</div>
</body>
</html>
|
There's only one last thing to do, we need to copy
index.html into a project
assets directory. It can be copied and paste there or you can copy it directly into the
assets directory. If you can't find your project folder just right click it -> select
Properties -> select
Resource and path will be shown in the window right side under the name
Location .
Last step requires us to execute out project. Right click on the project -> Select Run As - Select Android Application and wait for the emulator to boot up. This can take several minutes so be patient. If you don't want to wait and have an Android smartphone, just plug it into your PC (hopefully you have already installed device drivers). Because real device has a priority over a virtual one, application is going to be installed and executed on your mobile device. Also take care that device Android version is at least equal or higher then project Android version.