Friday, June 05, 2009

input.focus() ... something really annoying!

new libraries, new add-ons, new engines, new browsers, but still the bloody focus event directly in the onload one ... any chance we will go a step forward?

What is wrong with focus

The main usage of this strategy is to force via JavaScript the focus of the main input field and it is usually on the top of the page.
It could be a search input, a la Google, or it could be a generic log-in. It could be a blog post title, or it could be a comment ... whatever it is, it should NOT act like this!
Try to imagine you have a slow connection (I am still with mobile usb pen) or try to imagine you are using your A Grade browser mobile phone with still, a not that fast connection (I am still using my Android, iPhone is the same).
Since these magic-focused fields are usually at the beginning of the page and since the page will take more time to be downloaded, 90% of the time this automatic feature messes up my user and password or my searched keyword. Too often I have to correct or change back the field, specially when I need to log-in into my on-line banking service, where my actions are faster than page download. Am I that fast? OK, Android first model with its pretty keyboard let me type faster than how I could do with iPhone or second Android generation, but the main problem is that if there is an image, for example, or generally speaking just content after main focused input, the onload event will be fired too late and it will be completely useless and inefficient, rather than being an help for the user.

How could we solve the problem

In my opinion, it is the most simple thing ever. Assuming that the theoretically helping focus will be only one per page, if the site would like to make sense, all we need is a little manager able to understand if the input received focus before the onload event:

<form name="f" action="/search">
<input name="q" onfocus="fff=1" />
</form>

fff will be a global variable which name is absolutely irrelevant and which aim will be to stop the generic onload event to force focus in that input.

<body onload="if(!this.fff)document.f.q.focus();">
<!-- ... the rest of the page ... -->
</body>

With a zero effort + stress strategy that will not increase more than a couple of bytes our page, users will have more control over their fields. This simple trick could be used for every textarea, input, select, or button in the page making the auto focus really helpful in those case user has a fast connection or is lazy and does not want to point the focus automatically, rather than quick posts via mobile or slow connections.

Another Way Without Changing Every Layout


I agree that probably nobody will ever change every page layout adding an inline onfocus event for each field, so here I am with a better solution that should be widely copatible with every kind of device.

(function(){
// A WebReflection Anti Stress Idea
function onclick(e){
var target = (e && e.target) || event.srcElement;
if(/^(input|select|textarea|button)$/i.test(target.nodeName)){
window.fff = true;
if(document.detachEvent)
document.detachEvent("onclick", onclick);
else
document.removeEventListener("click", onclick, false);
}
};
if(document.attachEvent)
document.attachEvent("onclick", onclick);
else
document.addEventListener("click", onclick, false);
})();



// as body or window event
onload = function(){
if(!this.fff)
document.getElementById("main-input").focus();
};

Above snippet does not require both onReady or onload events so it should work just adding it inside the head tag. It is so simple, now let's see how people will react 8)

9 comments:

while1dan said...

Setting focus on page load is wrong. A good browser should allow you to jump into the first field using a single tab (and tabindex is still an HTML attribute right?). If you don't use keyboards for navigation, or don't know how, then clearly you don't mind using your mouse.

However, if you are forced to do it because some boss instructed you to (or whatever), what's wrong with:

<input id="my_input" />
<script type="text/javascript">
document.getElementById("my_input").focus();
</script>

This should load immediately after the input tag loads on most browsers and only screw up on the very slowest of connections. Right?

Andrea Giammarchi said...

while1dan, I would use <noscript> tag with the input, and a document write('... input ...') plus focus for W3 and WAI compatibility but still, this is not a "universal" solution because if for some reason I already put focus in another field, I do not get why in 2009 I should still loose that focus, my choices, before the page is totally loaded. Not flexible, focus has to be set only if not set already by user actions. That's my point of view.

Andrea Giammarchi said...

P.S. scenarios are a lot, the most common is the classic google adsense at the end of the page with an iframe plus images, etc etc ... if this is after the input when my page is loaded I could have written already main input so why the script which aim should be help me makes things more complicated removing my focus? ... hope you got my point.

while1dan said...

My point was that the focussing script would run before any more of the page loaded. No deferred onload script necessary. The Adwords iframe wouldn't have a chance to load before the focussing occurred.

Andrea Giammarchi said...

iframe was about this post, as example, but you are still not considering that as tabindex attribute exists because the order of the fields is not necessary related to fields importance, your script could run after the main input while I was writing something else in an input before. Let's say a age with a login and a search, the search has your script, login comes before and I am using it, or vice-versa, so still your solution is obtrusive, mine is user-action oriented, not developer oriented. Better? :)

Krijn Hoetmer said...

How about the autofocus attribute?

Andrea Giammarchi said...

it's gonna be for my children, if any :D ... jokes a part, HTML 5 autofocus is OK, I simply provided quick and cross-browser alternatives. Unfortunately, both Google guys, msn, my bank, or whoever mentioned developer will never implement this trick :(

while1dan said...

I catch your point, now. You're right, something must be done if the input is not the first on the page.

Andrea Giammarchi said...

... ehr ... yes, and that's why I've already posted the cross-browser unobtrusive code ...