13

Dynamically created form contains input elements. First elements may be disabled or readonly. I tired code below to set focus to first elemnt which accepts data to enable fast data enttry form keyboard. However if form fist element is disable or readonly, focus is not set. How to set focus to first element which accepts data ?

    <form style='margin: 30px' id="Form" class='form-fields' method='post' target='_blank'
    action='Report/Render'>
...
    <input id='_submit' type='submit' value='Show report' class='button blue bigrounded' />
    </form>
    <script type="text/javascript">
        $(function () {
            var elements = $('#Form').find(':text,:radio,:checkbox,select,textarea');
            elements[0].focus();
            elements[0].select();
});
</script>

Update

There are also hidden input fields, sorry. Answers provided set focus to hidden element. Answr containing function does not find any element.ˇ

Here is the update testcase:

$(function () {
  $("#form :input:not([readonly='readonly']):not([disabled='disabled'])").first() 
                                                                        .focus(); 
});

How to set focus to vist visible, enabled and not readonly element ?

Update 3

I tried Row W code where input element was added. Now it sets focus to second element. Testcase is shown at Revision 5 of Rob W's answer

Community
  • 1
  • 1
Andrus
  • 26,339
  • 60
  • 204
  • 378
  • 1
    See also http://stackoverflow.com/questions/1591910/how-to-focus-on-a-form-input-text-field-on-page-load-using-jquery – DOK Sep 14 '12 at 15:00

2 Answers2

10

Use the following code:

var elements = $('#Form').find(':text,:radio,:checkbox,select,textarea').filter(function(){
    return !this.readOnly &&
           !this.disabled &&
           $(this).parentsUntil('form', 'div').css('display') != "none";
});
elements.focus().select();

If you only want to select the first element, the following code is more efficient:

$('#Form').find(':text,:radio,:checkbox,select,textarea').each(function(){
    if(!this.readOnly && !this.disabled &&
                $(this).parentsUntil('form', 'div').css('display') != "none") {
        this.focus();  //Dom method
        this.select(); //Dom method
        return false;
    }
});

Update: if you want to have the elements in the same order, use:

var elements = $("#form").find("*").filter(function(){
   if(/^select|textarea|input$/i.test(this.tagName)) { //not-null
       //Optionally, filter the same elements as above
       if(/^input$/i.test(this.tagName) && !/^checkbox|radio|text$/i.test(this.type)){
           // Not the right input element
           return false;
       }
       return !this.readOnly &&
              !this.disabled &&
              $(this).parentsUntil('form', 'div').css('display') != "none";
   }
   return false;
});
Rob W
  • 341,306
  • 83
  • 791
  • 678
  • Thank you. There are also hidden divs containing input element. How to skip hidden divs? I updated question. – Andrus Nov 05 '11 at 22:21
  • 1
    @Andrus Updated answer with the most efficient solution. – Rob W Nov 05 '11 at 22:28
  • Row W: Thank you very much. I tried update but it fails since it does not found any element. I added failing testcase to update3 in my question. – Andrus Nov 05 '11 at 22:35
  • 1
    IDs are case-sensitive. Use an uppercase `f`: `$('#Form')`. Updated answer. – Rob W Nov 05 '11 at 22:36
  • Rob, thank you very much. It works. I marked and upvoted your answer and comments. – Andrus Nov 05 '11 at 22:44
  • I tried first code in your answer but `elements.focus().select(); ` sets focus to some other element, not first one. It looks like filter() sorts result in some way. – Andrus Nov 13 '11 at 20:20
  • IF last code is moved to separate method it does not find any elements. I updated question and provided testcase. How to fix? – Andrus Nov 20 '11 at 15:10
  • @Row W. Now it does not select first element. I updated question and provided testcase. – Andrus Nov 20 '11 at 16:27
  • 1
    @Andrus The function shows a method to select all "valid" elements in the right order. If you want to only get the first element, use `elements.eq(0).focus().select()`: http://jsfiddle.net/adQaN/ – Rob W Nov 20 '11 at 16:37
4

Use jQuery's :not() selector:

$("#myForm :input:not([readonly='readonly']):not([disabled='disabled']):reallyvisible").first()
                                                                                      .focus();

Here's a working fiddle.

EDIT:

To meet the new requirement you posted in the comments, you'll have to extend the :visible selector to check for parent visibility (untested):

jQuery.extend(
  jQuery.expr[ ":" ], 
  { reallyvisible : function (a) { return !(jQuery(a).is(':hidden') || jQuery(a).parents(':hidden').length); }}
);
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
James Hill
  • 60,353
  • 20
  • 145
  • 161
  • Thank you. Page may contain input elements outside #Form also. So I think it may focus wrong element. How to apply this to the form #Form only ? – Andrus Nov 05 '11 at 21:52
  • 1
    @Andrus, Add `#form` to the selector. I updated my answer and the fiddle. – James Hill Nov 05 '11 at 21:53
  • thank you. There is also `
    ` divs in form. How to ignore input elements in hidden divs ? I updated question
    – Andrus Nov 05 '11 at 22:16
  • 2
    @Andrus, it's not really appropriate to update a question so drastically after it's been answered - it invalidates all existing answers. – James Hill Nov 05 '11 at 22:17
  • I'm sorry about that. I added updates to end of question separately. Thank you very much for quick help. I upvoted your answer and comments. – Andrus Nov 05 '11 at 22:46