Handling click and touch events on the same element

Josh Sherman
2 min read
Software Development JavaScript

I’m starting to feel behind the curve. I started receiving feedback that some clickable elements on my social networks were not working on touch devices. Without much thought, I went ahead and added touchstart along side of click to bind both events:

$(document).on('click touchstart', '.feeny', function(e) {
  alert('Believe in yourselves. Dream. Try. Do good.');
});

“Problem solved!”, I thought. This resolved the issue with form submit buttons but not hearts. Hearts persist on the page when clicked. Things worked fine on the desktop but tapping a heart on your phone would fire both click and touchstart events. This would heart and immediately unheart the item.

I then did some research and polled my friends to see how they would do it. My buddy Khary suggested sniffing the browser for touch capabilities and setting the event handler accordingly. The interwebs corroborated this and I proceeded to use a variable for the event:

var clickEvent = (function() {
  if ('ontouchstart' in document.documentElement === true)
    return 'touchstart';
  else
    return 'click';
})();

Worked great on my desktop and Android phone. Even worked on iOS which was the platform that was double firing. Code went live. NEXT PROJECT!

Over the next two weeks I noticed the occasional “complaint status” about some click events not working. Nothing formal was reported so I assumed these were edge cases and did not action on them. I continued to research and eventually a formal bug report came in.

I learned about a third device I was not considering, the touchscreen laptop. It’s a hybrid device that supports both touch and click events. Binding one event means only that event be supported. Does that mean someone with a touchscreen and mouse would have to explicitly touch because that’s the only event I am handling?

Binding touchstart and click seemed ideal to handle these hybrid devices. To keep the event from firing twice, I added e.stopPropagation() and e.preventDefault() to the callback functions. e.stopPropagation() stops events from “bubbling up” to their parents but also keeps a second event from firing. I included e.preventDefault() as a “just in case” but seems like it could be omitted.

The code’s been live for a few days but I was only able to confirm that things are working on my devices. Until I can track down a user with a touchscreen laptop I won’t know for sure. Fortunately I have already seen a “praise status” about the problem “fixing itself” so the solution may be a hit.

Join the Conversation

Good stuff? Want more?

Weekly emails about technology, development, and sometimes sauerkraut.

100% Fresh, Grade A Content, Never Spam.

About Josh

Husband. Father. Pug dad. Musician. Founder of Holiday API, Head of Engineering and Emoji Specialist at Mailshake, and author of the best damn Lorem Ipsum Library for PHP.

Currently Reading

Parasie Eve

Previous Reads

Buy Me a Coffee Become a Sponsor

Related Articles