Using Lowpro To Create Autotab using Unobtrusive JavaScript and Rails

April 19, 2008

In the last article, I showed how to use composed_of to create a class to handle phone numbers. In this article, I'll show how you can use Unobtrusive JavaScript to make a spiffy interface for entering phone numbers. So first, here's the code we want for phone numbers:

Phone Number
<% f.fields_for :phone_number do |pn| %>
  (<%= pn.text_field :area_code, :size => 3, :class => "autotab" %>)
  <%= pn.text_field :prefix, :size => 3, :class => "autotab" %>
  -
  <%= pn.text_field :line_number, :size => 4, :class => "autotab" %>
  ext
  <%= pn.text_field :extension, :size => 4 %>
<% end %>

This goes in the form view code for the users resource. What this does is render separate fields for each part of the phone number. If you've generated the scaffolding for the users resource, you should be able to stick this in there and be able to create users with phone numbers using this form.

So that's nice, but it would be neat if we could have the cursor automatically jump from one field to the next once the correct number of digits have been entered? We've already got the first step of that in there by putting the class "autotab" on each of the first 3 fields. That is as much code as we are going to add into the actual view. We are going to do the rest unobtrusively, some might even say, Ninja-style.

The first step is to download Lowpro and put it into your public/javascripts directly. Lowpro is a library that enhances Prototype to make unobtrusive JavaScript easier. Once you've got that, make sure to include the javascript libraries in your layout:

<%= javascript_include_tag :defaults, "lowpro", "autotab" %> 

Autotab is a JavaScript file that we are going to create specifically for the purpose of providing the "autotab" functionality, which is the name I'm giving to the feature where the cursor will automatically move to the next field once the correct number of characters have been entered. The correct number of characters is determined from the size attribute of the input field. For staters, make sure you have firebug installed and enter in this code to public/javascripts/autotab.js:

Event.onReady(function() {
  console.log("These are a few of my favorite things:");
  $$('input.autotab').each(function(e){
    console.log(e);
  });
});

When you load the form, you should see the output in the firebug console, with the 3 inputs that have the autotab class. This doesn't do anything interesting at this point, but just shows the basis of how unobtrusive JavaScript works. There are no event handlers directly inline in the HTML code, instead some JavaScript code execute once the page has finished loading and adds functionality to DOM elements based on something like their CSS class.

So in order to introduce the functionality we want, we'll use Lowpro's addBehavior method, which attaches an event handler to elements that match a given CSS tag. Replace the contents of public/javascript/autotab.js with this:

Event.addBehavior({
  'input.autotab:keyup' : function(e) {
    if(e.keyCode != 9 && e.keyCode != 16) {
      if(e.target.value.length == e.target.size) {
        e.target.next().focus();  
      }      
    }
  }
});

So once the page has loaded (or the DOM is "ready", I should say more correctly), this will attach this function to the keyup event handler of all of the elements on the page that match the CSS selector input.autotab. In the function, we first make sure the key being released isn't tab or shift. This is because if you are filling out the form and you press shift+tab to go back to the previous field, you don't want it to jump ahead, because you must want to edit that field if you are going back to it. After that if statement we just check to see if the length of the value in the input field matches its size. If it does, then we call next() on the target to get the next field, and call focus() to change the focus to that field.

Posted in Technology | Tags Javascript, Autotab, Ruby, Lowpro, Unobtrusive, Rails, CSS | 2 Comments