140 votes

jQuery : déclencher click() avant blur()

J'ai un champ de saisie dans lequel j'essaie de faire une suggestion d'autocomplétion. Le code ressemble à

<input type="text" id="myinput">
<div id="myresults"></div>

Sur les entrées blur() Je veux cacher la div "résultats" :

$("#myinput").live('blur',function(){
     $("#myresults").hide();
});

Lorsque j'écris quelque chose dans mon input, j'envoie une requête au serveur et j'obtiens une réponse json, je l'analyse dans la structure ul->li et je place cet ul dans mon #myresults div.

Lorsque je clique sur cet élément li analysé, je veux définir la valeur de li comme entrée et la cacher. #myresults div

$("#myresults ul li").live('click',function(){
     $("#myinput").val($(this).html());
     $("#myresults").hide();
});

Tout se passe bien, mais lorsque je clique sur mon lien, j'ai l'impression d'être dans une impasse. blur() se déclenche avant que l'événement click() et la valeur de l'input ne reçoit pas le html du li.

Comment puis-je mettre en place click() événement avant blur() ?

330voto

Alexey Lebedev Points 4778

Solution 1

Écouter mousedown au lieu de click .

En mousedown y blur les événements se succèdent lorsque vous appuyez sur le bouton de la souris, mais click ne se produit que lorsque vous le relâchez.

Solution 2

Vous pouvez preventDefault() en mousedown pour empêcher la liste déroulante de voler le focus. Le léger avantage est que la valeur sera sélectionnée lorsque le bouton de la souris sera relâché, ce qui est le cas des composants de sélection natifs. JSFiddle

$('input').on('focus', function() {
    $('ul').show();
}).on('blur', function() {
    $('ul').hide();
});

$('ul').on('mousedown', function(event) {
    event.preventDefault();
}).on('click', 'li', function() {
    $('input').val(this.textContent).blur();
});

2voto

adeneo Points 135949
$(document).on('blur', "#myinput", hideResult);

$(document).on('mousedown', "#myresults ul li", function(){
     $(document).off('blur', "#myinput", hideResult); //unbind the handler before updating value
     $("#myinput").val($(this).html()).blur(); //make sure it does not have focus anymore
     hideResult(); 
     $(document).on('blur', "#myinput", hideResult);  //rebind the handler if needed
});

function hideResult() {
     $("#myresults").hide();
}

FIDDLE

2voto

geckob Points 3081

J'ai été confronté à ce problème et j'ai utilisé mousedown n'est pas une option pour moi.

J'ai résolu ce problème en utilisant setTimeout dans la fonction de traitement

        elem1.on('blur',function(e) {

            var obj = $(this);

            // Delay to allow click to execute
            setTimeout(function () {
                if (e.type == 'blur') {

                  // Do stuff here

                }
            }, 250);
        });

        elem2.click( function() {
            console.log('Clicked');
        });

2voto

dule Points 1830

Je viens de répondre à une question similaire : https://stackoverflow.com/a/46676463/227578

Une autre solution consiste à ignorer les événements de flou provoqués par un clic sur des éléments spécifiques (c'est-à-dire que dans votre gestionnaire de flou, sautez l'exécution s'il s'agit du résultat d'un clic sur un élément spécifique).

$("#myinput").live('blur',function(e){
     if (!e.relatedTarget || !$(e.relatedTarget).is("#myresults ul li")) {
         $("#myresults").hide();
     }
});

0voto

Andriy Points 857

Les solutions Mousedown ne fonctionnent pas pour moi, lorsque je clique sur des éléments qui ne sont pas des boutons. Voici donc ce que j'ai fait avec la fonction blur dans mon code :

.on("blur",":text,:checkbox,:radio,select",function() {
/*
* el.container 
* container, you want detect click function on.
*/
            var outerDir = el.container.find(':hover').last();
            if (outerDir.length) {
                if ($.inArray(outerDir.prop('tagName'), ["A","SELECT"] ) != -1 || outerDir.prop('type') == 'button' || outerDir.prop('type') == 'submit') {
                    outerDir.click();
                }
                if (outerDir.prop('type') == 'checkbox') {
                    outerDir.change();
                }
                return false;
            }
/*          
* YOUR_BLUR_FUNCTION_HERE;
*/
});

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X