Mark IJbema's Blog

Entries for Tuesday 02 November 2004

Giving a field focus

2nd November 2004, early evening | 2160 comments

I intend to post some of the javascripts I write on this blog. Those won't be the old evil javascripts, but nice pluggable new-style javascripts. That means the only thing you'll need to do is to include a link to the javascript in the head, and possible give certain elements certain classes or id's, but certainly no inline scripting.

Today's script is intentioned to do one very, very simple thing. It should give focus to some field. This could be the first, but I can see good reasons why it isn't (for instance when you have a site with a navigation which includes a search box, but you want to give focus to the login form in the main content). This is quite a long post for such a simple script, but I'm also using it to introduce some general functions which I will use in other scripts as well, and which are very useful for any scripting.

The first thing we need is a way to add multiple scripts to the body onload event. For this I use this little piece of "code i found on Simon Incutio's Blog":http://simon.incutio.com/archive/2004/05/26/addLoadEvent:


/*
 * addLoadEvent based upon this blog article:
 *
 * http://simon.incutio.com/archive/2004/05/26/addLoadEvent 
 */
function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {oldonload();func();}
  }
}

Now we need to mark the field we want to give focus in some way. The most logical way to do this would be to give that field an id. However, the fields already have their id's used in my situation (for coupling them with their labels), and since I want to be able to use the javascript for all pages I can't hardcode that id. It's neither an option to rename all those id's, since it wouldn't be very consistent with the other names then, which do have logical (semantical) names.

So I chose to mark the field with a class. This has flaws as well of course. You can now have multiple fields with this class, but you can only give focus to one field. But since you can give only one id to a tag it didn't leave me with much choice (though i could do it by defining with meta tags which id was the one to give focus, but that seemed overkill to me).

So now we need something to find an element with a certain class. I stumbled upon a "post on a forum on webmasterworld":http://www.webmasterworld.com/forum91/1729.htm in which Bernard Marx posted two functions: getElementsByCondition, a function to retrieve an element given an arbitrary condition and getElementsByAttribute. And though this was meant as a getAttributesByClass implementation, getElementsByAttribute isn't suitable, because it doesn't work when you define multiple classes. So i decided to use the getElementsByCondition:


/*
 * As proposed by Bernard Marx on:
 * http://www.webmasterworld.com/forum91/1729.htm
 */
function getElementsByCondition(condition,container) {
    container = container||document
    var all = container.all||container.getElementsByTagName('*')
    var arr = []
    for(var k=0;k

Now to create the function which checks wether this element is of a certain class and a function which combines this function with the previous one:


function checkWetherContainsClass(classname,element){
    var classes = element.className.split(" ");
    var found = false;

    for(var k=0;k

So now the only thing missing is the implementation of the function giving the focus itself. This is quite trivial, I retrieve the fields with the class 'focusfield', take the first one (there should be one, but if there are more this works as well), and give it focus. Finally we add this to the body onload event:


function givefocus (){
    var fields = getElementsByClass("focusfield");
    if (fields[0]!=null){
        fields[0].focus();
    }
}

addLoadEvent(givefocus);

I also provided the "complete source":http://www.markijbema.nl/static/focus.js for your convenience.