web-dev-qa-db-fra.com

La saisie semi-automatique vous oblige à cliquer deux fois dans iOS après la mise à jour vers 1.11.0

Utilisation de jQuery 2.1.0 et jQuery.ui 1.11.0 Testé sur iOS 7. iPhone et iPad Mini. Fonctionne sur Android et les navigateurs classiques.

Le problème

Nous avons récemment mis à niveau de jQuery UI 1.10.0 vers 1.11.0 et maintenant, lorsque vous cliquez sur un élément dans une liste de résultats de saisie semi-automatique, vous obtenez uniquement un survol, vous devez cliquer à nouveau sur le même élément pour obtenir un événement de clic. Cela fonctionnait bien avec la version 1.10.0.

(lien JSFiddle dans les commentaires)

Ce qui ne marche pas

en utilisant css {cursor: pointer} ne marche pas

en utilisant onclick="" ne marche pas

(lien JSFiddle dans les commentaires)

La partie bizarre

Mais voici la partie amusante/bizarre. Cela fonctionne dans JSFiddle éditer vue, mais pas sur la page "/ show" de JSFiddle.

JSFiddles: (taper une lettre pour afficher les résultats "s" est une bonne)

J'y travaille depuis des jours, mais je n'avais pas pu le reproduire dans JSFiddle avant de tester uniquement la vue html. Alors maintenant je me tourne vers vous. Je ne peux pas pour la vie de moi comprendre pourquoi une page déclenche un événement de clic, et l'autre pas.

J'utilise la fonction la plus élémentaire de la saisie semi-automatique de jQuery. En fait, en utilisant exactement le même code qui est présenté sur la page d'accueil de jQuery UI.

La question

Alors, comment faire pour que la saisie semi-automatique fonctionne en un seul clic dans iOS sur la page/show?

(Je posterai des liens supplémentaires dans les commentaires car je n'ai pas encore 10 représentants. À moins que je n'ai pas assez de représentants pour commenter ...)

52
Snorre Kim

Un peu plus tard, mais

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

Pour une raison étrange @onlydimon's la réponse n'a pas fonctionné pour moi. Il semble que nous ayons besoin de l'événement mouseenter. La réponse suivante a bien fonctionné pour moi.

open: function (result) {

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

J'ai ajouté une condition pour m'assurer qu'elle ne se brise pas dans d'autres appareils.

21
Sangram Nandkhile

S'appuyant sur la solution 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')

J'ai réduit la liste des événements à l'événement "mouseenter" de jQuery. La suppression de celui-ci corrige le bug pour moi. De plus, pas besoin de le supprimer à chaque ouverture de la liste; Une fois est assez.

13
fvsch

A écrit un hack super méchant qui semble faire l'affaire pour moi. Voici ce que j'ai fait.

  1. Vérifiez que nous utilisons un appareil tactile (dans mon cas, une variable que j'ai appelée IAmTouchy.
  2. Écoutez un tap (touchstart) sur un résultat de saisie semi-automatique.
  3. Après une durée définie, vérifiez si les résultats de la saisie semi-automatique sont toujours visibles. S'ils le sont et qu'un élément est focalisé, déclenchez un clic dessus.
  4. (facultatif) Essayez une fois de plus ... au cas où le temps défini ne serait pas assez long pour que l'élément gagne la classe 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);
        });
    

J'espère que quelqu'un a une meilleure solution!

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

Cela a fonctionné pour moi (fonctionne sur drupal 8 également). Maintenant, appuyez sur les appareils iOS pour rediriger vers la page de résultats de recherche.

3
YPatel

Le widget de saisie semi-automatique a des événements intégrés que vous pouvez ajouter à votre code ... jqueryui

J'avais le même problème et j'ai finalement compris comment tweeker le code et forcer les appareils mobiles à répondre en un seul clic.

Fondamentalement, pour les appareils mobiles (iOs) lorsque vous appuyez sur la liste de saisie semi-automatique "une fois", cela déclenchera l'événement "focus", si vous cliquez une fois de plus (2ème clic), il lira l'événement comme "sélectionnez". Donc, pour forcer les périphériques iOs à sélectionner en un seul clic, vous devez le forcer à sélectionner au premier 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
  }
});
1
andrewbkil

Basé sur Liam Johnston solution, j'ai écrit celle-ci qui fonctionne pour moi avec autoFocus défini sur 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;
    });
1
Raphaël Malié

La solution de Raphaël Malié est presque parfaite, mais elle nécessite evt.preventDefault () pour le toucher, sinon elle générera un clic sur un lien/bouton qui se trouve sous l'élément cliqué.

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

Utilisez fastclick.js, cela résoudra ce problème. Je sais que ce js est utilisé pour supprimer le retard de prise de 300 ms, mais il a également résolu ce problème pour moi.

  1. Téléchargez la version réduite de FastClick (vous pouvez également suivre les instructions d'installation de la version non réduite ici)

  2. Incluez le fichier dans votre projet:

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

  3. Attachez l'objet FastClick au document une fois FastClick chargé:

    var attachFastClick = Origami.fastclick;

    attachFastClick (document.body);

REMARQUE: Si vous essayez d'utiliser FastClick de manière non minifiée, à savoir:

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

Ensuite, utilisez

FastClick.attach (document.body);

mais si vous incluez le fichier minifié, vous recevrez des erreurs (vous indiquant que FastClick n'est pas défini). Si vous utilisez le fichier minifié, vous devez y accéder via Origami.

0
Swapnil Man

vous pouvez probablement utiliser l'événement focus de la saisie semi-automatique!

focus (événement, 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">
0
Nico

Ce code fonctionne avec 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);
    }
});
0
cby016

Je travaille avec jQuery UI avec et cordova, et j'ai le même problème dans l'application, ma solution pour ce problème est la suivante:

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

Cela arrête la mise au point sur l'élément sélectionné.

0
Jorge Mejia