javascript 自动完成需要您在更新到 1.11.0 后在 iOS 中单击两次

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25286685/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 04:17:45  来源:igfitidea点击:

Autocomplete requires you to click twice in iOS after update to 1.11.0

javascriptjqueryjquery-uiios7jquery-ui-autocomplete

提问by Snorre Kim

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.

使用 jQuery 2.1.0 和 jQuery.ui 1.11.0 在 iOS 7. iPhone 和 iPad Mini 中测试。适用于 android 和常规浏览器。

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.

我们最近从 jQuery UI 1.10.0 升级到 1.11.0,现在,当单击自动完成结果列表中的项目时,您只会得到一个悬停,您必须再次单击同一元素才能获得单击事件。这曾经在 1.10.0 版中运行良好。

(JSFiddle link in comments)

(评论中的 JSFiddle 链接)

What does not work

什么不起作用

using css {cursor: pointer}does not work

使用 css{cursor: pointer}不起作用

using onclick=""does not work

使用onclick=""不起作用

(JSFiddle link in comments)

(评论中的 JSFiddle 链接)

The weird part

奇怪的部分

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

但有趣/奇怪的部分来了。它适用于 JSFiddle编辑视图,但不适用于 JSFiddle "/show" 页面。

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

JSFiddles:(键入一个字母以显示结果“s”是一个很好的)

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.

我已经为此工作了好几天,但在仅测试 html 视图之前无法在 JSFiddle 中重现它。所以现在我转向你。我一生都无法弄清楚为什么一个页面会触发点击事件,而另一个页面则不会。

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.

我正在使用 jQuery 自动完成最基本的功能。事实上,使用与 jQuery UI 主页上显示的完全相同的代码。

The question

问题

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

那么,如何在 iOS 中的 /show 页面上一键完成自动完成?

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

(我会在评论中发布额外的链接,因为我还没有 10 个代表。除非我没有足够的代表来评论......)

回答by onlydimon

Just a bit later, but

过了一会儿,但

$("#input").autocomplete({
    open: function(event, ui) {
        $('.ui-autocomplete').off('menufocus hover mouseover mouseenter');
    }
});

回答by Sangram Nandkhile

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

出于某种奇怪的原因,@onlydimon's答案对我不起作用。看起来我们确实需要 event mouseenter。以下答案对我来说效果很好。

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.

我添加了一个条件以确保它不会在其他设备中损坏。

回答by fvsch

Building on onlydimon's solution:

基于 onlydimon 的解决方案:

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.

我将事件列表缩小到 jQuery 的 'mouseenter' 事件。仅删除这个就为我修复了错误。另外,每次打开列表时都不需要删除它;一次就够了。

回答by Liam Johnston

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);
        });
    
  1. 检查我们是否使用了触摸设备(在我的例子中,是一个我称之为 IAmTouchy 的变量。
  2. 聆听自动完成结果上的点击 (touchstart)。
  3. 一段时间后,检查自动完成结果是否仍然可见。如果是,并且某个项目被聚焦,则触发对它的单击。
  4. (可选)再试一次……以防设置的时间不够长,元素无法获得 ui-state-focus 类。

        $('.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!

希望有人有更好的解决方案!

回答by YPatel

$.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.

这对我有用(也适用于 drupal 8)。现在一键点击 iOS 设备重定向到搜索结果页面。

回答by andrewbkil

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

自动完成小部件具有一些内置事件,您可以将其添加到代码中... 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.

基本上对于移动设备 (iO),当您点击自动完成列表“一次”时,它将触发“焦点”事件,如果您再次单击(第二次单击),它将将该事件读取为“选择”。因此,为了强制 iOs 设备在单击时选择,您必须强制它在第一次单击时选择。

$("#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
  }
});

回答by Rapha?l Malié

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

基于Liam Johnston解决方案,我写了这个对我有用的 autoFocus 设置为 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;
    });

回答by CRK

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.

Rapha?l Malié 的解决方案几乎是完美的,但它需要 evt.preventDefault() for touchend,否则它会在被点击的项目下的链接/按钮上产生点击。

    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;
        });

回答by Jorge Mejia

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:

我正在使用 jQuery UI 和cordova,我在应用程序中遇到了同样的问题,我对这个问题的解决方案是这样的:

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

This stop the focus on the selected item.

这将停止对所选项目的关注。

回答by cby016

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);
    }
});