Form Design and Custom jQuery Selectors

May 3, 2010
Episode 23
Nick goes over the basics of web form design and Jim shows you step by step how to create a custom jQuery selector.
Spotlight

Thanks to those who make Doctype possible!

Form Design

If you’re not consuming content on the web, you’re creating it, and most of the time that comes in the form of a form. Filling out forms is a big part of any web experience.

Labels

When creating a form, you should of course label the form fields. You can use vertical labels, or horizontal labels, and there are pros and cons to each.

Vertical

Vertical labels are most common. This is where the labels appear above the field that they’re describing. These are best used when the data being collected is familiar to most users, and they don’t really need to think much about what it is that they’re inputting. This also increases speed because users only need to move their eyes down the page. The disadvantage to vertical labels is that the length of the page tends to increase.

Horizontal

Horizontal labels are placed next to the form field, and they usually produce the most aesthetically pleasing results. They reduce the vertical space that’s required, and the whole form generally fits more neatly into web applications because of the form’s wider shape. However, horizontal labels can be tricky to get right, and may even decrease usability.

With left-justified horizontal labels, the labels are very easy to scan down the page, but because they’re not adjacent to the form fields, it can sometimes be confusing when trying to figure out which label corresponds to which form field.

With right-justified horizontal labels, it’s very easy to see which label corresponds to which form field, but the downside is that the forms are more difficult to scan. In some cases, this can be exactly what you want. If a form is requesting data that’s less common, you may intentionally want to slow down your users so that they take a second to read what the form is asking for.

Validation

In an ideal world, you should be able to take any sort of natural language input, like Tuesday afternoon, or later today, for example and transform it into the format you need it in, but that’s not always possible. Instead, here are a few things you can do to make life easier on people that use your forms.

Hints

A great way to avoid frustration is to provide your users with hints. When they focus on an input element, show a tooltip that helps them understand what they should be inputting, perhaps with an example value. Make sure that these are hidden most of the time though, and that you only show a tooltip when it’s needed. If you were to show all of these hints at once, your form might end up looking very cluttered and confusing.

Errors

Sometimes, even with the help, a user might still type some unexpected input. When this happens, the best way to deal with it is to validate the form on the fly using JavaScript, and telling the user before they submit the form.

If real-time validation isn’t an option, simply put up a friendly error message after they’ve submitted the form, and if at all possible, highlight the form field that they need to correct. Also, make sure you save their data when an error occurs. Nothing is more frustrating for a user than having to fill out a form all over again just because of a small error on one field.

Resources

jQuery Pseudo Selectors

jQuery uses CSS selectors to find objects on the page, but did you know you can write your own pseudo-selectors for jQuery. We are going to show you how.

Example

If you have used jQuery, you have probably seen a wide variety of the selectors available to you. In addition to tag name, classes and IDs, there are a group of pseudo classes you can use that are prefixed with a colon instead of a dot.

These are things like :first-child, :even, :odd, :has, and :not. some of these pseudo classes take an argument to further define the behavior. A lot of these are straight out of the CSS specifications, but we can create our own pseudo classes to use in jQuery.

Our example is going to be a shortcut for looking up nodes where the method attribute is POST. Our pseudo selector will be called post.

It will be used like this:
$(':post')

And will match
<form method='post'></form>

And will not match
<form method='get'</form>

The code looks like this

(function($){

  $.expr[':'].post = function(node, index, properties, nodeStack){
    var method = node.method;
    if(method && method.toUpperCase() == 'POST'){
      return true;
    }else{
      return false;
    }
  }

})(jQuery)

We start by wrapping our code with an anonymous function that will locally alias jQuery to the dollar variable and will keep our global namespace clean.

Then we create a function on the $.expr[‘:’] property. The name we give our method will be the name of the pseudo-class we will use in our selectors, so in this example, it is called post.

The function we define takes four arguments.

  1. The first is an HTML node. This is not a jQuery object but an actual element, so if you need to use jQuery, you must wrap it in the jQuery function first.
  2. Second is an index. The selector engine works by taking list of elements and passing each one to our custom function one by one. The index argument indicates which element we are currently looking at in this list.
  3. Third is the properties which will give us various segments of how our pseudo class was called. For instance the second element will be the name of our pseudo selector, and the fourth will be a string of the arguments we passed to pseudo class, if any.
  4. Fourth is the full list of elements you are currently iterating over.

In our example, we get the method attribute from our node, and if it exists, and it equals the string POST, we will return true, saying that this node does match this pseudo class, otherwise we return false.

Arguments

Custom pseudo-classes can also take an argument that allows the user to customize how the selector works.

In our next example we will create a pseudo-class called twin, and this will take a selector string. It will only match if the element matches that selector string, and has one and only direct sibling that matches that same selector.

It will be used like this
$(':twin(.notice)')

And it will match the elements indicated below:
<div>
  <span class="notice">...</span>
  <span>...</span>
</div>

<div>
  <span class="notice">MATCH!</span>
  <span>...</span>
  <span class="notice">MATCH!</span>
</div>

<div>
  <span class="notice">...</span>
  <span class="notice">...</span>
  <span class="notice">...</span>
<div>

Again we create a function called twin on $.expr[‘:’]

We get the selector string that will be passed to twin by getting properties fourth item, or index number 3, we also create a jQuery version of our node.

We then return true if this node matches the selector, and if it has exactly one sibling who matches the selector.

(function($){

  $.expr[':'].twin = function(node, index, properties, nodeStack){
    var selector = properties[3],
        $node = $(node);

    return $node.is(selector) && $node.siblings(selector).length == 1;
  }

})(jQuery)

Now remember, the function we create for our pseudo class will get run on a lot of elements, sometimes even for every element on the page, so you do want to be as efficient as possible. You don’t want to do things like DOM manipulations or AJAX calls, or your page will become slow and unusable. Just use your function to determine if this element matches and return as quickly as you can.

Creating your own pseudo classes allows you to conveniently select elements that would be difficult to do with standard CSS.

What custom pseudo classes can you come up with? Show us what you got in the comments.