Search code examples
javascriptjquerymobilejquery-chosenfastclick.js

How to get Chosen and FastClick to work on mobile device


I'm trying to add FastClick to a site that already uses the Chosen jQuery plugin for selects. With FastClick, the selection boxes simply stop responding to taps on mobile browsers. This can also be replicated with Chrome device emulation.

You can test this for yourself on this simple jsFiddle:

<select id="foo">
    <option>Bar</option>
    <option>Asdf</option>
</select>

$("#foo").chosen()

Steps to replicate with Chome canary:

  1. Load http://fiddle.jshell.net/7ftdo0j3/3/show/
  2. Open developer tools and emulate Google Nexus 7 or Apple iPad 1/2 (others might work as well)
  3. Try to use the select.

Solution

  • The main problem you have is that you try to use two libraries together, which both either manipulate or interpret touch event weirdly. I wanted to use the phrase "which both do some black magic with touch events", but as I have almost none experience in using the libraries in question, I felt that perhaps it's not appropriate ;)

    Joking aside, the solution for your problem is to add FastClick's needsclick class to all DOM elements dynamically created by chosen:

    $("#test").chosen();
    $(".chosen-container *").addClass("needsclick");
    FastClick.attach(document.body);
    

    At least in my tests with the emulator this seemed to work. I'll tell you why I think it works.

    I noticed when I added the needsclick class only to div.chosen-container and to its direct children, that sometimes a touch opened the dropdown and sometimes it didn't. When added to all children, touch starts to work flawlessly. I'm quite sure something like this happens there:

    • Chosen creates dynamicly div elements, which mimic a dropdown.
    • When user touches this kind of div, the original top-most element gets stores in the mouse event
      • Eg. if user touches the main text of the dropdown (which is a span element), that element gets stored in the event
    • FastClick checks needsclick only from this element
      • As none of the dynamicly created elements have that magic class, the touch event gets prevented and a click event is sent to that element instead
    • This would work otherwise, but it seems that Chosen does not listen to click events at all. You can test this one by trying to send one to a .chosen-container with jQuery:

    $(".chosen-container").trigger('click');

    It does not work. But when you send a mousedown event instead, dropdown opens:

    $(".chosen-container").trigger('mousedown');

    This might mean that perhaps on touch devices Chosen already listens touchstart or touchend events directly, and that would mean you wouldn't need FastClick with Chosen dropdowns even in the first place. Unfortunately I do not have a real test device now with me, so I can not guarantee this kind of happy ending for your voyage :D

    We used Chosen in one project, and we had some event-related problems there as well. There is quite a much code related to event bindings in Chosen's source file, so I have to say I'm not completely sure what really happens there. But at least the explanation above made some sense in my wicked mind. Hope it helps you, and hope that you'll get your forms working once again.