2010-11-03 34 views
23

J'ai rencontré ce problème plusieurs fois et je ne suis pas satisfait des solutions que j'ai déjà utilisées.Comment devrais-je déclencher l'événement de flou Javascript après l'événement click qui provoque le flou?

J'ai une boîte de saisie avec un flou qui en valide le contenu et un bouton qui va remplir la boîte de saisie en cliquant sur. Le problème est de cliquer sur le bouton qui déclenche l'événement de flou d'entrée, puis sur l'événement de clic sur le bouton, de sorte que le contenu inséré par le bouton n'est pas ce qui est validé.

Voir http://jsfiddle.net/jakecr/dL3K3/

Je sais que c'est le comportement correct, mais je ne peux pas penser à un moyen propre pour contourner le problème.

+0

Votre question n'est pas clair? quel est votre problème et quelle est la solution attendue? –

+0

Fondamentalement, une action de l'utilisateur provoque deux événements qui se déclenchent dans l'ordre mais l'action du second repose sur celle du premier. J'ai envisagé d'utiliser setTimeout pour retarder le premier événement, mais cela ne semble pas être une solution idéale. – Jake

+0

J'ai posé cette question sous une forme assez générale parce que j'ai rencontré ce problème plusieurs fois dans des circonstances différentes. – Jake

Répondre

31

Nous avons eu un problème similaire au travail. ce que nous avons compris à la fin était que l'événement mousedown tirera avant l'événement de flou vous permettant de définir le contenu avant la validation ou même annuler le processus de validation complètement en utilisant un drapeau.

vérifier ce violon j'ai fait en utilisant votre exemple- http://jsfiddle.net/dL3K3/31/

$(function(){ 
    var flag = true; 
    $('input').blur(function(){ 
     if(!$(this).val() && flag){ 
      alert("Grrr, It's empty"); 
     } 
    }); 

    $('button').mousedown(function(){ 
     flag = false; 
    });  
    $('button').mouseup(function(){ 
     flag = true; 
     $('input').val('content').focus(); 
    }); 

}); 

-Edit-

Comme @mclin suggéré, en utilisant l'événement MouseDown et preventDefault empêchera le comportement de flou. Et vous pouvez laisser le clic événement original intact -

http://jsfiddle.net/dL3K3/364/

$(function(){ 
    $('input').blur(function(){ 
     if(!$(this).val()){ 
      alert("Grrr, It's empty"); 
     } 
    }); 

    $('button').mousedown(function(e){ 
     e.preventDefault(); 
    });  
    $('button').click(function(){ 
     $('input').val('content'); 
    }); 

}); 

Cette solution est peut-être un peu plus propre et mieux pour la plupart des cas simplement noter que si vous l'utilisez, vous aurez preventDefault et le flou de tout autre élément sur lequel porte actuellement l'attention, mais pour la plupart des cas d'utilisation, cela ne devrait pas être un problème.

+0

L'événement mousedown peut entraîner l'envoi de la soumission, quelle que soit sa validation, voir ici http://stackoverflow.com/questions/43011387/mousedown-still-submitting-form-when-it-should-not – DragonFire

+0

@DragonFire Ceci n'a rien à voir avec ce problème ou mouswdown. Votre code est en cours d'exécution asynchrone et votre traitement en tant que code synchrone –

1

Séparez la logique de validation d'entrée de sa propre fonction qui est appelée automatiquement par l'événement de flou puis par l'événement de clic après avoir modifié la valeur dans la zone de saisie. Vrai, votre logique de validation serait appelée deux fois, mais je ne vois pas comment contourner cela sans apporter beaucoup plus de changements.

Exemple avec jQuery:

$('input').blur(function() { 
    validate(this); 
}); 

$('submit').click(function() { 
    //modify the input element 
    validate(inputElement); 
}); 

var validate = function(obj) { 
    // validate the object 
} 
+0

Pas tout à fait la solution que j'avais après parce que l'événement de flou est toujours déclenché, mais je ne pense pas qu'il soit possible de faire exactement ce que je veux. – Jake

8

Cela pourrait aussi aider:

Régler une minuterie qui retarde l'action d'événement de flou avant qu'il déclenche le bouton événement click.

// Namespace for timer var setTimer = { timer: null } 

    $('input,select').blur(function() { 
     setTimer.timer = setTimeout(function() { 
      functionCall(); 
     }, 1000); 
    }); 

    $('input,select').focus(function() { 
     setTimer.timer = setTimeout(function() { 
      functionCall(); 
     }, 1000); 
    }); 

    $("#btn").click(function() { 
     clearTimeout(setTimer.timer); 
     functionCall(); 
    }); 
+0

Ceci est une solution intelligente. –

-2

L'astuce est de ne pas utiliser le flou et cliquez sur les événements, car ils sont toujours effectués afin de flou d'abord, cliquez sur seconde. Au lieu de cela, vous devriez vérifier quand l'élément ayant le focus a changé, car cela se produit seulement après le clic.

je pense avoir une solution élégante pour celle-ci:

var alreadyValidated = 'true'; 

setInterval(function(){ 
    if(document.activeElement.id != 'validation-field-id'){ 
     if(alreadyValidated=='false'){ 
      alreadyValidated = 'true'; 
      validate(document.activeElement);  
     } 
    } 
    else { 
     alreadyValidated = 'false'; 
    } 
}, 200); 

Ces jours-ci tous les navigateurs modernes prennent en charge document.activeElement.

+2

Vous devez utiliser 'true' et' false' plutôt que des chaînes parce que 'Boolean ('false') === true' – Jake

+7

" Elegant Solution "et setInterval n'appartiennent pas au même article. – aaronsnoswell

18

J'ai une meilleure solution que celle de Yoni Jah: appel preventDefault sur l'événement mousedown du bouton.L'onBlur n'arrive jamais et vous êtes libre de faire quoi que ce soit dans l'événement click. Ceci est préférable car cela ne change pas le comportement du clic en faisant en sorte que les choses se passent à la souris au lieu de la souris, ce qui peut être inattendu.

+0

Ceci est la meilleure solution. Exactement ce que je cherchais. –

+0

Merci j'ai mis à jour ma réponse –

0

Parfois, il est utile d'obtenir un objet enfant sur mouseup, mais le parent veut cacher ses enfants sur le flou. Nous pouvons annuler la dissimulation des éléments enfants, puis attendez que notre mouseup se produit, la force alors le flou de se produire lorsque nous sommes prêts

js

var cancelHide = false; 

$('.my-input').blur(function() { 
    if (!cancelHide) { 
     $('.my-item').hide(); 
    } 
}); 

$('.my-input').click(function() { 
    $('.my-item').show(); 
}); 

$('.my-item').mousedown(function() { 
    cancelHide = true; 
}); 

$('.my-item').mouseup(function() { 
    var text = $(this).text(); 
    alert(text); 
    cancelHide = false; 
    $('.my-input').blur(); 
}); 

html

<input type="text" class="my-input"/> 
<div class="my-item">Hello</div> 
<div class="my-item">Lovely</div> 
<div class="my-item">World</div> 

css

.my-item { 
    display:none; 
} 

https://jsfiddle.net/tic84/on421rxg/

En cliquant sur les éléments de liste alertent uniquement mouseup, malgré le parent essayant de les cacher sur le flou