IOS 7 status bar with fixed footer navbar in Cordova/JQuery Mobile

To avoid your content scrolling underneath the new IOS 7 status bar, you have a few choices but in most situations, org.apache.cordova.statusbar is the best solution.

From the CLI:

$ cordova plugin add org.apache.cordova.statusbar

And you can then turn the transparent IOS7 status bar into one which behaves as it does in IOS6 with the following in your config.xml:

<preference name="StatusBarOverlaysWebView" value="false" />
<preference name="StatusBarBackgroundColor" value="#000000" />

However, if you have a fixed navbar in the footer such as this to approximate the look of a tab bar in the new IOS7  Human Interface Guidelines:

<div data-role="footer" data-id="allot_footer" data-position="fixed">
    <div data-role="navbar" data-iconpos="bottom">
        <ul>
            <li><a href="#browse" data-id="footer_browse" data-theme="d" data-icon="grid">Browse</a></li>
            <li><a href="#find" data-id="footer_find" data-theme="d" data-icon="search">Find</a></li>
        </ul>
    </div>
</div>

then you’ll find that the statusbar plugin pushes the navbar down off the bottom of the page by the height of the status bar. So, for a fixed bottom navbar, the solution I’ve adopted inn the end is to forget the statusbar plugin and to allow the status bar to overlay my content. However, to create a bit of space at the top of the page for it to sit, I used this Gist from Shazron to arrive at:

function onDeviceReady() {
    if (parseFloat(window.device.version) >= 7.0) {
        $("div.ui-header").css("padding-top", "20px"); 
        }
    ...
    }

Note that you’ll need to install org.apache.cordova.device using the CLI:

$ cordova plugin add org.apache.cordova.device

It now looks fine on startup but if you need to scroll your content, it’ll still get overlayed by the IOS7 status bar so make your header fixed too:

<div data-role="header" data-id="allot_header" data-position="fixed" data-theme="d">
    <h1>Browse</h1>
</div>

Hoping that IOS7 issues will all become a distant memory very soon, but this is what works for me at the moment.

Migrating Cordova/JQuery Mobile app from Android to iOS

Some notes on this process in case they are useful to others:

Back button

Android specifically prohibits back buttons due to the presence of a physical Back button on all Android mobiles. However, in iOS, it’s the norm. JQuery mobile does provide an easy to insert header back button :

<a href="#" data-role="button" data-rel="back" data-icon="arrow-l">Back</a>

but it uses the JQuery theme. If you want to make it look like an iOS back button, this article makes it relatively easy.

Navigation

In Android,with Cordova, we have to use absolute URLs for navigation:

navigator.app.loadUrl("file:///android_asset/www/mypage.html");

In iOS, we can use the much simpler form:

location.href = "mypage.html";

Seemingly random clicks firing intermittently

It seems that using JQuery Mobile’s ‘vclick’ event in iOS can cause problems, although the same code was working fine in Android. I was seeing a page change, followed by another page change as if something in the first page loaded had been clicked. After trying all sorts of event undelegation and unbinding, I finally looked at JQuery’s vclick documentation. This explains that there is a slight delay between the JQuery’s ‘vclick’ event  and the native ‘click’ event. When the content under the clicked point changes (as in this case with a new page load), the click event can actually fire on the changed rather than the original content. In situations like this, the recommendation is to use the ‘click’ rather than ‘vclick’ which solved the problem for me.

External pages

My app opens links to an external site for further information. In Android, simply specifying a full http:// prefix URL was enough to ensure that it loaded in the device’s normal web browser. In iOS, the default to seems to be to load it within the embedded brwoser which is being used to run your Cordova application, which is far from ideal. The workaround seems to simply add:

target = '_blank'

to all external links – they then fire up the iOS device’s Safari browser.

Phonegap for Android JSCallback error meaning OnDeviceReady not called

Struggled for hours last night while trying to migrate this great example app Sample App using the PhoneGap Database API to work on Android using Eclipse and an Android emulator. Everything was going well until I tried to link to a second page using a query string parameter to pass through the id of the the employee. This resulted in:

JSCallback Error: Request failed. at file:///android_asset/www/js/cordova.js:3698

Eventually stumbled across PhoneGap – migrating iOS applications to Android (Part 1) which pointed out that this is a documented Android issue and proposed the following workaround:

function loadEmployeeDetail(id) {
localStorage.setItem( “employeeId”, id );
navigator.app.loadUrl(“file:///android_asset/www/employeedirectory/employeedetails.html”);
}

And then reading this  in employeedetails.html using:

id = localStorage.getItem( “employeeId”);

However, I was still having problems calling OnDeviceReady() until I stumbled across deviceReady not working in PhoneGap application, how to? which suggested that adding brackets into the function name in the eventListener method might be the problem, giving:

 document.addEventListener(“deviceready”, onDeviceReady(), false);

Problem solved.