javascript jquery jquery-ui ios7 jquery-ui-autocomplete

javascript - Autocompletar requiere que haga clic dos veces en iOS después de actualizar a 1.11.0



jquery jquery-ui (12)

Usando jQuery 2.1.0 y jQuery.ui 1.11.0 probado en iOS 7. iPhone y iPad Mini. Funciona en los navegadores android y regulares.

El problema

Recientemente actualizamos jQuery UI 1.10.0 a 1.11.0 y ahora, al hacer clic en un elemento en una lista de resultados de autocompletar, solo obtiene un elemento emergente, debe hacer clic nuevamente en el mismo elemento para obtener un evento de clic. Esto solía funcionar bien con la versión 1.10.0.

(Enlace JSFiddle en comentarios)

Qué no funciona

usar css {cursor: pointer} no funciona

usar onclick="" no funciona

(Enlace JSFiddle en comentarios)

La parte extraña

Pero aquí viene la parte divertida / extraña. Funciona en la vista de edición JSFiddle, pero no en la página JSFiddle "/ show".

JSFiddles: (escriba una letra para mostrar los resultados "s" es buena)

He estado trabajando en esto durante días, pero no he podido reproducirlo en JSFiddle antes de probar solo la vista html. Entonces ahora me dirijo a ti. No puedo entender por qué una página desencadena un clic y la otra no.

Estoy usando la función más básica de jQuery autocompletar. De hecho, usa exactamente el mismo código que se presenta en la página de inicio de jQuery UI.

La pregunta

Entonces, ¿cómo consigo la función autocompletar para trabajar con un clic en iOS en la página / show?

(Publicaré enlaces adicionales en los comentarios porque aún no tengo 10 representantes. A menos que no tenga suficientes representantes para comentar ...)


¡probablemente puedas usar el evento de focus desde autocompletar!

enfoque (evento, 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">


Basándose en la solución de 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'')

Reduje la lista de eventos para solo el evento ''mouseenter'' de jQuery. Eliminar solo esto soluciona el error por mí. Además, no es necesario eliminarlo cada vez que se abre la lista; una vez es suficiente.


Basado en la solución de Liam Johnston , escribí este que funciona para mí con autoFocus configurado en 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; });


El widget Autocompletar tiene algunos eventos integrados que puedes agregar a tu código ... jqueryui

Estaba teniendo el mismo problema y finalmente resolví cómo usar el código y obligar a los dispositivos móviles a responder con un solo clic.

Básicamente para dispositivos móviles (iOs) cuando toca la lista de autocompletar ''una vez'', activará el evento de "enfoque", si hace clic una vez más (segundo clic) leerá el evento como "seleccionar". Por lo tanto, para forzar a los dispositivos de iOs a seleccionar con un clic, debe forzarlo a seleccionar en el primer clic.

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


Escribió un truco súper desagradable que parece ser el truco para mí. Esto es lo que hice.

  1. Compruebe que estamos usando un dispositivo táctil (en mi caso, una variable que he llamado IAmTouchy).
  2. Escuche un toque (touchstart) en un resultado de autocompletar.
  3. Después de un tiempo establecido, verifique si los resultados de autocompletar aún son visibles. Si lo son, y un elemento está enfocado, active un clic.
  4. (opcional) Inténtelo una vez más ... en caso de que el tiempo establecido no sea lo suficientemente largo para que el elemento gane la clase 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); });

¡Espero que alguien tenga una mejor solución!


Este código funciona con autoenfoque

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


Estoy trabajando con jQuery UI con y cordova, y tengo el mismo problema en la aplicación, mi solución para ese problema es esta:

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

Esto detiene el enfoque en el elemento seleccionado.


La solución de Raphaël Malié es casi perfecta, pero necesita evt.preventDefault () para touchend, de lo contrario generará un clic en un enlace / botón que está debajo del elemento cliqueado.

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


Por alguna extraña razón, @onlydimon''s respuesta de @onlydimon''s no funcionó para mí. Parece que necesitamos el evento mouseenter . La siguiente respuesta funcionó bien para mí.

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

He agregado una condición para asegurarme de que no se rompa en otros dispositivos.


Solo un poco más tarde, pero

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


Usar fastclick.js resolverá este problema. Sé que este js se usa para eliminar 300ms de retraso de tap pero también solucionó este problema para mí.

  1. Descargue la versión reducida de FastClick (de forma alternativa, puede seguir las instrucciones para instalar la versión no minificada aquí)

  2. Incluye el archivo en tu proyecto:

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

  3. Adjunte el objeto FastClick al documento después de que se haya cargado FastClick:

    var attachFastClick = Origami.fastclick;

    attachFastClick (document.body);

NOTA: Si intenta utilizar FastClick de forma no minima, es decir:

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

Entonces usa

FastClick.attach (document.body);

pero si incluye el archivo minificado, recibirá errores (que le informan que FastClick no está definido). Si está utilizando el archivo modificado, debe acceder a él a través de Origami.


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

Esto funcionó para mí (también funciona en drupal 8). Ahora, un toque en dispositivos con iOS redirija a la página de resultados de búsqueda.