文章

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:

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

$(":text:visible:enabled").filter(function(){
     return $(this).parents(":hidden").size()==0;
 }).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:


(function($){
    $.fn.focusFirstField = function(){
        $this = this;
        $this.find(":text:visible:enabled").filter(function(){
            return $(this).parents(":hidden").size() == 0;
        }).slice(0,1).focus();
        return this;
    }
})(jQuery)

So that you can do this:

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

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

I've updated the demo page .

回應

  1. 用 prototype 的話我會這樣:

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

    ( 在page load 完後才 focus )

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

  3. 
      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 … 是不行的

  4. anonymous: yes, can use eq() also.

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

*