Touch screen swipe/scroll with IE10 support (Part 2)

In part 1 I showed how to add a swipe effect to a scrolling area using only the new CSS properties in IE10. I also added some JavaScript to create the same effect in other touch-supported browsers like iOS.

The CSS stuff in IE10 is great, but there is only so much you can do with it. If we want a completely custom effect we need to get involved with IE10’s touchscreen event model. Things get a bit more complicated now…

This demo uses JavaScript in IE10 to achieve the same swiping effect as the CSS solution in part 1. However, if you swipe harder you will move three places instead of one. This way you can essentially flick an item from one end to the other. Not the greatest effect in the world, it’s just an example.


 

You’ll notice the effect is not as smooth as the native version. As a general rule if you can use native touch interaction – do so! If you want highly custom effects, think carefully about whether they’re worth the trade-off. My silly example here is most certainly NOT.

Here’s the code on jsfiddle. http://jsfiddle.net/timwhitlock/DPtUv/

And now for the gotchas  –

 

1. Alternative touch events via Pointer model

First and foremost IE10 doesn’t have the same touch event model as any other browsers. They’ve gone their own way and created a family of MSPointer* events. This suits Windows 8 better because unlike an iPhone, you could be using your finger or a mouse or a pen interchangeably on the same device. It does however mean writing vendor specific code.

In my demo I’m using a bit of abstraction that looks like this.

Not hard, but there’s more …

 

2. Native interaction and DOM events are largely mutually exclusive

The oddest thing about the IE10 model is that if we ask the browser to take care of some touch interaction via CSS properties (like -ms-scroll-snap-type)  no DOM events will be fired! This is quite aggravating. The main problem here is that once you’ve told the browser you’ll be taking care of touch interaction, it stops doing a whole bunch of other stuff that’s really useful – such as preventing clicks inside an area that’s being swiped.

There are some exceptions to this. In my demo I am applying -ms-touch-action: pan-y; to the scrolling area’s children. This allows the whole page to be vertically scrolled, but the MSPointerMove event is still fired on our element.

 

3. Cancelling taps

While touch events are firing Windows 8 will still fire click events from child elements. In other words, if we’re handing touch interaction via JavaScript the browser is not going to help us out by identifying an obvious swipe and preventing clicks. (iOS does this transparently). This means more code for IE10.

I solved this by maintaing the state of any current swipe and binding a click event which has its propagation stopped. It looks like this:

element.addEventListener( 'click', function( event ){
    isSwiping && event.stopPropagation();
}, true );

 
The final useCapture argument is important as it ensures that we get the event before the link does. The links themselves must also be bound with useCapture.

 

4. MSPointerUp doesn’t fire if you leave the scroll area

If you begin a sideways swipe, but release your finger outside the scrolling area, a MSPointerUp event is not fired on the element that originally fired MSPointerDown. In this demo no ‘touchend’ callback would mean the scrolling items getting stuck wherever your finger left.

I solved this by simply applying a second MSPointerUp event on the window which calls the final handler too. Be careful if you have a page with other touch interactions going on – my example here doesn’t.

Note: the iframe housing of the demo above makes this fix hard to see. Open it in a new window.

 

5. Bug when setting scrollLeft

In this demo the scrollLeft property is set on MSPointerMove in order for the scroll to follow your finger. A bug in IE10 means as soon as you set this property no further events are fired.

In our demo we’re using overflow-x: scroll; for accessibility on non-touch devices. Setting this to hidden fixes this bug, but of course makes it less accessible.

You might think you could just set this to hidden for touch devices only, but consider that with Windows 8 there is no such thing as a ‘touch device’. Touch is just one form of input, and a mouse click or pen interaction could come at any time.