1

I've spent the better past of 2 hours trying out random code from different sources that claim they've managed to snap the slider to particular points. I'm not sure if this is feasible with the jQuery Mobile library, since the jQuery UI version does support it, but i'm really needing to figure something out for a current project.

Essentially I have a timeline with different dates. They're not in "steps", like 10's or 20's, they're different numbers. Something like 1, 3, 10, 12, 32. I need the slider to snap at those points.

Currently, I have something that's testing the step attr only.

$('#slider-1').live( "change", function(e) {
    var step = $(this).attr('step'),
        val = $(this).val();
    if(step % val == step || val == step){
        console.log(val)
    }
});

The issue i'm having with the slider, not only the snapping, is when i slide anywhere near 20 or 40 or 60 etc, i'm getting console logs. It's not logging ON 20 etc.

Asciiom
  • 9,867
  • 7
  • 38
  • 57
Rob Graham
  • 98
  • 6
  • Have you had a look at [this answer](http://stackoverflow.com/questions/681303/is-there-a-plugin-or-example-of-a-jquery-slider-working-with-non-equably-divisib)? – Owlvark Sep 18 '12 at 15:56
  • That is specific to the jQuery UI Slider. The jQuery Mobile slider is very different and doesn't support the same methods. – Rob Graham Sep 18 '12 at 23:51

1 Answers1

5

Figured it out after many iterations of code and reading the documentation for specific events I can bind.

So essentially I had a timeline of numbers in my array that looks something like:

-0--10--20-----70--100---150---200---250---300---350---400-----500----------------1000

I needed to snap to the nearest number depending on the position of the slider-handle. I did this by testing the current value when the slider was being moved against the closest number in the array. I would then dynamically change the sliders value and would then have to do a force refresh of the slider to see the change.

$(function() {

    /*  
    Array of values between 0 - 1000 (can be any set of numbers you want to snap to, 
    but you must make sure the 'max' attribute on the input element is <= the last 
    value in the array)  
    */
    var values = [0, 10, 20, 70, 100, 150, 200, 250, 300, 350, 400, 500, 1000],

        /*
        A way for us to check the current and previous values of the slider so we only 
        call doSomething() if these are different. This way the function isn't called twice. These should NOT have the same values on init.
        */
        currentVal = 0,
        prevVal = null,

        // Assign our slider to a variable so we're not hitting the dom repeatedly. 
        $slider = $("#slider-1");

    /*
    After each change of our input value, we assign the slider value to the nearest number
    in our array for our "snap" effect
    */
    $($slider).bind("change", function(){
        $($slider).val(findNearest($($slider).val()))
    });

    /*
    We must capture click events on the slider itself if the user doesn't drag the handle.
    */
    $(".ui-slider[role=application]").bind("vclick",function(){
        $($slider).slider('refresh');
    })

    /*
    jQuery creates new dom elements for us, which in the case of the handle, is an anchor element. 
    Use mouseup method to test on the computer, otherwise touchend method for mobile devices.
    */
    $("a.ui-slider-handle").touchend(function(){
        // If our currentVal hasn't changed after a snap action, do nothing, otherwise call doSomething()
        if(currentVal != prevVal) {
            prevVal = currentVal;
            doSomething();
        }

        // Force slider refresh for visible snap effect
        $($slider).slider('refresh');
    })

    // Used to iterate over our array and check for nearest value to what is passed in
    function findNearest(goal) {
        var closest = null;
        $.each(values, function(){
          if (closest == null || Math.abs(this - goal) < Math.abs(closest - goal)) {
            closest = this;
          }
        });
        return currentVal = Number(closest);
    }

    function doSomething(){
        ... 
    }
});

And my HTML:

<label for="slider-1" id="slider_label_1">Input slider:</label>
<input type="range" name="slider-1" id="slider-1" value="0" min="0" max="1000" step="10" />
Rob Graham
  • 98
  • 6