Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Occasionally unresponsive back button on jQueryMobile PhoneGap app

I've created an app using jQuery Mobile (1.3.1) and PhoneGap (3.4), and have skinned it to have a fairly "flat" looking interface:

home screen

I'm having some trouble where, only on iOS, and only occasionally, the "back" button on only one certain screen becomes unresponsive. The same HTML & CSS for the back button on other screens seems fine, it's just this one screen. Here it is in chrome with the button selected in devtools to highlight its hit area:

back button

And just for good measure, here's the header as well:

header

The code for this screen's header is the same for just about every screen in the app:

<div data-role="header" data-theme="e" data-position="fixed" data-tap-toggle="false">
    <h1>Event Detail</h1>
    <a data-rel="back">Back</a>
</div>

We've found that, should the user get stuck on this screen and force-close the app, the button seems to work as expected in subsequent use.

So my current theory is that the header is somehow getting in the way of the back button (sometimes). The fact that it's not every time makes me not really believe this theory completely, however.

The button has its z-index set to 10 and the header's z-index is left at the default (which is 1, correct?). So even if it were the header getting in the way, my understanding is that the z-index of 10 should put the button "on top" and give it the first opportunity to receive the click/tap event.

The app uses jQueryMobile 1.3.1 because of the timing of when and how it was created, and upgrading is not a reasonable option at this moment. (There have been a significant number of breaking changes in 1.4.x)

I have debugged the app on both iOS and Android and no JavaScript errors are thrown. I'm at a total loss for what to do. This app is in the process of rolling out to thousands of users and there's a high likelihood that many, possibly most, will run into this bug. I would rather not have to explain (with my tail between my legs) that force-closing is the only way to fix this... but that's what I've been doing so far.

Does anyone have any advice or ideas on how to fix this?


Update 1:

I've noticed while remote-debugging the app in Safari over USB that I can watch the classes on the back button change, when tapped, from ui-btn-up-e to ui-btn-hover-e briefly to ui-btn-down-e and back to ui-btn-up-e -- and yet the app is not going back! :(

And as requested, here is the CSS applied to the header, the H1, and the back button: (just the "computed" final values, not all of the intermediary overridden values)

header div:

-webkit-background-clip: border-box;
-webkit-background-origin: padding-box;
-webkit-background-size: auto;
background-attachment: scroll;
background-clip: border-box;
background-color: rgb(179, 27, 27);
background-image: none;
background-origin: padding-box;
background-size: auto;
border-bottom-color: rgb(179, 27, 27);
border-bottom-style: solid;
border-bottom-width: 1px;
border-image-outset: 0px;
border-image-repeat: stretch;
border-image-slice: 100%;
border-image-source: none;
border-image-width: 1;
border-left-color: rgb(179, 27, 27);
border-left-style: solid;
border-left-width: 0px;
border-right-color: rgb(179, 27, 27);
border-right-style: solid;
border-right-width: 0px;
border-top-color: rgb(179, 27, 27);
border-top-style: solid;
border-top-width: 1px;
color: rgb(255, 255, 255);
display: block;
font-family: MyriadPro, Helvetica, sans-serif;
font-weight: bold;
height: 45px;
left: 0px;
padding-top: 1px;
position: fixed;
right: 0px;
text-shadow: rgb(85, 85, 85) 0px 1px 0px;
top: -1px;
width: 320px;
z-index: 1000;
zoom: 1;

H1:

color: rgb(255, 255, 255);
display: block;
font-family: MyriadPro, Helvetica, sans-serif;
font-size: 18px;
font-weight: bold;
height: 23px;
margin-bottom: 10px;
margin-left: 48px;
margin-right: 48px;
margin-top: 12px;
min-height: 19.799999237060547px;
outline-color: rgb(255, 255, 255);
outline-style: none;
outline-width: 0px;
overflow-x: hidden;
overflow-y: hidden;
padding-bottom: 0px;
padding-left: 0px;
padding-right: 0px;
padding-top: 0px;
text-align: center;
text-overflow: ellipsis;
text-shadow: rgb(85, 85, 85) 0px 1px 0px;
white-space: nowrap;
width: 224px;
zoom: 1;

Back button:

