Autocomplete requires you to click twice in iOS after update to 1.11.0
Asked Answered
T

12

55

Using jQuery 2.1.0 and jQuery.ui 1.11.0 Tested in iOS 7. iPhone and iPad Mini. Works on android and regular browsers.

The problem

We recently upgraded from jQuery UI 1.10.0 to 1.11.0 and now, when clicking an item in an autocomplete results list, you only get a hover, you have to click the same element again to get a click event. This used to work fine with version 1.10.0.

(JSFiddle link in comments)

What does not work

using css {cursor: pointer} does not work

using onclick="" does not work

(JSFiddle link in comments)

The weird part

But here comes the fun/weird part. It works in JSFiddle edit view, but not on the JSFiddle "/show" page.

JSFiddles: (type a letter to show results "s" is a good one)

I've been working on this for days, but hadn't been able to reproduce it in JSFiddle before testing only the html view. So now I turn to you. I can't for the life of me figure out why the one page triggers a click event, and the other does not.

I am using the most basic function of jQuery autocomplete. In fact, using the exact same code that is presented on jQuery UI's home page.

The question

So, how do I get autocomplete to work with one click in iOS on the /show page?

(I will post additional links in comments because I don't have 10 rep yet. Unless I don't have enough rep to comment...)

Thieve answered 13/8, 2014 at 12:50 Comment(2)
Additional links: jQuery UI Autocomplete home page | "Fixes" that do not work | jQuery UI version 1.10.0 where it works Please add "/show" to the end of the url when actually testing the behaviour. The edit view changes the behavior.Thieve
Bug report for this issue: bugs.jqueryui.com/ticket/10544Palaver
N
48

Just a bit later, but

$("#input").autocomplete({
    open: function(event, ui) {
        $('.ui-autocomplete').off('menufocus hover mouseover mouseenter');
    }
});
Nutria answered 23/12, 2014 at 15:2 Comment(7)
That also solved issue for selection , However it's will not file click of autocomplete input which i have registered at beginning. do you have any idea ?Baran
Does not work with autoFocus set to true, because then always the first item is selected regardless of what you actually click on. Otherwise good workaround.Silas
This "fix" is only breaking the autocomplete. Don't listen that answer.Shilashilha
Thanks, this works for me especially i am using jquery tagit.Kali
@Silas any workarounds that work if autoFocus is true?Leyte
@Leyte Cannot remember, but I upvote Sangram's answer (https://mcmap.net/q/333866/-autocomplete-requires-you-to-click-twice-in-ios-after-update-to-1-11-0) so I might have used his approach.Silas
This leaves the Keyboard open on an iPhone. and blur doesn't work in Safari, so there's no way to lose focus on the autocomplete.Christadelphian
A
22

For some strange reason @onlydimon's answer didn't work for me. It seems like we do need event mouseenter. Following answer worked well for me.

open: function (result) {

            if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)) {
                $('.ui-autocomplete').off('menufocus hover mouseover');
            }
        },

I have added a condition to make sure that it doesn't break in other devices.

Aleedis answered 28/9, 2015 at 6:39 Comment(2)
this did it for me. menufocus was the culprit on my end. although i only had to call off the one time, not every time it opened. was using autocomplete in react so i just put the if statement in componentDidMount and used a ref to grab the dom node. $(this.refs.foo.getDOMNode()).autocomplete('widget').off('menufocus')Liaotung
This works but it doesn't remove the Keyboard on the iPhoneChristadelphian
B
13

Building on onlydimon’s solution:

var input = $("#input")
// Initialize autocomplete
input.autocomplete()
// Retrieve the autocomplete list and remove the mouseenter event
// which seems to trip up iOS Safari
input.autocomplete('widget').off('mouseenter')

I narrowed down the list of events to just jQuery's 'mouseenter' event. Removing just this one fixes the bug for me. Also, no need to remove it every time the list is opened; once is enough.

Blindage answered 9/9, 2015 at 17:37 Comment(1)
Does not work with autoFocus set to true, because then always the first item is selected regardless of what you actually click on. Otherwise good workaround.Silas
B
3

Wrote a super nasty hack which seems to do the trick for me. Here's what I did.

  1. Check that we're using a touch device (in my case, a variable I have called IAmTouchy.
  2. Listen for a tap (touchstart) on an autocomplete result.
  3. After a set time, check to see if the autocomplete results are still visible. If they are, and an item is focussed, trigger a click on it.
  4. (optional) Try once more... in case the set time wasn't long enough for the element to gain the ui-state-focus class.

        $('.autocompleteContainer').on('touchstart', 'li.ui-menu-item', function(){
    
            var $container = $(this).closest('.autocompleteContainer'),
                $item = $(this);
    
            //if we haven't closed the result box like we should have, simulate a click on the element they tapped on.
            function fixitifitneedsit() {
                if ($container.is(':visible') && $item.hasClass('ui-state-focus')) {
    
                    $item.trigger('click');
                    return true; // it needed it
                }
                return false; // it didn't
            }
    
            setTimeout(function () {
                if (!fixitifitneedsit()) {
                    setTimeout(fixitifitneedsit, 600);
                }
            }, 600);
        });
    

Hopefully someone has a nicer solution though!

Behoof answered 12/11, 2014 at 3:56 Comment(0)
A
3
$.ajax({
 url: '/ajax/xyz.json'
})
.done(function( data ) {
  $('#id').autocomplete({
    source: data,
    open: function( event, ui ) {
        if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)) {
          $('.ui-autocomplete').off('menufocus hover mouseover mouseenter');
        }
    },
    select: function( event, ui ) {
      window.location.href = ui.item.value;
      return false;
    }
  });
});

