Why isn't this textarea focusing with .focus()?
Asked Answered
K

5

55

I have this code to focus a textarea when the user clicks on the "Reply" button:

    $('#reply_msg').live('mousedown', function() {
        $(this).hide();
        $('#reply_holder').show();
        $('#reply_message').focus();
    });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script>
<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>

It shows the reply form, but the textarea won't focus. I'm adding the textarea via AJAX which is why I am using .live(). The box that I add shows (I even add #reply_msg via AJAX and stuff happens when I mouse down on it) but it won't focus on the textarea.

Kailey answered 5/12, 2011 at 3:43 Comment(0)
P
60

A mouse-click on a focusable element raises events in the following order:

  1. mousedown
  2. focus
  3. mouseup
  4. click

So, here's what's happening:

  1. mousedown is raised by <a>
  2. your event handler attempts to focus the <textarea>
  3. the default event behavior of mousedown tries to focus <a> (which takes focus from the <textarea>)

Here's a demo illustrating this behavior:

$("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>

So, how do we get around this?

Use event.preventDefault() to suppress mousedown's default behavior:

$(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>
Pierian answered 5/12, 2011 at 3:55 Comment(5)
I was already doing this, and it wasn't working, but thanks for your answer :)Kailey
Oh yeah, mouseup does work - and without any timeouts. Thanks :)Kailey
I know it's been some years since this answer was posted. I am looking for information about event raising order like mentioned: mousedown, focus, mouseup, click. @Pierian could you share where did you take it from? I cannot find it on neither of spec's sections: w3.org/TR/uievents/#events-focusevent-event-order, w3.org/TR/uievents/#legacy-uievent-event-order, w3.org/TR/uievents/#events-mouseevent-event-orderHonniball
@Chris92 testing and observation.Pierian
It's not standarized browser behavior, though? I hoped that's something to be find in specification.Honniball
C
37

Focusing on something from an event handler that, itself, grants focus, is always problematic. The general solution is to set focus after a timeout:

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

That lets the browser do its thing, and then you come back and yank focus over to where you want it.

Celindaceline answered 5/12, 2011 at 3:47 Comment(4)
Why use a timeout when you could just use the appropriate event in the first place?Pierian
@antisanity - good point, if that's what the OP is really interested in. That is, if for this particular case the "mouseup" event works as well as "mousedown" for the interaction desired.Celindaceline
@Pierian Because this solution is applicable beyond the OP's specific case.Heidelberg
Why is it "always problematic"?Tapia
K
4

Could it be the same issue as this? jQuery Textarea focus

Try calling .focus() after .show() has completed.

$('#reply_msg').live('mousedown', function() {
    $(this).hide();
    $('#reply_holder').show("fast", function(){
        $('#reply_message').focus();
    }); 
});
Knocker answered 5/12, 2011 at 3:48 Comment(0)
M
4

I ran into this issue today and in my case, it was caused by a bug in jQuery UI (v1.11.4) which causes textarea elements inside of draggable/droppable elements to stop default click behavior before the textarea receives the focus click.

The solution was to rework the UI so that the textarea no longer appears inside the draggable element.

This was a particularly difficult issue to debug, so I am leaving an answer here in case others find it helpful.

Mccray answered 19/8, 2015 at 18:52 Comment(0)
M
0

It might also come from the browser. I'm doing a project in Vue, and el.focus() on textarea works in Chrome (v101), but not in Firefox (v100.0).

Mosher answered 13/5, 2022 at 9:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.