jQuery .on() and .delegate() doesn't work on iPad
Asked Answered
O

7

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?

Olfe answered 15/4, 2012 at 19:9 Comment(4)
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.Pennsylvanian
@joeframbach, you mean it was added to jQuery 1.7Gourde
@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().Gourde
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.Gourde
Q
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

Quinte answered 15/4, 2012 at 19:55 Comment(6)
ah, this is also a good answer! Yes, this may be a global workaround!Olfe
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.Quinte
@mdi I'm not getting what do you mean. If you're getting #id from ajax request, you need to use delegation or .on()Olfe
That's exactly what I meant... direct bound on #id, unless Ajax.Quinte
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.Bunche
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.Acierate
R
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!".

Rondeau answered 29/8, 2012 at 13:33 Comment(3)
best explanation I've found for this bizarre behaviour is here (swsharinginfo.blogspot.in/2013/03/…). 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!Ayo
That is indeed what I am thinking.Tannen
Best explanation I've found for this behaviour: Apple can't code for s**t. This brokenness still persists on Safari on iOS 9.Manly
O
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

Olfe answered 15/4, 2012 at 19:9 Comment(1)
It's entirely OK to ask a question and answer it immediately. 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.Lora
C
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.

Cohesion answered 13/11, 2014 at 20:57 Comment(1)
Simon, you rock! This is both simple explanation for this behaviour and quick workaround. You saved my day.Bunche
L
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.

Loki answered 5/10, 2012 at 14:38 Comment(2)
This makes sense with no hack!Killion
Can't you declare two events in the same on()? So why not just do $(document).on("click touchstart,".class",function)Sedimentary
Q
0

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

body {
  cursor:pointer;
}
Qualify answered 16/2, 2016 at 12:45 Comment(0)
P
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

Phlegmy answered 6/10, 2016 at 8:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.