views:

310

answers:

8

I have a simple login form with 2 input fields: "username" and "password". "username" field is focused by default. The problem is that when user clicks outside "username" or "password" fields, the focus is gone (it is neither on "username" nor on "password" fields"). How can I force the focus to be on these 2 fields only ?

In my case, this is a really annoying behavior, so I really want to do this :)

Can I do something like:

$("*").focus(function() {
    if (!$(this).hasClass("my_inputs_class")) {
        // How to stop the focusing process here ?
    }
});

?

+7  A: 

You could use javascript to set the focus on focusout, but you really shoudn't. Forcing focus on those fields would break the normal interaction of the page. It would mean a user couldn't do something as simple as clicking on a link on the page, because focus would always be on those inputs.

Please don't do it :)

Bala Clark
please see my updated question
Misha Moroshko
+2  A: 

If you really really want to do this (and you shouldn't) use delegate() instead of setting a separate event handler on every single HTML element:

$('body').delegate('*', 'focus', function() {
  if (!$(this).hasClass("my_inputs_class")) {
    $('#username').focus();
    return false;
  }
});

But consider that this will make unacessible all elements except the two input fields via keyboard navigation (including the submit button, any links on the page etc.)

Tgr
A: 

Set blur event handler so it brings back focus to one of your inputs.

Thevs
A: 

You could do like this (in psuedo code):

if user || pass blured  
    if user.len > 0 
        pass.setFocus
    else
        user.setFocus

Hope you get it.

hellozimi
It's not good enough because if user enters username and password, and then he wants to change the username, he can't because the focus will be on the password.
Misha Moroshko
A: 

Install an onClick handler on the body element (or a div that covers most of the page). Clicking on the div should then set the focus on the username/password field.

I also suggest to bind Return in the "username" to "Set focus on password" and Return in the "password" field to "Submit form".

Aaron Digulla
+7  A: 

It sounds like you always want one of your inputs to be focused, fair enough. The way I would do this is to bind each of your inputs blur() events so that if it occurs, it goes to the next element.

Here's the markup:

<body>
<form method="POST" action=".">
    <input type="text" name="username" />
    <input type="password" name="password" />
    <input type="submit" name="submit" />
</form>
</body>

And here's the jQuery:

$(document).ready(function() {
    // what are the named fields the user may focus on?
    var allowed = ['username', 'password', 'submit'];
    $.each(allowed, function(i, val) {
        var next = (i + 1) % allowed.length;
        $('input[name='+val+']').bind('blur', function(){
            $('input[name='+allowed[next]+']').focus();
        });
    });
    $('input[name='+allowed[0]+']').focus();
});
artlung
+1 for the concept, but the jQuery example could be a little less complex. -- Slightly cleaner jQuery code at http://www.jsfiddle.net/bKuUV/2/
gnarf
Also, naming / setting the ID of a `<input>` to `submit` can cause issues with the jQuery `.submit()` function. http://dev.jquery.com/ticket/6264
gnarf
I don't set the `id` of the `input` to submit, so the ticket is not relevant. My example doesn't use `id`s at all, I just don't see how they're necessary to answering the question. I like your use of `next()` though. Also, I don't use `first()` very much but I like that too.
artlung
Oh - And I solved the shift+tab issue with a little `setTimeout` -- http://www.jsfiddle.net/bKuUV/3/ -- feel free to edit in my examples if you want to use them...
gnarf
@artlung - The same bug occurs with `<input name="submit">` as well as `<input id="submit">` -- http://www.jsfiddle.net/SLAAc/
gnarf
A: 

You could enable the click on links by re-focusing on you inputs after a minimum time interval.

Every time an object gains the focus you check if it has the required class: if not set the focus to the first of the form inputs; this way:

<html>
<head>
<title>Example</title>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.2.min.js" />
    <script type="text/javascript" >
    $(function() {
    $('*').focus(function() { var obj = this; setTimeout(function () {checkFocus(obj)}, 1)});
    })

    function checkFocus(obj) {
        if (!$(obj).hasClass('force_focus')){
            $('input.force_focus:first').focus()
        }
    }
    </script>
</head>
<body>
    <a href="http://www.google.com"&gt;Extrnal link</a>
    <form><div>
User: <input type="text" name="user" class="force_focus"/><br/>
Password: <input type="password" name="password" class="force_focus"/><br/>
Other: <input type="text" name="other" class=""/><br/>
<input type="submit" name="submit" value="Login" />
</div></form>
</body>
</html>
Iacopo
A: 

this is only an idea, you can use a setInterval function to put the focus in the username field, and you can interrupt it when you want with clearInterval function.

var A = setInterval(function(){ $('#username').focus();}, 100); 

... and for interrumpt it, you can do something like this

$('#password').focus(function(){ clearInterval(A);});
eos87