ARIA Slider, Part 3

Posted on Friday, 20 June 2008 by Hans Hillen

After covering a basic ARIA slider as well as a more complex slider component, we will take a closer look at how a slider can be used to create a more obscure but very powerful widget: the double slider (or ‘range slider’). We will discuss what to think about when creating a double slider, and what changes to make to your slider’s ARIA properties.

A double slider allows the user select a range of values by specifying a minimum and maximum value, using two thumbs instead of one. For example, a double slider can be used to set a price range when searching for products, or a time window when searching for available flights.

Example

The TPG slider component mentioned in my previous article also allows for the creation of double sliders. The double slider example page shows a few samples. At the end of the article I will describe how to create a double slider using this component.

What to Think About When Creating a Double Slider

Focus and Keyboard Support

Although a double slider may look like a single widget visually, it behaves as two individual sliders conceptually as well as programatically. In order to be keyboard accessible, each individual thumb must be focusable and part of the tab order. As the WAI-ARIA Authoring Practices 1.0 tells us, each thumb has the same interface as a single slider: arrow keys, page up/down and home/end keys are used to change the value.

Naming and Describing

Because non sighted users will perceive the double slider as separate widgets, you must make it clear for both thumbs that they are part of the same widget. The current recommendation is to add ‘range minimum’ and ‘range maximum’ in the thumb’s title. Since the TPG slider already requires a label element for each thumb, I think it will suffice to include it in the label text as well.

If you want to be more verbose, you can also use the aria-describedby property to explain to the user that the thumb is part of a double slider. Don’t be too verbose though, as aria-describedby text is announced automatically by most screen readers on focus, and too much accessibility is seldom appreciated. A suitable description text would simply be: ‘part of range’.

Specifying Relationships

The thumbs of a double slider influence each other: the lower limit thumb move go past the upper limit thumb, and vice versa. In other words, the currently selected value of each thumb determines the limit of the other thumb. As developer, you must reflect this relationship in the sliders’ ARIA properties as well. First of all, to indicate the relationship between the thumbs you must give each of them an aria-controls property. This property takes the ID of the element that is being controlled as a value. In the case of a double slider, the thumbs control each other, so they would reference each other’s ID value. The simplified code snippet below illustrates this:

<div id="slider1" role="slider" aria-controls="slider2"></div>
<div id="slider2" role="slider" aria-controls="slider1"></div>

Note: This snippet only illustrates the use of the aria-controls property, and in no way reflects a complete or properly implemented slider.

As each thumb limits how far the other can be moved, you will have to dynamically update the other thumb’s limit in ARIA as well. You do this by changing the aria-valuemin and aria-valuemax properties:

For example. Let’s say your horizontal double slider starts off with a value range of 0 to 100. If we drag the right thumb to 50, it means that the left thumb now can’t get further than 49. In this example we would change the aria-valuemax property on the left slider to 49.

Mouse Input

The keyboard input may not be much different from single sliders, but mouse input is. Obviously, the thumbs can still be dragged using the mouse, but what should happen when the user clicks on the rail? Normally the thumb either moves to the location where the rail was clicked, or it moves an increment in that direction. In the case of a double slider, we have two thumbs and one rail, so you will have to decide on which thumb responds to what and how. The TPG double slider is implemented in the following way (assuming a horizontal, left to right slider rail):

  • Clicking to the left of the lower limit thumb will move it to where the user clicked.
  • Clicking to the right of the upper limit thumb moves it to where the user clicked.
  • Clicking in the middle of two thumbs moves both thumbs one increment closer to each other. Holding the CTRL key will move them a large increment (which is the same as using the page up or page down key).

This is not necessarily how it should be done, it is how I have implemented it for now. If anybody has suggestions I would love to hear them.

Using the TPG Slider

To create a double slider using the TPG slider, perform the following steps:

  1. Create two separate fallback elements (either a select or text input control) adjacent to each other. Create a separate label element for each, and have the label text specify whether the slider represents the lower or upper limit of the range.
  2. Wrap both controls in a div element, and give this a class name of tpgDoubleSlider. Any TPG slider parameters can be specified in the div element’s class name as well. The exceptions are the tpg_labelledBy, tpg_defaultMin and tpg_defaultMax values, which must be specified for the individual controls.

Give it a try by downloading the source code (still under development).

Resources

Some similar double ARIA slider components:


