The Smield: An unobtrusive javascript UI Helping Smart Field

posted on 14th May 2007

The 'smield', or smart field, is a useful little user interface widget written in javascript. It combines the values of other fields on the page to allow for easier input of repeated content. Based on some javascript configuration, the smield will insert an unordered list of label and radio button pairs under the target input field (of the smield).

A few common examples might be:

  • You have a list of customers. Some of those customers might be known by a their company name, others might use first and last name combined, and others again might use a nick name.
  • You've just uploaded a file to the web server, and you need an intuitive option to leave the file as the original file name, or select an option and specify a new name.

The smield allows the user to easily select the value for the new field based on the information already entered in the form. Don't want to enter your new username because you want to use your email? Click the "Use Email" option below the username field, or check the option that combines your first and last names with a dot.

The next image (an animated gif no less!) gives you an idea of how it works (thanks Cropper).

Animated gif showing the Smield in action

Example and Source Code

View the Smield Demo Page for all the info (source code, example setup, etc...) and a working example. Or just grab the javascript source for the smield (or minified smield source).

Features

  • Unobtrusively extends input fields in HTML forms
  • Combine fields to populate another field
  • Doesn't require any additional frameworks or libraries.
  • Plays nicely with with 3 great frameworks: YUI, Prototype and Microsoft ASP.NET AJAX Extensions (erm, Atlas)
  • Easily apply custom filtering of input; useful for stripping unwanted characters, normalising usernames etc...
  • Minimal setup
  • Supports form resetting
  • Minified javascript source <7Kb
  • Saves your users time and helps lead data entry
  • Makes you happy *

* individual results may vary

Configuration

Configuration isn't difficult, although it could be shorter.

If you want to use a smield, this is what you need:

for the smield:

new CSharpVitamins.Smield(
  [input field (String or HTMLElement)],
  [choices (SmieldChoice array)],
  [options (Object, optional)]
  );

and for the choices of a smield:

new CSharpVitamins.SmieldChoice(
  [name (String)],
  [label (String)],
  [fields (String or HTMLElement array)],
  [separator (String, optional)]
  );

A simple code example for two options, say to specify a value or use the user's first and last name, would be:

var myChoices = [
  new CSharpVitamins.SmieldChoice("other", "Specify"),
  new CSharpVitamins.SmieldChoice("name", "Your Name", ["txtFirstName", "txtLastName"], " ")
];
new CSharpVitamins.Smield("txtKnownAs", myChoices);

There are some options that can be passed in as the smield's third argument. They are as follows:

var myOptions = {
  group: "auto-generated if empty|name of group",
  listClass: "disabled|unordered list class",
  disabledClass: "input field class when the input field is readonly/disabled",
  // for the filter, specify any function that accepts and returns a string
  filter: function(value){return value.replace(/[^a-z]/g, "");},
  position: "below|above",
  protection: "readonly|disabled"
};

so our example becomes:

new CSharpVitamins.Smield("myTextbox", myChoices, myOptions);

Note the "filter" option. In the example above, we provide our own custom function that strips out anything that is not a lowercase letter. Mmmm, Handy!

You might get a better idea of the configuration and how it works by looking at the source of the smield example page.

Question and Answer time

That's amazing! What doesn't the smield do?

It is amazing what something so simple can do. Alas, the smield does nothing beyond helping you create a slightly more intuitive user interface. It's quite superficial really.

The smield does not:

  • make use of AJAX. (It's DHTML, whether it's Web Two Point Ohhh is up to you.)
  • remove your original input field. (It's still a plain 'input of type equals text' field. Nothing funky is done to it; the field's value is submitted as any other form element without a smield.)
  • improve your sex life (well, it could, but I doubt it)

What do you mean "plays nicely" with other libraries?

Good question, I'm glad you asked.

In the interest of making the smield independent of any particular library, we chose to use a fairly standard implementation for adding event handlers to elements in the DOM. Originally, the smield was created using Prototype, but things have moved on and we use a variety of frameworks to get the job done these days.

Initially, given that most of the time we'd be using one library or another, I shied away from adding another set of event handling routines to the smield, bloating the code and potentially breaking functionality of those libraries. But instead, for the sake of portability, we decided to make the most of both worlds, and go with a default implementation as well - after all it would be silly not to for such a small piece of the overall pie.

What is meant by "plays nicely" is that, if it can, the smield will use the library method to add, remove and purge events, so that all the expected behaviour of those libraries stays in-tact.

For example, the chosen libraries handle adding and removing events in different ways:

  • Prototype Adds event handlers to a global cache object, which is automatically cleared when the page unloads (helping to prevent memory leaks in IE)

  • YUI Also keeps track of handlers via a global cache and clears them on page unload. Can purge an element of all attached listeners.

  • Microsoft ASP.NET AJAX Adds event handlers to an element and caches them on the element itself, but doesn't have automatic purging. Can purge an element of the attached handlers.

So if we added handlers by another means than the library's method, and then tried to get or purge an element's events, because the smield didn't use the library, the smield's events would not be included and would still be left attached.

It's a border-line argument, but still a valid one. It introduces ambiguous behaviour if you're relying on the framework you use every day, and could be difficult to troubleshoot/debug. Whether anyone would be affected by it is another story. So for the sake of a little more code, we can play nice with YUI, Prototype and MS AJAX.

It's worth noting that the chosen library should be including before the smield. If the smield can't detect one of the libraries when it's loaded, it'll use it's own implementation.

But where do you draw the line? If we support "playing nicely" for every library out there, we might have a file that is a lot bigger than the functionality warrants.

We could take the Ext approach, and introduce an 'adapter'  or 'bridge' for the library that overrides the smields default implementation, but then that gives us two files to include - and isn't really worth the hassle for a small widget.

Thinking forward, a better way might be to simply provide a default method, so the smield can work in a stand-alone fashion. Then allow the smield's methods to be overridden as desired from your project.\

Maybe we'll do this in a future version.

Summing up

So there you have it. The Smield, a helpful little UI tool to improve on the monotony of web forms. It's unobtrusive, simple to implement, has a small footprint and plays nicely with the 'big kid' libraries out there. If you have comments or questions, please leave your message below; or use the contact form.