IE10 Touch Interactions

Published on 8/22/2013

Man using a touch screen device.
Man using a touch screen device.

Taking Advantage of Touch Screens

Since the touch screen craze began to boom with the introduction of the iPhone, web developers have been looking for ways to enhance their websites and applications with the addition of touch interactions. Not only can we create simple functions such as touch-swipeable carousels, but we can take it even further and add multi-touch gestures to a page.

For a long time, we simply had to code for iOS and Android which use the same set of touch events. With the new addition of Windows 8, however, comes the Internet Explorer 10 browser that carries it's own set of touch events that we need to code for to get the same functionality. While it is quite annoying to have to redo some of this work, there are some benefits to Microsoft's new approach.

Building a Carousel

For this example, we'll go over how to create a simple carousel control. For iOS and Andoird, the touch events that we will need are "touchstart", "touchmove", and "touchend". For IE10 we will need "MSPointerDown", "MSPointerMove", and "MSPointerUp". The IE10 events provide another challenge though. They are not simply for touch events, but for all interactions including mouse and pen. In order to differentiate, we would need to detect what form of input is being used within the event.

The jQuery library will be required for this example.

The HTML and CSS

First we need to set up the basic HTML and CSS for the carousel.

<div class="carousel clearfix">
    <div class="current">Item 1</div>
    <div>Item 2</div>
    <div>Item 3</div>
    <div>Item 4</div>
</div>

The CSS is hard coded for 4 pages for simplicity's sake.

.carousel { width: 400%; -ms-touch-action: none; }
.carousel > div { width: 25%; float: left; padding: 10px; }
.clearfix:after { content: ""; display: table; clear: both; }
* { box-sizing: border-box; }

Now we can start binding our touch events. We will create some variables to detect if we need the iOS/Android or IE10 touch events. We will also need a few global variables to use across all three events.

var touchStart = window.navigator.msPointerEnabled ? "MSPointerDown" : "touchstart";
var touchMove = window.navigator.msPointerEnabled ? "MSPointerMove" : "touchmove";
var touchEnd = window.navigator.msPointerEnabled ? "MSPointerUp" : "touchend";

var start;
var end;
var left;

Touch Start

$("body").on(touchStart, ".carousel", function (e) {
    //grab the initial touch location
    start = e.originalEvent.pageX || e.originalEvent.targetTouches[0].pageX;
    end = start;
        
    //grab the current page and left values
    var index = $(this).children("div.current").index();
    left = -1 * 100 * index;
});

Touch Move

$("body").on(touchMove, ".carousel", function (e) {
    //set the current finger position
    end = e.originalEvent.pageX || e.originalEvent.targetTouches[0].pageX;

    //prevent page scrolling
    e.preventDefault();

    //calculate the new position based on a percentage
    var width = $(this).children("div:first").width();
    var moveVal = left + (((end - start) / width) * 100);
    var move = moveVal + "%";

    //move the carousel
    $(this).css("margin-left", move);
});

Touch End

$("body").on(touchEnd, ".carousel", function (e) {
    //grab current page index, we will rubber band back to this if the carousel is not moved at least 50 pixels
    var index = $(this).children("div.current").index();
		
    if (end > (start + 50)) {
        //going left
        var prev = $(this).children("div.current").prev("div");
			
	//make sure we aren't all the way left
	if (prev.length > 0) {
	    //set the new current page
	    $(this).children("div.current").removeClass("current");
            prev.addClass("current");
            index = prev.index();
	}
    } else if (end < (start - 50)) {
	//going right
	var next = $(this).children("div.current").next("div");
			
	if (next.length > 0) {
	    //set the new current page
	    $(this).children("div.current").removeClass("current");
            next.addClass("current");
	    index = next.index();
	}
    }
		
    //set new left value
    var leftVal = -1 * 100 * index;
		
    //scroll the carousel to the final position
    $(this).stop().animate({ margin-left: leftVal + "%" }, 200);
});