Comments

  1. This is an awesome control. One question, and one comment.

    1) How can a fire a javascript function? The onchange event for a select box doesn’t fire consistently.

    2) A great control to have would be a version of the double slider that supports the selection of multiple options.
    Let’s say I have a dropdown with “bad” “good”, “better”, and “best”. If I could turn that into a slider where the user could select both “good” and “better”, that would be awesome.

    Thanks for posting this code.

  2. Hi Rick,

    You can define a callback function as a parameter, for example: TPG_callback-myFunction. This will cause the ‘myFunction’ function to be called whenever the slider value changes. The callback function will be sent two parameters: the slider’s current value, and the slider’s ID. The callback function can also be an object method: tpg_callback-myObject.myFunction. Alternatively, you can call the slider’s ‘addListener’ method, which allows you to attach multiple callback functions for one slider.

    I deliberately did not use the onChange handler for the select boxes, because this may be too disruptive for keyboard users. Instead, the change is applied when the select element’s blur event occurs. I guess this behavior is not always what the user expects, but I’ll probably leave it like this for now.

    Yes, a slider which allows multiple values to be selected would be great, and I’m thinking about including this feature in a future version.

  3. Is it possible to set/modify the minLimit , maxLimit values using Javascript. I have two sliders in a page and depending on what value is selected on the first one ,the minLimit of the second value should be changed.

    Thanks
    Zafer

  4. Hi Zafer,

    Yes this is possible. You can control the thumbs boundaries through scripting, by calling the slider object’s updateLowerLimit() and updateUpperLimit() methods. This does not change the actual range of the slider, but it limits ow far the thumb can go. For example, if your slider ‘mySlider’ has a range of 0-100, and you call mySlider.updateLowerLimit(20), the thumb will not be able to go lower than 20. The values 0-19 can not be selected, but are still visible.

    However, if you want to change the actual range of the slider, you will have to remove the existing slider and create a new one in its place. You can do this by calling the TPG .Control.Slider constructor, and passing it three parameters: 1. a unique ID to use, 2. a reference to the fallback input or select element, and 3. a custom object that contains all configuration parameters.

    Regards,
    Hans Hillen

  5. Thanks Han,

    You first option is the one I want, but I am not able to get an handle to the slider. I tried as below

    var slide2 = document.getElementById(“tpgSlider_0″);
    slide2.updateLowerLimit(50);

    The actual id of the my slider element is “slider01″, but I figured out that the javascript creates a element with id “tpgSlider_0″ for the control. Tried on both, but neither seems to work.

    Thanks
    Zafer Mohamed

  6. Hi Zafer,

    When a slider is created, the slider object is automatically stored in TPG.Control.Slider.instances . You can reference a slider using the ‘get’ method, which takes either the slider’s ID or its index as a parameter. For example

    var mySliders = TPG.Control.Slider.instances;
    var slider1 = mySliders.get(0); //returns the first slider found on the page
    var slider2 = mySliders.get(‘tpgSlider_volume’) //returns the slider with ID ‘tpgSlider_volume’

    you can then call the slider’s public methods, for example:

    slider1.changeHumanValue(20) // changes the value
    slider1.updateLowerLimit(10) // sets the lower limit to 10

    I made some important changes to the code today, so make sure you get the latest from http://www.paciellogroup.com/blog/misc/samples/aria/slider/tpgSlider_source.zip . One of the things that has changed is the way the IDs are assigned to the slider objects. Now a slider is given an ID of ‘tpgSlider’ followed by the ID of the fallback input element.

  7. Hi,
    This is a great stuff, I am trying this out, but I am getting an ..log console at the below like…
    1:39:25 PM: adding function _handleMaxChange (newValue) {
    _thumbMin.updateUpperLimit(newValue – 1); _update(); }
    1:39:25 PM: adding function _handleMinChange (newValue) {
    _thumbMax.updateLowerLimit(newValue + 1); _update(); }
    what is this?? how can i avoid it??

  8. Thanks for flagging that SRAO. It was some debug code I forgot to remove after the last update. I updated both the example and the source code so the console messages.

    Regards,
    Hans Hillen

  9. Hi Hans,
    I am using Vertical Double Slider. Based on my input I need to dynamically change the min and max value of the slider control. I also have to dynamically set step size. I used the below code -

    var mySliders = TPG.Control.Slider.instances;
    var slider2 = mySliders.get(’doubleSlider2’) //returns the slider with ID

    but .. this is not working, I think this is for Single simple slider, can you give me the API details for double slider for the above three requirements.

    Thanks.

  10. Hi SRAO, I updated the code to match your request (please make sure to replace ALL files in the zip when updating).

    First of all, to reference a double slider, you must use a different object:

    TPG.Control.DoubleSLider.instances

    It works the same as the single slider reference object (the ‘get’ method takes either an index number or ID value).

    Once you have a reference to a double slider object, you can reference its individual thumbs using the getMinThumb() and getMaxThumb() methods. These objects are exactly the same as regular slider objects, meaning that you can call changeUpperLimit() and changeLowerLimit() on them (note that the names of these methods have changed, they used to be updateLowerlimit, etc.) .

    By default, changing these limits will not have much effect in a double slider, because double sliders automatically update each others’ limits (one thumb cannot overlap or pass the other one) whenever a value is changed. So if you were to manually change a limit it would be overridden immediately. Since you want to be able to update the limits yourself, I added a new configuration variable: ‘tpg_bindThumbs’, if you set this to false (e.g. by adding ‘tpg_bindThumbs-false’ to the slider’s classname), the boundaries will NOT be automatically updated, and the thumbs WILL be able to pass each other. You can then manually set the limits to whatever you want.

    To change the stepsize, you can use the ‘changeStepSize()’ method. This method can be called either on a double slider object (to change the stepsize for both thumbs) or on an individual thumb object (to set different stepsizes for each thumb). Note that you can only change the stepSize if the fallback input element is a textbox. For selectboxes, the stepsize is always 1.

    Here are some code snippets that illustrate the above:
    The HTML code: (note that I included ‘tpg_bindThumbs-false’ to allow the limits to be change manually)

    <div id="priceRange" class="sliderDiv tpgDoubleSlider tpg_dynamicLabel-true tpg_railLength-15em tpg_range-0-1000 tpg_stepSize-50 tpg_valueText-dollar tpg_bindThumbs-false">
    <label id="ds2MinLbl" for="ds2Min">Minimum Amount</label>
    <input id="ds2Min" type="text" maxlength="4" class=" tpg_labelledby-ds2MinLbl" />
    <input id="ds2Max" type="text" maxlength="4" class=" tpg_labelledby-ds2MaxLbl" />
    <label id="ds2MaxLbl" for="ds2Max">maximum Amount</label>
    </div>

    JavaScript:

    var mySlider = TPG.Control.DoubleSlider.instances.get('priceRange'); // get double slider reference
    var mySlider.changeStepSize(5) //change stepsize from 50 to 5 for both thumbs
    var minThumb = mySlider.getMinthumb();
    minThumb.changeStepSize(10); // change stepsize to 10 only for the left thumb
    minThumb.changeUpperLimit(100) // now the left thumb can't go further than 100.

    I currently haven’t got the API details ready. A good approach might be to use Firebug (http://www.getfirebug.com), which is a Firefox extension that has a helpful command panel. You can use this panel to quickly try out code snippets like the ones above, but you can also use it to see which public methods each object has using the ‘console.dir’ command:

    var mySlider = TPG.Control.DoubleSlider.instances.get('priceRange');
    console.dir(mySlider); //lists all available methods and properties for the double slider object
    console.dir(mySlider.getMaxThumb()); //lists all public methods and properties for the right thumb object

    One day I’ll have proper documentation for this component, but not now.

    Regards,

    Hans Hillen

  11. Thanks for the code, it worked. I appreciate your quick responses to my query.

    1) On Click of a Checkbox I need to update the min,max and range of the Slider Component loaded. I am setting the upper and lower limits of the DoubleSlider component but the slider component does not get loaded with the new values until I click on the page.

    2) And my requirement is to reload the same component with the new upper and lower limits and range. Should I create DoubleSlider using TPG.Control.DoubleSlider constructor?? Can you give me a code snippet for the same.

  12. Hi,

    I am trying to use the callback functionality but not having any joy.

    The callback function is defined in a separate js file. (I tried adding it to slider.js but the same result). I have added some debug in the addListener() method and when it does
    callback = window[listener];
    callback comes back as undefined.

    Any ideas as to what I might be doing wrong?

    Many thanks,
    Dewang

Comments are closed.

Recent Posts

See all posts in the blog archive

We are incredibly proud of how easy the site (New Meadowlands Stadium) is to use for people with disabilities and couldn’t achieve it without your help.

Milan Bilac, Lead Designer, Channel1 Media