Click here to Skip to main content
Click here to Skip to main content

Set Focus to First Input on Web Page

By , 9 Sep 2005
 

Introduction

I was developing a web application that had some pretty complex authorization logic, and would enable and disable certain inputs on many different web forms. For example, user A would have the first 5 text boxes disabled and user B would have text boxes 5 through 10 disabled. That made it difficult to set the focus to the proper input. Difficult in terms of the amount of code required to accomplish such a simple task.

Options

  1. At each step of the authorization stage, write hard-coded code to set the focus to an input (i.e. duplicate logic dozens of times on dozens of pages).
  2. Write client-side JavaScript to dynamically handle it.

A Few Tries

Since duplicating logic is generally agreed to be a bad practice, I went for the dynamic option.

My first idea was to simply set the focus to the first element of the first form, which would work in some instances and not in others. For example, in a .NET application the first element of the first form is a hidden element which cannot accept the focus. Also, my application has many disabled fields which also cannot accept the focus. The code below doesn't work in all situations:

document.forms[0][0].focus();

My next idea was to loop through the items of the first form and find the first non-hidden, non-disabled element. The code below still doesn't fulfill my ultimate requirement because sometimes I have multiple forms on a page:

var bFound = false;
for(i=0; i < document.forms[0].length; i++)
{
  if (document.forms[0][i].type != "hidden")
  {
    if (document.forms[0][i].disabled != true)
    {
        document.forms[0][i].focus();
        var bFound = true;
    }
  }
  if (bFound == true)
    break;
}

Solution

The problem with the code above is that it has a hard coded reference to forms[0], so it will not work when the input you want to set the focus to is not within the first form. For example, a complex page might contain several forms for various purposes. My final solution was to use a nested loop that loops through all forms until it finds an input that is not hidden and not disabled. The code below has been tested in Internet Explorer 6.0 and Mozilla Firefox 1.0.4:

  var bFound = false;

  // for each form
  for (f=0; f < document.forms.length; f++)
  {
    // for each element in each form
    for(i=0; i < document.forms[f].length; i++)
    {
      // if it's not a hidden element
      if (document.forms[f][i].type != "hidden")
      {
        // and it's not disabled
        if (document.forms[f][i].disabled != true)
        {
            // set the focus to it
            document.forms[f][i].focus();
            var bFound = true;
        }
      }
      // if found in this element, stop looking
      if (bFound == true)
        break;
    }
    // if found in this form, stop looking
    if (bFound == true)
      break;
  }

I copied the code above into a .js file and included a reference on all pages of my application. Now, no matter what inputs are disabled on a form, the focus finds its way to the first one that is enabled.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

JohnStanfield
Web Developer
United States United States
Member
John Stanfield, MBA, has been an application architect and developer for eight years, currently using C#, VB.Net, Microsoft Visual Studio.NET, and Microsoft Visual Studio 2005.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralThere is a ready to use solution for ASP.NET 2.0memberWereWolf00719 Aug '08 - 0:55 
See this link: http://www.beansoftware.com/asp.net-tutorials/focus-asp.net.aspx[^]
GeneralImprovedmemberWarazen19 Mar '08 - 5:14 
This is a slight improvement to the above code.   It checks for undefined elements like <label> or <fieldset>. This works in both Internet Explorer and Firefox.   I tested IE Version 7.0.5730.11 and Firefox Version 2.0.0.12.
 
An if/or construct could have been used rather than switch; but switch/case makes the code easier to read. There may be a few element types I missed in the switch statement, but that's easy to extend.
 
<script language="javascript" type="text/javascript">
function FocusFirst() {
      // Based on http://www.codeproject.com/KB/scripting/FocusFirstInput.aspx
      var bFound = false;
      //for each form
      for (f=0; f < document.forms.length; f++) {
            //for each form element
            for (i=0; i < document.forms[f].length; i++) {
                  el = document.forms[f][i]
                  if (el.disabled != true) {
                        if (el.type != undefined) {
                              switch (el.type.toLowerCase()) {
                                    case "text" : el.focus(); bFound = true; break;
                                    case "textarea" : el.focus(); bFound = true; break;
                                    case "checkbox" : el.focus(); bFound = true; break;
                                    case "radio" : el.focus(); bFound = true; break;
                                    case "file" : el.focus(); bFound = true; break;
                                    case "password" : el.focus(); bFound = true; break;
                                    case "select-one" : el.focus(); bFound = true; break;
                                    case "select-multiple" : el.focus(); bFound = true; break;
                              } // switch el.type
                        } //if (el.type != undefined)
                  } //if (el.disabled != true)
                  if (bFound == true) break;
            } //for each form element
            if (bFound == true) break;
      } //for each form
}
</script>
QuestionQuestion?memberchimchim9 Nov '06 - 3:58 
This is great and thanks to everyone for the help! I am wondering though if someone has the code done and working with all of the comments and addons people have been talking about here? This is exactly what i am looking for and if someone has a completed version that is working for them i would be very thankfull if they could post the code here for me to put in a javascript file. Smile | :)
 
Thanks so much again for this!
 
