Intercepter la touche Entrée, mais pas lors du choix de la suggestion de saisie semi-automatique du navigateur

StackOverflow https://stackoverflow.com/questions/1648993

  •  22-07-2019
  •  | 
  •  

Question

J'ai des zones de texte sur une page et je souhaite cliquer sur un lien lorsque l'utilisateur appuie sur pour entrer l'une d'entre elles.

Je peux facilement intercepter le bouton Entrée à l'aide de javascript (en recherchant 13 dans event.keyCode et event.which ), mais je pose un problème lorsque la saisie semi-automatique du navigateur fonctionnalité entre en jeu et suggère ce que l'utilisateur peut vouloir taper. Nous constatons que les utilisateurs appuient souvent sur entrée pour accepter la suggestion du navigateur plutôt que sur l'onglet. Cela confond les utilisateurs lorsque le lien est cliqué immédiatement, alors qu'ils avaient toujours l'intention de saisir du texte dans certains des autres champs.

Je sais qu'il serait préférable d'utiliser un formulaire et un bouton de soumission ici, mais pour diverses raisons, ce n'est pas pratique.

J'utilise jQuery, alors n'hésitez pas à proposer des solutions jQuery.

Était-ce utile?

La solution

L'utilisateur doit toujours appuyer sur la touche bas s'il choisit de sélectionner un des droits de saisie automatique, pourquoi ne pas définir une variable sur quelque chose lorsqu'il appuie sur la touche bas, puis s'il appuie sur la touche Entrée après variable. Vous ne devez pas utiliser la fonction de lien de lien si la variable est définie, sinon faites-le normalement.

Autres conseils

En utilisant l’idée de tuanvt dans la réponse acceptée, j’ai écrit un plugin jQuery qui fait le travail.

Je surveille le moment où l'utilisateur appuie sur les touches haut, bas, page précédente et page suivante pour indiquer quand il se trouve dans la zone de saisie semi-automatique. Toutes les autres clés impliquent qu'ils l'ont laissée.

Je m'assure que nous appliquons ces règles uniquement aux zones de texte: tous les autres éléments d'entrée se comportent normalement.

Opera réalise déjà assez bien ce que j’essayais de faire. Je n’applique donc pas mes règles dans ce navigateur. Dans le cas contraire, l’utilisateur devra appuyer deux fois sur la touche Entrée.

Testé dans IE6, IE7, IE8, Firefox 3.5.5, Google Chrome 3.0, Safari 4.0.4, Opera 10.00.

Il est disponible sur jquery.com en tant que plug-in SafeEnter . Pour votre commodité, le code de la version 1.0 est le suivant:

// jQuery plugin: SafeEnter 1.0
// http://plugins.jquery.com/project/SafeEnter
// by teedyay
//
// Fires an event when the user presses Enter, but not whilst they're in the browser's autocomplete suggestions

//codesnippet:2e23681e-c3a9-46ce-be93-48cc3aba2c73
(function($)
{
    $.fn.listenForEnter = function()
    {
        return this.each(function()
        {
            $(this).focus(function()
            {
                $(this).data('safeEnter_InAutocomplete', false);
            });
            $(this).keypress(function(e)
            {
                var key = (e.keyCode ? e.keyCode : e.which);
                switch (key)
                {
                    case 13:
                        // Fire the event if:
                        //   - we're not currently in the browser's Autocomplete, or
                        //   - this isn't a textbox, or
                        //   - this is Opera (which provides its own protection)
                        if (!$(this).data('safeEnter_InAutocomplete') || !$(this).is('input[type=text]') || $.browser.opera)
                        {
                            $(this).trigger('pressedEnter', e);
                        }
                        $(this).data('safeEnter_InAutocomplete', false);
                        break;

                    case 40:
                    case 38:
                    case 34:
                    case 33:
                        // down=40,up=38,pgdn=34,pgup=33
                        $(this).data('safeEnter_InAutocomplete', true);
                        break;

                    default:
                        $(this).data('safeEnter_InAutocomplete', false);
                        break;
                }
            });
        });
    };

    $.fn.clickOnEnter = function(target)
    {
        return this.each(function()
        {
            $(this)
                .listenForEnter()
                .bind('pressedEnter', function()
                {
                    $(target).click();
                });
        });
    };
})(jQuery);

Essayez de désactiver la complétion automatique dans votre case à cocher, bien que cela ne soit pas standard pour tous les navigateurs, mais que cela fonctionne avec les navigateurs courants.

