menu

Update: jQuery UI Slider from a Select Element - now with ARIA Support

Posted by Scott on 04/16/2009

We’ve updated our popular jQuery UI selectToUISlider
plugin
with ARIA support, making the
jQuery UI slider widget more accessible to users on assistive devices.
The plugin uses progressive enhancement to replace an already-functional
HTML select element with a jQuery UI slider control, and adds a number
of features for both visual users and those on assistive technologies.

Our selectToUISlider plugin uses progressive enhancement to scrape the
data from a select element (or two for a range) and generate a jQuery UI
Slider in its place, acting as a proxy to the select element (regardless
of whether it is still visible, or hidden from the user). This means you
can use the jQuery Slider plugin alongside other input elements in a
form and submit or serialize the form as if the slider is not even
there. It also allows the user to interact and make a choice with or
without javascript, since the select element can be used if the slider
is unavailable.

The plugin enhances the jQuery UI slider in many ways, adding text
labels and ticks on the slider axis, and tooltips that appear while a
slider is being used. In this most recent update, we’ve also added ARIA
support and a tabindex to the slider, allowing it to be accessible to
users on assistive technologies, such as a screen reader. More info on
that below.

WAI-ARIA, the Web Accessibility Initiative’s Accessible Rich Internet
Applications Suite, is a set of specifications for applying meaningful
roles to web widgets, allowing them to be accessible to assistive
technologies. You can find out more about ARIA here: WAI-ARIA
Overview.

The ARIA spec provides the aria-labelledby attribute as a means of
associating an ARIA widget with a label element on the page. By setting
the value of the aria-labelledby attribute to the ID of a label, a
screenreader should read that label’s text aloud and associate the ARIA
widget with its purpose.

While testing on Jaws and NVDA, we noticed that the aria-labelledby
attribute was not being read aloud to the user as we expected. It seemed
that while using “role=application” allowed the screenreader to
recognize the markup as a slider widget, it also disabled the
functionality of the aria-labelledby attribute. Unfortunately, we
couldn’t find a workaround, so we added a hidden span element inside
each slider handle which acts in its place as a label for screenreader
users. The text within the span reads “Slider control for” followed by
the text contained in the form label on your page. In the case of the
demo above, for instance, upon focusing on a slider handle, the screen
reader will say “Slider control for Start Date”, followed by
instructions for using the control with keyboard commands.

To anyone who downloaded the earlier version of this plugin: The zip
contains an update to the CSS file that hides this new span element
visually, so be sure to update your code.

Now that this slider component is fairly accessible on its own, we found
that, while it might be useful for a sighted user to see both the
selects and the slider on the page and see them interacting with one
another, it may lead to a confusing experience to screenreader users to
have duplicate controls on the page that do the same thing. To work
around this problem, we think it’s best to hide the original select
element from all users (screenreader users too) by styling it with
display: none; once the slider has been generated. You can either hide
the select by adding a class to it and creating a style in your CSS for
it, or by simply adding a call to the .hide(); method to the end of
your selectToUISlider(); call, as shown below:

$('select').selectToUISlider().hide();

The hidden select menu will still be able to store the value of the
slider, so you can submit your form as if the slider was never there.

Don’t want to hide the select element? If you can not hide the
select element from the interface, perhaps you could provide some text
for all users instructing that they can use either the select menu or
the slider to accomplish the task at hand.

To use this widget, you’ll need to include jQuery version 1.3+, and the
jQuery UI 1.7+ Slider plugin (which requires jQuery UI Core as well).
You can get all of the necessary code through the zip provided below.

The following code example demonstrates the basic way to use this
plugin:

sliderOptions:Object, accepts native jQuery UI slider
options. **Note:**This plugin generates some of the native slider
options. For the plugin to work as shown, do not override these
options: step, min, max, range, slide, and values.

Just like the jQuery UI slider widget, this plugin is ThemeRoller-ready,
allowing it to be easily skinned to match your website’s design. You can
design and download a theme for this widget at
ThemeRoller.com.

