IE10 Touch Interactions
Published on 8/22/2013
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);
});