<input type="text" autocomplete="off" />

JQuery est bien et tout mais pourquoi ne pas utiliser du simple JavaScript?

function submit_on_enter(e) {
    var keycode;
    if (window.event) keycode = window.event.keyCode;
    else if (e) keycode = (e.keyCode ? e.keyCode : e.which);
    else return true;

    if (keycode == 13) {
        if (window.previousKeyCode) {
            // down=40,up=38,pgdn=34,pgup=33
            if (window.previousKeyCode == 33 || window.previousKeyCode == 34 ||
                window.previousKeyCode == 39 || window.previousKeyCode == 40) {
                    window.previousKeyCode = keycode;
                    return true;
            }
        }
        submit_form();
        return false;
    } else {
        window.previousKeyCode = keycode;
        return true;
    }
}

retracez la touche Entrée lors d'un événement keyup, la sélection est complétée par l'heure à laquelle vous détectez la touche Entrée lors d'un événement keyup.

détecter la touche Entrée à la touche enfoncée et à ce que l'opération interfère avec la fonctionnalité de saisie semi-automatique.

Cela fonctionne pour moi:

$('input').keypress(function(e) {
    if(e.which == 13) {
        if(this.value)
        {
            $("#submitbutton").click();
        }
    }
});

Si vous utilisez les nouveaux types de champs de formulaire html5, vous pouvez modifier le code de teedyay comme suit:

case 13:
                    // Fire the event if:
                    //   - we're not currently in the browser's Autocomplete, or
                    //   - this isn't a textbox, or
                    //   - this is Opera (which provides its own protection)
                    if (!$(this).data('safeEnter_InAutocomplete') || !$(this).is('input([type=text],[type=email],[type=number],[type=search],[type=tel],[type=url])') || $.browser.opera)
                    {
                        ...

Notez les nouveaux types d'entrée.

Je ne sais pas si vous interceptez les touches sur la fenêtre ou sur des éléments DOM spécifiques. Vous devez effectuer cette dernière opération (par exemple sur l'élément form ), puis dans votre gestionnaire d'événements, examinez l'objet événement pour déterminer quel élément DOM était à l'origine de l'événement. S'il s'agissait d'un champ de texte avec la saisie semi-automatique, alors return false; .

Jetez un coup d'œil à la .keypress () de jQuery > gestionnaire d'événements et event.target propriété de l'objet événement.

J’ai fait face au même problème et bien que cela ne soit pas parfait, j’ai utilisé une autre approche que j’estime plus simple. Lors de la création de la saisie semi-automatique, je définis l'heure actuelle de l'événement select, puis je le compare avant d'entreprendre toute action:

$('#completer').autocomplete({
  source: ['First', 'Last'], delay: 0, minLength: 0,
  select: function(ev, ui) {
    $(ev.target).data('lastAutocompleteSelectTimestamp', new Date().getTime())
  }
})

$(document).on('keydown', '#completer', function(ev){
  if (ev.which != 13) return
  var lastAutocompletionTime = $(ev.currentTarget).data('lastAutocompleteSelectTimestamp')
  if (!lastAutocompletionTime || (new Date().getTime() - lastAutocompletionTime) > 100)
    alert('Enter pressed outside autocomplete context')
})
<html>
<head>
  <link href="https://code.jquery.com/ui/1.11.0/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
  <script src="https://code.jquery.com/ui/1.11.0/jquery-ui.min.js"></script>
</head>
<body>
  <input id=completer type=text />
</body>
</html>

Une autre approche (plus sûre) consiste à utiliser les événements keyup et keydown pour détecter les modifications de valeur.

La saisie semi-automatique définit la valeur après l'événement keyDown . Lorsque les deux événements sont observés, les solutions suivantes sont beaucoup plus fiables que les autres solutions:

var tempValue;
// fire when enter is 1. pressed and 2. released
function handlerEnter(type){
     // save the value for comparison
     if(type == 'keyDown'){
         tempValue = document.activeElement.value;
         return null; // quit
     }

     // quit when the value changed in between keyDown & keyUp
     if(type == 'keyUp' && tempValue != document.activeElement.value){
         return null;
     }

     // autocomplete wasn't used
     doStuff();
}

Vous pouvez vérifier si document.activeElement est une entrée. N'hésitez pas à utiliser l'extension de mon prototype diabolique . >

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top