For many users, the most noticeable difference between a website and a native
application is the way each one transitions between screens or pages. Native applications
respond instantly, sometimes sliding or fading content on and off the screen, whereas
websites show a few seconds of white screen before the next page’s content starts loading
in.There are a number of ways we can make our web app feel more responsive. As you’ve
probably guessed, using Ajax to pull in page components to avoid a refresh is an important
component of our strategy.
Before we load in content with Ajax, and use transitions and animations to swoosh things
around, we’ll need to capture some events. For the most part, handling events on mobile is
no different from the desktop, but there are a few key points worth learning about, so we’ll
start there.
Let’s begin by capturing click events on the links in our tab bar. As a quick refresher, here’s
the markup for the navigation:
listing 1. ch4/02-clicks.html (excerpt)
<ul id="tab-bar"> <li id="tab-spots"> <a href="#page-spots"> Spots </a> </li> <li id="tab-sighting"> <a href="#page2"> Add a sighting </a> </li> <li id="tab-stars"> <a href="#page3"> Stars </a> </li> </ul><!-- #tab-bar -->
|
To verify that we can capture click events on each list item, we’ll fire off another
alert message:
listing 2. javascripts/ch4/02-clicks.html (excerpt)
$("#tab-bar li").click(function(e){ e.preventDefault(); alert("Coming soon!"); });
|
Note:
All the code snippets that follow will assume the code is either inside, or is called
from inside the ready function. That way, we’re sure that our
document is loaded before we run any code that relies on its presence.
We’ve attached our function to the click event on all the list items, and we’ve
prevented the event’s default behavior from occurring, so the browser won’t navigate away to
the link address. Fire that up on your mobile phone to make sure it’s working. It might be a
boring alert message, but seeing your code running in the palm of your hand is fairly cool.
Figure 1 shows the output on the Android browser.
The DOM click event comprises two separate steps:
a mousedown, followed by a mouseup. Evidently, it’s an event designed for a mouse, where clicking takes
just a fraction of a second, and is done after the user has moved the mouse into the correct
position. This interaction doesn’t always replicate so well on the touch screen, and the
click can end up feeling a bit sluggish on some devices.
For a slight improvement, only target the mouseup event; however, the mouseup
event is independent of the click event, so we still
need to stop the click from following the link to another page. Once we’ve curtailed the
hyperlink, we can run our code in the mouseup event
handler, which we attach using jQuery’s bind method:
listing 3. javascripts/ch4/03-mouseup.js (excerpt)
// Stop clicks from following links $("#tab-bar li a").click(function(e){ e.preventDefault(); });
// Do our magic on mouse-up! $("#tab-bar li").bind("mouseup", function(){ alert("Coming soon!"); });
|
1. Simple Touch Events
Although mobile devices can pretend that your finger is a mouse pointer, and fire
regular click events, they also generate touch events, which are more
accurate and useful. However, these come loaded with so many cross-browser booby traps,
that you’ll start wishing you could go back to developing for IE6!
Fortunately for us, detecting a touch is simple enough:
listing 4. javascripts/ch4/04-touchend.js (excerpt)
$("#tab-bar li").bind("touchend", function(e){ alert("Coming soon!"); });
|
Most recent mobile touch devices will fire the touchend event. This fires when the user lifts their finger from the
screen after touching it. There are also a few other events that map quite nicely to the
mouse equivalents, as Table 1 summarizes.
Table 1. Touch events and their corresponding mouse events
Touch event | Mouse event |
---|
touchstart | mousedown |
touchmove | mousemove |
touchend | mouseup |
| mouseover |
Notice that there’s no mouseover event on a mobile
device—after all, it’s impossible to know where you’re hovering your finger! It might be a
small detail, but it has some interesting implications for user interaction design. No hover states or tooltips means the
user can no longer move their mouse around the screen looking for help, so you have to
make your interfaces nice and self-explanatory.
2. Clicking with Feature Detection
Touch events can be more responsive and accurate, but they’re
not supported on all devices. We may be focusing our attention on the latest generation of
super-duper phones, but it’s always a good idea to provide support for as many browsers as
possible. In addition, relying solely on touch events makes it impossible to test your app
on a desktop browser. It’s great fun to see your hard work displayed on a phone, but not
so fun having to switch between desktop and mobile phone copious times as you’re testing
features.
You can (and should) use the various device emulators that will
interpret your mouse clicks as touch events, but if you’re used to desktop web
development, being able to test your apps in your desktop browser is very
convenient.
To make our code run on both new and old mobile browsers—and
desktop browsers too—we’ll implement a piece of feature detection.
Feature detection involves probing the user’s browser to see which cool features we can
use, as well as (we hope) providing adequate fallbacks for features that are
missing.
We can do this by assigning a few variables:
listing 5. javascripts/ch4/05-touchdetect.js (excerpt)
var hasTouch = "ontouchend" in document, touchEndEvent = "touchend";
// Default to mouse up, if there's no touching if (!hasTouch) { touchEndEvent = "mouseup"; }
|
If a browser supports touch events, the window’s document
object will have the ontouchend event in it. We
create a variable called touchEndEvent, which initially contains the
string "touchend"; we replace this with "mouseup" if
our touch detection turns up nothing.
Now that we have a variable containing
the event we want to target, we can bind the variable instead of a static string, and the
correct event will be handled based on the device’s capabilities:
listing 6. javascripts/ch4/05-touchdetect.js (excerpt)
$("#tab-bar li").bind(touchEndEvent, function(){ alert("Coming soon!"); });
|
Tip:
Ternary Operator
There’s a shortcut in JavaScript (and in many other programming languages) that
allows you to set a variable conditionally as we did above. It’s called the
ternary operator. It has the syntax a ? b :
c, which translates to: if a is true, return b; otherwise, return c.
So we could have written the touchend assignment above as:
var touchEndEvent = "ontouchend" in document ? "touchend" : "mouseup";
This reads as “if document contains the property ontouchend, return "touchend"; otherwise, return
"mouseup".” The result is then assigned to the
touchEndEvent variable. Ternary operators are a terse (some would
argue “cryptic”) way to do a conditional assignment, and, as with the traditional
programmer battle of tabs versus spaces, you either love the ternary operator or hate
it!
Without trying to scare you, there is still more to say on the topic of
clicking. Even the simple click has a raft of new problems when moving from the mouse to
the finger, one being the implications of the double-click. Your mobile device needs to
wait a relatively long time to see if your click is going to become a double-click, and that delay manifests itself as a small but noticeable lag.