4
votes

I'm using a jQuery slider where users can select a time range between 00:00 and 1d+12:00. 36 hours all together. Anyway.

I would like to apply min and max values to my handles based on what they're set to. These are my requirements:

  1. left handle can never go over midnight on the next day (max is 24 hours)
  2. left handle can never go more left than -24 hours from right handle (min is right handle value minus 24 hours)
  3. right handle can never go more than +24 hours from the left handle (max is left handle value plus 24 hours)

As I understand, minimum and maximum values can only be applied to single handle slider control and not to range slider?

Is it possible to set minimums and maximums individually to both handles?

I've tried initializing it this way but no luck:

$(".timing-slider", timing).slider({
    range: true,
    min: [0, 0],
    max: [24, 36],
}
1

1 Answers

10
votes

This jQuery UI slider extension satisfies all upper requirements

I've managed to change default jQuery UI slider to include a few more configuration properties:

  • minRangeSize - sets minimum range size so ranges can't be narrower than this setting
  • maxRangeSize - sets maximum range size so ranges can't be wider than this setting
  • autoShift - when set to true it automatically drags the other handle along when range width reaches maximum; when set to false handle just can't be moved beyond maximum range width
  • lowMax - sets the lower handle upper boundary so it's impossible to set lower handle beyond this value
  • topMin - sets the upper handle lower boundary so it's impossible to set upper handle below this value

This is a working example of such range slider.

This is the extra code that has to be run after jQuery slider. It actually rewrites one of its internal functions to also check the new settings. This code will only change slider code when slider script has been loaded (hence the first if statement that checks whether slider widget has been loaded):

(function ($) {
    if ($.ui.slider)
    {
        // add minimum range length option
        $.extend($.ui.slider.prototype.options, {
            minRangeSize: 0,
            maxRangeSize: 100,
            autoShift: false,
            lowMax: 100,
            topMin: 0
        });

        $.extend($.ui.slider.prototype, {
            _slide: function (event, index, newVal) {
                var otherVal,
                newValues,
                allowed,
                factor;

                if (this.options.values && this.options.values.length)
                {
                    otherVal = this.values(index ? 0 : 1);
                    factor = index === 0 ? 1 : -1;

                    if (this.options.values.length === 2 && this.options.range === true)
                    {
                        // lower bound max
                        if (index === 0 && newVal > this.options.lowMax)
                        {
                            newVal = this.options.lowMax;
                        }
                        // upper bound min
                        if (index === 1 && newVal < this.options.topMin)
                        {
                            newVal = this.options.topMin;
                        }
                        // minimum range requirements
                        if ((otherVal - newVal) * factor < this.options.minRangeSize)
                        {
                            newVal = otherVal - this.options.minRangeSize * factor;
                        }
                        // maximum range requirements
                        if ((otherVal - newVal) * factor > this.options.maxRangeSize)
                        {
                            if (this.options.autoShift === true)
                            {
                                otherVal = newVal + this.options.maxRangeSize * factor;
                            }
                            else
                            {
                                newVal = otherVal - this.options.maxRangeSize * factor;
                            }
                        }
                    }

                    if (newVal !== this.values(index))
                    {
                        newValues = this.values();
                        newValues[index] = newVal;
                        newValues[index ? 0 : 1] = otherVal;
                        // A slide can be canceled by returning false from the slide callback
                        allowed = this._trigger("slide", event, {
                            handle: this.handles[index],
                            value: newVal,
                            values: newValues
                        });
                        if (allowed !== false)
                        {
                            this.values(index, newVal, true);
                            this.values((index + 1) % 2, otherVal, true);
                        }
                    }
                } else
                {
                    if (newVal !== this.value())
                    {
                        // A slide can be canceled by returning false from the slide callback
                        allowed = this._trigger("slide", event, {
                            handle: this.handles[index],
                            value: newVal
                        });
                        if (allowed !== false)
                        {
                            this.value(newVal);
                        }
                    }
                }
            }
        });
    }
})(jQuery);