Scriptaculous slider trick

Yesterday I was looking at the Scriptaculous library, in particular the slider bar. I had used it once before with some success, using a graphic for the track and gripper. But that’s was boring! What I wanted was to see the bar fill up with colour when it was slid. Something like this:

Slider demo

I hadn’t seen anything like this around (not saying it hasn’t been done, just that I hadn’t seen it!), so after a bit of playing I found out it was actually very easy to create. And this is how I did it…

All it really does is use a handy little trick with transparent PNG images and background-image positions. You can find details of what I mean in this handy article by Dave Stone, over at Bare Naked App.

So basically I have my slider gripper (or handle), which has a transparent background:

Slider gripper

And the slider track, which has an opaque white background but is transparent where I want the colour to show through (thumbnail shown, but links through to full size image):

Slider track

And then I have the background image, which is essentially double the size of the track and has one half in off-white and one in green (thumbnail shown, but links through to full size image):

Slider background

The XHTML used for the slider looks like this:

<div id="slider">
    <div id="slider-bar">
        <div id="slider-handle"><p id="percent"></p></div>
    </div>
</div>

The CSS looks like this:

#slider, #slider-bar, #slider-handle {
    border: 0;
    padding: 0;
    margin: 0;
}
#slider {
    width: 300px;
    height:42px;
    background: url(img/bg.gif) no-repeat -300px;
    margin-left: 42px;
}
#slider-bar {
    width:300px;
    height:42px;
    background: url(img/track.png) no-repeat;
}
#slider-handle {
    width:42px;
    height:42px;
    cursor:move;
    background: url(img/gripper.png) no-repeat;
}
#percent {
    font-size: 75%;
    font-family: arial;
    font-weight: bold;
    text-align: center;
    padding-top: 1.1em;
}

And finally, the Javascript looks like this:

<script type="text/javascript">
// <!&#91;CDATA&#91;
var hWidth, bWidth;

function setBgPos(v) {
    var off = v * hWidth;
    var pos = -bWidth + (v * bWidth);
    $('slider').setStyle({backgroundPosition: Math.round(pos - off) + 'px'});
}

function setSlideOutput(v) {
    $('percent').innerHTML = Math.round(v * 100) + '%';
}

Event.observe(window, 'load', function() {
    hWidth = $('slider-handle').getWidth();
    bWidth = $('slider-bar').getWidth();
    var slide = new Control.Slider('slider-handle', 'slider-bar', {
        sliderValue: 0.25,
        onSlide: 
            function(v) {
                setBgPos(v);
                setSlideOutput(v);
            },
        onChange:
            function(v) {
                setBgPos(v);
                setSlideOutput(v);
            }
    });
    setBgPos(slide.value);
    setSlideOutput(slide.value);
});
// &#93;&#93;>
</script>

You may notice the offset value, off. I’m using this because in my experiment the slider handle doesn’t fully cover the bar (nor did I want it to), so I cannot have the background image colour go fully across the track. I had to incrementally offset it depending on the position and size of the handle.

And that’s it! Pretty darned easy, but looks really neat. You can see it in action at http://dev.amnuts.com/slider/.

Did you like this? Share it:

15 thoughts on “Scriptaculous slider trick

  1. I thought this was a little dodgy on Safari; the track image wouldn’t update and the percentage value wouldn’t display. In the end it turned out to be the version of Safari I was using not having Javascript 1.5, which the .toFixed() method requires. Changing that to use Math.round() fixes the issues in Safari (version < 2.0). I've updated the code to reflect this change.

  2. Hello, I tried to use this nifty slider in a school project for MYSQL and PHP, unfortunately when I tried to capture the percentage value to use it in a Form I didn’t succeed.I’m asking you for your help if possible since I’m really new to JavaScript and i just can’t find any solution to use the value effectively 🙁
    Thanks in advance.

    P.S.: Congrats for this Blog, it will surely one of my references.

  3. dj_thekid; thanks for the kind words! One way to do this (and there are probably plenty of ways that you could), is to set a hidden form value on slide and change. So say you had a form element:

    <input type=”hidden” id=”percentage” name=”percentage” value=”0″ />

    Then you’d update the onSlide and onChange events to be something like:

            onSlide:
                function(v) {
                    setBgPos(v);
                    setSlideOutput(v);
                    $('percentage').value = Math.round(v * 100);
                },
            onChange:
                function(v) {
                    setBgPos(v);
                    setSlideOutput(v);
                    $('percentage').value = Math.round(v * 100);
                }
    

    Hope that helps.

  4. Dear Andy,
    Thank you for your precious help. Your suggestion worked perfectly as intended, now I can use the slider value inside the form.

  5. Thanks Andy. Very good job on the visual. One problem I am having though is when going from horizontal to vertical I can not get 0% to be at the bottom and 100% to be at the top. Could you instruct me on how to achieve this?
    Thanks

  6. Very, nice. But I can’t get it to work on any of my browsers (FF3, gChrome, etc.) I get a “Control is not defined — on Line 26 of index.html)” showing up on my FF Error Console. I simply copy and pasted everything from your web page and followed your directory structures. Any thoughts on what is causing this error?

  7. I used this your code and it was really helpful. What I just need to do more on it is, make it stepped such that the slider stops on predefined intervals. How can i do this. I would appreciate your help

  8. I have to admit that it’s been a very long time since I’ve used scriptaculous, preferring these days to use jQuery, and I don’t own an iPad, either… So what I’m pretty much trying to tell you is that I don’t have a clue! Anyone else out there happen to have tried it on an iPad and got it working?

  9. OK, I forgot that if it works on an iPhone it’d work on an iPad, and I also forgot that I borrowed work’s iPad the other day and still have it…. I’m tired, give me a break! 😉

    It’s actually really easy to make it work with the touch interface – as you’ll be able to see on http://dev.amnuts.com/slider/ – I updated that it works perfectly on the iPad, iPhone and also my Android-based phone.

    All you have to do is make the adjustments to scriptaculous’ slider.js file that are shown here:

    https://github.com/w3news/scriptaculous/commit/6031ed46b87aeca837d5ca5ee33ddfbca4c6fd46

    and that’s it! A few minutes work to implement the new lines and change the ones that you need to and touch-dragging goodness is yours. 🙂

Leave a Reply