Creating a Nice Slider With jQuery UI
March 29th, 2008
Sliders have many things going for them as a UI element; they offer the benefit restricting the choice a user has, without taking up the space of a drop down. If you need to ask the user to select a number between a range, you can either do an input box with validation, a drop down select element listing each possibility, or you can do a slider.
One drawback of a slider is the user not knowing what he’s selected as there’s no discrete output. If you are sliding to scale something, you can eyeball something, but wouldn’t it be nice if the slider provided some feedback to the user (“50%”) as the user was fiddling with it? I’m going to show you how to do just that with the jQuery UI library.
I had a local backup of the demo, thank goodness, so that’s still up. Unfortunately, not the video.
The necessary dependencies :
The code I used is as follows :
HTML
<div id='container'>
<div class="slider_container">
<div class='small_label'></div>
<div class='slider_bar'>
<div id="slider_callout"></div>
<div id='slider1_handle' class='slider_handle'></div>
</div>
<div class='large_label'></div>
</div>
</div>
CSS
body { background: #284a6e; }
#container { height: 100px; border: 1px solid #284a6e;}
.slider_container { position: relative; margin-top: 50px; height: 40px;}
.small_label { background: url(minus.gif) no-repeat; height: 19px; width: 19px; overflow: hidden; float: left; }
.slider_bar { background: url(bar.gif) no-repeat; height: 19px; width: 260px; float: left; margin: 0px 5px; position: relative;}
.large_label { background: url(plus.gif) no-repeat; height: 19px; width: 19px; overflow: hidden; float: left; }
.slider_handle { background: url(selector.png) no-repeat; height: 19px; width: 20px; overflow: hidden; position: absolute; top: 1px;}
#slider_callout { background: url(callout.gif) no-repeat; height: 45px; width: 38px; overflow: hidden; position: absolute; top: -50px; margin-left:-10px; padding: 8px 0px 0px 0px; font-family: "Myriad Pro"; color: #284a6e; font-weight: bold; text-align: center;}
Update: A couple commenters noticed a little outline gremlin in Firefox 3 when using the slider. Just add * :focus { outline:none } to get rid of it. I’m not sure which element the outline is on, so applying it to * can’t hurt
JavaScript
After I recorded the video, it dawned on me that there’s a way to do this that is a bit simpler: by using the ui object passed in by slider, and grabbing the “left” css property of the handle. That way, the callout matches the css handle at all times, with no calculations needed; and you can reserve minValue and maxValue to return values that are useful for your web application.
Thanks to Andrew and John in the comments, I have fixed some bugs with the code. Now you can click on the bar itself and the callout will fire correctly. For this I utilized the “stop” event, checked if the callout was already visible, and displayed it if not.
The code looks like this :
$(function() {
$('#slider_callout').hide();
var calloutVisible = false;
$('.slider_bar').slider({
handle: '.slider_handle',
minValue: 0,
maxValue: 25,
start: function(e, ui) {
$('#slider_callout').fadeIn('fast', function() { calloutVisible = true;});
},
stop: function(e, ui) {
if (calloutVisible == false) {
$('#slider_callout').fadeIn('fast', function() { calloutVisible = true;});
$('#slider_callout').css('left', ui.handle.css('left')).text(Math.round(ui.value));
}
$('#slider_callout').fadeOut('fast', function() { calloutVisible = false; });
},
slide: function(e, ui) {
$('#slider_callout').css('left', ui.handle.css('left')).text(Math.round(ui.value));
}
});
});
For reference purposes, here is the code I used in the video :
$(function() {
$('#slider_callout').hide();
$('.slider_bar').slider({
handle: '.slider_handle',
minValue: 0,
maxValue: 240,
start: function(e, ui) {
$('#slider_callout').fadeIn('fast');
},
stop: function(e, ui) {
$('#slider_callout').fadeOut('fast');
},
slide: function(e, ui) {
$('#slider_callout').css('left', ui.value).text(Math.round(ui.value * (100/240)));
}
});
});
You may want to remove the console.log() statements from your demo (the prevent it from working in browsers that don’t have Firebug – or that have Firebug disabled).
Very cool work, though!