Handling Click Events on a Tablet
One thing I discovered recently is that when using a web browser, tablets purposefully impose a 300ms delay on all click events so that they can differentiate between a click and gesture, such as swiping. When entering answers on MathScore, we present an on-screen number pad. If students pressed our buttons too quickly, the 300ms delay would have the effect of some button presses not registering, which was a huge usability problem.
My first solution was to use the ontouchstart handler and treat them like clicks. This seemed to work great, but had one issue: if a student wanted to scroll the screen downward, and did the swipe gesture on top of the keyboard, a button click would register and then the swipe would occur. The preferred action would have been to handle the swipe, but not process the button click.
My next approach was to integrate a tool called FastClick. At first, I thought this solution was perfect. After adjusting one of the constants within the file, it seemed that I had the best of both worlds, where button presses were very responsive, yet if you wanted to scroll on top of the keypad, it would scroll without registering a button press. In truth, I think this is a perfect approach, provided that you are a coordinated tablet user. The problem I discovered today with a group of 1st graders is the fact that some students initiate a slight swipe gesture when they poke at the buttons on the keypad. As a result, even though they appeared to be tapping the buttons, they were doing swipes, which meant the button presses were not registering.
So it turns out, directly handing ontouchstart was the lesser of 2 evils when compared with using FastClick, which I really didn't expect. The compromise is to disable swiping whenever your touch event starts on a button, so now my jQuery-enabled click handler looks like this:
function addClickHandler($jQueryElement, $function) {
$jQueryElement.on('touchstart click', function(e){
e.stopPropagation();
e.preventDefault();
$function();
});
}
So as you can see, the first argument it accepts is a jquery element, and the second is your custom function. By adding e.stopPropagation() and e.preventDefault(), I was able to disable the swipe gesture entirely when the touch event starts on a button.
If I were still using FastClick, the code would have looked like this instead:
function addClickHandler($jQueryElement, $function) {
$jQueryElement.click($function);
}
Obviously this looks appealing due to its simplicity. FastClick does some fancy stuff behind the scenes to override the click handler to take into account touchstart and a whole bunch of other things as well as the nuances of different tablet devices. It's a shame that I have to do away with FastClick.
Click handlers are needed all over my code, so relying on my addClickHandler() function allowed me to change the implementation from FastClick to the new approach in exactly one place. The alternative would be to directly embed the click handlers everywhere, which would lead to a lot more search and replace.
If you happen to be a web programmer and your audience is adults, I recommend that you look into FastClick to get the best possible compromise, but if your audience is young kids, I think the approach I settled on is ultimately best, even if it means swipe behaviors sometimes don't work as intended.
My first solution was to use the ontouchstart handler and treat them like clicks. This seemed to work great, but had one issue: if a student wanted to scroll the screen downward, and did the swipe gesture on top of the keyboard, a button click would register and then the swipe would occur. The preferred action would have been to handle the swipe, but not process the button click.
My next approach was to integrate a tool called FastClick. At first, I thought this solution was perfect. After adjusting one of the constants within the file, it seemed that I had the best of both worlds, where button presses were very responsive, yet if you wanted to scroll on top of the keypad, it would scroll without registering a button press. In truth, I think this is a perfect approach, provided that you are a coordinated tablet user. The problem I discovered today with a group of 1st graders is the fact that some students initiate a slight swipe gesture when they poke at the buttons on the keypad. As a result, even though they appeared to be tapping the buttons, they were doing swipes, which meant the button presses were not registering.
So it turns out, directly handing ontouchstart was the lesser of 2 evils when compared with using FastClick, which I really didn't expect. The compromise is to disable swiping whenever your touch event starts on a button, so now my jQuery-enabled click handler looks like this:
function addClickHandler($jQueryElement, $function) {
$jQueryElement.on('touchstart click', function(e){
e.stopPropagation();
e.preventDefault();
$function();
});
}
So as you can see, the first argument it accepts is a jquery element, and the second is your custom function. By adding e.stopPropagation() and e.preventDefault(), I was able to disable the swipe gesture entirely when the touch event starts on a button.
If I were still using FastClick, the code would have looked like this instead:
function addClickHandler($jQueryElement, $function) {
$jQueryElement.click($function);
}
Obviously this looks appealing due to its simplicity. FastClick does some fancy stuff behind the scenes to override the click handler to take into account touchstart and a whole bunch of other things as well as the nuances of different tablet devices. It's a shame that I have to do away with FastClick.
Click handlers are needed all over my code, so relying on my addClickHandler() function allowed me to change the implementation from FastClick to the new approach in exactly one place. The alternative would be to directly embed the click handlers everywhere, which would lead to a lot more search and replace.
If you happen to be a web programmer and your audience is adults, I recommend that you look into FastClick to get the best possible compromise, but if your audience is young kids, I think the approach I settled on is ultimately best, even if it means swipe behaviors sometimes don't work as intended.