202

Is it possible to recognize touch events on the iPad's Safari browser using jQuery?

I used mouseOver and mouseOut events in a web application. Are there any similar events for the iPad's Safari browser since there are no events like mouseOut and mouseMove?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Abhishek B.
  • 5,112
  • 14
  • 51
  • 90

8 Answers8

256

Core jQuery doesn't have anything special for touch events, but you can easily build your own using the following events

  • touchstart
  • touchmove
  • touchend
  • touchcancel

For example, the touchmove

document.addEventListener('touchmove', function(e) {
    e.preventDefault();
    var touch = e.touches[0];
    alert(touch.pageX + " - " + touch.pageY);
}, false);

This works in most WebKit based browsers (incl. Android).

Here is some good documentation.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
David Pean
  • 2,906
  • 1
  • 15
  • 6
  • 2
    Thanks a lot David, I think it will work but what is e.touches[0] ? can you describe argument "e" in detail? – Abhishek B. Jan 21 '11 at 05:32
  • 7
    e is the event object that gets automatically passed to the handler. For the safari browser (and android too) it now contains an array of all the touches the user has made on the screen. Each touch has its own properties (x,y coords for example) – David Pean Jan 21 '11 at 06:05
  • 1
    now how do you go about finding what element to trigger event on -__- – Muhammad Umer Aug 17 '13 at 20:33
  • Note that the right answer is the one made by Timothy Perez, this one is not updated. – EPurpl3 Jul 13 '20 at 11:59
153

If you're using jQuery 1.7+ it's even simpler than all these other answers.

$('#whatever').on({ 'touchstart' : function(){ /* do something... */ } });
Timothy Perez
  • 20,154
  • 8
  • 51
  • 39
  • 1
    Yes, Timothy, I was not used 1.7+ version at the time I start my project. now onwords I am using jquery 1.7+.. Thanks for good suggestion & reply.. Thanks lot. :) – Abhishek B. Mar 25 '13 at 07:07
  • 8
    This works well. I needed click and touchstart to do the same thing, and I'm used to the non-object syntax, as `$('#whatever').on('touchstart click', function(){ /* do something... */ });` – goodeye Jun 18 '13 at 21:56
  • I have used Timothy Perez solution and it works, but not goodeye solution. Is there any way to add also for newly added elements to change code Timothy Perez ? – edonbajrami Sep 24 '13 at 14:47
  • 1
    when I go `$('#whatever').on({ 'touchstart' : function(ev){}});`, `ev` doesn't seem to have any info about the touches (touches, targetTouches or changedTouches) – Octopus Jan 15 '14 at 08:23
  • 8
    @Octopus : You'll find the touches info under `ev.originalEvent`. – Peter Bloomfield Jan 21 '14 at 16:34
  • 1
    @edonbajrami yes, of course. check the [docs](https://api.jquery.com/on/) and look for "delegated events". $("#element to monitor for new elements").on("eventX", "#element", function( event ) {/*whatever*/}); – honk31 Jun 26 '14 at 07:59
31

Using touchstart or touchend alone is not a good solution, because if you scroll the page, the device detects it as touch or tap too. So, the best way to detect a tap and click event at the same time is to just detect the touch events which are not moving the screen (scrolling). So to do this, just add this code to your application:

$(document).on('touchstart', function() {
    detectTap = true; // Detects all touch events
});
$(document).on('touchmove', function() {
    detectTap = false; // Excludes the scroll events from touch events
});
$(document).on('click touchend', function(event) {
    if (event.type == "click") detectTap = true; // Detects click events
       if (detectTap){
          // Here you can write the function or codes you want to execute on tap

       }
 });

I tested it and it works fine for me on iPad and iPhone. It detects tap and can distinguish tap and touch scroll easily.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Iman Sedighi
  • 7,624
  • 4
  • 48
  • 55
24

The simplest approach is to use a multitouch JavaScript library like Hammer.js. Then you can write code like:

canvas
    .hammer({prevent_default: true})
    .bind('doubletap', function(e) { // And double click
        // Zoom-in
    })
    .bind('dragstart', function(e) { // And mousedown
        // Get ready to drag
    })
    .bind('drag', function(e) { // And mousemove when mousedown
        // Pan the image
    })
    .bind('dragend', function(e) { // And mouseup
        // Finish the drag
    });

And you can keep going. It supports tap, double tap, swipe, hold, transform (i.e., pinch) and drag. The touch events also fire when equivalent mouse actions happen, so you don't need to write two sets of event handlers. Oh, and you need the jQuery plugin if you want to be able to write in the jQueryish way as I did.

David Johnstone
  • 24,300
  • 14
  • 68
  • 71
  • 31
    the "simplest" solution never involves making a problem more complicated by adding libraries – Octopus Jan 15 '14 at 08:31
  • 14
    @Octopus The simplest solution is using hammer.js that abstracts away cross-browser headaches. Use the jQuery extension to be in your familiar zone. Doesn't seem too complicated to me. – trusktr Jan 22 '14 at 05:41
  • 1
    the supposed "simplest" solution is often the one that people screw up the most... whatever you do, don't forget to make sure your solution works on devices that support both touch AND mouse, such as Microsoft Surface – Simon_Weaver Sep 16 '14 at 15:37
  • 1
    @Octopus: "When all you have is a hammer [sic]... everything looks like a nail" :) – iCollect.it Ltd Jun 23 '15 at 16:32
  • It's HAMMER TIME! Thank you for sharing this library, it was easy to install on my application and get running! Took a second to setup because the event handler is different, but a simple console.log(event) tells you what you need. THANKS! – Andy May 04 '17 at 11:50
21

You can use .on() to capture multiple events and then test for touch on the screen, e.g.:

$('#selector')
.on('touchstart mousedown', function(e){
  e.preventDefault();
  var touch = e.touches[0];
  if(touch){
    // Do some stuff
  }
  else {
    // Do some other stuff
  }
});
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
featherbelly
  • 935
  • 11
  • 16
15

jQuery Core doesn't have anything special, but you can read on jQuery Mobile Events page about different touch events, which also work on other than iOS devices as well.

They are:

  • tap
  • taphold
  • swipe
  • swipeleft
  • swiperight

Notice also, that during scroll events (based on touch on mobile devices) iOS devices freezes DOM manipulation while scrolling.

Karol
  • 7,803
  • 9
  • 49
  • 67
6

I was a little bit worried about using only touchmove for my project, since it only seems to fire when your touch moves from one location to another (and not on the initial touch). So I combined it with touchstart, and this seems to work very well for the initial touch and any movements.

<script>

function doTouch(e) {
    e.preventDefault();
    var touch = e.touches[0];

    document.getElementById("xtext").innerHTML = touch.pageX;
    document.getElementById("ytext").innerHTML = touch.pageY;   
}

document.addEventListener('touchstart', function(e) {doTouch(e);}, false);
document.addEventListener('touchmove', function(e) {doTouch(e);}, false);

</script>

X: <div id="xtext">0</div>
Y: <div id="ytext">0</div>
hanamj
  • 133
  • 1
  • 6
  • I also added this to detect how much time passed since the last event.. `document.getElementById("ttime").innerHTML = ((new Date()) - touchTime); touchTime = new Date();` – hanamj Apr 25 '12 at 19:16
3

I just tested benmajor's GitHub jQuery Touch Events plugin for both 1.4 and 1.7+ versions of jQuery. It is lightweight and works perfectly with both on and bind while providing support for an exhaustive set of touch events.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rohan
  • 3,296
  • 2
  • 32
  • 35