$(document).click() not working correctly on iPhone. jquery

156,595

Solution 1

Adding in the following code works.

The problem is iPhones dont raise click events. They raise "touch" events. Thanks very much apple. Why couldn't they just keep it standard like everyone else? Anyway thanks Nico for the tip.

Credit to: http://ross.posterous.com/2008/08/19/iphone-touch-events-in-javascript

$(document).ready(function () {
  init();
  $(document).click(function (e) {
    fire(e);
  });
});

function fire(e) { alert('hi'); }

function touchHandler(event)
{
    var touches = event.changedTouches,
        first = touches[0],
        type = "";

    switch(event.type)
    {
       case "touchstart": type = "mousedown"; break;
       case "touchmove":  type = "mousemove"; break;        
       case "touchend":   type = "mouseup"; break;
       default: return;
    }

    //initMouseEvent(type, canBubble, cancelable, view, clickCount, 
    //           screenX, screenY, clientX, clientY, ctrlKey, 
    //           altKey, shiftKey, metaKey, button, relatedTarget);

    var simulatedEvent = document.createEvent("MouseEvent");
    simulatedEvent.initMouseEvent(type, true, true, window, 1, 
                          first.screenX, first.screenY, 
                          first.clientX, first.clientY, false, 
                          false, false, false, 0/*left*/, null);

    first.target.dispatchEvent(simulatedEvent);
    event.preventDefault();
}

function init() 
{
    document.addEventListener("touchstart", touchHandler, true);
    document.addEventListener("touchmove", touchHandler, true);
    document.addEventListener("touchend", touchHandler, true);
    document.addEventListener("touchcancel", touchHandler, true);    
}

Solution 2

Short answer:

<style>
    .clickable-div 
    {
         cursor: pointer;
    }
</style>

Longer answer:

It's important to realize that if you're just using <a> tags everything will work as expected. You can click or drag by mistake on a regular <a> link on an iPhone and everything behaves as the user would expect.

I imagine that you have arbitrary HTML that is not clickable - such as a panel containing text and images that cannot be wrapped with <a>. I found out about this problem when I had such a panel that I wanted to be entirely clickable.

<div class='clickable-div' data-href="http://www.stackoverflow.com">

 ... clickable content here (images/text) ...

</div>

To detect a click anywhere within this div I am using jQuery with a data-href html attribute which is shown above (this attribute is invented by myself and is not a standard jQuery or HTML data attribute.)

$(document).on('click', '.clickable-div', function() {

    document.location = $(this).data('href');

});

This will work on your desktop browser but not iPad no matter how much you click.

You may be tempted to change your event handler from click to click touchstart - and this indeed does trigger the event handler. However if the user wants to drag the page up (to scroll) they'll trigger it too - which is a terrible user experience. [you may have noticed this behavior by sneaky banner ads]

The answer is incredibly simple: Just set the css cursor: pointer.

<style>
    .clickable-div 
    {
         cursor: pointer;
    }
</style>

This had the added benefit for desktop users to indicate the area is clickable with a hand icon.

Thanks to https://stackoverflow.com/a/4910962/16940

Solution 3

Change this:

