Search code examples
javascriptjquerycssjquery-uiuislider

jQuery Slider performing unexpectedly?


I have, after many tutorials and lots of time, managed to build a slider with jQuery. However, it's not working as smoothly as I would have hoped. I have used a custom handle, and seeing as the new jQueryUI doesn't have a handle option, I have created a handle in CSS. However, this handle is going beyond the required bounds of the slider. I have uploaded a test page which can be found here.

My code is as follows:

CSS

<style type="text/css" media="screen">
<!--
    body {
        padding: 0; 
        font: 1em "Trebuchet MS", verdana, arial, sans-serif; 
        font-size: 100%;
        background-color: #212121;
        margin: 0;
    }

    h1 { 
        margin-bottom: 2px; 
    }

    #container {
        background-color: #fff;
        width: 580px;
        margin: 15px auto;
        padding: 50px;
    }

    /* slider specific CSS */
    .sliderGallery {
        background: url(productbrowser_background_20070622.jpg) no-repeat;
        overflow: hidden;
        position: relative;
        padding: 10px;
        height: 160px;
        width: 560px;
    }

    .sliderGallery UL {
        position: absolute;
        list-style: none;
        overflow: none;
        white-space: nowrap;
        padding: 0;
        margin: 0;
    }

    .sliderGallery UL LI {
        display: inline;
    }

    .slider {
        width: 542px;
        height: 17px;
        margin-top: 140px;
        margin-left: 5px;
        padding: 1px;
        position: relative;
        background: url(productbrowser_scrollbar_20070622.png) no-repeat;
    }

    .ui-slider .ui-slider-handle {
        width:180px;
        margin-left:-90px;
    }

    .ui-slider-handle {
        position: absolute;
        cursor: default;
        height: 17px;
        top: 0;
        background: url(productbrowser_scroller_20080115.png) no-repeat;
        z-index: 100;
    }

    .slider span {
        color: #bbb;
        font-size: 80%;
        cursor: pointer;
        position: absolute;
        z-index: 110;
    }

    .slider .slider-lbl1 {
        left: 50px;
    }

    .slider .slider-lbl2 {
        left: 220px;
    }

    .slider .slider-lbl3 {
        left: 156px;
    }

    .slider .slider-lbl4 {
        left: 280px;
    }

    .slider .slider-lbl5 {
        left: 455px;
    }
-->
</style>

jQuery

<script src="jqueryui.js" type="text/javascript" charset="utf-8"></script>

<script type="text/javascript" charset="utf-8">
    window.onload = function () {
        var container = $('div.sliderGallery');
        var ul = $('ul', container);

        var itemsWidth = ul.innerWidth() - container.outerWidth() + 50;

        $('.handle', container).slider({
            min: -50,
            max: itemsWidth,
            stop: function (event, ui) {
                ul.animate({'left' : ui.value * -1}, 500);
            },
            slide: function (event, ui) {
                ul.css('left', ui.value * -1);
            }
        });
    };
</script>

Body

<div id="container">
    <div class="sliderGallery">
        <ul>
            <li><a href="#"><img src="ki_aikido.png"></a></li>
            <li><a href="#"><img src="ki_aikido.png"></a></li>
            <li><a href="#"><img src="ki_aikido.png"></a></li>
            <li><a href="#"><img src="ki_aikido.png"></a></li>
            <li><a href="#"><img src="ki_aikido.png"></a></li>
            <li><a href="#"><img src="ki_aikido.png"></a></li>
            <li><a href="#"><img src="ki_aikido.png"></a></li>
            <li><a href="#"><img src="ki_aikido.png"></a></li>
            <li><a href="#"><img src="ki_aikido.png"></a></li>
            <li><a href="#"><img src="ki_aikido.png"></a></li>
            <li><a href="#"><img src="ki_aikido.png"></a></li>
            <li><a href="#"><img src="ki_aikido.png"></a></li>
            <li><a href="#"><img src="ki_aikido.png"></a></li>
            <li><a href="#"><img src="ki_aikido.png"></a></li>
            <li><a href="#"><img src="ki_aikido.png"></a></li>
            <li><a href="#"><img src="ki_aikido.png"></a></li>
            <li><a href="#"><img src="ki_aikido.png"></a></li>
            <li><a href="#"><img src="ki_aikido.png"></a></li>
            <li><a href="#"><img src="ki_aikido.png"></a></li>
            <li><a href="#"><img src="ki_aikido.png"></a></li>
            <li><a href="#"><img src="ki_aikido.png"></a></li>
            <li><a href="#"><img src="ki_aikido.png"></a></li>
            <li><a href="#"><img src="ki_aikido.png"></a></li>
        </ul>
        <div class="slider ui-slider">
            <div class="handle"></div>
            <span class="slider-lbl1">Our Books</span>
            <span class="slider-lbl2">Other Books</span>
        </div>
    </div>
</div>

What I'd like to know is if there is any way to force the slider bar to stay inside the image behind it? The test link will let you understand what I mean if I didn't explain myself clearly.

Thanks in advance, Dronnoc


Solution

  • The problem is coming from the fact that your handle is set to go outside of it's container.

    The two problems are coming from the following

    .ui-slider .ui-slider-handle {
        width:180px;
        margin-left:-90px;
    }
    

    The second line says that the slider is allowed to go 90px before the left of it's initial container (hence the left overflow)

    And when setting the left of the handle to 100%, it means that it will overflow on the right from 90px (180-90).

    The way I would handle that would be to drop the margin-left:-90px;, to reduce the width of the scrolling div by 180px and to use another div to display the scroll bar image (positioned under your sliding div, but wider).

    Something like:

    .slider {
        width: 362px;
        height: 17px;
        margin-top: 140px;
        margin-left: 5px;
        padding: 1px;
        position: relative;
    }
    
    .ui-slider .ui-slider-handle {
        width:180px;
    }
    .sliderImg{
        background: url(productbrowser_scrollbar_20070622.png) no-repeat;
        /*add css to position it correctly here*/
    }
    

    EDIT: To answer to your comment, the following correction to the CSS on your page should make that work:

    .slider {
        /*let the rest as is*/
        margin-left: 90px;
    }
    
    .ui-slider .ui-slider-handle {
        width:180px;
        margin-left:-90px;
    }
    

    This combination will let it with the same boundaries (-90 + 90 = 0 ) but are going to make it move nicely.

    EDIT2:

    TO enable the click on the handle, you'll need to specify a height to your handle (otherwise you wouldn't be able to click on it). However this will move your span under the sliding div, to overcome it you'll have to specify their top position (as you already have them in absolute it's easy ;) ).

    The following should do.

    .handle {
        height: 100%;
    } 
    .slider span {
        /*let the rest as is*/
        top: 0;
    }
    

    To make that work above the span, you'll need to change your html a bit like that:

      <div class="handle">
          <span id="slider-tags" class="slider-lbl1">Our Books</span>
          <span id="slider-tags" class="slider-lbl2">Other Books</span>
      </div>