31

If you try this snippet on desktop, everything works.
Whenever you try it on iPad, it won't do anything.

$('body').on('click', '#click', function() {
    alert("This alert won't work on iPad");
});
div { 
  font-size: 24px; 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="click">Click here</div>

Simple .click() handler works, but it isn't what I want. The same applies for .delegate(); and .live()

Is it a bug or something?

Simon Arnold
  • 15,849
  • 7
  • 67
  • 85
Martin.
  • 10,494
  • 3
  • 42
  • 68
  • Are you using jquery mobile? `on` was added to jquery 1.7.2 in November 2011 and hasn't made it to jquery mobile yet. – 000 Apr 15 '12 at 19:22
  • @joeframbach, you mean it was added to jQuery 1.7 – Sparky Apr 15 '12 at 19:27
  • @joeframbach, I also don't understand your point. jQuery Mobile is not standalone... it requires jQuery; so if you're using jQuery 1.7, you have `on()`. – Sparky Apr 15 '12 at 19:42
  • Martin, is it possible that using the word `click` as the name of your `id` is the root problem? (I have no way to test it) Maybe it's not a reserved word, but personally, I'd stay away from naming things in this fashion. – Sparky Apr 15 '12 at 19:50

7 Answers7

34

It's a Safari mobile bug/feature : click events won't bubble all the way up to body.

Adding onclick="" is a known workaround, but IMHO it's easier to attach your listener on a first child of <body>.

See: http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html

mddw
  • 5,570
  • 1
  • 30
  • 32
  • ah, this is also a good answer! Yes, this may be a global workaround! – Martin. Apr 15 '12 at 20:00
  • Moreover, the less the event has to bubble up, the better. Attaching .on() to body is often (not always) counter-productive. Here, your element is an unique #id, so direct-bound would be enough, providing it's not injected with Ajax. – mddw Apr 15 '12 at 20:05
  • @mdi I'm not getting what do you mean. If you're getting #id from ajax request, you need to use delegation or .on() – Martin. Apr 15 '12 at 21:38
  • That's exactly what I meant... direct bound on #id, unless Ajax. – mddw Apr 15 '12 at 22:21
  • Good research, your test examples prove the behaviour. But the simplest workaround is to add cursor:poiner - it will make the clicks bubble up. Look up Simon Arnold's answer here. – 1234ru Sep 24 '15 at 14:54
  • If anyone is having this problem even on non-body elements, problem could be other hover events attached to your elements, like bootstrap tooltips. I noticed I had to touch twice for my event delegate to fire, but when I disabled tooltips the event fired on first touch, as expected. – Philip Holly Jan 18 '16 at 16:36
30

Change the cursor style of the body on iOS to "pointer" and everything will work perfectly. You won't have to add onclick="" on every element you want clickable...

<script type="text/javascript">
    $(function() {
        // The trick
        if (/ip(hone|od)|ipad/i.test(navigator.userAgent)) {
           $("body").css ("cursor", "pointer");
        }
        // The test
        $("body").on("click", "#click", function() {
            alert("This also works on iOS !");
        });
    });
</script>
<div id="click">Click here</div>

I know what you're thinking right now: "WTF!".

Boroboro
  • 301
  • 3
  • 3
  • 6
    best explanation I've found for this bizarre behaviour is here (http://swsharinginfo.blogspot.in/2013/03/solution-for-click-event-issue-on-ipad.html). In summary, the first touch on an IPad/pod/phone is treated as hover. In order to tell the browser that the element is clickable you need to add cursor:pointer to the element. Note 1. add add `cursor:pointer` to the underlying element $('#myElement') not just $('myElement:hover'). Note 2. You can simply **add** `cursor:pointer` **to your css**. It worked for me! – dunxz Oct 16 '13 at 21:30
  • That is indeed what I am thinking. – troelskn May 09 '14 at 18:44
  • Best explanation I've found for this behaviour: Apple can't code for s**t. This brokenness still persists on Safari on iOS 9. – Ian Kemp Apr 28 '16 at 12:51
12

I'm not sure why doesn't it work, it's probably a bug, but there's a nice workaround. Simply put onclick="" to the div you're delegating and it will work perfectly

<div id="click" onclick="">Click here</div>
<script>
$("body").on("click", "#click", function() {
    alert("This works on iPad");
});
</script>

fiddle

Martin.
  • 10,494
  • 3
  • 42
  • 68
  • 4
    [It's entirely OK to ask a question and answer it immediately.](http://meta.stackexchange.com/questions/17845/etiquette-for-answering-your-own-question) Even I've done it before. If you have any objections, feel free to raise it on meta; don't hijack an answer's comment thread. Thanks. – BoltClock Apr 15 '12 at 19:58
12

On iOS there is no event bubbling without a cursor style.
So in your CSS you need to add cursor: pointer; to the element.

$('body').on('click', '#click', function() {
    alert("This alert won't work on iPad");
});
#click { 
  font-size: 24px; 
  cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="click">Click here</div>

I know it been asked a long time ago, but I thought a simple CSS solution might help.

Simon Arnold
  • 15,849
  • 7
  • 67
  • 85
  • 2
    Simon, you rock! This is both simple explanation for this behaviour and quick workaround. You saved my day. – 1234ru Sep 24 '15 at 14:51
3

i found a solution on http://www.danwellman.co.uk/fixing-jquery-click-events-for-the-ipad/

do the following approach:

var isIPad = function() {
    return (/ipad/i).test(navigator.userAgent);
};
var isIPhone = function() {
    return (/iphone/i).test(navigator.userAgent);
};
var isIPod = function() {
    return (/ipod/i).test(navigator.userAgent);
};

and where you bind the click-event-handler do so:

var eventName = (isIPod() || isIPad() || isIPhone()) ? "touchstart" : "click";
// if you are using jquery-mobile
eventName = (isIPod() || isIPad() || isIPhone()) ? "touchstart" : "vclick";

$(".selector").bind(eventName, function(e) {
    //do something here
});
// or
$(document).on(eventName, ".selector", function(e) {
    //do something here
});

that's it.

Zain Shaikh
  • 6,013
  • 6
  • 41
  • 66
algorhythm
  • 8,530
  • 3
  • 35
  • 47
0

I was facing this issue on iPhone 5C and below.
This worked for me:

body {
  cursor:pointer;
}
showdev
  • 28,454
  • 37
  • 55
  • 73
Rakesh Yembaram
  • 433
  • 4
  • 7
0

I had an issue with a message that I prepend to the html body. I found this issue on [jQuery 'click' event doesn't work on iOS Safari?

I used this

$('body').on('click touchstart', 'someselect', function(){})

And it worked on iPhone 4S and iPhone 5S

Community
  • 1
  • 1