-webkit-background-clip: border-box;
-webkit-background-origin: padding-box;
-webkit-background-size: auto;
-webkit-box-shadow: none;
background-attachment: scroll;
background-clip: border-box;
background-color: rgb(179, 27, 27);
background-image: none;
background-origin: padding-box;
background-size: auto;
border-bottom-color: rgb(179, 27, 27);
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-bottom-style: solid;
border-bottom-width: 0px;
border-image-outset: 0px;
border-image-repeat: stretch;
border-image-slice: 100%;
border-image-source: none;
border-image-width: 1;
border-left-color: rgb(179, 27, 27);
border-left-style: solid;
border-left-width: 0px;
border-right-color: rgb(179, 27, 27);
border-right-style: solid;
border-right-width: 0px;
border-top-color: rgb(179, 27, 27);
border-top-left-radius: 4px;
border-top-right-radius: 4px;
border-top-style: solid;
border-top-width: 0px;
box-shadow: none;
color: rgb(255, 255, 255);
cursor: pointer;
display: block;
font-family: MyriadPro, Helvetica, sans-serif;
font-weight: bold;
height: 31px;
left: 5px;
margin-bottom: 0px;
margin-left: 0px;
margin-right: 0px;
margin-top: 0px;
padding-bottom: 0px;
padding-left: 0px;
padding-right: 0px;
padding-top: 0px;
position: absolute;
text-align: center;
text-decoration: none solid rgb(255, 255, 255);
text-shadow: rgb(0, 0, 0) 0px 1px 0px;
top: 15px;
vertical-align: middle;
width: 60px;
z-index: 10;
zoom: 1;
like image 552
Adam Tuttle Avatar asked May 30 '14 13:05

Adam Tuttle


People also ask

Can I use PhoneGap with jQuery Mobile?

Since PhoneGap is frequently used in conjunction with jQuery Mobile, we wanted to offer a few tips and recommendations to help you get started. The initial application document is loaded by the PhoneGap application by a local file:// URL.

What is PhoneGap?

Building PhoneGap (Cordova) apps with jQuery Mobile PhoneGapis an HTML5 app platform that allows developers to author native applications with web technologies and get access to APIs and app stores.

Does PhoneGap work with honeycomb navigator?

On Android PhoneGap has as special navigation helper in place to work around issues with Honeycomb navigator.app.backHistory that replaces window.history.back.

How do I access cross-domain pages from within a PhoneGap application?

Your ability to access cross-domain pages from within a Phone Gap jQuery Mobile application is controlled by two key things: $.support.cors and $.mobile.allowCrossDomainPages, and can also be influenced by the white list feature in later builds of PhoneGap.


1 Answers

First let me tell you that your problem probably don't have nothing to do with button/header CSS. If this error is showing sporadically and only during back function your problem is happening probably due to data-rel="back" functionality.

Unlike classic href page movement, data-rel="back" uses javascript navigation history which may or may not work depending on your app content. Because jQuery Mobile uses AJAX for page handling (and from your button I can see you are using this method) it also has its own way of handling navigation history.

Now, lets say your application heavily uses dynamic content generation (including content removal), and for example previous page is removed from the DOM, in this case data-rel="back" will not work. If previous page don't exist you will not be able to move back. There are several other factors that can also affect this functionality.

What you can do to solve this problem:

  1. Give this button a class name or even an id. After that bind a click event to it (vclick even better because it is as fast as tap, without 300ms delay, and works on desktop and mobile browsers a like) and add a console output each time you click on this button. So you would do it like this:

    $(document).on('vclick', '#button-ID-goes-here', function(){ 
        console.log('Problematic button');
    });
    

    This way you can test if button has been clicked.

  2. Next thing is little bit complicated. You never posted your page HTML but looking at your page image I think you are using correct jQuery Mobile paradigm, basically you are using data-role="page" div containers as page containers. You would be amazed how many jQuery Mobile developers don't know/understand they need/must have it if they want a proper jQuery Mobile app.

    Take a look at a page that holds this button in its header. Bind a pagebeforeshow event to that page and monitor will it trigger, and if it triggers you can use it to show previous and next page.

    Working example: http://jsfiddle.net/Gajotres/vds2U/72/

    $(document).on('pagebeforeshow', '.ui-page',function (e, data) {
        alert("Previous page : " + data.prevPage.attr('id') + " - Next page: " + $.mobile.activePage.attr('id'));
    }); 
    

    Use this solution to check if next page is correct and if it even exist. If this page event is not triggering when you click back button then something bad is happening.

  3. Use this next code as a workaround. Basically use page events and remember your previous page. Because you are currently using back button this solution will be viable here. We will use pagebeforeshow event to find out our previous page, we will store it into some JavaScript object (it will persist between page transitions).

    Working example: http://jsfiddle.net/Gajotres/vds2U/73/

    $(document).on('pagebeforeshow', '#second',function (e, data) {
        pageHandler.prevPage = data.prevPage.attr('id');
    
        $(document).on('click', '#custom-back-button',function () {
            $.mobile.changePage( "#"+pageHandler.prevPage);
        });    
    }); 
    
    var pageHandler = {
        prevPage : null
    }
    

    This is complete custom solution to data-rel="back" page handling.

like image 137
Gajotres Avatar answered Oct 05 '22 23:10

Gajotres