Skip to content

February 21, 2012

Photo Gallery with PhoneGap and jQuery Mobile

by nady

This tutorial will cover a basic photo gallery app. You will learn how to use jQuery Mobile grid layout, how to get files from the device’s file system and list them and how to show a picture.

Final result:


Download Sources

The grid layout is a multi-column layout that is better suited for mobile interfaces when you need to place small elements side by side.
This layout has four preset configurations, from two columns to five columns. The grid should not interfere with your styles because it doesn’t have any borders, background, padding or margins.

The <div> containing the grid should have an ui-grid-letter class, where letter is ‘a’, ‘b’, ‘c’ or ‘d’.

  • ui-grid-a – two columns
  • ui-grid-b – three columns
  • ui-grid-c – four columns
  • ui-grid-d – five columns

In the grid container, the elements have the class ui-block-letter, where letter starts from ‘a’ and goes in a sequential manner for each block in row. Each new row should start with ui-block-a
A three column grid layout example:

[html]
<div class="ui-grid-b">
<div class="ui-block-a">col 1, row 1</div>
<div class="ui-block-b">col 2, row 1</div>
<div class="ui-block-c">col 3, row 1</div>

<div class="ui-block-a">col 1, row 2</div>
<div class="ui-block-b">col 2, row 2</div>
<div class="ui-block-c">col 3, row 2</div>
</div>
[/html]

Every block from this grid example will occupy 33% from the width of the device and will have three columns and two rows.

If you haven’t already, setup your new project to work with PhoneGap and jQuery Mobile by following this basic cross-platform mobile app tutorial. You can also check other interesting tutorials on this topic from the mobile development category.

Open index.html from www and add into the <body> the following code:

[html]
<div data-role="page" id="home">
<div data-role="header">
<h1>DigitalNoiz</h1>
</div>
<div data-role="content">
<h2>Gallery</h2>
<div id="gallery" class="ui-grid-a"></div>
</div>
</div>

<div data-role="page" id="picture">
<div data-role="header">
<a href="#" data-rel="back" data-icon="arrow-l">Back</a>
<h1>DigitalNoiz</h1>
</div>
<div data-role="content">
<div id="pic"></div>
</div>
</div>
[/html]

The home page will list in a grid the photos from the device and the picture page will show the photo you click from the grid.

Because images from the device have big resolution open css/style.css and add:

[css]
img{
width:100%;
}

.thumbnail{
padding:5px;
height:150px;
}

#gallery img{
height:100%;
}
[/css]

This will make sure that the images will be resized to fit the layout. In a real application you should generate real thumbnails for the photos to optimize the speed.

Now we need to have access to the file system of the device. Open js/script.js an create a function getFileSystem() that we’ll run onDeviceReady(). Use the window.requestFileSystem(CONSTANTS, 0, onSuccess, onError) function, where CONSTANTS is LocalFileSystem.PERSISTENT that is used for storage that can’t be removed without the user or application permission, or LocalFileSystem.TEMPORARY that is used for storage with no guarantee of persistence. onSuccess is the callback function that runs when we get the file system and onError is the callback function that runs when an error occurs.

In this example I use the file structure from Android to get the photos, but this can be easily modified to work with other platforms if you know the structure of the that file system.

[js]
function getFileSystem(){
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fileSystem){ // success get file system
var sdcard = fileSystem.root;
sdcard.getDirectory(‘dcim’,{create:false}, function(dcim){
var gallery = $(‘#gallery’);
listDir(dcim, gallery);
}, function(error){
alert(error.code);
})
}, function(evt){ // error get file system
console.log(evt.target.error.code);
});
}
[/js]

The fileSystem.root is an DirectoryEntry object that on Android points on the sdcard.

DirectoryEntry properties:

isFile – always false. (Boolean)
isDirectory – always true. (Boolean)
name – the name of the directory. (DOMString)
fullPath – the absolute path. (DOMString)

DirectoryEntry methods:

getMetadata – metadata about the directory.
moveTo – move the directory to a different location on the file system.
copyTo – copy the directory to a different location on the file system.
toURI – locate the directory by URI.
remove – removes the directory if it’s empty.
getParent – get the parent of the directory.
createReader – create a DirectoryReader object to read entries from the directory.
getDirectory – create or find a child directory.
getFile – create or find a child file.
removeRecursively – removes the directory and all of it’s content.

On the listDir function we pass as parameters the dcim DirectoryEntry object and the DOM object where we want to list the photos. From the DirectoryEntry object we need to create a DirectoryReader object by using createReader() function. The DirectoryReader object has one method readEntries(onReadSuccess, onReadError) where onReadSuccess is the success callback function and onReadError is the error callback function. onReadSuccess receives as parameter an array of DirectoryEntry and FileEntry objects, onReadError receives as parameter a FileError object.

FileEntry properties:

isFile – always true. (Boolean)
isDirectory – always false. (Boolean)
name – the name of the file. (DOMString)
fullPath – the absolute path. (DOMString)

FileEntry methods:

getMetadata – metadata about the file.
moveTo – move the file to a different location on the file system.
copyTo – copy the file to a different location on the file system.
toURI – locate the file by URI.
remove – removes the file.
getParent – get the parent of the file.
createWriter – create a FileWriter object to write to a file.
getDirectory – create or find a child directory.
file – create a File object

FileError properties:

code – one of the constants: NOT_FOUND_ERR, SECURITY_ERR, ABORT_ERR, NOT_READABLE_ERR, ENCODING_ERR, NO_MODIFICATION_ALLOWED_ERR, INVALID_STATE_ERR, SYNTAX_ERR, INVALID_MODIFICATION_ERR, QUOTA_EXCEEDED_ERR, TYPE_MISMATCH_ERR, PATH_EXISTS_ERR

When we read entries from the DirectoryReader object we put in a two column grid an image with the full path of every entry.

[js]
function listDir(directoryEntry, domParent){
$.mobile.showPageLoadingMsg(); // show loading message

var directoryReader = directoryEntry.createReader();

directoryReader.readEntries(function(entries){ // success get files and folders
for(var i=0; i<entries.length; ++i){
if( i%2 == 0) domParent.append(‘<div class="ui-block-a"><div class="thumbnail"><img src="’+entries[i].fullPath+’" title="’+entries[i].name+’" /></div></div>’);
else domParent.append(‘<div class="ui-block-b"><div class="thumbnail"><img src="’+entries[i].fullPath+’" title="’+entries[i].name+’" /></div></div>’);
//console.log(entries[i].name);
}
$.mobile.hidePageLoadingMsg(); // hide loading message
}, function(error){ // error get files and folders
alert(error.code);
});
}
[/js]

To show the photo when we click one from the grid create a function showImage() that will set the content of the picture page with that photo and will show the picture page. Invoke showImage() on onDeviceReady().

[js]
/* show an image */
function showImage(){
var imgs = $(‘#gallery img’);
imgs.live(‘click’, function(){
var title = $(this).attr(‘title’);
$(‘#picture h1′).text(title);
$(‘#pic’).html($(this).clone());

$.mobile.changePage($(‘#picture’));
});
}
[/js]

Now you have your own photo gallery app. Have fun!

Read more from Android, Mobile

Leave a Reply

required
required

Note: HTML is allowed. Your email address will never be published.

Subscribe to comments