Tuesday, April 24, 2012

Jquery Mobile - iOS location bar hiding research


So I’ve been trying to learn about location bar behavior of the iOS Safari browser on the iPhone/iPod Touch, and just wanted to share some of my observations. All of the observations below, are based on a test-case I wrote, which can be found here:

Observations:

  • The dropping of the location bar is triggered by the clicking of a link that has a reference to an external file. - You can preventDefault and stopPropagation on the “click” event so the link does nothing, but the location bar will still drop down. - The location bar does not drop down for links that contain just hashes. - We’re often compared to jQTouch in this department …” Why doesn’t jQTouch have this location bar problem?” and its because they only use internal content so their links all use hashes.
  • Loading content via XHR does NOT trigger the location bar to drop down.
  • Links with href=”#” cause the document to scroll to the top and the location bar is updated. You need to preventDefault() on the “click” event to kill this behavior.
  • Links with hashes to non-existent content do nothing. Location bar is updated though. preventDefault() on the “click” event kills this behavior.
  • Updating location.hash does NOT cause the location bar to drop down.
  • Calling preventDefault() and stopPropagation() on “touchend” events seem to have no impact on the location bar behavior or the default click behavior.

Fastclick Fixes Branch:

Given the observations above, I’m a bit puzzled as to what exactly moving our link click handler to vclick accomplishes. I originally created the branch based on previous discussions I had with Scott that calling preventDefault() on any touch event prevents the location bar from dropping, but I’m not seeing that with my test case above. After thinking about it a bit, I think I know why links in jQM are broken on the fastclick-fixes branch. My touchend handler that does a preventDefault() is called before vclick is dispatched … this is important because when my vclick handler kicks in, it creates a virtual event event based on the native touchend event … since that native event already has preventDefault called on it, the vclick event I create also has its preventDefault set because it copies it off the native event. For a vclick event, if preventDefault has been called on it, it automatically blocks any click events, which is why the links don’t fire.
So now I’m trying to figure out what to do. I still occasionally see the location bar drop down on the jquerymobile.com/test/ site, but it doesn’t happen most of the time. What I’m wondering is if it seems suppressed because we are also scrolling to the top. I just added that to the test case above, but I can’t test that theory since Adobe’s public network, which all my devices communicate through just went off line. < sigh >

Final Analysis

I spent most of today so far trying to figure out why moving click handling to vclick stops the location bar from dropping down. And I think I’ve figured some things out.
  • We are NOT doing a preventDefault on the touchend event. So that isn’t what is preventing the location bar from dropping.
  • Commenting out the $.mobile.showPageLoadingMsg() call in loadPage() is enough to make the location bar start dropping down anytime you click on a link to an external file.
  • Armed with this knowledge, I went down the path of thinking it had to do with the fact that we were using CSS3 animations for the load image. Turns out it contributes but that isn’t the whole story.
  • It seems as if there are a couple of things at play here:
-- The amount of work that is done in a touchend callback. -- The speed at which the user taps the link.
Moving the click handling to the “vclick” event places all that page loading logic, including the display of the loading dialog, on to the touchend notification. It seems like there is logic in Safari that tracks the amount of time between the touchstart and touchend events. If the time between these 2 events exceeds some “show location bar” threshold, but is less than the threshold that shows the “Open, Open in New Page, Copy, Cancel” dialog, the location bar is guaranteed to drop down when the click event is dispatched.
If the time between the 2 events is less than this “show location bar” threshold, the display of the location bar when the click event is fired seems to depend on how long, or the amount of work was generated off of the touchend event. In the case we have today where we are processing stuff on “vclick”, which is really touchend, we are doing quite a bit of work:
  • Search the current page for the active button. (vclick handler)
  • Search the entire document for an active button. (showPageLoadingMsg())
  • Re-inserting the load dialog markup at the end of the DOM. (triggers a reflow request)
  • Retrieval of scroll position for positioning of the dialog. -- This triggers a synchronous layout.
  • Setting of inline CSS on the loading dialog for positioning. -- Triggers an async layout and paint request.
  • Setting of the ui-loading class on the HTML element. -- Causes the body and page elements to adjust their overflow. -- Displays the dialog and starts the CSS3 animations.
  • Kick-off an ajax load.
I think this amount of work that we are doing and generating for the browser is enough to exceed this theoretical threshold that keeps the location bar from dropping. In a nutshell, I think we’re just getting lucky.

No comments:

Post a Comment