This is another excerpt from the upcoming book “Build Mobile Websites and Apps for Smart Devices” by Earle Castledine, Myles Eftos and Max Wheeler. BuildMobile is exclusively publishing a complete chapter from the book, the chapter on Mobile Web Apps, this is the second section on Events.
2. Events
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. This approach will pay dividends in Chapter 7, Introducing PhoneGap when we use PhoneGap to bring our app into the native world.
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:
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:
$("#tab-bar li").click(function(e){ e.preventDefault(); alert("Coming soon!"); });
Running Scripts
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 4.2, “We’ve captured the click event and used it to display a message” 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:
// 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!"); });
2.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:
$("#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 summarized in the book.
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, as we discussed briefly in Chapter 2, Design for Mobile. 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.
So far, we’ve wound up a subset of mouse events—nothing too fancy. In the next chapter, we’ll explore some advanced touch features of mobile devices like swiping and gesturing. In the meantime, let’s continue our investigation of simple touch events.
2.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:
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:
$("#tab-bar li").bind(touchEndEvent, function(){ alert("Coming soon!"); });
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. In Chapter 6, Polishing Up Our App, we’ll have a look at removing this, with the “quick click.” For the rest of this chapter, though, we’ll err on the side of simplicity and rely on the good old click
event.