Wheels + jQuery partial for setting form focus

Tuesday, August 25th, 2009

Update: I definitely recommend reading through this, but I was a little flawed in my implementation, as Stephen pointed out in the comments. Read my follow-up for more details.

You’ve seen it before: you get to a login screen, and the cursor automatically jumps to the username box so you can just start typing. It’s very convenient.

But developers seem to screw this up regularly. I’ve seen it implemented so poorly that it becomes highly unusable and opens potential security problems.

On my bank’s website, for example, the focus will jump to the username field if you’ve started typing the password before the page has fully loaded. (Sometimes the home page will load slowly, which happens from time to time, you know?) This causes me to expose part of my password to anyone who may be looking over my shoulder!

jQuery to the rescue

As I pointed out in my post about my first learnings of jQuery, the framework provides a method called ready(), which basically helps you to load events as soon as the page is ready for them.

So we can write this simple jQuery code:

$(document).ready(function(){
    $("#my-form-element").focus();
});

This causes focus to jump to the form element with an id of my-form-element on page load.

This won’t cause cursor-jumping mishaps if the user starts typing before the page is ready. (Well, because the page will be ready before the user starts typing. Trippy…)

Making this reusable in ColdFusion on Wheels

I have a couple layouts in my current Wheels application that could use this functionality. So I created this partial that can be included in both layouts via includePartial().

This is the partial at views/_layout_focus.cfm:

<cfsetting enablecfoutputonly="true">
 
<cfparam name="arguments.focus" type="string" default="">
 
<cfif Len(arguments.focus)>
    <cfoutput>
        <script type="text/javascript">
            $(document).ready(function(){
                $("#arguments.focus#").focus();
            });
        </script>
    </cfoutput>
</cfif>
 
<cfsetting enablecfoutputonly="false">

This allows me to put this line in the <head> section of my layout files:

<!--- Note: This should be <cfparam>'ed earlier in the file, of course --->
#includePartial(name="/layout_focus", focus=layout.focus)#

Now whenever one of my views need to put focus on a particular form input, I can add this call to the view file:

<cfset layout.focus = "##my-form-element">

Pretty flexible and available whenever it’s needed.

Most of the time, the view template will set layout.focus, but it’s also available when the controller needs to do the thinking. Sometimes the controller may need to make a decision like putting focus on the username field vs. the password field, for example. Maybe the username field is already filled in by a cookie or previous user input.

I hope this helps you better understand some of these jQuery and Wheels concepts. I’m trying to think of interesting real-world examples of where I’ve started to use this new stuff. I’ll keep trying until you guys start showering me with praise in the comments. :)

Technorati Tags: , , , , , , , ,

2 Responses to “Wheels + jQuery partial for setting form focus”

  1. Stephen Says:

    Chris, this is a nice approach but it seems a bit clunky what with all the inclusions and params and what not.
    Wouldn’t it be nicer to just include jquery and your custom functions in your layout, then assign the “focusOnMe” class to any field you want focused on?
    In the <head> of your layout:
    #javaScriptIncludeTag(“jquery-1.3.2.min.js”)#
    #javaScriptIncludeTag(“myFunctions.js”)#
    In your javascripts/myFunctions.js
    $(document).ready(function(){
    $(“.jqFocusMe”).focus();
    });
    Then, in your view form:
    #textField(objectName=”message”, property=”title”, class=”jqFocusMe”)#
    Wheels seems to accept the class argument being passed to it and creates the <input class=”jqFocusMe”… >
    So now that textfield will get focused without the need for partials, setting params.
    Cheers

  2. Chris Peters Says:

    Stephen,

    That’s an interesting approach. So jQuery/JavaScript doesn’t choke if there is no class of .jqFocusMe on the page?

    As I said, I’m just learning jQuery, so I definitely appreciate your advice. Plus there are so many ways of skinning the cat! :)

Leave a Reply