Phantom Limb

phantom-limbWith some mobile web app projects coming up at Vodori, I cleaned up Phantom Limb, a mobile web dev utility. Phantom Limb does just one thing:

It fires a corresponding touch event for each mouse event on the page.

Now you can test your mobile web app with your browser.

Mobile browsers ensure basic compatibility with normal sites by simulating mouse events. When a user touches a DOM node, the following events fire:

  1. `touchstart`, as a finger touches the screen
  2. `touchmove`, while the finger moves
  3. `touchend`, when the finger lifts off the screen

If that node is clickable (it’s a button, a link, or has a click event handler), the browser rapidly fires off the next series of events:

  1. `mouseover`
  2. `mousemove` (only once)

And if those events don’t change the DOM, the browser finally fires:

  1. `mousedown`
  2. `mouseup`
  3. `click`

This behavior ensures that mouse events will function in a mouse-less environment, but you get more control and create a better experience in your mobile web app by using native touch events.

Generally not a problem, except desktop browsers don’t do touch events, so you’ll have to do all your testing on the device itself (or the iOS Simulator app included with the iOS SDK), without the benefit of a decent debugger or comfortable posture.

Phantom Limb makes desktop browsers simulate touch events

Phantom Limb makes desktop browsers simulate touch events by dispatching a custom touch event for every mouse event it receives. A `mousedown` fires a `touchstart`. A `mousemove` fires a `touchmove` if the mouse is down, and a `mouseup` fires a `touchend`. These custom events are also assigned a `touches` array containing a reference to the event, just like a real touch event in a mobile browser.

I’ve only really been running it in Safari. I’m primarily writing for iOS, but Chrome and Firefox should work okay, too. Gestures/multitouch are not currently supported (that’ll be quite the trick).

In Firefox, Phantom Limb converts inline `ontouchstart=”doSometing();”` handlers into `node.addEventListener(…)` handlers. Inline event handlers can’t be triggered by artificially dispatched events in Firefox. By adding listeners for inline handlers (and removing the inline handler) we can simulate touches for these nodes too.

…I lied. Phantom Limb does something else:

Phantom Limb replaces your mouse cursor with a creepy disembodied hand

I added this for my own amusement, and you can shut it off with the button in the bottom right corner. But it can serve a purpose while you’re designing and testing a mobile web app.

Fingers are kinda stubby, for one, and tend to be less accurate than a mouse cursor. By hiding the cursor and providing a sorta-inaccurate faux-finger to faux-poke the screen with, you’ll get a sense of how easy it’ll be to poke the right element on a real mobile device.

Also, your hand is opaque (I hope) and covers up some portion of the screen on a mobile device. By blocking part of the screen, you’ll be able to make sure the user will see everything they need to as they’re interacting with your app.

A basic Phantom Limb test page

And here’s Phantom Limb in action, applied to my on-again-off-again metronome iPad webapp. Run it in Safari to get the full effect.

Phantom Limb can be activated from this bookmarklet:

javascript:void(function(scriptSrc,config){var script=document.createElement(‘script’);script.src=scriptSrc;script.type=’text/javascript’;script.addEventListener(‘load’,function(){if(‘phantomLimb’in window){phantomLimb.init(config)}else{console.error(‘Phantom Limb could not be loaded’)}},false);document.head.appendChild(script)}(‘’,{src:’’,lefty:false}));

If you want to include it in your project, the latest source can be found on GitHub.

I’d love to read your suggestions or comments. And if you’re interested in working on developments like this, Vodori is currently hiring for positions in Chicago!