This worked for me (works on drupal 8 as well). Now one tap on iOS devices redirect to search result page.

Anlace answered 10/2, 2017 at 15:44 Comment(1)
Thanks. It is the simplest solution in this thread. Works in iOS 10. open() function is the relevant part.Immersion
P
1

Based on Liam Johnston solution, I wrote this one which work for me with autoFocus set to true:

var movedWhildAutocomplete = false;
$(document)
    .on('touchstart', '.ui-autocomplete li.ui-menu-item', function(){
        $(this).trigger('mouseenter');
        movedWhildAutocomplete = false;
    })
    .on('touchmove', '.ui-autocomplete li.ui-menu-item', function(){
        movedWhildAutocomplete = true;
    })
    .on('touchend', '.ui-autocomplete li.ui-menu-item', function(){
        if (!movedWhildAutocomplete) {
            var $el = $(this);
            if ($el.is(':visible') && $el.hasClass('ui-state-focus')) {
                $el.trigger('click');
            }
        }
        movedWhildAutocomplete = false;
    });
Psf answered 9/2, 2016 at 22:39 Comment(0)
M
1

Autocomplete widget has some built in events that you can add on to your code... jqueryui

I was having the same problem and finally figured out how to tweek the code and force mobile devices to respond with one click.

Basically for mobile devices (iOs) when you tap on the autocomplete list 'once', it will trigger the "focus" event, if you click once more (2nd click) it will read the event as "select". So in order to force iOs devices to select on one click you have to force it to select on the first click.

$("#input").autocomplete({
  source: yourSourceList,
  focus: function(event, ui) {
    $(this).val(ui.item.value);
    $(".ui-menu").hide(); //you can also console.log(ui.item.value); for the selected widget object
  }
});
Manus answered 12/7, 2017 at 20:7 Comment(0)
B
0

Use fastclick.js it will solve this problem. I know this js is used for removing 300ms tap delay but it solved this problem also for me.

  1. Download the minified version of FastClick (alternatively, you can follow the instructions for installing the non-minified version here)

  2. Include the file in your project:

    <script src = "js/fastclick.min.js"></script>

  3. Attach the FastClick object to the document after FastClick has been loaded:

    var attachFastClick = Origami.fastclick;

    attachFastClick(document.body);

NOTE: If you try using FastClick the non-minified way, i.e:

<script src = "js/fastclick.js"></script>;

Then use

FastClick.attach(document.body);

but are including the minified file you will receive errors (telling you that FastClick is undefined). If you are using the minified file you must access it through Origami.

Bad answered 20/10, 2015 at 10:9 Comment(0)
D
0

you can probably can use the focus event from autocomplete!

focus( event, ui )

$(function() {
  var availableTags = [
    "ActionScript",
    "AppleScript",
    "Asp",
    "BASIC",
    "C",
    "C++",
    "Clojure",
    "COBOL",
    "ColdFusion",
    "Erlang",
    "Fortran",
    "Groovy",
    "Haskell",
    "Java",
    "JavaScript",
    "Lisp",
    "Perl",
    "PHP",
    "Python",
    "Ruby",
    "Scala",
    "Scheme"
  ];

  var selectAction = function(event, ui) {
    //do whatever you want with event and ui objects
    console.log(ui.item)
  }

  $("#tags").autocomplete({
    source: availableTags,
    focus: selectAction,
    select: selectAction
  });
});
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>

<label for="tags">Tags:</label>
<input id="tags">
Dicot answered 22/1, 2016 at 15:5 Comment(0)
C
0

Solution from Raphaël Malié is almost perfect, but it needs evt.preventDefault() for touchend, otherwise it will generate a click on a link/button that is under clicked item.

    var movedWhildAutocomplete = false;
    $(document)
        .on('touchstart', '.ui-autocomplete li.ui-menu-item', function(){
            $(this).trigger('mouseenter');
            movedWhildAutocomplete = false;
        })
        .on('touchmove', '.ui-autocomplete li.ui-menu-item', function(){
            movedWhildAutocomplete = true;
        })
        .on('touchend', '.ui-autocomplete li.ui-menu-item', function(evt){
            if (!movedWhildAutocomplete) {
                var $el = $(this);
                if ($el.is(':visible') && $el.hasClass('ui-state-focus')) {
                    evt.preventDefault();
                    $el.trigger('click');
                }
            }
            movedWhildAutocomplete = false;
        });
Contradiction answered 15/4, 2016 at 11:52 Comment(0)
I
0

I´m working with jQuery UI with and cordova, and I have the same problem in the app, my solution for that problem is this:

$('.ui-autocomplete').mouseenter( function( e ){
    e.preventDefault();
    e.stopPropagation();
});

This stop the focus on the selected item.

Incubator answered 12/5, 2016 at 17:39 Comment(0)
W
0

This code works with autoFocus

$("#input").autocomplete({
    source: ["Test 1", "Test 2", "Test 3", "Test 4", "Test 5"],
    autoFocus: true,
    focus: function(event, ui) {
        if (navigator.userAgent.match(/(iPod|iPhone|iPad)/) && event.bubbles) {
            $(this).data("ui-autocomplete")._trigger("select", "autocompleteselect", {item: ui.item} );
            $(this).autocomplete("close");
        }
        return false;
    },
    select: function(event, ui) {
        $(this).val(ui.item.label);
    }
});
Wainscoting answered 24/10, 2016 at 16:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.