37 votes

Recherche d'une meilleure solution de contournement du bogue de Chrome concernant la sélection sur le focus

J'ai le même problème que l'utilisateur dans cette question qui est due à ce bug dans Webkit. Cependant, la solution de contournement fournie ne fonctionnera pas pour mon application. Permettez-moi de reformuler le problème afin que vous n'ayez pas à lire une autre question :

J'essaie de sélectionner tout le texte d'une zone de texte lorsqu'elle reçoit le focus. Le code jQuery suivant fonctionne dans IE/FF/Opera :

$('#out').focus(function(){
  $('#out').select();
});

Cependant, dans Chrome/Safari, le texte est sélectionné - très brièvement - mais l'événement mouseUp est ensuite déclenché et le texte est désélectionné. La solution de contournement suivante est proposée dans les liens ci-dessus :

$('#out').mouseup(function(e){
  e.preventDefault();
});

Cependant, cette solution de contournement n'est pas bonne pour moi . Je veux sélectionner tout le texte seulement lorsque l'utilisateur met le focus sur la zone de texte. Il doit pourra ensuite sélectionner une partie seulement du texte s'il le souhaite. Quelqu'un peut-il trouver une solution de contournement qui réponde à cette exigence ?

5 votes

Un grand +1 pour avoir repéré la faille évidente dans la solution la plus communément suggérée au problème.

29voto

tcooc Points 5006

Que pensez-vous de ça ?

$('#out').focus(function () {
    $('#out').select().mouseup(function (e) {
        e.preventDefault();
        $(this).unbind("mouseup");
    });
});

9 votes

Probablement .one() est un meilleur moyen ici.

0 votes

+1. Je ne comprends pas pourquoi tant de personnes pensent que la base preventDefault() est suffisant. Il a clairement de graves défauts, et pourtant il est suggéré comme la solution partout où vous regardez. Merci de l'avoir résolu. (bien que oui, je suis d'accord avec @InviS que .one() pourrait être une meilleure façon de le faire)

1 votes

.one() serait mieux et cette méthode ne gère pas très bien le focus par tabulation.

25voto

Adrian Lang Points 1667

La réponse acceptée (et pratiquement toutes les autres solutions que j'ai trouvées jusqu'à présent) ne fonctionne pas avec le focus clavier, c'est-à-dire en appuyant sur la touche tabulation, du moins pas dans mon Chromium 21. J'utilise l'extrait suivant à la place :

$('#out').focus(function () {
  $(this).select().one('mouseup', function (e) {
    $(this).off('keyup');
    e.preventDefault();
  }).one('keyup', function () {
    $(this).select().off('mouseup');
  });
});

e.preventDefault() en el keyup o focus n'aide pas, donc la désélection après un focus clavier semble ne pas se produire dans leurs gestionnaires par défaut, mais plutôt quelque part entre le gestionnaire focus y keyup événements.

Comme suggéré par @BarelyFitz, il serait peut-être préférable de travailler avec des événements nommés afin de ne pas délier accidentellement d'autres gestionnaires d'événements. Remplacer 'keyup' avec 'keyup.selectText' y 'mouseup' avec 'mouseup.selectText' pour ça.

4 votes

Lorsque vous dissociez des événements, vous pouvez dissocier par inadvertance d'autres gestionnaires qui pourraient se trouver sur l'entrée. Pour éviter cela, vous pouvez utiliser un espace de noms tel que "mouseup.selectText" au lieu de "mouseup", de sorte que seul votre gestionnaire d'événement unique sera supprimé.

0 votes

Combinée à l'indication de l'espace de nom, c'est la meilleure solution que j'ai trouvée jusqu'à présent pour ce problème épineux et je la recommande à la maison.

4voto

Barbarab Points 21

Pourquoi pas simplement :

$('#out').focus(function(){
    $(this).one('mouseup', function() {
        $(this).select();
    });
});

Il semble fonctionner dans tous les principaux navigateurs...

3 votes

Ça a marché pour moi. Il est intéressant de noter que cela ne semble pas fonctionner lorsque vous vous concentrez sur une entrée par le biais du code. Pour contourner ce problème, j'utilise $('#element').select().focus() au lieu de $('#element').focus() .

2voto

zneak Points 45458

Faites un bool . Réglez-le sur true après un événement de focus et le réinitialiser après un événement de mouse up. Lors du passage de la souris, si c'est true vous savez que l'utilisateur vient de sélectionner le champ de texte ; vous savez donc que vous devez empêcher le passage de la souris. Sinon, vous devez la laisser passer.

var textFieldGotFocus = false;

$('#out').focus(function()
{
    $('#out').select();
    textFieldGotFocus = true;
});

$('#out').mouseup(function(e)
{
    if (textFieldGotFocus)
        e.preventDefault();
});

$(document).mouseup(function() { textFieldGotFocus = false; });

Il est important que vous mettiez l'écouteur de mouseup qui réinitialise la variable sur document car il n'est pas garanti que l'utilisateur relâche le bouton de la souris sur le champ de texte.

0 votes

Merci ! cela m'a inspiré une idée encore plus simple : au lieu d'un écouteur sur document.mouseup, il suffit de mettre le drapeau à false sur out.mouseup : if(textFieldGotFocus){ e.preventDefault(); textFieldGotFocus = false;}

0 votes

Les variables globales + la gestion des événements = = recette pour les problèmes.

2voto

Terje Points 51
onclick="var self = this;setTimeout(function() {self.select();}, 0);"

0 votes

Cette réponse m'a inspiré : $("#one").on('focus', null, function() { var $that = $(this); setTimeout(function() { $that.select(); }, 0); });

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