$(document).click( function () {

To this

$(document).on('click touchstart', function () {

Maybe this solution don't fit on your work and like described on the replies this is not the best solution to apply. Please, check another fixes from another users.

Solution 4

try this, applies only to iPhone and iPod so you're not making everything turn blue on chrome or firefox mobile;

/iP/i.test(navigator.userAgent) && $('*').css('cursor', 'pointer');

basically, on iOS, things aren't "clickable" by default -- they're "touchable" (pfffff) so you make them "clickable" by giving them a pointer cursor. makes total sense, right??

Solution 5

CSS Cursor:Pointer; is a great solution. FastClick https://github.com/ftlabs/fastclick is another solution which doesn't require you to change css if you didn't want Cursor:Pointer; on an element for some reason. I use fastclick now anyway to eliminate the 300ms delay on iOS devices.

Share:
156,595

Related videos on Youtube

Garrows
Author by

Garrows

I am a tech enthusiast, computer systems engineer, nerd, geek, lover and fighter. I run my a little old blog http://garrows.com I contribute to the cellbots robotics project http://www.cellbots.com I love to push things to the limit including my sanity.

Updated on November 16, 2020

Comments

  • Garrows
    Garrows over 3 years

    This function works perfectly on IE, Firefox and Chrome but when on the iPhone, it will only work when clicking on a <img>. Clicking on the page (anywhere but on a img) wont fire the event.

    $(document).ready(function () {
      $(document).click(function (e) {
        fire(e);
      });
    });
    
    function fire(e) { alert('hi'); }
    

    The HTML part is extremely basic and shouldnt be a problem.

    Any ideas?

    • bevacqua
      bevacqua over 13 years
      it is my understanding that on iPhone you never actually raise click events... isn't there something like a touch event?
    • Garrows
      Garrows over 13 years
      probably could Christopher. Its just example code though.
    • Deepak Kamat
      Deepak Kamat almost 6 years
      Faced this issue recently, all you need is cursor: pointer or use an element that is supposed to have that by default like a, button etc.
  • BoltClock
    BoltClock over 13 years
    The official mobile version of jQuery is jQuery Mobile (but jQTouch is also pretty good).
  • lock
    lock over 13 years
    is it downloadable already? last time i heard it was still conceptual
  • Garrows
    Garrows over 13 years
    Sadly, it did not work. I did only include the library without changing my javascript. It seems like jQTouch should overload the $(document).click function.
  • aruno
    aruno almost 11 years
    tada NO! tada this is horrible - well at least if you want to capture a 'click' event on an arbitrary DIV it is. you can't even drag the screen up without triggering the event. grr
  • ceejayoz
    ceejayoz almost 11 years
    Agreed with @Simon_Weaver. This is an awful answer.
  • aruno
    aruno almost 11 years
    I didn't want to sound too mean, but when I tried this the behavior was so awful that it made me frustrated! (even though I got the exact behavior I was expecting) Fortunately (see my other answer) there is a better, incredibly simple solution
  • jon
    jon almost 11 years
    Clever... like that alot :)
  • aruno
    aruno almost 11 years
    yes it's nice when the answer is so simple :-) but a little frustrating seeing everyone propose crazy JS solutions that aren't necessary
  • Matt Cashatt
    Matt Cashatt over 10 years
    Bravo! This simple solution put an end to my misery!
  • Adrien
    Adrien over 10 years
    it doesn't work for me on ios 7
  • smilyface
    smilyface about 10 years
    my ipod got hang after adding this code. Is tehre any other way ?
  • Jatin Dhoot
    Jatin Dhoot about 10 years
    Base link leads to Page not available error
  • aruno
    aruno about 10 years
    Despite this being a bad answer - it's important for people to see it and realize why not to do this (you can't even scroll the screen without triggering the event) so I hope it doesn't get deleted
  • Ray Suelzer
    Ray Suelzer almost 10 years
    Appears to stop working in ios 7.
  • Abhi Beckert
    Abhi Beckert almost 10 years
    Confirmed, it works in iOS 7. I'm adding it to document.body to detect clicks on the entire page (then removing the css after the click). Bounty forthcoming!
  • aruno
    aruno almost 10 years
    this is really overkill - just cursor: pointer; is all you need
  • Matias
    Matias about 9 years
    Works, one thing to add though, we just had this issue on the project I'm on right now and the cursor: pointer solution won't work if it's set to an :after or :before, it needs to be on the main element for it to work, so we basically moved the cursor: pointer from the :after to the main class name and it was solved. THANKS!
  • Dirty Henry
    Dirty Henry almost 9 years
    It seems like a major Safari Mobile bug.
  • Martyn Chamberlin
    Martyn Chamberlin almost 9 years
    I would have never guessed this would be the hack that iOS 8 needs in order to register a click event, but I'm so happy that it works!!
  • Mathijs Segers
    Mathijs Segers over 8 years
    I just want to close a div when user clicks anywhere :'(
  • pscheit
    pscheit almost 8 years
    be sure that you're a-tag has an href-property. Otherwise it won't work
  • Mr Washington
    Mr Washington almost 8 years
    While most people describe this answer as terrible this solution could be very handy in some (specfic) cases. Imagine for example you want to close a menu on mobile on click this would be a very efficient solution!
  • Matthew Schinckel
    Matthew Schinckel almost 8 years
    Links sometimes go away: consider reproducing the explanation for how the problem is fixed by this package, as well as including the link.
  • Felix Geenen
    Felix Geenen almost 8 years
    thats the smartest and shortest option in many cases i think
  • Eaten by a Grue
    Eaten by a Grue almost 8 years
    why a CSS rule should affect a javascript event from bubbling up is beyond me. this makes absolutely no sense but it works. thanks
  • aruno
    aruno over 7 years
    @billynoah it's not about bubbling. it's about whether a click event is raised in the first place. on a phone you don't want unnecessary click events triggered when people drag around on the screen.
  • Karl-Johan Sjögren
    Karl-Johan Sjögren over 7 years
    Amazing find, saved us a lot of time in getting our click event to work as it should! Thanks!
  • Pbinder
    Pbinder over 7 years
    Amazing solution, thanks!
  • Oleg Popov
    Oleg Popov over 7 years
    Thank you. It just works :)
  • Nick Coad
    Nick Coad over 7 years
    @MrWashinton is correct, the other users should be ashamed by their overreactions. This is the only acceptable approach for several specific situations.
  • aruno
    aruno over 7 years
    this is really inefficient and doesn't account for elements added later. it is far better to add the pointer css as needed to the elements that do need it (remember it isn't needed for <a> tags in the first place) and not globally like this. if this is REALLY what you choose to do you should have a css rule like html.cursorpointer * { cursor: pointer } and then add .cursorpointer to <html> using your preferred method - preferably as a Modernizr test
  • Dens
    Dens about 7 years
    Your one line 'cursor:pointer;' will give me PROMOTION. Amazing! Thanks!
  • aruno
    aruno about 7 years
    @Dens like I said I found it from someone else, but thanks. And congratulations!
  • Snsxn
    Snsxn almost 7 years
    It works perfect with my situation. Thanks!
  • K. Maliszewski
    K. Maliszewski over 6 years
    Thx! You save me day! :D
  • foxy
    foxy about 6 years
    I wouldn't expect that such simple css attribute could fix it. Apple messed up with that behavior, but this quick fix is stellar. Thanks for an amazing answer!
  • Hung Tran
    Hung Tran about 6 years
    This helped me solve my issue. Thanks a lot :)
  • 7urkm3n
    7urkm3n over 5 years
    You deserve my Like!
  • M.Arjmandi
    M.Arjmandi about 5 years
    It works, but howww?? how could it be even related?
  • Muz
    Muz about 5 years
    This doesn't seem to work on the iPhone XS, or at least it seems difficult to test.
  • aruno
    aruno about 5 years
    @Muz it definitely does - I’m using one right now
  • Muz
    Muz about 5 years
    @Simon_Weaver sorry, my bad, the server was still using cached scripts.
  • Akin Hwan
    Akin Hwan almost 5 years
    what if its an <a> child element of <li> does that affect this solution? i used jquery to find my <a> with class name, and then used [0].click() vanilla JS to click, and can't get click to register on iOS
  • aruno
    aruno almost 5 years
    @AkinHwan this solution is really only about explicit ‘clicking’ with a finger on iOS. You’re saying it works ok on other platforms?There may be certain calls to click() that iOS vetos - especially if it’s on a video. (You can’t play a video with audio without iOS detecting a true touch event from the user). You should try alert($(‘....’)[0].click) to make sure you’re really getting a click handler (deliberately no parenthesis after click). iOS does weird things so if you’re able to run the action some other way that’s best - eg. set window.location. Make a new question if this doesn’t help.