We’d love to hear what you think of this plugin and any suggestions you
have for how it could be improved. These progressive enhancement
features will eventually be rolled into the jQuery UI slider itself. You
can track its progress at the jQuery UI Planning Wiki (Slider planning
page), or better, post feedback or
share your own ideas about the jQuery UI planning process by joining the
development and planning
wiki.

As far as custom select menus go, there are definitely jQuery plugins out there that will help you with that. We’ve actually built them several times but haven’t gotten around to posting an article about it the process yet. The challenge is making sure that whenever you’re replacing a native form control that your replacement component handles all of the functionality of the component you’re replacing (before enhancing it with more features). It also needs to communicate back to the select menu so the form can be submitted normally, similar to how this slider plugin works. These look pretty good at a glance:
http://www.givainc.com/labs/linkselect_jquery_plugin.htmhttp://www.brainfault.com/2007/07/23/select-box-replacement/

@Craig: Thanks. That’s actually a reported bug in jQuery UI’s slider plugin. Programatically setting the values doesn’t trigger the handle value validation script. The bug is marked to be fixed in the tracker for 1.6 final I think.

That aside, the common use of this will be setting the selects to display none once the slider is there. So at least it isn’t a major issue in the meantime.

Something rather wrong with the styling - with both sliders the label that appears is clipped on the left when the slider is at its leftmost position, and when at the far right it clips the right hand side AND causes a horizontal scrollbar to appear.

I am testing in FF 3.05 and this behaviour occurs with all the themes.

@skube - We haven’t used the custom dropdown with this slider so you’ll probably have to so some customization. Hope it’s a good start for you.

@MarkusT - The clipped tooltips and horizontal scrollbar is just a byproduct of the way we’ve embedded these demos into iframes to make it easy for people to see an example in the main narrative of the page. If you open the example in a new page, you’ll see it looks right in FF 3.0.5. The iframes just aren’t smart enough to display this right.

Can you give an example of proper syntax when using sliderOptions? Say I wish to override the jQueryUI slider option “stop”. Would the syntax be:
$(select).selectToUISlider({
stop: function(e,ui) {
alert(’stopped’);
}
});

@doom: If you want the function to fire after you let go of your mouse button, you do exactly as Scott outlined above. Use the “sliderOptions” option to access the jQuery UI Slider’s “stop” option, which fires when the slider has stopped moving.