Aaron
GeneralBetter ImplementationsussJoel P14 Sep '05 - 3:57 
This is a good start, but IMO, the function below works better. I've been using it in a production system for over a year with no problems. One caveat: it's an intranet app so I've only tested on IE. Feel free to Firefox-ize it.
 
-joel
 
============================================
 
function focus_first_field()
{
// loop through all forms on the page
for(var f=0; f < document.forms.length; f++)
{
// set frm variable so we don't have to call 'document.forms[f]' everywhere
var frm = document.forms[f]
 
// loop through all fields in the form
for(var x=0; x < frm.length; x++)
{
// set fld variable so we don't have to call 'document.forms[f][x]' everywhere
var fld = frm[x]
 
// use a try/catch block so that if anything fails we just go to the next field
try
{
if(!fld.isDisabled && !fld.readOnly)
{
// I want to handle different field types differently, so switch on the type
switch(fld.type)
{
// for text boxes, set the focus AND select the text, just like a Windows app
case 'text':
case 'password':
fld.select()
fld.focus()
return
// for check boxes and radio buttons, set the focus to the one that is already
// checked in the group.
case 'checkbox':
case 'radio':
// if it's not an array, there's only one, so focus on it
if(frm[fld.name].length == undefined)
fld.focus()
else
{
// find which one is checked and focus on it
for(var x=0; x < frm[fld.name].length; x++)
{
fld = frm[fld.name][x]
if(fld.checked)
{
fld.focus()
break
}
}
// if we didn't find the checked one, just focus on the first one
if(x == frm[fld.name].length)
fld = frm[fld.name][0].focus()
}
return
// select boxes and buttons can just have a simple focus() call
case 'select-one':
case 'select-multiple':
case 'button':
fld.focus()
return
}
}
}
// if anything fails for any reason (hidden div, etc.), execution jumps to catch
// then goes through the loop again
catch(e)
{}
}
}
}

Questionhidden parent element?memberjcluggish14 Sep '05 - 3:33 
What if the first input element is inside a hidden div? You'll need to find the first valid input element and then check that elements parents to make they are not hidden. For instance, something like this would check the parent nodes of the input element:
 
// Inside the for loop of document elements
// after you've found a valid input element
// valid element boolean set
if (bFocus) {
// get parent node of input element
oParEl = oEl.parentNode;
// while parent node exists and isn't body or html tag
while (oParEl) {
if ((oParEl.tagName == "BODY") || (oParEl.tagName == "HTML")) {
break;
}
// The parent node is hiddden this so this element is no good.
if ((oParEl.style.display == "none") || (oParEl.style.visibility == "hidden")) {
bFocus = false;
break;
}
// climb up DOM tree
oParEl = oParEl.parentNode;
}
// passed both valid input field and parent nodes aren't hidden, set focus.
if (bFocus) {
oEl.focus();
break;
}
QuestionNo forms ?memberzefrit13 Sep '05 - 9:21 
First: excuse me for the english, i can do it again in french Wink | ;)
//
 
I've a look likes function and i've integrated it in a javascript module for a framework in PHP. In this way of using you'll might be forced to include your function inside some pages containing no forms.
 
// Before your code
if (document.forms.length==0) return;
//
 
Always in this way of use, you'll might be use rich client side pages, including read only input (type text) for display dynamic data.
 
//
if (document.forms[f].elements[i].readonly != "true")
{
// put the focus
}
 
I say it again I can do it in french (euh... i think so !)

Best regards
 
Toms Sniff | :^)
AnswerRe: No forms ?memberJohnStanfield13 Sep '05 - 14:10 
I believe that the loop checks to see if forms.length is equal to zero, but it does it in a not-so-obvious way.   Consider this loop (in which I substituted 0 for document.forms.length):
 
for(i=0; i<0; i++)
{
   // this code should never execute
   // because zero is not less than zero
}
 
Thank you for your comment, and indeed I will test this on a document with no form tags when I get a chance.
GeneralYou need one more conditional testmemberDidier Frund13 Sep '05 - 6:29 
Hi,
 
If the form contains a tag like <fieldset>, <legend>, or <label>, your have to add another conditional test. For example:
 

if(document.forms[f][i].tagName=="INPUT" || document.forms[f][i].tagName=="SELECT"){
...
}

 
All the best,
 
Didier
 
-- modified at 12:31 Tuesday 13th September, 2005
GeneralRe: You need one more conditional testmemberJohnStanfield13 Sep '05 - 13:58 
Thank you for your comment. I will be taking a look at this in the next few days.
 
I think I'm going to figure out a way to see if document.forms[f][i] implements the focus() method, and if so, invoke it.
GeneralDrawbacksussAnonymous12 Sep '05 - 20:05 
One problem I find with this helpful feature (I'm sure the Yahoo login page does it) is that if the user has already moved the focus, they're suddenly moved back to another control and may not notice. So for example on the Yahoo page I'll have typed in my username and be partway through the password when, ding, the focus moves back to the username and the second half of the password appears in plain text. Very annoying, though probably only an issue for dial-up users unless your page is very long.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 9 Sep 2005
Article Copyright 2005 by JohnStanfield
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid