web-dev-qa-db-fra.com

Pourquoi cette zone de texte ne se concentre-t-elle pas avec .focus ()?

J'ai ce code pour mettre au point une zone de texte lorsque l'utilisateur clique sur le bouton "Répondre":

$('#reply_msg').live('mousedown', function() {
    $(this).hide();
    $('#reply_holder').show();
    $('#reply_message').focus();
});

Il montre le formulaire de réponse, mais la zone de texte ne se concentrera pas. J'ajoute la zone de texte via AJAX, raison pour laquelle j'utilise .live(). La boîte que j’ajoute montre (j’ajoute même #reply_msg via AJAX et tout se passe lorsque je passe la souris dessus), mais elle ne se concentre pas sur la zone de texte. 


Modifier

Mon HTML ressemble à:

<div id="reply_msg">
  <div class="replybox">
  <span>Click here to <span class="link">Reply</span></span>
  </div>
  </div>
  <div id="reply_holder" style="display: none;">
  <div id="reply_tab"><img src="images/blank.gif" /> Reply</div>
  <label class="label" for="reply_subject" style="padding-top: 7px; width: 64px; color: #999; font-weight: bold; font-size: 13px;">Subject</label>
  <input type="text" id="reply_subject" class="input" style="width: 799px;" value="Re: <?php echo $info['subject']; ?>" />
  <br /><br />
  <textarea name="reply" id="reply_message" class="input" spellcheck="false"></textarea>
  <br />
  <div id="reply_buttons">
  <button type="button" class="button" id="send_reply">Send</button>
  <button type="button" class="button" id="cancel_reply_msg">Cancel</button>
  <!--<button type="button" class="button" id="save_draft_reply">Save Draft</button>-->
  </div>
</div> 
44
Nathan

Un clic sur un élément déclenche des événements dans l'ordre suivant:

  1. souris vers le bas 
  2. concentrer
  3. mouseup
  4. cliquez sur

Alors, voici ce qui se passe:

  1. mousedown est soulevé par <a>
  2. vous focalisez manuellement le <textarea>
  3. le comportement d'événement par défaut essaie de focaliser <a> (qui prend le focus de <textarea>)

Voici une démo illustrant ce comportement:

$("a,textarea").on("mousedown mouseup click focus blur", function(e) {
  console.log("%s: %s", this.tagName, e.type);
})
$("a").mousedown(function(e) {
  $("textarea").focus();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="javascript:void(0)">reply</a>
<textarea></textarea>

Alors, comment pouvons-nous contourner cela?

Option 1: Utilisez event.preventDefault() pour supprimer le comportement par défaut de mousedown:

$(document).on("mousedown", "#reply_msg", function(e) {
    e.preventDefault();
    $(this).hide();
    $("#reply_message").show().focus();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="javascript:void(0)" id="reply_msg">reply</a>
<textarea id="reply_message"></textarea>

Option 2: Utilisez un événement qui se déclenche après focus, par exemple mouseup ou click

$(document).on("mouseup", "#reply_msg", function(e) {
    $(this).hide();
    $("#reply_message").show().focus();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="javascript:void(0)" id="reply_msg">reply</a>
<textarea id="reply_message"></textarea>

46
canon

Se concentrer sur quelque chose d'un gestionnaire d'événements qui, en soi, donne le focus, est toujours problématique. La solution générale consiste à définir le focus après un délai d'attente:

setTimeout(function() {
  $('#reply_message').focus();
}, 0);

Cela permet au navigateur d’agir, puis vous revenez et concentrez-vous là où vous le souhaitez.

32
Pointy

Pourrait-il s'agir du même problème? focus jQuery Textarea

Essayez d'appeler .focus() après la fin de .show().

$('#reply_msg').live('mousedown', function() {
    $(this).hide();
    $('#reply_holder').show("fast", function(){
        $('#reply_message').focus();
    }); 
});
4
Jeremy Wiggins

J'ai rencontré ce problème aujourd'hui et dans mon cas, il était dû à un bogue dans jQuery UI (v1.11.4) qui faisait en sorte que les éléments textarea à l'intérieur des éléments glissables/droppables arrêtaient le comportement de clic par défaut avant le textarea reçoit le clic de mise au point.

La solution consistait à retravailler l'interface utilisateur afin que la textarea n'apparaisse plus à l'intérieur de l'élément déplaçable. 

C’était une question particulièrement difficile à résoudre, je laisse donc une réponse ici au cas où d’autres le jugeraient utile.

1
tohster