Great Stuff, one problem is (with the jQuery UI Slider) - if i drag both slid problem? I’ve tried to hide the left slider if the right slider is total left but that doesn’t help..no chance to drag it. :(

Oh sorry - i wanted to write: Great stuff one problem is (with the jQuery UI Slider) - if i drag both sliders to the left, than i have no chance to drag the slider to the right anymore. Any solution for this problem? I’ve tried to hide the left slider if the right slider is total left but that doesn’t help..no chance to drag it. :(

@skube: Thanks, we fixed it in the docs.
The slider is always appended after your selector used to make the slider, so in other words, you can get to the slider through the .next() method after you build it. Then you can do whatever you want to it, such as adding an ID:
$(’select#foo’).selectToUISlider().next().attr(’id’, ‘myId’);

@ngupta: as noted above, you can get the slider through the next() method, so that’s where you’ll direct your slider methods. I guess you could even set a variable to the return of your slider plugin creation and add .next() to the end to keep your slider easy to refer to. Like this:
var mySlider= $(’select#foo’).selectToUISlider().next();

Then you could apply methods like this:
mySlider.slider( “moveTo”, 56, 0 );

Hi, thx for the plugin, nice work! Can anyone help with a jQuery val() and alert(’Max Qty Reached’) ? I’m using a slider as a Quantity select. In my jQuery script I trigger a select alert if the user selects more than 1000 qty. But—does anyone know how to get my alert to popup using this filamentgroup slider? Note: the select DOES change on slide. Thanks anyone!

Thanks Scott. I have an almost identical block as you suggested - which works fine. However, if I *slide* past say, 99, the alert does not trigger. It only triggers when I change() the select menu itself. Should I bind an onrelease event to the slider ya’think? Sorry, still new to jQuery and all over the Docs. Thanks again.

@a: We’ll update this plugin once UI 1.6 final is released. Once that happens, we can rename the conflicting variable. For now, you can just find replace ‘int’ with a non-conflicting name. Thanks for the heads up!

It seems that when you have your elements hidden first, then the slider won’t show up correctly. I’ve seen that problem here on this site as well in your example just above the ‘Features and Updates’. When you open it in the new window all seems nice, but when you just look at it like this, it’s all packed together.

I’m having this problem as well as my selectboxes are in a tabbed panel which is hidden at first. Even when I show the panel directly and run the initiation of the slider after it, it still shows up incorrect all packed together.

Great work on the slider it’s excellent! The math for label placement seems to be off though. My slider starts at 5 and ends at 100 with a 5 step incrementation so that’s 20 options in all. With three labels there is no “center” so the toss up should be between the two middle elements but the middle label ends up on the element before the two middle elements instead. This behavior continues if I increase the label amount with the slider putting the new labels close together and then having a big jump to the last label.

Also if I add one more option so my slider starts at 0 instead of 5 and choose three labels then the middle label ends up at 35, not 50. That’s element 8 out of 21. The expected placement of the third label is element 11 since that is right in the middle (10 elements on each side) in this case.

When I create a really long select list the slider gets pressed together. (see my screenshot - http://www.imageno.com/jq5qxei57bzdpic.html)
The same thing happens with the example on this website with the two dates slider.

Hi everyone,
As a few people pointed out, there was a slight problem with this plugin and the new UI slider in that UI tries to auto-detect the slider orientation (horizontal or vertical) and will set it to vertical if its parent container is less than a certain width.
I’ve updated the source code and zip with a fix that sets the slider’s orientation option to ‘horizontal’ by default. This should fix the stacking issues people were seeing.
Thanks!

there a way to show multiple values on the slider? I want to represent time segments on the slider itself, and allow the user to select, and then tweak the segments, even add new ones, without overlapping.

I guess with the way you have done this with select boxes, there a way to show multiple value sets on the 1 slider?

I have a case with more than two selects on the same page. I tried this out on a page with some selects at the top and some the date selects towards the bottom, and the result was messed up since it’s being called on $(’select’).

I’m getting an “contructor is null or not an object” error in Line 75.
...
function isArray(obj) {
return obj.constructor == Array;
}
...
I’ve put it in a try and catch, but then I get another error in line 84 and so I gave up.

I’m using jQuery 1.3.2
jQuery UI 1.7
ASP.NET (VB)

- Script files are all found (according to Firebug)
- The start code is like this:
$(document).ready(function() {
$(’select’).selectToUISlider();
});

This plugin is now running on jQuery UI 1.7.1 and jQuery 1.3.2. All of the demos are updated and some bug fixes are included for IE6 and 7.

@patchinko, @Dmitry, @ iceanfire: Updating the code to the newest version of jQuery UI fixed some of the issues in IE6. There are still some minor pixel differences in that browser, but it’s usable. Let us know if you come up with any fixes.

@Matthias Otto, @Adam: You’re welcome. Glad you like!

@Burke Davis: Are you still seeing that bug? I think it should be fixed with the new version of jQuery UI.

@Neal Lober: It’s up to you how you call it. You can specify the selects by id or class if you’d like… $(’select#dateA, select#dateB’).selectToUISlider();

@jason kuhn: neat idea. We’ll think about adding that.

@ skube: you’ll want to call that on the slider itself, not the select. Try finding the slider div and calling the slider methods on that. it should be appended after your select menus.. so .next() should do it.

@ Fred: You should be able to bind your slide event in addition to the one we’ve preset by using the bind method…
$(’.selector’).bind(’slide’, function(event, ui) {
$(’#My_Specific_Info_Area’).html(ui.value);
});
Let me know if that works.

@ RS71: See my comment to @Fred.

@ kris: We have not built a vertical version of this plugin. When these features are integrated into jQuery UI, you’ll likely see a solution for that.

The idea would be, there are multiple data points and they are all shown on a single slider. You could only edit a single set of data at a time, either by clicking on the little grid, or the marked area in the slider.

Am trying to get a two-handle slider to trigger an event when a handle is released, as per the code discussed above on 01/20, but all I’m managing to do is break the slider! Does anyone have an example page they can show me which shows this in action?

I set the number of labels to 7, like the example you provided, and then generated
the select options dynamically (from database data). In the case I was considering there were two dates, hence, math.round(2/7) = 0. In general, it went wrong if the number of labels is more than twice the number of select options.

I have one problem to solve, hopefully you can help me with it. I cannot seem to
set the slider to a certain value. Should be easy, and as done below, according to some documentation I read. However, I must be doing something silly, do you see it? The console.log correctly prints value = 0 (min = 0, max = 1).

I used your .next().attr(’id’, ‘timeSlider’) technique a few message above to set the id, and then:

The labels underneath the slider got covered up for some reason. I have the latest version of the code but still in ie 6 the entire labels are not showing up. Its seems a major issue for me. Can any one suggest me a work around for this.

Sorry for my english.
I do a slider with two cursors. There is always one step betwen the two cursors.
the problem: when I click whereever between two cursors (two intervalls), I would like that the label of cursor left always show ( at the moment if I click on more an half of interval it’s a date of cursor right show). I think that i must modify jquery.ui but I don’t know where..

Why when I have generated ID (JSF) so with : e.g: form:valueAA, form:valueBB the second select is never updated.It’s always the first one who’s updated.
Is it a bug or there is a solution to fix that?
Here is my script:

Hey friend,
can u give this slider files working with jquery-ui 1.2.6 and jquery-1.2-core. I need that.. plz give me that code it will be great help...i cant use latest verison of ur Slider working with jquery-ui-1..7.2 and jquery-1.3.2...because it is getting clashed with my richfaces scripts....normal slider with jquery-ui.1.6.2 is working fine with my application. Thats y i need that.... it will be great help for me…

EXCELLENT plugin guys!
BUT, how can I detect which button has been moved? I use
sliderOptions: {stop: function(e,ui) {alert(ui.value);}
...which gives my the index-position on the slider… but for which of the both buttons??
thanx for help :-)

Very nice plugin...i love it.
I’m using it in my application.I came across one issue while implemeting it in my app. As this is using select element, it conflicts with other select elements in the same page. Ofcource i solved this my checking the id’s of actually required select elements.

Very nice plugin. Unfortunately, my requirement is to be able to drag the selected range rather than have arbitrarily one of the endpoints snap to the mouse event. It’s strange ... to me dragging the range seems like the most intuitive user interaction ... and yet, for the life of me, I can’t seem to find any framework that supports such an operation.

I was trying to programatically set the value of slider using a different icon on the row (not from a click on the slider or the select box). How do I change the slider value? I tried something like you suggested above using the slider in your example with the speed range:

I want to fix the position of the slider bar in the design of my web page,… i want to place the slider in the specified row and column of the table,.... but the slider acquire position itself,.... so plz give me the information about this,… how can i do this,....

I’m having this problem as well as my selectboxes are in a tabbed panel which is hidden at first. Even when I show the panel directly and run the initiation of the slider after it, it still shows up incorrect all packed together.

Hi,
eeh it seams the plugin has a bug or am I missing something. Even in your working demo on this site.

If I klick on the select box and change the date, and then mouse over to the slider which was changed the mouse over Label still contains the old value.
Are you planing to solve this problem? Or is there a workaround?