JavaScript custom controls

I spend a lot of time writing bespoke content management systems, a lot! I'm always trying to add some small, lightweight additions to make the user experience a little bit better. One means of doing this is by providing some better custom controls which give good user feedback and emulate similar offline controls.

Ordering Control

One such control is a linear range control, catchy I know, which allows the user to select a value within a particular range with a given default value. An example of this may be selecting an ordering value for a blog post, Figure 1, ranging from say -100 to 100 with a default value of 0. Posts in our imaginary blog would be ordered by this ordering field ascending with 0 being the default value, resulting in posts being ordered automatically by date. Rather than using a plain text box to allow the user to enter the ordering value directly, subsequently giving us little or no control over the contents of the field until the form is submitted and no means to convey the nature of the field itself, we can create controls to manipulate the value ourselves.

Creating a custom control allows us to do a number of things that we just cannot do with a normal HTML form element:

Figure 2: Lower Bounds Figure 3: Non-Default Value Figure 4: Upper Bounds

Controls

Annotated Ordering Field

By using JavaScript onclick or onmousedown events we can manipulate the contents of our ordering field held behind the scenes. The addition of functions and some variables defining the bounds and the default value of our control then allows us to constrain the upper and lower limits, as we've seen, and to reset the field back to it's defaults. This gives us the following interaction:

This interaction is fairly rudimentary and not very exciting to say the least. We really want to provide more desktop-like interaction via our own custom controls such as the ability to click-and-hold a button in order to scroll through available values. With such a control, in the majority of desktop applications, when the button is held the action that button denotes will be repeated after a short delay usually with increasing speed the longer it's held. We can emulate this in JavaScript using a timeout to create the pause and a modifier to decrease the length of this pause and in turn increase the speed with which the actions are executed.

Code Snippit 1 contains a brief outline of how to create a mechanism for firing events when a button is held.

Code Snippit 1: Rough JavaScript to deal with the click-and-hold updating mechanism

<script type="text/javascript">
    var timeout          = 1000;
    var timeout_limit    = 200;
    var timeout_speedup  = 1.5;
    var default          = 0;
    var lower_bounds     = -100;
    var upper_bounds     = 100;

    function setView( str, element ) {
        // Update the ordering element setting the values and
        // icons as necessary
      ...
    }

    function updateVariable() {
        // Update variable
        order        = document.getElementById( "ordering" );
        order_disp   = document.getElementById( "order_disp" );

        // Update variable
        order.value  = order.value + 1;

        // Check Bounds
        if( order.value &gt;= upper_bounds )
            setView( "upper_bounds", order_disp );
        elseif( order.value == default )
            setView( "Default", order_disp );
        else
            setView( "" + order.value, order_disp );

        // Start firing click-and-hold events
        if( timeout &gt; timeout_limit )
            timeout = max( timeout / timeout_speedup, timeout_limit );
        t = setTimeout( updateVariable, timeout );
    }

    function buttonStop( t ) {
        timeout = 1000;
        clearTimeout( t );
    }
</script>

timeout is the time between calling button events, the timeout_speedup modifier is used to recalculate the timeout on each event in order to increase the speed with which the event is fired. We set a lower limit, timeout_limit, to ensure that the events aren't called too quickly to update the display and to give the user time to react once they near their desired value. A plot of time between ticks against ticks is shown in Graph 1, as you can see it quickly ramps up so timeout is set to the lower limit, much like you would expect from a desktop application's click-and-hold button interaction.

Timeout vs. Ticks

Code Snippit 2 shows sample HTML used to create the next button with the appropriate onmousedown, onmouseup and onmouseout JavaScript calls to add the desired functionality to the button.

Code Snippit 2: Button calling the events when clicked

<img
    title="Next" src="images/javascript-custom-controls/icons/arrow_right.png" alt="&amp;rarr;"
    <!-- Update the variable and fire click-and-hold events -->
    onmousedown="updateVariable();"
    <!-- Stop the timer if mouse released -->
    onmouseup="buttonStop( t );"
    <!-- Stop the timer if the mouse moves off the control -->
    onmouseout="buttonStop( t );"
/>

We use both onmouseup and onmouseout to ensure that the click-and-hold behavior ceases when the user either releases the mouse button or moves the cursor off the control.

Textentry into ordering field

We can extend the custom control even further and give the user a less stringent method of inputting a value by allowing them to type directly into the field in the same manner as the original textbox, Figure 6.

Feedback

Here's where our custom controls can really begin to shine, we can give the user direct feedback in the control that they're manipulating in real-time. Sure we can do this with JavaScript as it stands, but extending beyond the "red border = wrong" methodology we can give visual cues to the user to show that they're trying to do something thata's wrong and what specifically is wrong with what they're doing.

Showing the bounds of the field is easy using the visual cues we've detailed in Figures 2 & 4. Other visual cues we can use are that of text/background colouring to show that an error occurred. We can also, using the same timeout methods used for the click-and-hold interaction, display useful messages to the user for a brief time before correcting their mistakes telling them what they did wrong and why their entries have been changed, Figure 7.

Error detection and correction

It's only an example!

Other possible controls?

Of course using such controls for an ordering field is only one example where we can extend upon HTML form elements with this simple control. This type of control mechanism could be used for any field that has a linear progression in values. Not only that, you could extend upon the functionality of this example to meet your specific requirements, by wrapping the bounds around to the start, having varying degrees of scale over numerous controls that are swapped in and out for fine or granular interaction or just have it toggle between two set values.

What's the point? There's so much we can do nowadays in terms of interaction, even on the web. Try to add a little bit of interactive zest to your HTML controls, it makes everyone's experience that little bit easier and better.

Thanks for reading,
- Chris