Focus first text field using jQuery

When it comes to focus the first text field on a page using jQuery , the usual solution would be:

JavaScript:
  1. $(“:text:visible:enabled:eq(0)”).focus();

This query means to find the first of input text field(s), which is/are visible and enabled. However, this would also extract text field(s) which is/are under a display:none parent(s). So a more complete way would be:

JavaScript:
  1. $(“:text:visible:enabled”).filter(function(){
  2.      return $(this).parents(“:hidden”).size()==0;
  3.  }).slice(0,1).focus();

The filter here would try to determine if the text field is a descendant of a hidden ancestor. The usage of slice(0,1) instead of get(0) is to keep the chainability. A test page is put up here .

Finally, you may wrap it up with a plugin:

JavaScript:
  1. (function($){
  2.     $.fn.focusFirstField = function(){
  3.         $this = this;
  4.         $this.find(“:text:visible:enabled”).filter(function(){
  5.             return $(this).parents(“:hidden”).size() == 0;
  6.         }).slice(0,1).focus();
  7.         return this;
  8.     }
  9. })(jQuery)

So that you can do this:

JavaScript:
  1. $(“#form1,#form2”).focusFirstField(); //form1 or form2 may be ‘hidden’ dynamically

I just wonder if there is any ‘selector-only’ solution for this?

Update: It turns out that the child’s visiblity would override parent’s visibility. So the filter should only check display none:

JavaScript:
  1. $(":text:visible:enabled").filter(function(){
  2.      return $(this).parents.filter(function(){
  3.          return this.style.display == "none"; })
  4.     .size()==0;
  5.  }).slice(0,1).focus();

I’ve updated the demo page .


“Focus first text field using jQuery” - 7 個回應

  1. gr 小影 說:

    用 prototype 的話我會這樣:

    
     Event.observe(window, 'load', function() {
    	try{
    		($$('form')[0]).focusFirstElement();
    	} catch (e) {}
     });
    

    ( 在page load 完後才 focus )

  2. gr 小影 說:

    呃… 上面 [ 0 ] 變了 [0]

  3. gr Jacky 說:

    Can this function handle when
    1) style=“display:none” on the input?
    2) the form itself is under a div with display:none?

  4. gr anonymous 說:

    Why slice() instead of eq()?

    http://docs.jquery.com/Core/eq#position

  5. gr 小影 說:
    
      findFirstElement: function(form) {
        var elements = $(form).getElements().findAll(function(element) {
          return 'hidden' != element.type && !element.disabled;
        });
        var firstByIndex = elements.findAll(function(element) {
          return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
        }).sortBy(function(element) { return element.tabIndex }).first();
        return firstByIndex ? firstByIndex : elements.find(function(element) {
          return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
        });
      },
      focusFirstElement: function(form) {
        form = $(form);
        form.findFirstElement().activate();
        return form;
      }
    

    form 或 form 上層的 elements 是 hidden … 是不行的

  6. gr Jacky 說:

    anonymous: yes, can use eq() also.

    小影: that’s my interest… multiple forms, which may be ‘hidden’

  7. gr Jacky 說:

    BTW, eq() also uses slice()

回覆

*必需
*必需 (不會公開)